Skip to content

Commit c461528

Browse files
committed
git-gui: fix error handling of Revert Changes command
The command Revert Changes has two different erroneous behaviors depending on the Tcl version used. The command uses a "chord" facility where different "notes" are evaluated asynchronously and any error is reported after all of them have finished. The intent is that a private namespace is used where the notes can store the error state. Tcl 9 changed namespace handling in a subtle way, as https://www.tcl-lang.org/software/tcltk/9.0.html summarizes under "Notable incompatibilities": Unqualified varnames resolved in current namespace, not global. Note that in almost all cases where this causes a change, the change is actually the removal of a latent bug. And that's exactly what happens here. - Under Tcl 9: - When the command operates without any errors, the variable `err` is never set. When the error handler wants to inspect `err` (in the correct private namespace), it does not find it and a Tcl error about an unset variable occurs. Incidentally, this is also the case when the user cancels the operation with the option "Do Nothing"! On the other hand, when an error occurs during the operation, `err` is set and found as intended. Check for the existence of the variable `err` before the attempt to read it. - Under Tcl 8.6: The error handler looks up `err` in the global namespace, which is bogus and unintended. The variable is set due to the many `catch ... err` that occur during startup in the global namespace. - When the command operates without any errors, the error handler finds the global `err`, which happens to be the empty string at this point, and no error is reported. On the other hand, when an error occurs during the operation, the global `err` is set and found, so that an error is reported as desired. However, the value of `err` persists in the global namespace. When the command is repeated, an error is reported again, even if there was actually no error, and even "Do Nothing" was used to cancel the operation. Clear the global `err` before the operation begins. The lingering error message is not a problem under Tcl 9, because a prestine namespace is established every time the command is used. This fixes j6t/git-gui#21. Helped-by: Igor Stepushchik Signed-off-by: Johannes Sixt <[email protected]>
1 parent e3923e3 commit c461528

File tree

1 file changed

+6
-1
lines changed

1 file changed

+6
-1
lines changed

lib/index.tcl

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -425,14 +425,19 @@ proc revert_helper {txt paths} {
425425

426426
if {![lock_index begin-update]} return
427427

428+
# Workaround for Tcl < 9.0: chord namespaces are not obeyed and
429+
# operated in the global namespace. This clears an error that could
430+
# have been left over from a previous operation.
431+
set ::err {}
432+
428433
# Common "after" functionality that waits until multiple asynchronous
429434
# operations are complete (by waiting for them to activate their notes
430435
# on the chord).
431436
#
432437
# The asynchronous operations are each indicated below by a comment
433438
# before the code block that starts the async operation.
434439
set after_chord [SimpleChord::new {
435-
if {[string trim $err] != ""} {
440+
if {[info exists err] && [string trim $err] ne ""} {
436441
rescan_on_error $err
437442
} else {
438443
unlock_index

0 commit comments

Comments
 (0)