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. +