From f2b3940df694a3017de6174a1f9c8f6481c14dd2 Mon Sep 17 00:00:00 2001
From: Suzanne Soy
Date: Wed, 23 Jun 2021 22:02:50 +0100
Subject: [PATCH] Removed the arcane regexp in parse_tree, added some prose
---
git-tutorial.css | 3 +-
git-tutorial.js | 36 ++++++++++++++++----
index.html | 87 ++++++++++++++++++++++++++++++++----------------
3 files changed, 91 insertions(+), 35 deletions(-)
diff --git a/git-tutorial.css b/git-tutorial.css
index e2c88f4..374d6aa 100644
--- a/git-tutorial.css
+++ b/git-tutorial.css
@@ -136,4 +136,5 @@ article#git-tutorial .onlytoc { display: none; }
#git-tutorial .exercise-task { border: thin solid #80c5c5; background: #f1faff; padding: 1em }
#git-tutorial .exercise-reason { border: thin solid #80c5c5; background: #f8fdff; padding: 1em }
-#git-tutorial .exercise-reason:before { content: "Rationale "; margin-bottom: 0.7em; font-weight: bold; display: block; }
\ No newline at end of file
+#git-tutorial .exercise-reason:before { content: "Rationale "; margin-bottom: 0.7em; font-weight: bold; display: block; }
+#git-tutorial .log-alert { color: red; font-weight: 500; }
\ No newline at end of file
diff --git a/git-tutorial.js b/git-tutorial.js
index d7dbe85..82c4095 100644
--- a/git-tutorial.js
+++ b/git-tutorial.js
@@ -590,11 +590,17 @@ function ___copyprintf_click(id) {
}
var ___script_log_header = ''
+ 'var ___log = [];\n'
+ + 'var alert = (function (real_console, real_alert) {\n'
+ + ' return function(message) {\n'
+ + ' ___log[___log.length] = { alert: true, txt: message };\n'
+ + ' real_console.log("alert:", message);\n'
+ + ' };\n'
+ + '})(window.console, window.alert);\n'
+ 'var console = (function(real_console) {\n'
+ ' return {\n'
+ ' log: function() {\n'
- + ' ___log[___log.length] = Array.from(arguments);\n'
- + ' real_console.log.apply(console, arguments);\n'
+ + ' ___log[___log.length] = { alert: false, txt: Array.from(arguments).map(function (x) { return x.toString(); }).join(", ") };\n'
+ + ' real_console.log.apply(real_console, arguments);\n'
+ ' },\n'
+ ' assert: real_console.assert,\n'
+ ' };\n'
@@ -810,19 +816,30 @@ function ___filesystem_to_graphview(filesystem, previous_filesystem) {
}
}
-function ___eval_result_to_html(id, filesystem, previous_filesystem, log, quiet) {
- var loghtml = '' + log.map(function(l) { return l.map(function (x) { return x.toString(); }).join(', '); }).join('\n') + '
'
+function ___log_to_html(log) {
+ return ''
+ + log.map(function(l) {
+ return ''
+ + ___specialchars(l.txt)
+ + '
';
+ }).join('\n')
+ + '
'
+}
+
+function ___eval_result_to_html(id, filesystem, previous_filesystem, log, quiet, omit_graph) {
+ var loghtml = ___log_to_html(log);
var table = ___filesystem_to_string(filesystem, quiet, previous_filesystem);
var gv = ___filesystem_to_graphview(filesystem, previous_filesystem);
var html = (log.length > 0 ? 'Console output:
' + loghtml : '')
- + gv.html
+ + (omit_graph ? '' : gv.html)
+ table;
document.getElementById(id).innerHTML = '' + html + '
';
- gv.js();
+ if (!omit_graph) { gv.js(); }
}
function ___git_eval(current) {
document.getElementById('hide-eval-' + current).style.display = '';
var script = ___script_log_header;
+ script += 'try {';
for (i = 0; i <= current - 1; i++) {
script += ___textarea_value(___global_editors[i]);
}
@@ -832,6 +849,13 @@ function ___git_eval(current) {
+ '___log = [];\n';
script += ___textarea_value(___global_editors[current]);
script += '\n'
+ + '} catch (e) {'
+ + ' if (("" + e.message).indexOf("GIT: assertion failed: ") != 0) {'
+ + ' throw e;'
+ + ' } else {'
+ + ' ___log.push({ alert: true, txt: "command failed" });'
+ + ' }'
+ + '}'
+ '"End of the script";\n'
+ '\n'
+ '\n'
diff --git a/index.html b/index.html
index 7739f69..f43a93b 100644
--- a/index.html
+++ b/index.html
@@ -17,7 +17,7 @@
@@ -251,8 +251,8 @@ function hash_object(must_write, type, is_data, path_or_data) {
if (must_write) {
mkdir(join_paths(current_directory, '.git/objects'));
- mkdir(join_paths(current_directory, '.git/objects/' + hash.substr(0,2)));
- var object_path = join_paths(current_directory, '.git/objects/' + hash.substr(0,2) + '/' + hash.substr(2));
+ mkdir(join_paths(current_directory, '.git/objects/' + hash.substring(0,2)));
+ var object_path = join_paths(current_directory, '.git/objects/' + hash.substring(0,2) + '/' + hash.substring(2));
// deflate() compresses using zlib
write(object_path, deflate(object_contents));
}
@@ -363,7 +363,7 @@ function hex_to_raw_bytes(hex) {
var hex = String(hex);
var str = ""
for (var i = 0; i < hex.length; i+=2) {
- str += String.fromCharCode(parseInt(hex.substr(i, 2), 16));
+ str += String.fromCharCode(parseInt(hex.substring(i, i + 2), 16));
}
return str;
}
@@ -571,7 +571,7 @@ any other non-branch reference.
+
+ After the object header, we have a mode, a filename, a null byte and a hash consisting of 20 bytes.
+ The null byte cannot appear in the mode or filename, so we use this null + hash as a delimiter
+ (the non-greedy match ensures the null byte terminator will not match with a 00
byte in the hash)
+
-
-
-The parse_tree
function above needs a small utility to convert hashes represented using raw bytes to a hexadecimal representation.
+
+ The parse_tree
function above needs a small utility to convert hashes represented using
+ raw bytes to a hexadecimal representation.
+