api-config.html   [plain text]


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
    "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="generator" content="AsciiDoc 8.5.2" />
<title>config API</title>
<style type="text/css">
/* Debug borders */
p, li, dt, dd, div, pre, h1, h2, h3, h4, h5, h6 {
/*
  border: 1px solid red;
*/
}

body {
  margin: 1em 5% 1em 5%;
}

a {
  color: blue;
  text-decoration: underline;
}
a:visited {
  color: fuchsia;
}

em {
  font-style: italic;
  color: navy;
}

strong {
  font-weight: bold;
  color: #083194;
}

tt {
  color: navy;
}

h1, h2, h3, h4, h5, h6 {
  color: #527bbd;
  font-family: sans-serif;
  margin-top: 1.2em;
  margin-bottom: 0.5em;
  line-height: 1.3;
}

h1, h2, h3 {
  border-bottom: 2px solid silver;
}
h2 {
  padding-top: 0.5em;
}
h3 {
  float: left;
}
h3 + * {
  clear: left;
}

div.sectionbody {
  font-family: serif;
  margin-left: 0;
}

hr {
  border: 1px solid silver;
}

p {
  margin-top: 0.5em;
  margin-bottom: 0.5em;
}

ul, ol, li > p {
  margin-top: 0;
}

pre {
  padding: 0;
  margin: 0;
}

span#author {
  color: #527bbd;
  font-family: sans-serif;
  font-weight: bold;
  font-size: 1.1em;
}
span#email {
}
span#revnumber, span#revdate, span#revremark {
  font-family: sans-serif;
}

div#footer {
  font-family: sans-serif;
  font-size: small;
  border-top: 2px solid silver;
  padding-top: 0.5em;
  margin-top: 4.0em;
}
div#footer-text {
  float: left;
  padding-bottom: 0.5em;
}
div#footer-badges {
  float: right;
  padding-bottom: 0.5em;
}

div#preamble {
  margin-top: 1.5em;
  margin-bottom: 1.5em;
}
div.tableblock, div.imageblock, div.exampleblock, div.verseblock,
div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock,
div.admonitionblock {
  margin-top: 1.0em;
  margin-bottom: 1.5em;
}
div.admonitionblock {
  margin-top: 2.0em;
  margin-bottom: 2.0em;
  margin-right: 10%;
  color: #606060;
}

div.content { /* Block element content. */
  padding: 0;
}

/* Block element titles. */
div.title, caption.title {
  color: #527bbd;
  font-family: sans-serif;
  font-weight: bold;
  text-align: left;
  margin-top: 1.0em;
  margin-bottom: 0.5em;
}
div.title + * {
  margin-top: 0;
}

td div.title:first-child {
  margin-top: 0.0em;
}
div.content div.title:first-child {
  margin-top: 0.0em;
}
div.content + div.title {
  margin-top: 0.0em;
}

div.sidebarblock > div.content {
  background: #ffffee;
  border: 1px solid silver;
  padding: 0.5em;
}

div.listingblock > div.content {
  border: 1px solid silver;
  background: #f4f4f4;
  padding: 0.5em;
}

div.quoteblock, div.verseblock {
  padding-left: 1.0em;
  margin-left: 1.0em;
  margin-right: 10%;
  border-left: 5px solid #dddddd;
  color: #777777;
}

div.quoteblock > div.attribution {
  padding-top: 0.5em;
  text-align: right;
}

div.verseblock > div.content {
  white-space: pre;
}
div.verseblock > div.attribution {
  padding-top: 0.75em;
  text-align: left;
}
/* DEPRECATED: Pre version 8.2.7 verse style literal block. */
div.verseblock + div.attribution {
  text-align: left;
}

div.admonitionblock .icon {
  vertical-align: top;
  font-size: 1.1em;
  font-weight: bold;
  text-decoration: underline;
  color: #527bbd;
  padding-right: 0.5em;
}
div.admonitionblock td.content {
  padding-left: 0.5em;
  border-left: 3px solid #dddddd;
}

