* [PATCH (GIT-GUI BUG) v2] git-gui: Avoid an infinite rescan loop in handle_empty_diff.
@ 2009-02-07 16:24 Alexander Gavrilov
0 siblings, 0 replies; only message in thread
From: Alexander Gavrilov @ 2009-02-07 16:24 UTC (permalink / raw)
To: git; +Cc: Shawn O. Pearce, Junio C Hamano
If the index update machinery and git diff happen to disagree
on whether a particular file is modified, it may cause git-gui
to enter an infinite index rescan loop, where an empty diff
starts a rescan, which finds the same set of files modified,
and tries to display the diff for the first one, which happens
to be the empty one. A current example of a possible disagreement
point is the autocrlf filter.
This patch breaks the loop by using a global counter to track
the auto-rescans. The variable is reset whenever a non-empty
diff is displayed.
Another suggested approach, which is based on giving the
--exit-code argument to git diff, cannot be used, because
diff-files seems to trust the timestamps in the index, and
returns a non-zero code even if the file is actually
unchanged, which essentially defeats the purpose of the
auto-rescan logic.
Signed-off-by: Alexander Gavrilov <angavrilov@gmail.com>
---
Apparently git-diff also has a small crlf-related bug.
It can be reproduced using the following commands:
$ rm -rf .git *
$ git init
$ echo > foo
$ git add foo && git commit -m init
$ git diff-files -p --exit-code && echo unchanged
unchanged
$ git diff --exit-code && echo unchanged
unchanged
$ touch foo
$ git diff-files -p --exit-code && echo unchanged
diff --git a/foo b/foo
$ git diff --exit-code && echo unchanged
unchanged
Without autocrlf git-diff recognizes that
the file is unchanged.
$ rm -rf .git *
$ git init
$ git config core.autocrlf true
$ echo > foo
$ unix2dos -o foo
$ git add foo && git commit -m init
$ git diff-files -p --exit-code && echo unchanged
unchanged
$ git diff --exit-code && echo unchanged
unchanged
$ touch foo
$ git diff-files -p --exit-code && echo unchanged
diff --git a/foo b/foo
$ git diff --exit-code && echo unchanged
diff --git a/foo b/foo
With crlf it prints an empty diff and says
that there are some changes.
I don't think that this behavior should depend
on the autocrlf setting.
-- Alexander
lib/diff.tcl | 9 +++++++++
1 files changed, 9 insertions(+), 0 deletions(-)
diff --git a/lib/diff.tcl b/lib/diff.tcl
index bbbf15c..925b3f5 100644
--- a/lib/diff.tcl
+++ b/lib/diff.tcl
@@ -51,11 +51,16 @@ proc force_diff_encoding {enc} {
proc handle_empty_diff {} {
global current_diff_path file_states file_lists
+ global diff_empty_count
set path $current_diff_path
set s $file_states($path)
if {[lindex $s 0] ne {_M}} 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.
@@ -310,6 +315,7 @@ proc read_diff {fd cont_info} {
global ui_diff diff_active
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} {
@@ -415,7 +421,10 @@ proc read_diff {fd 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]
if {$callback ne {}} {
eval $callback
--
1.6.1.63.g950db
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2009-02-07 16:24 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-02-07 16:24 [PATCH (GIT-GUI BUG) v2] git-gui: Avoid an infinite rescan loop in handle_empty_diff Alexander Gavrilov
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).