diff --git a/index.html b/index.html index 12d2df5..7b9355b 100644 --- a/index.html +++ b/index.html @@ -254,18 +254,22 @@ h1:hover + .permalink, .permalink:hover { opacity: 1; } } function ___lolite(src, dest) { } + function ___hex_hash(s) { + var id = ___global_unique_id++; + var hash = "object-hash-"+___to_hex(s.substr(0,20)); + return '' + + ___to_hex_for_printf(s.substr(0,10)) + + ___to_hex_for_printf(s.substr(10,10)) + + '' + + ___specialchars_and_colour(s.substr(20) /* should be empty unless there's a bug */); + } function ___specialchars_and_colour_and_hex(s) { if (s.substr(0,5) == "tree ") { var sp = s.split('\0'); sp[0] = ___specialchars_and_colour(sp[0]); sp[1] = ___specialchars_and_colour(sp[1]); for (i = 2; i < sp.length; i++) { - var id=___global_unique_id++; - var hash = "object-hash-"+___to_hex(sp[i].substr(0,20)); - sp[i] = '' - + ___to_hex_for_printf(sp[i].substr(0,10)) - + ___to_hex_for_printf(sp[i].substr(10,10)) - + '' + sp[i] = ___hex_hash(sp[i].substr(0,20)) + ___specialchars_and_colour(sp[i].substr(20)); } return sp.join('\\000'); @@ -284,6 +288,56 @@ h1:hover + .permalink, .permalink:hover { opacity: 1; } + ___specialchars_and_colour(s.substr(5, s.length-6)) + '' + ___specialchars_and_colour(s.substr(s.length-1)); + } else if(s.substr(0,4) == "DIRC") { + var html = 'DIRC'; // magic + var i = 4; + var binary_span = function(bits) { + var bytes = bits / 8; + html += '' + ___to_hex_for_printf(s.substr(i, bytes)) + ''; + i += bytes; + } + binary_span(32); // version + binary_span(32); // entries + + var entry_start = i; + while (i + 20 < s.length) { + binary_span(64); // ctime + binary_span(64); // mtime + binary_span(32); // device + binary_span(32); // inode + binary_span(32); // mode (stored as octal → binary) + binary_span(32); // uid + binary_span(32); // gid + binary_span(32); // size + html += ___hex_hash(s.substr(i, 20)); // hash + i += 20; + var length = s.substr(i, 2); + length = length.charCodeAt(0) * 256 + length.charCodeAt(1); + length &= 0xfff; + binary_span(16); // 4 bits flags, 12 bits file length + // file path until null + html += ___specialchars_and_colour(s.substr(i, length)); + i += length; + while (i < s.length && (i - entry_start) % 8 != 0) { + // null bytes + if (s.charCodeAt(i) == 0) { + // as expected + html += '\\000'; + } else { + // there's a bug in this git index, display the hex chars as they come. + html += ___specialchars_and_colour(s.substr(i, 1)); + } + i++; + } + entry_start = i; + } + + html += ___hex_hash(s.substr(i, 20)); // hash + i += 20; + + html += ___specialchars_and_colour(s.substr(i)); // should be empty + + return html; } else if(s.substr(0,7) == "commit ") { var sz = s.split('\0'); var sp = sz[1].split('\n'); @@ -397,7 +451,7 @@ h1:hover + .permalink, .permalink:hover { opacity: 1; } + "." + "
" + '' + "" + entries.join('') + "
"; } @@ -1140,12 +1194,70 @@ git_checkout(initial_commit); to the default branch (a file which does not exist yet, as this branch does not contain any commit at this point).

+
+

The index

+

When adding files with git add, GIT does not immediately create a commit object. + Instead, it adds the files to the index, which uses a binary format with lots of metadata. + The mock filesystem used here lacks most of these pieces of information, so thr value 0 + will be used for most fields. See this blog post + for a more in-depth study of the index.

+ + + +
+

Playground

The implementation is now sufficiently complete to create a small repository.

@@ -1172,12 +1284,19 @@ write('proj/src/main.scm', "(define filesystem '())\n(define current_directory \ git_commit(['README', 'src/main.scm'], 'What an update!'); git_checkout('main'); + +// update the cache of the working directory. Without this, +// GIT finds an empty cache, and thinks all files are scheduled +// for deletion, until "git add ." allows it to realize that +// the working directory matches the contents of HEAD. +store_index(['README', 'src/main.scm']);

Conclusion

-

This article shows that the core of GIT can be re-implemented in a few lines of code.

+

This article shows that a large part of the core of GIT can be re-implemented in a few lines of code (copy all the code).

+ @@ -1351,7 +1470,34 @@ git_checkout('main'); document.getElementById('hide-eval-' + editor_id).style.display = 'none'; ___hilite_off(); } + function ___get_all_code() { + var all = ''; + for (var i = 0; i < ___global_editors.length; i++) { + all += ___global_editors[i].getValue(); + } + return all; + } + function ___copy_all_code() { + var elem = document.getElementById('copy-all-code'); + if (elem.style.display != "none") { + elem.style.display = "none"; + } else { + elem.style.display = ''; + var elem2 = document.createElement('textarea'); + elem.innerHTML = ''; + elem.appendChild(elem2); + var all_code = ___get_all_code(); + elem2.value = all_code + elem2.focus(); + elem2.disabled = false; + elem2.select(); + elem2.setSelectionRange(0, elem2.value.length * 10); // for mobile devices? + document.execCommand('copy'); + elem2.disabled = true; + } + } ___process_elements(); + document.getElementById('loc-count').innerText = ___get_all_code().split('\n').length; \ No newline at end of file