]> git.ipfire.org Git - thirdparty/git.git/commitdiff
git-gui: Remove forced rescan of stat-dirty files.
authorJohannes Sixt <j6t@kdbg.org>
Sat, 3 Aug 2024 15:22:51 +0000 (17:22 +0200)
committerJohannes Sixt <j6t@kdbg.org>
Sat, 3 Aug 2024 16:56:35 +0000 (18:56 +0200)
It is possible that stat information of tracked files is modified without
actually modifying the content. Plumbing commands would detect such files
as modified, so that Git GUI runs `git update-info --refresh` in order to
synchronize the cached stat info with the reality. However, this can be
an expensive operation in large repositories. As remediation,
e534f3a88676 (git-gui: Allow the user to disable update-index --refresh
during rescan, 2006-11-07) introduced an option to skip the expensive
part.

The option was named "trust file modification timestamp". But the catch
is that sometimes file timestamps can't be trusted. In this case, a file
would remain listed in Unstaged Changes although there are no changes.
So 16403d0b1f9d (git-gui: Refresh a file if it has an empty diff,
2006-11-11) introduced a popup message informing the user about the
situation and then removed the file from the Unstaged Changes list.

Now users had to click away the message box for every file that was
stat-dirty. Under the assumption that a file in such a state is not
the only one, 124355d32c06 (git-gui: Always start a rescan on an empty
diff, 2007-01-22) introduced a forced (potentially expensive) refresh
that would de-list all stat-dirty files after the first notification was
dismissed.

Along came 6c510bee2013 (Lazy man's auto-CRLF, 2007-02-13) in Git. It
introduced a new case where a file in the worktree can have no essential
differences to the staged version, but still be detected as modified by
plumbing commands. This time, however, the index cannot be synchronized
fully by `git update-index --refresh`, so that the file remains listed
in Unstaged Changes until it is staged manually.

Needless to say that the message box now becomes an annoyance, because
it must be dismissed every time an affected file is selected, and the
file remains listed nevertheless.

Remove the message box. Write the notice that no differences were found
in the diff panel instead. Also include a link that, when clicked,
initiates the rescan. With this scheme, the rescan does not happen
automatically anymore, but requires an additional click. (This is now
two clicks in total for users who encounter stat-dirty files after
enabling the "trust file modification timestamps" option.) However,
users whom the rescan does not help (autocrlf-related dirty files) save
half the clicks because there is no message box to dismiss.

Signed-off-by: Johannes Sixt <j6t@kdbg.org>
git-gui.sh
lib/diff.tcl

index 8fe7538e72084d1d794c88e00402602be7df7d65..887d6d596c16fc33ec1dcfd72ddb94f04fdbaa3b 100755 (executable)
@@ -1357,7 +1357,6 @@ set current_diff_path {}
 set is_3way_diff 0
 set is_submodule_diff 0
 set is_conflict_diff 0
-set diff_empty_count 0
 set last_revert {}
 set last_revert_enc {}
 
@@ -3594,6 +3593,8 @@ $ui_diff tag configure clr1 -font font_diffbold
 $ui_diff tag configure clr4 -underline 1
 
 $ui_diff tag conf d_info -foreground blue -font font_diffbold
+$ui_diff tag conf d_rescan -foreground blue -underline 1 -font font_diffbold
+$ui_diff tag bind d_rescan <Button-1> { clear_diff; rescan ui_ready 0 }
 
 $ui_diff tag conf d_cr -elide true
 $ui_diff tag conf d_@ -font font_diffbold
index 871ad488c2a1c010c8a9edd66ae6a6bfd9d4213e..d657bfec05b49865627f321ab260633f250f71c6 100644 (file)
@@ -63,28 +63,17 @@ proc force_diff_encoding {enc} {
 }
 
 proc handle_empty_diff {} {
-       global current_diff_path file_states file_lists
-       global diff_empty_count
+       global current_diff_path file_states
+       global ui_diff
 
        set path $current_diff_path
        set s $file_states($path)
        if {[lindex $s 0] ne {_M} || [has_textconv $path]} return
 
-       # Prevent infinite rescan loops
-       incr diff_empty_count
-       if {$diff_empty_count > 1} return
-
-       info_popup [mc "No differences detected.
-
-%s has no changes.
-
-The modification date of this file was updated by another application, but the content within the file was not changed.
-
-A rescan will be automatically started to find other files which may have the same state." [short_path $path]]
-
-       clear_diff
-       display_file $path __
-       rescan ui_ready 0
+       $ui_diff conf -state normal
+       $ui_diff insert end [mc "* No differences detected; stage the file to de-list it from Unstaged Changes.\n"] d_info
+       $ui_diff insert end [mc "* Click to find other files that may have the same state.\n"] d_rescan
+       $ui_diff conf -state disabled
 }
 
 proc show_diff {path w {lno {}} {scroll_pos {}} {callback {}}} {
@@ -387,7 +376,6 @@ proc read_diff {fd conflict_size cont_info} {
        global ui_diff diff_active is_submodule_diff
        global is_3way_diff is_conflict_diff current_diff_header
        global current_diff_queue
-       global diff_empty_count
 
        $ui_diff conf -state normal
        while {[gets $fd line] >= 0} {
@@ -559,8 +547,6 @@ proc read_diff {fd conflict_size cont_info} {
 
                if {[$ui_diff index end] eq {2.0}} {
                        handle_empty_diff
-               } else {
-                       set diff_empty_count 0
                }
 
                set callback [lindex $cont_info 1]