All of lore.kernel.org
 help / color / mirror / Atom feed
From: Alexander Gavrilov <angavrilov@gmail.com>
To: git@vger.kernel.org
Cc: "Shawn O. Pearce" <spearce@spearce.org>,
	Junio C Hamano <gitster@pobox.com>
Subject: [PATCH (GIT-GUI BUG) v2] git-gui: Avoid an infinite rescan loop in handle_empty_diff.
Date: Sat, 7 Feb 2009 19:24:01 +0300	[thread overview]
Message-ID: <200902071924.02419.angavrilov@gmail.com> (raw)

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

                 reply	other threads:[~2009-02-07 16:24 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=200902071924.02419.angavrilov@gmail.com \
    --to=angavrilov@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=spearce@spearce.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.