div.exampleblock > div.content {
  border-left: 3px solid #dddddd;
  padding-left: 0.5em;
}

div.imageblock div.content { padding-left: 0; }
span.image img { border-style: none; }
a.image:visited { color: white; }

dl {
  margin-top: 0.8em;
  margin-bottom: 0.8em;
}
dt {
  margin-top: 0.5em;
  margin-bottom: 0;
  font-style: normal;
  color: navy;
}
dd > *:first-child {
  margin-top: 0.1em;
}

ul, ol {
    list-style-position: outside;
}
ol.arabic {
  list-style-type: decimal;
}
ol.loweralpha {
  list-style-type: lower-alpha;
}
ol.upperalpha {
  list-style-type: upper-alpha;
}
ol.lowerroman {
  list-style-type: lower-roman;
}
ol.upperroman {
  list-style-type: upper-roman;
}

div.compact ul, div.compact ol,
div.compact p, div.compact p,
div.compact div, div.compact div {
  margin-top: 0.1em;
  margin-bottom: 0.1em;
}

div.tableblock > table {
  border: 3px solid #527bbd;
}
thead, p.table.header {
  font-family: sans-serif;
  font-weight: bold;
}
tfoot {
  font-weight: bold;
}
td > div.verse {
  white-space: pre;
}
p.table {
  margin-top: 0;
}
/* Because the table frame attribute is overriden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
  border-style: none;
}
div.tableblock > table[frame="hsides"] {
  border-left-style: none;
  border-right-style: none;
}
div.tableblock > table[frame="vsides"] {
  border-top-style: none;
  border-bottom-style: none;
}


div.hdlist {
  margin-top: 0.8em;
  margin-bottom: 0.8em;
}
div.hdlist tr {
  padding-bottom: 15px;
}
dt.hdlist1.strong, td.hdlist1.strong {
  font-weight: bold;
}
td.hdlist1 {
  vertical-align: top;
  font-style: normal;
  padding-right: 0.8em;
  color: navy;
}
td.hdlist2 {
  vertical-align: top;
}
div.hdlist.compact tr {
  margin: 0;
  padding-bottom: 0;
}

.comment {
  background: yellow;
}

.footnote, .footnoteref {
  font-size: 0.8em;
}

span.footnote, span.footnoteref {
  vertical-align: super;
}

#footnotes {
  margin: 20px 0 20px 0;
  padding: 7px 0 0 0;
}

#footnotes div.footnote {
  margin: 0 0 5px 0;
}

#footnotes hr {
  border: none;
  border-top: 1px solid silver;
  height: 1px;
  text-align: left;
  margin-left: 0;
  width: 20%;
  min-width: 100px;
}


@media print {
  div#footer-badges { display: none; }
}

div#toc {
  margin-bottom: 2.5em;
}

div#toctitle {
  color: #527bbd;
  font-family: sans-serif;
  font-size: 1.1em;
  font-weight: bold;
  margin-top: 1.0em;
  margin-bottom: 0.1em;
}

div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 {
  margin-top: 0;
  margin-bottom: 0;
}
div.toclevel2 {
  margin-left: 2em;
  font-size: 0.9em;
}
div.toclevel3 {
  margin-left: 4em;
  font-size: 0.9em;
}
div.toclevel4 {
  margin-left: 6em;
  font-size: 0.9em;
}
/* Workarounds for IE6's broken and incomplete CSS2. */

div.sidebar-content {
  background: #ffffee;
  border: 1px solid silver;
  padding: 0.5em;
}
div.sidebar-title, div.image-title {
  color: #527bbd;
  font-family: sans-serif;
  font-weight: bold;
  margin-top: 0.0em;
  margin-bottom: 0.5em;
}

div.listingblock div.content {
  border: 1px solid silver;
  background: #f4f4f4;
  padding: 0.5em;
}

div.quoteblock-attribution {
  padding-top: 0.5em;
  text-align: right;
}

div.verseblock-content {
  white-space: pre;
}
div.verseblock-attribution {
  padding-top: 0.75em;
  text-align: left;
}

