blob: 2d26147ebad368340d8cb24d25186eed7d7cefd6 [file] [log] [blame]
Junio C Hamanof2b74942012-11-20 21:06:261<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
2 "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
4<head>
Junio C Hamano9d971152012-12-19 00:43:115<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
Junio C Hamano61525f92014-01-17 22:46:496<meta name="generator" content="AsciiDoc 8.6.6" />
Junio C Hamano076ffcc2013-02-06 05:13:217<title>Use of index and Racy Git problem</title>
Junio C Hamanof2b74942012-11-20 21:06:268<style type="text/css">
Junio C Hamano9d971152012-12-19 00:43:119/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
10
11/* Default font. */
12body {
13 font-family: Georgia,serif;
14}
15
16/* Title font. */
17h1, h2, h3, h4, h5, h6,
18div.title, caption.title,
19thead, p.table.header,
20#toctitle,
21#author, #revnumber, #revdate, #revremark,
22#footer {
23 font-family: Arial,Helvetica,sans-serif;
Junio C Hamanof2b74942012-11-20 21:06:2624}
25
26body {
27 margin: 1em 5% 1em 5%;
28}
29
30a {
31 color: blue;
32 text-decoration: underline;
33}
34a:visited {
35 color: fuchsia;
36}
37
38em {
39 font-style: italic;
40 color: navy;
41}
42
43strong {
44 font-weight: bold;
45 color: #083194;
46}
47
Junio C Hamanof2b74942012-11-20 21:06:2648h1, h2, h3, h4, h5, h6 {
49 color: #527bbd;
Junio C Hamanof2b74942012-11-20 21:06:2650 margin-top: 1.2em;
51 margin-bottom: 0.5em;
52 line-height: 1.3;
53}
54
55h1, h2, h3 {
56 border-bottom: 2px solid silver;
57}
58h2 {
59 padding-top: 0.5em;
60}
61h3 {
62 float: left;
63}
64h3 + * {
65 clear: left;
66}
Junio C Hamano9d971152012-12-19 00:43:1167h5 {
68 font-size: 1.0em;
69}
Junio C Hamanof2b74942012-11-20 21:06:2670
71div.sectionbody {
Junio C Hamanof2b74942012-11-20 21:06:2672 margin-left: 0;
73}
74
75hr {
76 border: 1px solid silver;
77}
78
79p {
80 margin-top: 0.5em;
81 margin-bottom: 0.5em;
82}
83
84ul, ol, li > p {
85 margin-top: 0;
86}
Junio C Hamano9d971152012-12-19 00:43:1187ul > li { color: #aaa; }
88ul > li > * { color: black; }
Junio C Hamanof2b74942012-11-20 21:06:2689
Junio C Hamano61525f92014-01-17 22:46:4990pre {
Junio C Hamanof2b74942012-11-20 21:06:2691 padding: 0;
92 margin: 0;
93}
94
Junio C Hamano9d971152012-12-19 00:43:1195#author {
Junio C Hamanof2b74942012-11-20 21:06:2696 color: #527bbd;
Junio C Hamanof2b74942012-11-20 21:06:2697 font-weight: bold;
98 font-size: 1.1em;
99}
Junio C Hamano9d971152012-12-19 00:43:11100#email {
Junio C Hamanof2b74942012-11-20 21:06:26101}
Junio C Hamano9d971152012-12-19 00:43:11102#revnumber, #revdate, #revremark {
Junio C Hamanof2b74942012-11-20 21:06:26103}
104
Junio C Hamano9d971152012-12-19 00:43:11105#footer {
Junio C Hamanof2b74942012-11-20 21:06:26106 font-size: small;
107 border-top: 2px solid silver;
108 padding-top: 0.5em;
109 margin-top: 4.0em;
110}
Junio C Hamano9d971152012-12-19 00:43:11111#footer-text {
Junio C Hamanof2b74942012-11-20 21:06:26112 float: left;
113 padding-bottom: 0.5em;
114}
Junio C Hamano9d971152012-12-19 00:43:11115#footer-badges {
Junio C Hamanof2b74942012-11-20 21:06:26116 float: right;
117 padding-bottom: 0.5em;
118}
119
Junio C Hamano9d971152012-12-19 00:43:11120#preamble {
Junio C Hamanof2b74942012-11-20 21:06:26121 margin-top: 1.5em;
122 margin-bottom: 1.5em;
123}
Junio C Hamano9d971152012-12-19 00:43:11124div.imageblock, div.exampleblock, div.verseblock,
Junio C Hamanof2b74942012-11-20 21:06:26125div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock,
126div.admonitionblock {
127 margin-top: 1.0em;
128 margin-bottom: 1.5em;
129}
130div.admonitionblock {
131 margin-top: 2.0em;
132 margin-bottom: 2.0em;
133 margin-right: 10%;
134 color: #606060;
135}
136
137div.content { /* Block element content. */
138 padding: 0;
139}
140
141/* Block element titles. */
142div.title, caption.title {
143 color: #527bbd;
Junio C Hamanof2b74942012-11-20 21:06:26144 font-weight: bold;
145 text-align: left;
146 margin-top: 1.0em;
147 margin-bottom: 0.5em;
148}
149div.title + * {
150 margin-top: 0;
151}
152
153td div.title:first-child {
154 margin-top: 0.0em;
155}
156div.content div.title:first-child {
157 margin-top: 0.0em;
158}
159div.content + div.title {
160 margin-top: 0.0em;
161}
162
163div.sidebarblock > div.content {
164 background: #ffffee;
Junio C Hamano9d971152012-12-19 00:43:11165 border: 1px solid #dddddd;
166 border-left: 4px solid #f0f0f0;
Junio C Hamanof2b74942012-11-20 21:06:26167 padding: 0.5em;
168}
169
170div.listingblock > div.content {
Junio C Hamano9d971152012-12-19 00:43:11171 border: 1px solid #dddddd;
172 border-left: 5px solid #f0f0f0;
173 background: #f8f8f8;
Junio C Hamanof2b74942012-11-20 21:06:26174 padding: 0.5em;
175}
176
177div.quoteblock, div.verseblock {
178 padding-left: 1.0em;
179 margin-left: 1.0em;
180 margin-right: 10%;
Junio C Hamano9d971152012-12-19 00:43:11181 border-left: 5px solid #f0f0f0;
182 color: #888;
Junio C Hamanof2b74942012-11-20 21:06:26183}
184
185div.quoteblock > div.attribution {
186 padding-top: 0.5em;
187 text-align: right;
188}
189
Junio C Hamano9d971152012-12-19 00:43:11190div.verseblock > pre.content {
191 font-family: inherit;
192 font-size: inherit;
Junio C Hamanof2b74942012-11-20 21:06:26193}
194div.verseblock > div.attribution {
195 padding-top: 0.75em;
196 text-align: left;
197}
198/* DEPRECATED: Pre version 8.2.7 verse style literal block. */
199div.verseblock + div.attribution {
200 text-align: left;
201}
202
203div.admonitionblock .icon {
204 vertical-align: top;
205 font-size: 1.1em;
206 font-weight: bold;
207 text-decoration: underline;
208 color: #527bbd;
209 padding-right: 0.5em;
210}
211div.admonitionblock td.content {
212 padding-left: 0.5em;
213 border-left: 3px solid #dddddd;
214}
215
216div.exampleblock > div.content {
217 border-left: 3px solid #dddddd;
218 padding-left: 0.5em;
219}
220
221div.imageblock div.content { padding-left: 0; }
222span.image img { border-style: none; }
223a.image:visited { color: white; }
224
225dl {
226 margin-top: 0.8em;
227 margin-bottom: 0.8em;
228}
229dt {
230 margin-top: 0.5em;
231 margin-bottom: 0;
232 font-style: normal;
233 color: navy;
234}
235dd > *:first-child {
236 margin-top: 0.1em;
237}
238
239ul, ol {
240 list-style-position: outside;
241}
242ol.arabic {
243 list-style-type: decimal;
244}
245ol.loweralpha {
246 list-style-type: lower-alpha;
247}
248ol.upperalpha {
249 list-style-type: upper-alpha;
250}
251ol.lowerroman {
252 list-style-type: lower-roman;
253}
254ol.upperroman {
255 list-style-type: upper-roman;
256}
257
258div.compact ul, div.compact ol,
259div.compact p, div.compact p,
260div.compact div, div.compact div {
261 margin-top: 0.1em;
262 margin-bottom: 0.1em;
263}
264
Junio C Hamanof2b74942012-11-20 21:06:26265tfoot {
266 font-weight: bold;
267}
268td > div.verse {
269 white-space: pre;
270}
Junio C Hamanof2b74942012-11-20 21:06:26271
272div.hdlist {
273 margin-top: 0.8em;
274 margin-bottom: 0.8em;
275}
276div.hdlist tr {
277 padding-bottom: 15px;
278}
279dt.hdlist1.strong, td.hdlist1.strong {
280 font-weight: bold;
281}
282td.hdlist1 {
283 vertical-align: top;
284 font-style: normal;
285 padding-right: 0.8em;
286 color: navy;
287}
288td.hdlist2 {
289 vertical-align: top;
290}
291div.hdlist.compact tr {
292 margin: 0;
293 padding-bottom: 0;
294}
295
296.comment {
297 background: yellow;
298}
299
300.footnote, .footnoteref {
301 font-size: 0.8em;
302}
303
304span.footnote, span.footnoteref {
305 vertical-align: super;
306}
307
308#footnotes {
309 margin: 20px 0 20px 0;
310 padding: 7px 0 0 0;
311}
312
313#footnotes div.footnote {
314 margin: 0 0 5px 0;
315}
316
317#footnotes hr {
318 border: none;
319 border-top: 1px solid silver;
320 height: 1px;
321 text-align: left;
322 margin-left: 0;
323 width: 20%;
324 min-width: 100px;
325}
326
Junio C Hamano9d971152012-12-19 00:43:11327div.colist td {
328 padding-right: 0.5em;
329 padding-bottom: 0.3em;
330 vertical-align: top;
331}
332div.colist td img {
333 margin-top: 0.3em;
Junio C Hamanof2b74942012-11-20 21:06:26334}
335
Junio C Hamano9d971152012-12-19 00:43:11336@media print {
337 #footer-badges { display: none; }
338}
339
340#toc {
Junio C Hamanof2b74942012-11-20 21:06:26341 margin-bottom: 2.5em;
342}
343
Junio C Hamano9d971152012-12-19 00:43:11344#toctitle {
Junio C Hamanof2b74942012-11-20 21:06:26345 color: #527bbd;
Junio C Hamanof2b74942012-11-20 21:06:26346 font-size: 1.1em;
347 font-weight: bold;
348 margin-top: 1.0em;
349 margin-bottom: 0.1em;
350}
351
Junio C Hamano61525f92014-01-17 22:46:49352div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 {
Junio C Hamanof2b74942012-11-20 21:06:26353 margin-top: 0;
354 margin-bottom: 0;
355}
356div.toclevel2 {
357 margin-left: 2em;
358 font-size: 0.9em;
359}
360div.toclevel3 {
361 margin-left: 4em;
362 font-size: 0.9em;
363}
364div.toclevel4 {
365 margin-left: 6em;
366 font-size: 0.9em;
367}
Junio C Hamanof2b74942012-11-20 21:06:26368
Junio C Hamano9d971152012-12-19 00:43:11369span.aqua { color: aqua; }
370span.black { color: black; }
371span.blue { color: blue; }
372span.fuchsia { color: fuchsia; }
373span.gray { color: gray; }
374span.green { color: green; }
375span.lime { color: lime; }
376span.maroon { color: maroon; }
377span.navy { color: navy; }
378span.olive { color: olive; }
379span.purple { color: purple; }
380span.red { color: red; }
381span.silver { color: silver; }
382span.teal { color: teal; }
383span.white { color: white; }
384span.yellow { color: yellow; }
385
386span.aqua-background { background: aqua; }
387span.black-background { background: black; }
388span.blue-background { background: blue; }
389span.fuchsia-background { background: fuchsia; }
390span.gray-background { background: gray; }
391span.green-background { background: green; }
392span.lime-background { background: lime; }
393span.maroon-background { background: maroon; }
394span.navy-background { background: navy; }
395span.olive-background { background: olive; }
396span.purple-background { background: purple; }
397span.red-background { background: red; }
398span.silver-background { background: silver; }
399span.teal-background { background: teal; }
400span.white-background { background: white; }
401span.yellow-background { background: yellow; }
402
403span.big { font-size: 2em; }
404span.small { font-size: 0.6em; }
405
406span.underline { text-decoration: underline; }
407span.overline { text-decoration: overline; }
408span.line-through { text-decoration: line-through; }
409
Junio C Hamano9d971152012-12-19 00:43:11410
411/*
412 * xhtml11 specific
413 *
414 * */
415
Junio C Hamano61525f92014-01-17 22:46:49416tt {
417 font-family: monospace;
418 font-size: inherit;
419 color: navy;
420}
421
Junio C Hamano9d971152012-12-19 00:43:11422div.tableblock {
423 margin-top: 1.0em;
424 margin-bottom: 1.5em;
Junio C Hamanof2b74942012-11-20 21:06:26425}
Junio C Hamano9d971152012-12-19 00:43:11426div.tableblock > table {
427 border: 3px solid #527bbd;
428}
429thead, p.table.header {
Junio C Hamanof2b74942012-11-20 21:06:26430 font-weight: bold;
Junio C Hamano9d971152012-12-19 00:43:11431 color: #527bbd;
432}
433p.table {
434 margin-top: 0;
435}
436/* Because the table frame attribute is overriden by CSS in most browsers. */
437div.tableblock > table[frame="void"] {
438 border-style: none;
439}
440div.tableblock > table[frame="hsides"] {
441 border-left-style: none;
442 border-right-style: none;
443}
444div.tableblock > table[frame="vsides"] {
445 border-top-style: none;
446 border-bottom-style: none;
Junio C Hamanof2b74942012-11-20 21:06:26447}
448
Junio C Hamano9d971152012-12-19 00:43:11449
450/*
451 * html5 specific
452 *
453 * */
454
Junio C Hamano61525f92014-01-17 22:46:49455.monospaced {
456 font-family: monospace;
457 font-size: inherit;
458 color: navy;
459}
460
Junio C Hamano9d971152012-12-19 00:43:11461table.tableblock {
462 margin-top: 1.0em;
463 margin-bottom: 1.5em;
464}
465thead, p.tableblock.header {
466 font-weight: bold;
467 color: #527bbd;
468}
469p.tableblock {
470 margin-top: 0;
471}
472table.tableblock {
473 border-width: 3px;
474 border-spacing: 0px;
475 border-style: solid;
476 border-color: #527bbd;
477 border-collapse: collapse;
478}
479th.tableblock, td.tableblock {
480 border-width: 1px;
481 padding: 4px;
482 border-style: solid;
483 border-color: #527bbd;
Junio C Hamanof2b74942012-11-20 21:06:26484}
485
Junio C Hamano9d971152012-12-19 00:43:11486table.tableblock.frame-topbot {
487 border-left-style: hidden;
488 border-right-style: hidden;
489}
490table.tableblock.frame-sides {
491 border-top-style: hidden;
492 border-bottom-style: hidden;
493}
494table.tableblock.frame-none {
495 border-style: hidden;
496}
497
498th.tableblock.halign-left, td.tableblock.halign-left {
499 text-align: left;
500}
501th.tableblock.halign-center, td.tableblock.halign-center {
502 text-align: center;
503}
504th.tableblock.halign-right, td.tableblock.halign-right {
Junio C Hamanof2b74942012-11-20 21:06:26505 text-align: right;
506}
507
Junio C Hamano9d971152012-12-19 00:43:11508th.tableblock.valign-top, td.tableblock.valign-top {
509 vertical-align: top;
Junio C Hamanof2b74942012-11-20 21:06:26510}
Junio C Hamano9d971152012-12-19 00:43:11511th.tableblock.valign-middle, td.tableblock.valign-middle {
512 vertical-align: middle;
513}
514th.tableblock.valign-bottom, td.tableblock.valign-bottom {
515 vertical-align: bottom;
Junio C Hamanof2b74942012-11-20 21:06:26516}
517
Junio C Hamano9d971152012-12-19 00:43:11518
519/*
520 * manpage specific
521 *
522 * */
523
524body.manpage h1 {
525 padding-top: 0.5em;
526 padding-bottom: 0.5em;
527 border-top: 2px solid silver;
528 border-bottom: 2px solid silver;
529}
530body.manpage h2 {
531 border-style: none;
532}
533body.manpage div.sectionbody {
534 margin-left: 3em;
Junio C Hamanof2b74942012-11-20 21:06:26535}
536
Junio C Hamano9d971152012-12-19 00:43:11537@media print {
538 body.manpage div#toc { display: none; }
539}
Junio C Hamanof2b74942012-11-20 21:06:26540</style>
541<script type="text/javascript">
542/*<![CDATA[*/
Junio C Hamanof2b74942012-11-20 21:06:26543var asciidoc = { // Namespace.
544
545/////////////////////////////////////////////////////////////////////
546// Table Of Contents generator
547/////////////////////////////////////////////////////////////////////
548
549/* Author: Mihai Bazon, September 2002
550 * http://students.infoiasi.ro/~mishoo
551 *
552 * Table Of Content generator
553 * Version: 0.4
554 *
555 * Feel free to use this script under the terms of the GNU General Public
556 * License, as long as you do not remove or alter this notice.
557 */
558
559 /* modified by Troy D. Hanson, September 2006. License: GPL */
560 /* modified by Stuart Rackham, 2006, 2009. License: GPL */
561
562// toclevels = 1..4.
563toc: function (toclevels) {
564
565 function getText(el) {
566 var text = "";
567 for (var i = el.firstChild; i != null; i = i.nextSibling) {
568 if (i.nodeType == 3 /* Node.TEXT_NODE */) // IE doesn't speak constants.
569 text += i.data;
570 else if (i.firstChild != null)
571 text += getText(i);
572 }
573 return text;
574 }
575
576 function TocEntry(el, text, toclevel) {
577 this.element = el;
578 this.text = text;
579 this.toclevel = toclevel;
580 }
581
582 function tocEntries(el, toclevels) {
583 var result = new Array;
Junio C Hamano61525f92014-01-17 22:46:49584 var re = new RegExp('[hH]([2-'+(toclevels+1)+'])');
Junio C Hamanof2b74942012-11-20 21:06:26585 // Function that scans the DOM tree for header elements (the DOM2
586 // nodeIterator API would be a better technique but not supported by all
587 // browsers).
588 var iterate = function (el) {
589 for (var i = el.firstChild; i != null; i = i.nextSibling) {
590 if (i.nodeType == 1 /* Node.ELEMENT_NODE */) {
591 var mo = re.exec(i.tagName);
592 if (mo && (i.getAttribute("class") || i.getAttribute("className")) != "float") {
593 result[result.length] = new TocEntry(i, getText(i), mo[1]-1);
594 }
595 iterate(i);
596 }
597 }
598 }
599 iterate(el);
600 return result;
601 }
602
603 var toc = document.getElementById("toc");
Junio C Hamano9d971152012-12-19 00:43:11604 if (!toc) {
605 return;
606 }
607
608 // Delete existing TOC entries in case we're reloading the TOC.
609 var tocEntriesToRemove = [];
610 var i;
611 for (i = 0; i < toc.childNodes.length; i++) {
612 var entry = toc.childNodes[i];
Junio C Hamano61525f92014-01-17 22:46:49613 if (entry.nodeName == 'div'
Junio C Hamano9d971152012-12-19 00:43:11614 && entry.getAttribute("class")
615 && entry.getAttribute("class").match(/^toclevel/))
616 tocEntriesToRemove.push(entry);
617 }
618 for (i = 0; i < tocEntriesToRemove.length; i++) {
619 toc.removeChild(tocEntriesToRemove[i]);
620 }
621
622 // Rebuild TOC entries.
Junio C Hamanof2b74942012-11-20 21:06:26623 var entries = tocEntries(document.getElementById("content"), toclevels);
624 for (var i = 0; i < entries.length; ++i) {
625 var entry = entries[i];
626 if (entry.element.id == "")
627 entry.element.id = "_toc_" + i;
628 var a = document.createElement("a");
629 a.href = "#" + entry.element.id;
630 a.appendChild(document.createTextNode(entry.text));
631 var div = document.createElement("div");
632 div.appendChild(a);
633 div.className = "toclevel" + entry.toclevel;
634 toc.appendChild(div);
635 }
636 if (entries.length == 0)
637 toc.parentNode.removeChild(toc);
638},
639
640
641/////////////////////////////////////////////////////////////////////
642// Footnotes generator
643/////////////////////////////////////////////////////////////////////
644
645/* Based on footnote generation code from:
646 * http://www.brandspankingnew.net/archive/2005/07/format_footnote.html
647 */
648
649footnotes: function () {
Junio C Hamano9d971152012-12-19 00:43:11650 // Delete existing footnote entries in case we're reloading the footnodes.
651 var i;
Junio C Hamanof2b74942012-11-20 21:06:26652 var noteholder = document.getElementById("footnotes");
Junio C Hamano9d971152012-12-19 00:43:11653 if (!noteholder) {
654 return;
655 }
656 var entriesToRemove = [];
657 for (i = 0; i < noteholder.childNodes.length; i++) {
658 var entry = noteholder.childNodes[i];
Junio C Hamano61525f92014-01-17 22:46:49659 if (entry.nodeName == 'div' && entry.getAttribute("class") == "footnote")
Junio C Hamano9d971152012-12-19 00:43:11660 entriesToRemove.push(entry);
661 }
662 for (i = 0; i < entriesToRemove.length; i++) {
663 noteholder.removeChild(entriesToRemove[i]);
664 }
665
666 // Rebuild footnote entries.
667 var cont = document.getElementById("content");
Junio C Hamanof2b74942012-11-20 21:06:26668 var spans = cont.getElementsByTagName("span");
669 var refs = {};
670 var n = 0;
671 for (i=0; i<spans.length; i++) {
672 if (spans[i].className == "footnote") {
673 n++;
Junio C Hamano9d971152012-12-19 00:43:11674 var note = spans[i].getAttribute("data-note");
675 if (!note) {
676 // Use [\s\S] in place of . so multi-line matches work.
677 // Because JavaScript has no s (dotall) regex flag.
678 note = spans[i].innerHTML.match(/\s*\[([\s\S]*)]\s*/)[1];
679 spans[i].innerHTML =
680 "[<a id='_footnoteref_" + n + "' href='#_footnote_" + n +
681 "' title='View footnote' class='footnote'>" + n + "</a>]";
682 spans[i].setAttribute("data-note", note);
683 }
Junio C Hamanof2b74942012-11-20 21:06:26684 noteholder.innerHTML +=
685 "<div class='footnote' id='_footnote_" + n + "'>" +
686 "<a href='#_footnoteref_" + n + "' title='Return to text'>" +
687 n + "</a>. " + note + "</div>";
Junio C Hamanof2b74942012-11-20 21:06:26688 var id =spans[i].getAttribute("id");
689 if (id != null) refs["#"+id] = n;
690 }
691 }
692 if (n == 0)
693 noteholder.parentNode.removeChild(noteholder);
694 else {
695 // Process footnoterefs.
696 for (i=0; i<spans.length; i++) {
697 if (spans[i].className == "footnoteref") {
698 var href = spans[i].getElementsByTagName("a")[0].getAttribute("href");
699 href = href.match(/#.*/)[0]; // Because IE return full URL.
700 n = refs[href];
701 spans[i].innerHTML =
702 "[<a href='#_footnote_" + n +
703 "' title='View footnote' class='footnote'>" + n + "</a>]";
704 }
705 }
706 }
Junio C Hamano9d971152012-12-19 00:43:11707},
708
709install: function(toclevels) {
710 var timerId;
711
712 function reinstall() {
713 asciidoc.footnotes();
714 if (toclevels) {
715 asciidoc.toc(toclevels);
716 }
717 }
718
719 function reinstallAndRemoveTimer() {
720 clearInterval(timerId);
721 reinstall();
722 }
723
724 timerId = setInterval(reinstall, 500);
725 if (document.addEventListener)
726 document.addEventListener("DOMContentLoaded", reinstallAndRemoveTimer, false);
727 else
728 window.onload = reinstallAndRemoveTimer;
Junio C Hamanof2b74942012-11-20 21:06:26729}
730
731}
Junio C Hamano9d971152012-12-19 00:43:11732asciidoc.install();
Junio C Hamanof2b74942012-11-20 21:06:26733/*]]>*/
734</script>
735</head>
Junio C Hamano9d971152012-12-19 00:43:11736<body class="article">
Junio C Hamanof2b74942012-11-20 21:06:26737<div id="header">
Junio C Hamano076ffcc2013-02-06 05:13:21738<h1>Use of index and Racy Git problem</h1>
Junio C Hamanof2b74942012-11-20 21:06:26739</div>
740<div id="content">
Junio C Hamano9d971152012-12-19 00:43:11741<div class="sect1">
Junio C Hamanof2b74942012-11-20 21:06:26742<h2 id="_background">Background</h2>
743<div class="sectionbody">
Junio C Hamano076ffcc2013-02-06 05:13:21744<div class="paragraph"><p>The index is one of the most important data structures in Git.
Junio C Hamanof2b74942012-11-20 21:06:26745It represents a virtual working tree state by recording list of
746paths and their object names and serves as a staging area to
747write out the next tree object to be committed. The state is
748"virtual" in the sense that it does not necessarily have to, and
749often does not, match the files in the working tree.</p></div>
Junio C Hamano076ffcc2013-02-06 05:13:21750<div class="paragraph"><p>There are cases Git needs to examine the differences between the
Junio C Hamanof2b74942012-11-20 21:06:26751virtual working tree state in the index and the files in the
Junio C Hamano61525f92014-01-17 22:46:49752working tree. The most obvious case is when the user asks <tt>git
753diff</tt> (or its low level implementation, <tt>git diff-files</tt>) or
754<tt>git-ls-files --modified</tt>. In addition, Git internally checks
Junio C Hamanof2b74942012-11-20 21:06:26755if the files in the working tree are different from what are
756recorded in the index to avoid stomping on local changes in them
757during patch application, switching branches, and merging.</p></div>
758<div class="paragraph"><p>In order to speed up this comparison between the files in the
759working tree and the index entries, the index entries record the
Junio C Hamano61525f92014-01-17 22:46:49760information obtained from the filesystem via <tt>lstat(2)</tt> system
Junio C Hamanof2b74942012-11-20 21:06:26761call when they were last updated. When checking if they differ,
Junio C Hamano61525f92014-01-17 22:46:49762Git first runs <tt>lstat(2)</tt> on the files and compares the result
Junio C Hamanof2b74942012-11-20 21:06:26763with this information (this is what was originally done by the
Junio C Hamano61525f92014-01-17 22:46:49764<tt>ce_match_stat()</tt> function, but the current code does it in
765<tt>ce_match_stat_basic()</tt> function). If some of these "cached
Junio C Hamano076ffcc2013-02-06 05:13:21766stat information" fields do not match, Git can tell that the
Junio C Hamanof2b74942012-11-20 21:06:26767files are modified without even looking at their contents.</p></div>
Junio C Hamano61525f92014-01-17 22:46:49768<div class="paragraph"><p>Note: not all members in <tt>struct stat</tt> obtained via <tt>lstat(2)</tt>
769are used for this comparison. For example, <tt>st_atime</tt> obviously
Junio C Hamano076ffcc2013-02-06 05:13:21770is not useful. Currently, Git compares the file type (regular
Junio C Hamanof2b74942012-11-20 21:06:26771files vs symbolic links) and executable bits (only for regular
Junio C Hamano61525f92014-01-17 22:46:49772files) from <tt>st_mode</tt> member, <tt>st_mtime</tt> and <tt>st_ctime</tt>
773timestamps, <tt>st_uid</tt>, <tt>st_gid</tt>, <tt>st_ino</tt>, and <tt>st_size</tt> members.
774With a <tt>USE_STDEV</tt> compile-time option, <tt>st_dev</tt> is also
Junio C Hamanof2b74942012-11-20 21:06:26775compared, but this is not enabled by default because this member
Junio C Hamano61525f92014-01-17 22:46:49776is not stable on network filesystems. With <tt>USE_NSEC</tt>
777compile-time option, <tt>st_mtim.tv_nsec</tt> and <tt>st_ctim.tv_nsec</tt>
Junio C Hamanof2b74942012-11-20 21:06:26778members are also compared, but this is not enabled by default
779because in-core timestamps can have finer granularity than
780on-disk timestamps, resulting in meaningless changes when an
781inode is evicted from the inode cache. See commit 8ce13b0
782of git://git.kernel.org/pub/scm/linux/kernel/git/tglx/history.git
Junio C Hamanod7fccbf2013-07-25 03:24:57783([PATCH] Sync in core time granularity with filesystems,
Junio C Hamanof2b74942012-11-20 21:06:267842005-01-04).</p></div>
785</div>
Junio C Hamano9d971152012-12-19 00:43:11786</div>
787<div class="sect1">
Junio C Hamano076ffcc2013-02-06 05:13:21788<h2 id="_racy_git">Racy Git</h2>
Junio C Hamanof2b74942012-11-20 21:06:26789<div class="sectionbody">
790<div class="paragraph"><p>There is one slight problem with the optimization based on the
791cached stat information. Consider this sequence:</p></div>
792<div class="literalblock">
793<div class="content">
Junio C Hamano61525f92014-01-17 22:46:49794<pre><tt>: modify 'foo'
Junio C Hamanof2b74942012-11-20 21:06:26795$ git update-index 'foo'
Junio C Hamano61525f92014-01-17 22:46:49796: modify 'foo' again, in-place, without changing its size</tt></pre>
Junio C Hamanof2b74942012-11-20 21:06:26797</div></div>
Junio C Hamano61525f92014-01-17 22:46:49798<div class="paragraph"><p>The first <tt>update-index</tt> computes the object name of the
799contents of file <tt>foo</tt> and updates the index entry for <tt>foo</tt>
800along with the <tt>struct stat</tt> information. If the modification
801that follows it happens very fast so that the file&#8217;s <tt>st_mtime</tt>
Junio C Hamanof2b74942012-11-20 21:06:26802timestamp does not change, after this sequence, the cached stat
803information the index entry records still exactly match what you
Junio C Hamano61525f92014-01-17 22:46:49804would see in the filesystem, even though the file <tt>foo</tt> is now
Junio C Hamanof2b74942012-11-20 21:06:26805different.
Junio C Hamano076ffcc2013-02-06 05:13:21806This way, Git can incorrectly think files in the working tree
Junio C Hamanof2b74942012-11-20 21:06:26807are unmodified even though they actually are. This is called
Junio C Hamano076ffcc2013-02-06 05:13:21808the "racy Git" problem (discovered by Pasky), and the entries
Junio C Hamanof2b74942012-11-20 21:06:26809that appear clean when they may not be because of this problem
810are called "racily clean".</p></div>
Junio C Hamano076ffcc2013-02-06 05:13:21811<div class="paragraph"><p>To avoid this problem, Git does two things:</p></div>
Junio C Hamanof2b74942012-11-20 21:06:26812<div class="olist arabic"><ol class="arabic">
813<li>
814<p>
815When the cached stat information says the file has not been
Junio C Hamano61525f92014-01-17 22:46:49816 modified, and the <tt>st_mtime</tt> is the same as (or newer than)
817 the timestamp of the index file itself (which is the time <tt>git
818 update-index foo</tt> finished running in the above example), it
Junio C Hamanof2b74942012-11-20 21:06:26819 also compares the contents with the object registered in the
820 index entry to make sure they match.
821</p>
822</li>
823<li>
824<p>
825When the index file is updated that contains racily clean
Junio C Hamano61525f92014-01-17 22:46:49826 entries, cached <tt>st_size</tt> information is truncated to zero
Junio C Hamanof2b74942012-11-20 21:06:26827 before writing a new version of the index file.
828</p>
829</li>
830</ol></div>
831<div class="paragraph"><p>Because the index file itself is written after collecting all
Junio C Hamano61525f92014-01-17 22:46:49832the stat information from updated paths, <tt>st_mtime</tt> timestamp of
Junio C Hamanof2b74942012-11-20 21:06:26833it is usually the same as or newer than any of the paths the
834index contains. And no matter how quick the modification that
Junio C Hamano61525f92014-01-17 22:46:49835follows <tt>git update-index foo</tt> finishes, the resulting
836<tt>st_mtime</tt> timestamp on <tt>foo</tt> cannot get a value earlier
Junio C Hamanof2b74942012-11-20 21:06:26837than the index file. Therefore, index entries that can be
838racily clean are limited to the ones that have the same
839timestamp as the index file itself.</p></div>
840<div class="paragraph"><p>The callers that want to check if an index entry matches the
841corresponding file in the working tree continue to call
Junio C Hamano61525f92014-01-17 22:46:49842<tt>ce_match_stat()</tt>, but with this change, <tt>ce_match_stat()</tt> uses
843<tt>ce_modified_check_fs()</tt> to see if racily clean ones are
Junio C Hamanof2b74942012-11-20 21:06:26844actually clean after comparing the cached stat information using
Junio C Hamano61525f92014-01-17 22:46:49845<tt>ce_match_stat_basic()</tt>.</p></div>
Junio C Hamanof2b74942012-11-20 21:06:26846<div class="paragraph"><p>The problem the latter solves is this sequence:</p></div>
847<div class="literalblock">
848<div class="content">
Junio C Hamano61525f92014-01-17 22:46:49849<pre><tt>$ git update-index 'foo'
Junio C Hamanof2b74942012-11-20 21:06:26850: modify 'foo' in-place without changing its size
851: wait for enough time
Junio C Hamano61525f92014-01-17 22:46:49852$ git update-index 'bar'</tt></pre>
Junio C Hamanof2b74942012-11-20 21:06:26853</div></div>
854<div class="paragraph"><p>Without the latter, the timestamp of the index file gets a newer
Junio C Hamano61525f92014-01-17 22:46:49855value, and falsely clean entry <tt>foo</tt> would not be caught by the
Junio C Hamanof2b74942012-11-20 21:06:26856timestamp comparison check done with the former logic anymore.
Junio C Hamano61525f92014-01-17 22:46:49857The latter makes sure that the cached stat information for <tt>foo</tt>
Junio C Hamanof2b74942012-11-20 21:06:26858would never match with the file in the working tree, so later
Junio C Hamano61525f92014-01-17 22:46:49859checks by <tt>ce_match_stat_basic()</tt> would report that the index entry
Junio C Hamano076ffcc2013-02-06 05:13:21860does not match the file and Git does not have to fall back on more
Junio C Hamano61525f92014-01-17 22:46:49861expensive <tt>ce_modified_check_fs()</tt>.</p></div>
Junio C Hamanof2b74942012-11-20 21:06:26862</div>
Junio C Hamano9d971152012-12-19 00:43:11863</div>
864<div class="sect1">
Junio C Hamanof2b74942012-11-20 21:06:26865<h2 id="_runtime_penalty">Runtime penalty</h2>
866<div class="sectionbody">
Junio C Hamano61525f92014-01-17 22:46:49867<div class="paragraph"><p>The runtime penalty of falling back to <tt>ce_modified_check_fs()</tt>
868from <tt>ce_match_stat()</tt> can be very expensive when there are many
Junio C Hamanof2b74942012-11-20 21:06:26869racily clean entries. An obvious way to artificially create
870this situation is to give the same timestamp to all the files in
Junio C Hamano61525f92014-01-17 22:46:49871the working tree in a large project, run <tt>git update-index</tt> on
Junio C Hamanof2b74942012-11-20 21:06:26872them, and give the same timestamp to the index file:</p></div>
873<div class="literalblock">
874<div class="content">
Junio C Hamano61525f92014-01-17 22:46:49875<pre><tt>$ date &gt;.datestamp
Junio C Hamanof2b74942012-11-20 21:06:26876$ git ls-files | xargs touch -r .datestamp
877$ git ls-files | git update-index --stdin
Junio C Hamano61525f92014-01-17 22:46:49878$ touch -r .datestamp .git/index</tt></pre>
Junio C Hamanof2b74942012-11-20 21:06:26879</div></div>
Junio C Hamanoa1952302013-07-01 21:31:18880<div class="paragraph"><p>This will make all index entries racily clean. The linux project, for
881example, there are over 20,000 files in the working tree. On my
882Athlon 64 X2 3800+, after the above:</p></div>
Junio C Hamanof2b74942012-11-20 21:06:26883<div class="literalblock">
884<div class="content">
Junio C Hamano61525f92014-01-17 22:46:49885<pre><tt>$ /usr/bin/time git diff-files
Junio C Hamanof2b74942012-11-20 21:06:268861.68user 0.54system 0:02.22elapsed 100%CPU (0avgtext+0avgdata 0maxresident)k
8870inputs+0outputs (0major+67111minor)pagefaults 0swaps
888$ git update-index MAINTAINERS
889$ /usr/bin/time git diff-files
8900.02user 0.12system 0:00.14elapsed 100%CPU (0avgtext+0avgdata 0maxresident)k
Junio C Hamano61525f92014-01-17 22:46:498910inputs+0outputs (0major+935minor)pagefaults 0swaps</tt></pre>
Junio C Hamanof2b74942012-11-20 21:06:26892</div></div>
Junio C Hamano61525f92014-01-17 22:46:49893<div class="paragraph"><p>Running <tt>git update-index</tt> in the middle checked the racily
894clean entries, and left the cached <tt>st_mtime</tt> for all the paths
Junio C Hamanof2b74942012-11-20 21:06:26895intact because they were actually clean (so this step took about
Junio C Hamano61525f92014-01-17 22:46:49896the same amount of time as the first <tt>git diff-files</tt>). After
Junio C Hamanof2b74942012-11-20 21:06:26897that, they are not racily clean anymore but are truly clean, so
Junio C Hamano61525f92014-01-17 22:46:49898the second invocation of <tt>git diff-files</tt> fully took advantage
Junio C Hamanof2b74942012-11-20 21:06:26899of the cached stat information.</p></div>
900</div>
Junio C Hamano9d971152012-12-19 00:43:11901</div>
902<div class="sect1">
Junio C Hamanof2b74942012-11-20 21:06:26903<h2 id="_avoiding_runtime_penalty">Avoiding runtime penalty</h2>
904<div class="sectionbody">
Junio C Hamano076ffcc2013-02-06 05:13:21905<div class="paragraph"><p>In order to avoid the above runtime penalty, post 1.4.2 Git used
Junio C Hamanof2b74942012-11-20 21:06:26906to have a code that made sure the index file
907got timestamp newer than the youngest files in the index when
908there are many young files with the same timestamp as the
909resulting index file would otherwise would have by waiting
910before finishing writing the index file out.</p></div>
911<div class="paragraph"><p>I suspected that in practice the situation where many paths in the
912index are all racily clean was quite rare. The only code paths
913that can record recent timestamp for large number of paths are:</p></div>
914<div class="olist arabic"><ol class="arabic">
915<li>
916<p>
Junio C Hamano61525f92014-01-17 22:46:49917Initial <tt>git add .</tt> of a large project.
Junio C Hamanof2b74942012-11-20 21:06:26918</p>
919</li>
920<li>
921<p>
Junio C Hamano61525f92014-01-17 22:46:49922<tt>git checkout</tt> of a large project from an empty index into an
Junio C Hamanof2b74942012-11-20 21:06:26923 unpopulated working tree.
924</p>
925</li>
926</ol></div>
Junio C Hamano61525f92014-01-17 22:46:49927<div class="paragraph"><p>Note: switching branches with <tt>git checkout</tt> keeps the cached
Junio C Hamanof2b74942012-11-20 21:06:26928stat information of existing working tree files that are the
929same between the current branch and the new branch, which are
930all older than the resulting index file, and they will not
931become racily clean. Only the files that are actually checked
932out can become racily clean.</p></div>
933<div class="paragraph"><p>In a large project where raciness avoidance cost really matters,
934however, the initial computation of all object names in the
935index takes more than one second, and the index file is written
936out after all that happens. Therefore the timestamp of the
937index file will be more than one seconds later than the
938youngest file in the working tree. This means that in these
939cases there actually will not be any racily clean entry in
940the resulting index.</p></div>
941<div class="paragraph"><p>Based on this discussion, the current code does not use the
942"workaround" to avoid the runtime penalty that does not exist in
943practice anymore. This was done with commit 0fc82cff on Aug 15,
9442006.</p></div>
945</div>
946</div>
Junio C Hamano9d971152012-12-19 00:43:11947</div>
Junio C Hamanof2b74942012-11-20 21:06:26948<div id="footnotes"><hr /></div>
949<div id="footer">
950<div id="footer-text">
Junio C Hamano683a8612013-08-23 20:50:09951Last updated 2013-08-20 08:40:27 PDT
Junio C Hamanof2b74942012-11-20 21:06:26952</div>
953</div>
954</body>
955</html>