@matheusbsbs / matheus-bagliano / commits / 7cf4566f48
Fork 0

git-gui: Fix the after callback execution in rescan.

The rescan function receives a callback command as its parameter, which is supposed to be executed after the scan finishes. It is generally used to update status. However, rescan may initiate a loading of a diff, which always calls ui_ready after completion. If the after handler is called before that, ui_ready will override the new status. This commit ensures that the after callback is properly threaded through the diff machinery. Since it uncovered the fact that force_first_diff actually didn't work due to an undeclared global variable, and the desired effects appeared only because of the race condition between the diff system and the rescan callback, I also reimplement this function to make it behave as originally intended. Signed-off-by: Alexander Gavrilov <angavrilov@gmail.com> Signed-off-by: Shawn O. Pearce <spearce@spearce.org>

Alexander Gavrilov committed Nov 16, 2008 at 21:46 UTC 7cf4566f48b7f17c68ab215a9ca6ef7792d9d791
2 files changed +31 -16
git-gui.sh
+28 -13
@@ -1491,10 +1491,8 @@ proc rescan_done {fd buf after} {
1491 prune_selection
1492 unlock_index
1493 display_all_files
1494 - if {$current_diff_path ne {}} reshow_diff
1495 - if {$current_diff_path eq {}} select_first_diff
1496 -
1497 - uplevel #0 $after
1494 + if {$current_diff_path ne {}} { reshow_diff $after }
1495 + if {$current_diff_path eq {}} { select_first_diff $after }
1496 }
1497
1498 proc prune_selection {} {
@@ -2006,16 +2004,16 @@ proc do_rescan {} {
2004 }
2005
2006 proc ui_do_rescan {} {
2009 - rescan {force_first_diff; ui_ready}
2007 + rescan {force_first_diff ui_ready}
2008 }
2009
2010 proc do_commit {} {
2011 commit_tree
2012 }
2013
2016 -proc next_diff {} {
2014 +proc next_diff {{after {}}} {
2015 global next_diff_p next_diff_w next_diff_i
2018 - show_diff $next_diff_p $next_diff_w {}
2016 + show_diff $next_diff_p $next_diff_w {} {} $after
2017 }
2018
2019 proc find_anchor_pos {lst name} {
@@ -2100,25 +2098,42 @@ proc next_diff_after_action {w path {lno {}} {mmask {}}} {
2098 }
2099 }
2100
2103 -proc select_first_diff {} {
2101 +proc select_first_diff {after} {
2102 global ui_workdir
2103
2104 if {[find_next_diff $ui_workdir {} 1 {^_?U}] ||
2105 [find_next_diff $ui_workdir {} 1 {[^O]$}]} {
2108 - next_diff
2106 + next_diff $after
2107 + } else {
2108 + uplevel #0 $after
2109 }
2110 }
2111
2112 -proc force_first_diff {} {
2113 - global current_diff_path
2112 +proc force_first_diff {after} {
2113 + global ui_workdir current_diff_path file_states
2114
2115 if {[info exists file_states($current_diff_path)]} {
2116 set state [lindex $file_states($current_diff_path) 0]
2117 + } else {
2118 + set state {OO}
2119 + }
2120
2118 - if {[string index $state 1] ne {O}} return
2121 + set reselect 0
2122 + if {[string first {U} $state] >= 0} {
2123 + # Already a conflict, do nothing
2124 + } elseif {[find_next_diff $ui_workdir $current_diff_path {} {^_?U}]} {
2125 + set reselect 1
2126 + } elseif {[string index $state 1] ne {O}} {
2127 + # Already a diff & no conflicts, do nothing
2128 + } elseif {[find_next_diff $ui_workdir $current_diff_path {} {[^O]$}]} {
2129 + set reselect 1
2130 }
2131
2121 - select_first_diff
2132 + if {$reselect} {
2133 + next_diff $after
2134 + } else {
2135 + uplevel #0 $after
2136 + }
2137 }
2138
2139 proc toggle_or_diff {w x y} {
lib/diff.tcl
+3 -3
@@ -16,7 +16,7 @@ proc clear_diff {} {
16 $ui_workdir tag remove in_diff 0.0 end
17 }
18
19 -proc reshow_diff {} {
19 +proc reshow_diff {{after {}}} {
20 global file_states file_lists
21 global current_diff_path current_diff_side
22 global ui_diff
@@ -30,13 +30,13 @@ proc reshow_diff {} {
30 || [lsearch -sorted -exact $file_lists($current_diff_side) $p] == -1} {
31
32 if {[find_next_diff $current_diff_side $p {} {[^O]}]} {
33 - next_diff
33 + next_diff $after
34 } else {
35 clear_diff
36 }
37 } else {
38 set save_pos [lindex [$ui_diff yview] 0]
39 - show_diff $p $current_diff_side {} $save_pos
39 + show_diff $p $current_diff_side {} $save_pos $after
40 }
41 }
42