git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH (GIT-GUI) v2 2/5] git-gui: Fix the after callback execution in rescan.

From
Alexander Gavrilov <angavrilov@gmail.com>
Date
Nov 16, 2008, 18:46 UTC
Message-ID
<1226861211-16995-3-git-send-email-angavrilov@gmail.com>
In-Reply-To
<1226861211-16995-2-git-send-email-angavrilov@gmail.com>

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>
---
 git-gui.sh   |   41 ++++++++++++++++++++++++++++-------------
 lib/diff.tcl |    6 +++---
 2 files changed, 31 insertions(+), 16 deletions(-)
diff --git a/git-gui.sh b/git-gui.sh
index 34214b6..2709f6e 100755
--- a/git-gui.sh
+++ b/git-gui.sh
@@ -1469,10 +1469,8 @@ proc rescan_done {fd buf after} {
 	prune_selection
 	unlock_index
 	display_all_files
-	if {$current_diff_path ne {}} reshow_diff
-	if {$current_diff_path eq {}} select_first_diff
-
-	uplevel #0 $after
+	if {$current_diff_path ne {}} { reshow_diff $after }
+	if {$current_diff_path eq {}} { select_first_diff $after }
 }
 
 proc prune_selection {} {
@@ -1984,16 +1982,16 @@ proc do_rescan {} {
 }
 
 proc ui_do_rescan {} {
-	rescan {force_first_diff; ui_ready}
+	rescan {force_first_diff ui_ready}
 }
 
 proc do_commit {} {
 	commit_tree
 }
 
-proc next_diff {} {
+proc next_diff {{after {}}} {
 	global next_diff_p next_diff_w next_diff_i
-	show_diff $next_diff_p $next_diff_w {}
+	show_diff $next_diff_p $next_diff_w {} {} $after
 }
 
 proc find_anchor_pos {lst name} {
@@ -2078,25 +2076,42 @@ proc next_diff_after_action {w path {lno {}} {mmask {}}} {
 	}
 }
 
-proc select_first_diff {} {
+proc select_first_diff {after} {
 	global ui_workdir
 
 	if {[find_next_diff $ui_workdir {} 1 {^_?U}] ||
 	    [find_next_diff $ui_workdir {} 1 {[^O]$}]} {
-		next_diff
+		next_diff $after
+	} else {
+		uplevel #0 $after
 	}
 }
 
-proc force_first_diff {} {
-	global current_diff_path
+proc force_first_diff {after} {
+	global ui_workdir current_diff_path file_states
 
 	if {[info exists file_states($current_diff_path)]} {
 		set state [lindex $file_states($current_diff_path) 0]
+	} else {
+		set state {OO}
+	}
 
-		if {[string index $state 1] ne {O}} return
+	set reselect 0
+	if {[string first {U} $state] >= 0} {
+		# Already a conflict, do nothing
+	} elseif {[find_next_diff $ui_workdir $current_diff_path {} {^_?U}]} {
+		set reselect 1
+	} elseif {[string index $state 1] ne {O}} {
+		# Already a diff & no conflicts, do nothing
+	} elseif {[find_next_diff $ui_workdir $current_diff_path {} {[^O]$}]} {
+		set reselect 1
 	}
 
-	select_first_diff
+	if {$reselect} {
+		next_diff $after
+	} else {
+		uplevel #0 $after
+	}
 }
 
 proc toggle_or_diff {w x y} {
diff --git a/lib/diff.tcl b/lib/diff.tcl
index 94ee38c..bbbf15c 100644
--- a/lib/diff.tcl
+++ b/lib/diff.tcl
@@ -16,7 +16,7 @@ proc clear_diff {} {
 	$ui_workdir tag remove in_diff 0.0 end
 }
 
-proc reshow_diff {} {
+proc reshow_diff {{after {}}} {
 	global file_states file_lists
 	global current_diff_path current_diff_side
 	global ui_diff
@@ -30,13 +30,13 @@ proc reshow_diff {} {
 		|| [lsearch -sorted -exact $file_lists($current_diff_side) $p] == -1} {
 
 		if {[find_next_diff $current_diff_side $p {} {[^O]}]} {
-			next_diff
+			next_diff $after
 		} else {
 			clear_diff
 		}
 	} else {
 		set save_pos [lindex [$ui_diff yview] 0]
-		show_diff $p $current_diff_side {} $save_pos
+		show_diff $p $current_diff_side {} $save_pos $after
 	}
 }
 
-- 
1.6.0.3.15.gb8d36
Previous: Alexander GavrilovNext: Alexander Gavrilov
Message 3 of 7 in “Add a customizable Tools menu.”
  1. 0/5 Add a customizable Tools menu.Alexander Gavrilov, Nov 16, 2008
  2. 1/5 git-gui: Implement system-wide configuration handling.Alexander Gavrilov, Nov 16, 2008
  3. 2/5 git-gui: Fix the after callback execution in rescan.Alexander Gavrilov, Nov 16, 2008
  4. 3/5 git-gui: Add a Tools menu for arbitrary commands.Alexander Gavrilov, Nov 16, 2008
  5. 4/5 git-gui: Allow Tools request arguments from the user.Alexander Gavrilov, Nov 16, 2008
  6. 5/5 git-gui: Implement automatic rescan after Tool execution.Alexander Gavrilov, Nov 16, 2008
  7. Shawn O. PearceNov 16, 2008

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.