div.exampleblock-content {
  border-left: 3px solid #dddddd;
  padding-left: 0.5em;
}

/* IE6 sets dynamically generated links as visited. */
div#toc a:visited { color: blue; }
</style>
<script type="text/javascript">
/*<![CDATA[*/
window.onload = function(){asciidoc.footnotes();}
var asciidoc = {  // Namespace.

/////////////////////////////////////////////////////////////////////
// Table Of Contents generator
/////////////////////////////////////////////////////////////////////

/* Author: Mihai Bazon, September 2002
 * http://students.infoiasi.ro/~mishoo
 *
 * Table Of Content generator
 * Version: 0.4
 *
 * Feel free to use this script under the terms of the GNU General Public
 * License, as long as you do not remove or alter this notice.
 */

 /* modified by Troy D. Hanson, September 2006. License: GPL */
 /* modified by Stuart Rackham, 2006, 2009. License: GPL */

// toclevels = 1..4.
toc: function (toclevels) {

  function getText(el) {
    var text = "";
    for (var i = el.firstChild; i != null; i = i.nextSibling) {
      if (i.nodeType == 3 /* Node.TEXT_NODE */) // IE doesn't speak constants.
        text += i.data;
      else if (i.firstChild != null)
        text += getText(i);
    }
    return text;
  }

  function TocEntry(el, text, toclevel) {
    this.element = el;
    this.text = text;
    this.toclevel = toclevel;
  }

  function tocEntries(el, toclevels) {
    var result = new Array;
    var re = new RegExp('[hH]([2-'+(toclevels+1)+'])');
    // Function that scans the DOM tree for header elements (the DOM2
    // nodeIterator API would be a better technique but not supported by all
    // browsers).
    var iterate = function (el) {
      for (var i = el.firstChild; i != null; i = i.nextSibling) {
        if (i.nodeType == 1 /* Node.ELEMENT_NODE */) {
          var mo = re.exec(i.tagName);
          if (mo && (i.getAttribute("class") || i.getAttribute("className")) != "float") {
            result[result.length] = new TocEntry(i, getText(i), mo[1]-1);
          }
          iterate(i);
        }
      }
    }
    iterate(el);
    return result;
  }

  var toc = document.getElementById("toc");
  var entries = tocEntries(document.getElementById("content"), toclevels);
  for (var i = 0; i < entries.length; ++i) {
    var entry = entries[i];
    if (entry.element.id == "")
      entry.element.id = "_toc_" + i;
    var a = document.createElement("a");
    a.href = "#" + entry.element.id;
    a.appendChild(document.createTextNode(entry.text));
    var div = document.createElement("div");
    div.appendChild(a);
    div.className = "toclevel" + entry.toclevel;
    toc.appendChild(div);
  }
  if (entries.length == 0)
    toc.parentNode.removeChild(toc);
},


/////////////////////////////////////////////////////////////////////
// Footnotes generator
/////////////////////////////////////////////////////////////////////

/* Based on footnote generation code from:
 * http://www.brandspankingnew.net/archive/2005/07/format_footnote.html
 */

footnotes: function () {
  var cont = document.getElementById("content");
  var noteholder = document.getElementById("footnotes");
  var spans = cont.getElementsByTagName("span");
  var refs = {};
  var n = 0;
  for (i=0; i<spans.length; i++) {
    if (spans[i].className == "footnote") {
      n++;
      // Use [\s\S] in place of . so multi-line matches work.
      // Because JavaScript has no s (dotall) regex flag.
      note = spans[i].innerHTML.match(/\s*\[([\s\S]*)]\s*/)[1];
      noteholder.innerHTML +=
        "<div class='footnote' id='_footnote_" + n + "'>" +
        "<a href='#_footnoteref_" + n + "' title='Return to text'>" +
        n + "</a>. " + note + "</div>";
      spans[i].innerHTML =
        "[<a id='_footnoteref_" + n + "' href='#_footnote_" + n +
        "' title='View footnote' class='footnote'>" + n + "</a>]";
      var id =spans[i].getAttribute("id");
      if (id != null) refs["#"+id] = n;
    }
  }
  if (n == 0)
    noteholder.parentNode.removeChild(noteholder);
  else {
    // Process footnoterefs.
    for (i=0; i<spans.length; i++) {
      if (spans[i].className == "footnoteref") {
        var href = spans[i].getElementsByTagName("a")[0].getAttribute("href");
        href = href.match(/#.*/)[0];  // Because IE return full URL.
        n = refs[href];
        spans[i].innerHTML =
          "[<a href='#_footnote_" + n +
          "' title='View footnote' class='footnote'>" + n + "</a>]";
      }
    }
  }
}

}
/*]]>*/
</script>
</head>
<body>
<div id="header">
<h1>config API</h1>
</div>
<div id="content">
<div id="preamble">
<div class="sectionbody">
<div class="paragraph"><p>The config API gives callers a way to access git configuration files
(and files which have the same syntax). See <a href="../git-config.html">git-config(1)</a> for a
discussion of the config file syntax.</p></div>
</div>
</div>
<h2 id="_general_usage">General Usage</h2>
<div class="sectionbody">
<div class="paragraph"><p>Config files are parsed linearly, and each variable found is passed to a
caller-provided callback function. The callback function is responsible
for any actions to be taken on the config option, and is free to ignore
some options. It is not uncommon for the configuration to be parsed
several times during the run of a git program, with different callbacks
picking out different variables useful to themselves.</p></div>
<div class="paragraph"><p>A config callback function takes three parameters:</p></div>
<div class="ulist"><ul>
<li>
<p>
the name of the parsed variable. This is in canonical "flat" form: the
  section, subsection, and variable segments will be separated by dots,
  and the section and variable segments will be all lowercase. E.g.,
  <tt>core.ignorecase</tt>, <tt>diff.SomeType.textconv</tt>.
</p>
</li>
<li>
<p>
the value of the found variable, as a string. If the variable had no
  value specified, the value will be NULL (typically this means it
  should be interpreted as boolean true).
</p>
</li>
<li>
<p>
a void pointer passed in by the caller of the config API; this can
  contain callback-specific data
</p>
</li>
</ul></div>
<div class="paragraph"><p>A config callback should return 0 for success, or -1 if the variable
could not be parsed properly.</p></div>
</div>
<h2 id="_basic_config_querying">Basic Config Querying</h2>
<div class="sectionbody">
<div class="paragraph"><p>Most programs will simply want to look up variables in all config files
that git knows about, using the normal precedence rules. To do this,
call <tt>git_config</tt> with a callback function and void data pointer.</p></div>
<div class="paragraph"><p><tt>git_config</tt> will read all config sources in order of increasing
priority. Thus a callback should typically overwrite previously-seen
entries with new ones (e.g., if both the user-wide <tt>~/.gitconfig</tt> and
repo-specific <tt>.git/config</tt> contain <tt>color.ui</tt>, the config machinery
will first feed the user-wide one to the callback, and then the
repo-specific one; by overwriting, the higher-priority repo-specific
value is left at the end).</p></div>
<div class="paragraph"><p>The <tt>git_config_with_options</tt> function lets the caller examine config
while adjusting some of the default behavior of <tt>git_config</tt>. It should
almost never be used by "regular" git code that is looking up
configuration variables. It is intended for advanced callers like
<tt>git-config</tt>, which are intentionally tweaking the normal config-lookup
process. It takes two extra parameters:</p></div>
<div class="dlist"><dl>
<dt class="hdlist1">
<tt>filename</tt>
</dt>
<dd>
<p>
If this parameter is non-NULL, it specifies the name of a file to
parse for configuration, rather than looking in the usual files. Regular
<tt>git_config</tt> defaults to <tt>NULL</tt>.
</p>
</dd>
<dt class="hdlist1">
<tt>respect_includes</tt>
</dt>
<dd>
<p>
Specify whether include directives should be followed in parsed files.
Regular <tt>git_config</tt> defaults to <tt>1</tt>.
</p>
</dd>
</dl></div>
<div class="paragraph"><p>There is a special version of <tt>git_config</tt> called <tt>git_config_early</tt>.
This version takes an additional parameter to specify the repository
config, instead of having it looked up via <tt>git_path</tt>. This is useful
early in a git program before the repository has been found. Unless
you&#8217;re working with early setup code, you probably don&#8217;t want to use
this.</p></div>
</div>
<h2 id="_reading_specific_files">Reading Specific Files</h2>
<div class="sectionbody">
<div class="paragraph"><p>To read a specific file in git-config format, use
<tt>git_config_from_file</tt>. This takes the same callback and data parameters
as <tt>git_config</tt>.</p></div>
</div>
<h2 id="_value_parsing_helpers">Value Parsing Helpers</h2>
<div class="sectionbody">
<div class="paragraph"><p>To aid in parsing string values, the config API provides callbacks with
a number of helper functions, including:</p></div>
<div class="dlist"><dl>
<dt class="hdlist1">
<tt>git_config_int</tt>
</dt>
<dd>
<p>
Parse the string to an integer, including unit factors. Dies on error;
otherwise, returns the parsed result.
</p>
</dd>
<dt class="hdlist1">
<tt>git_config_ulong</tt>
</dt>
<dd>
<p>
Identical to <tt>git_config_int</tt>, but for unsigned longs.
</p>
</dd>
<dt class="hdlist1">
<tt>git_config_bool</tt>
</dt>
<dd>
<p>
Parse a string into a boolean value, respecting keywords like "true" and
"false". Integer values are converted into true/false values (when they
are non-zero or zero, respectively). Other values cause a die(). If
parsing is successful, the return value is the result.
</p>
</dd>
<dt class="hdlist1">
<tt>git_config_bool_or_int</tt>
</dt>
<dd>
<p>
Same as <tt>git_config_bool</tt>, except that integers are returned as-is, and
an <tt>is_bool</tt> flag is unset.
</p>
</dd>
<dt class="hdlist1">
<tt>git_config_maybe_bool</tt>
</dt>
<dd>
<p>
Same as <tt>git_config_bool</tt>, except that it returns -1 on error rather
than dying.
</p>
</dd>
<dt class="hdlist1">
<tt>git_config_string</tt>
</dt>
<dd>
<p>
Allocates and copies the value string into the <tt>dest</tt> parameter; if no
string is given, prints an error message and returns -1.
</p>
</dd>
<dt class="hdlist1">
<tt>git_config_pathname</tt>
</dt>
<dd>
<p>
Similar to <tt>git_config_string</tt>, but expands <tt>~</tt> or <tt>~user</tt> into the
user&#8217;s home directory when found at the beginning of the path.
</p>
</dd>
</dl></div>
</div>
<h2 id="_include_directives">Include Directives</h2>
<div class="sectionbody">
<div class="paragraph"><p>By default, the config parser does not respect include directives.
However, a caller can use the special <tt>git_config_include</tt> wrapper
callback to support them. To do so, you simply wrap your "real" callback
function and data pointer in a <tt>struct config_include_data</tt>, and pass
the wrapper to the regular config-reading functions. For example:</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>int read_file_with_include(const char *file, config_fn_t fn, void *data)
{
        struct config_include_data inc = CONFIG_INCLUDE_INIT;
        inc.fn = fn;
        inc.data = data;
        return git_config_from_file(git_config_include, file, &amp;inc);
}</tt></pre>
</div></div>
<div class="paragraph"><p><tt>git_config</tt> respects includes automatically. The lower-level
<tt>git_config_from_file</tt> does not.</p></div>
</div>
<h2 id="_writing_config_files">Writing Config Files</h2>
<div class="sectionbody">
<div class="paragraph"><p>TODO</p></div>
</div>
</div>
<div id="footnotes"><hr /></div>
<div id="footer">
<div id="footer-text">
Last updated 2012-06-08 11:37:18 PDT
</div>
</div>
</body>
</html>