git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/4] "diff -p" patch header generation updates
@ 2012-03-01  2:14 Junio C Hamano
  2012-03-01  2:14 ` [PATCH 1/4] t4011: modernise style Junio C Hamano
                   ` (3 more replies)
  0 siblings, 4 replies; 10+ messages in thread
From: Junio C Hamano @ 2012-03-01  2:14 UTC (permalink / raw)
  To: git

There has always been one thing fishy about the plumbing level "diff" used
to generate patches with "-p" option: we produced a header-only diff when
there is no patch necessary to be shown, when there is no contents change.
We are calling into xdiff to produce a patch, and we should have all the
necessary information to suppress the unnecessary header, but because
historically we didn't, we never updated the code to do so.

It turns out that we already have the necessary machinery to notice such a
situation and suppressing the useless header. We just did not realize that
we could use it. There is a backward compatibility worry for scripts, but
I would imagine that the scripts saw these header-only diff as a nuisance
that needs to be filtered out, not a feature to learn about paths that are
only stat-dirty.  And more importantly, even if this _were_ a feature, it
was not working correctly when "-w" option was in effect to begin with, as
the second one in the series illustrates.

This series changes the world order that is almost 6 years old.  No more
phantom diff headers in patch output due to stat-dirtiness.

The first patch in this series replaces the one I posted earlier (one
block that prepares the expected result was in a wrong test).

The second patch adds test vectors that illustrate the current behaviour
that will be changed with this series.

The third patch is the real change, whose effect can be seen in the patch
to the test the second one introduces.

The fourth one is unrelated from the rest of the series from the feature
point of view, but its implementation depends on the updated semantics of
header suppression.

The series is designed to apply on top of v1.7.4-rc0~147 and has trivial
conflict in diff.h if applied/merged to 'master'.  Just take the addition
of DIFF_OPT* macros from both sides.

Junio C Hamano (4):
  t4011: modernise style
  t4011: illustrate "diff-index -p" on stat-dirty paths
  diff -p: squelch "diff --git" header for stat-dirty paths
  diff --ignore-mode-change

 diff.c                  |   31 +++++++-
 diff.h                  |    1 +
 t/t4011-diff-symlink.sh |  196 +++++++++++++++++++++++++++--------------------
 3 files changed, 141 insertions(+), 87 deletions(-)

-- 
1.7.9.2.350.g74d65

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 1/4] t4011: modernise style
  2012-03-01  2:14 [PATCH 0/4] "diff -p" patch header generation updates Junio C Hamano
@ 2012-03-01  2:14 ` Junio C Hamano
  2012-03-01  2:14 ` [PATCH 2/4] t4011: illustrate "diff-index -p" on stat-dirty paths Junio C Hamano
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 10+ messages in thread
From: Junio C Hamano @ 2012-03-01  2:14 UTC (permalink / raw)
  To: git

Match the style to more modern test scripts, namely:

 - The first line of each test has prereq, title and opening sq for the
   script body.  This makes the test shorter while reducing the need for
   backquotes.

 - Be prepared for the case in which the previous test may have failed.
   If a test wants to start from not having "frotz" that the previous test
   may have created, write "rm -f frotz", not "rm frotz".

 - Prepare the expected output inside your own test.

 - The order of comparison to check the result is "diff expected actual",
   so that the output will show how the output from the git you just broke
   is different from what is expected.

 - Write no SP between redirection '>' (or '<' for that matter) and the
   filename.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---

 * replaces the one I posted earlier (one block that prepares the expected
   result was in a wrong test).

 t/t4011-diff-symlink.sh |  168 +++++++++++++++++++++++------------------------
 1 file changed, 82 insertions(+), 86 deletions(-)

diff --git a/t/t4011-diff-symlink.sh b/t/t4011-diff-symlink.sh
index 408a19c..cb47ec1 100755
--- a/t/t4011-diff-symlink.sh
+++ b/t/t4011-diff-symlink.sh
@@ -9,85 +9,81 @@ test_description='Test diff of symlinks.
 . ./test-lib.sh
 . "$TEST_DIRECTORY"/diff-lib.sh
 
-cat > expected << EOF
-diff --git a/frotz b/frotz
-new file mode 120000
-index 0000000..7c465af
---- /dev/null
-+++ b/frotz
-@@ -0,0 +1 @@
-+xyzzy
-\ No newline at end of file
-EOF
-
-test_expect_success SYMLINKS \
-    'diff new symlink' \
-    'ln -s xyzzy frotz &&
-    git update-index &&
-    tree=$(git write-tree) &&
-    git update-index --add frotz &&
-    GIT_DIFF_OPTS=--unified=0 git diff-index -M -p $tree > current &&
-    compare_diff_patch current expected'
-
-test_expect_success SYMLINKS \
-    'diff unchanged symlink' \
-    'tree=$(git write-tree) &&
-    git update-index frotz &&
-    test -z "$(git diff-index --name-only $tree)"'
-
-cat > expected << EOF
-diff --git a/frotz b/frotz
-deleted file mode 120000
-index 7c465af..0000000
---- a/frotz
-+++ /dev/null
-@@ -1 +0,0 @@
--xyzzy
-\ No newline at end of file
-EOF
-
-test_expect_success SYMLINKS \
-    'diff removed symlink' \
-    'mv frotz frotz2 &&
-    git diff-index -M -p $tree > current &&
-    compare_diff_patch current expected'
+test_expect_success SYMLINKS 'diff new symlink' '
+	cat >expected <<-\EOF &&
+	diff --git a/frotz b/frotz
+	new file mode 120000
+	index 0000000..7c465af
+	--- /dev/null
+	+++ b/frotz
+	@@ -0,0 +1 @@
+	+xyzzy
+	\ No newline at end of file
+	EOF
+	ln -s xyzzy frotz &&
+	git update-index &&
+	tree=$(git write-tree) &&
+	git update-index --add frotz &&
+	GIT_DIFF_OPTS=--unified=0 git diff-index -M -p $tree >current &&
+	compare_diff_patch expected current
+'
 
-cat > expected << EOF
-diff --git a/frotz b/frotz
-EOF
+test_expect_success SYMLINKS 'diff unchanged symlink'  '
+	tree=$(git write-tree) &&
+	git update-index frotz &&
+	test -z "$(git diff-index --name-only $tree)"
+'
 
-test_expect_success SYMLINKS \
-    'diff identical, but newly created symlink' \
-    'ln -s xyzzy frotz &&
-    git diff-index -M -p $tree > current &&
-    compare_diff_patch current expected'
+test_expect_success SYMLINKS 'diff removed symlink' '
+	cat >expected <<-\EOF &&
+	diff --git a/frotz b/frotz
+	deleted file mode 120000
+	index 7c465af..0000000
+	--- a/frotz
+	+++ /dev/null
+	@@ -1 +0,0 @@
+	-xyzzy
+	\ No newline at end of file
+	EOF
+	mv frotz frotz2 &&
+	git diff-index -M -p $tree >current &&
+	compare_diff_patch expected current
+'
 
-cat > expected << EOF
-diff --git a/frotz b/frotz
-index 7c465af..df1db54 120000
---- a/frotz
-+++ b/frotz
-@@ -1 +1 @@
--xyzzy
-\ No newline at end of file
-+yxyyz
-\ No newline at end of file
-EOF
+test_expect_success SYMLINKS 'diff identical, but newly created symlink' '
+	cat >expected <<-\EOF &&
+	diff --git a/frotz b/frotz
+	EOF
+	ln -s xyzzy frotz &&
+	git diff-index -M -p $tree >current &&
+	compare_diff_patch expected current
+'
 
-test_expect_success SYMLINKS \
-    'diff different symlink' \
-    'rm frotz &&
-    ln -s yxyyz frotz &&
-    git diff-index -M -p $tree > current &&
-    compare_diff_patch current expected'
+test_expect_success SYMLINKS 'diff different symlink' '
+	cat >expected <<-\EOF &&
+	diff --git a/frotz b/frotz
+	index 7c465af..df1db54 120000
+	--- a/frotz
+	+++ b/frotz
+	@@ -1 +1 @@
+	-xyzzy
+	\ No newline at end of file
+	+yxyyz
+	\ No newline at end of file
+	EOF
+	rm -f frotz &&
+	ln -s yxyyz frotz &&
+	git diff-index -M -p $tree >current &&
+	compare_diff_patch expected current
+'
 
-test_expect_success SYMLINKS \
-    'diff symlinks with non-existing targets' \
-    'ln -s narf pinky &&
-    ln -s take\ over brain &&
-    test_must_fail git diff --no-index pinky brain > output 2> output.err &&
-    grep narf output &&
-    ! grep error output.err'
+test_expect_success SYMLINKS 'diff symlinks with non-existing targets' '
+	ln -s narf pinky &&
+	ln -s take\ over brain &&
+	test_must_fail git diff --no-index pinky brain >output 2>output.err &&
+	grep narf output &&
+	! test -s output.err
+'
 
 test_expect_success SYMLINKS 'setup symlinks with attributes' '
 	echo "*.bin diff=bin" >>.gitattributes &&
@@ -96,19 +92,19 @@ test_expect_success SYMLINKS 'setup symlinks with attributes' '
 	git add -N file.bin link.bin
 '
 
-cat >expect <<'EOF'
-diff --git a/file.bin b/file.bin
-index e69de29..d95f3ad 100644
-Binary files a/file.bin and b/file.bin differ
-diff --git a/link.bin b/link.bin
-index e69de29..dce41ec 120000
---- a/link.bin
-+++ b/link.bin
-@@ -0,0 +1 @@
-+file.bin
-\ No newline at end of file
-EOF
 test_expect_success SYMLINKS 'symlinks do not respect userdiff config by path' '
+	cat >expect <<-\EOF &&
+	diff --git a/file.bin b/file.bin
+	index e69de29..d95f3ad 100644
+	Binary files a/file.bin and b/file.bin differ
+	diff --git a/link.bin b/link.bin
+	index e69de29..dce41ec 120000
+	--- a/link.bin
+	+++ b/link.bin
+	@@ -0,0 +1 @@
+	+file.bin
+	\ No newline at end of file
+	EOF
 	git config diff.bin.binary true &&
 	git diff file.bin link.bin >actual &&
 	test_cmp expect actual
-- 
1.7.9.2.350.g74d65

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 2/4] t4011: illustrate "diff-index -p" on stat-dirty paths
  2012-03-01  2:14 [PATCH 0/4] "diff -p" patch header generation updates Junio C Hamano
  2012-03-01  2:14 ` [PATCH 1/4] t4011: modernise style Junio C Hamano
@ 2012-03-01  2:14 ` Junio C Hamano
  2012-03-01  9:05   ` Thomas Rast
  2012-03-01 10:05   ` [PATCH 2/4] " Zbigniew Jędrzejewski-Szmek
  2012-03-01  2:14 ` [PATCH 3/4] diff -p: squelch "diff --git" header for " Junio C Hamano
  2012-03-01  2:14 ` [PATCH 4/4] diff --ignore-mode-change Junio C Hamano
  3 siblings, 2 replies; 10+ messages in thread
From: Junio C Hamano @ 2012-03-01  2:14 UTC (permalink / raw)
  To: git

The plumbing that looks at the working tree, i.e. "diff-index" and
"diff-files", always emit the "diff --git a/path b/path" header lines
without anything else for paths that are only stat-dirty (i.e. different
only because the cached stat information in the index no longer matches
that of the working tree, but the real contents are the same), when
these commands are run with "-p" option to produce patches.

Illustrate this current behaviour.  The new part that uses "-w" option
demonstrates that we do not show any "diff --git" header for blobs whose
true contents are different but compares the same when whitespaces are
ignored, which is inconsistent with the behaviour for stat-dirty paths.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 t/t4011-diff-symlink.sh |   47 ++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 40 insertions(+), 7 deletions(-)

diff --git a/t/t4011-diff-symlink.sh b/t/t4011-diff-symlink.sh
index cb47ec1..6097e19 100755
--- a/t/t4011-diff-symlink.sh
+++ b/t/t4011-diff-symlink.sh
@@ -9,7 +9,7 @@ test_description='Test diff of symlinks.
 . ./test-lib.sh
 . "$TEST_DIRECTORY"/diff-lib.sh
 
-test_expect_success SYMLINKS 'diff new symlink' '
+test_expect_success SYMLINKS 'diff new symlink and file' '
 	cat >expected <<-\EOF &&
 	diff --git a/frotz b/frotz
 	new file mode 120000
@@ -19,22 +19,30 @@ test_expect_success SYMLINKS 'diff new symlink' '
 	@@ -0,0 +1 @@
 	+xyzzy
 	\ No newline at end of file
+	diff --git a/nitfol b/nitfol
+	new file mode 100644
+	index 0000000..7c465af
+	--- /dev/null
+	+++ b/nitfol
+	@@ -0,0 +1 @@
+	+xyzzy
 	EOF
 	ln -s xyzzy frotz &&
+	echo xyzzy >nitfol &&
 	git update-index &&
 	tree=$(git write-tree) &&
-	git update-index --add frotz &&
+	git update-index --add frotz nitfol &&
 	GIT_DIFF_OPTS=--unified=0 git diff-index -M -p $tree >current &&
 	compare_diff_patch expected current
 '
 
-test_expect_success SYMLINKS 'diff unchanged symlink'  '
+test_expect_success SYMLINKS 'diff unchanged symlink and file'  '
 	tree=$(git write-tree) &&
-	git update-index frotz &&
+	git update-index frotz nitfol &&
 	test -z "$(git diff-index --name-only $tree)"
 '
 
-test_expect_success SYMLINKS 'diff removed symlink' '
+test_expect_success SYMLINKS 'diff removed symlink and file' '
 	cat >expected <<-\EOF &&
 	diff --git a/frotz b/frotz
 	deleted file mode 120000
@@ -44,22 +52,39 @@ test_expect_success SYMLINKS 'diff removed symlink' '
 	@@ -1 +0,0 @@
 	-xyzzy
 	\ No newline at end of file
+	diff --git a/nitfol b/nitfol
+	deleted file mode 100644
+	index 7c465af..0000000
+	--- a/nitfol
+	+++ /dev/null
+	@@ -1 +0,0 @@
+	-xyzzy
 	EOF
 	mv frotz frotz2 &&
+	mv nitfol nitfol2 &&
 	git diff-index -M -p $tree >current &&
 	compare_diff_patch expected current
 '
 
-test_expect_success SYMLINKS 'diff identical, but newly created symlink' '
+test_expect_success SYMLINKS 'diff identical, but newly created symlink and file' '
 	cat >expected <<-\EOF &&
 	diff --git a/frotz b/frotz
+	diff --git a/nitfol b/nitfol
 	EOF
+	sleep 3 &&
+	rm -f frotz &&
+	echo xyzzy >nitfol3 &&
+	mv nitfol3 nitfol &&
 	ln -s xyzzy frotz &&
 	git diff-index -M -p $tree >current &&
+	compare_diff_patch expected current &&
+
+	>expected &&
+	git diff-index -M -p -w $tree >current &&
 	compare_diff_patch expected current
 '
 
-test_expect_success SYMLINKS 'diff different symlink' '
+test_expect_success SYMLINKS 'diff different symlink and file' '
 	cat >expected <<-\EOF &&
 	diff --git a/frotz b/frotz
 	index 7c465af..df1db54 120000
@@ -70,9 +95,17 @@ test_expect_success SYMLINKS 'diff different symlink' '
 	\ No newline at end of file
 	+yxyyz
 	\ No newline at end of file
+	diff --git a/nitfol b/nitfol
+	index 7c465af..df1db54 100644
+	--- a/nitfol
+	+++ b/nitfol
+	@@ -1 +1 @@
+	-xyzzy
+	+yxyyz
 	EOF
 	rm -f frotz &&
 	ln -s yxyyz frotz &&
+	echo yxyyz >nitfol &&
 	git diff-index -M -p $tree >current &&
 	compare_diff_patch expected current
 '
-- 
1.7.9.2.350.g74d65

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 3/4] diff -p: squelch "diff --git" header for stat-dirty paths
  2012-03-01  2:14 [PATCH 0/4] "diff -p" patch header generation updates Junio C Hamano
  2012-03-01  2:14 ` [PATCH 1/4] t4011: modernise style Junio C Hamano
  2012-03-01  2:14 ` [PATCH 2/4] t4011: illustrate "diff-index -p" on stat-dirty paths Junio C Hamano
@ 2012-03-01  2:14 ` Junio C Hamano
  2012-03-01  2:14 ` [PATCH 4/4] diff --ignore-mode-change Junio C Hamano
  3 siblings, 0 replies; 10+ messages in thread
From: Junio C Hamano @ 2012-03-01  2:14 UTC (permalink / raw)
  To: git

The plumbing "diff" commands look at the working tree files without
refreshing the index themselves for performance reasons (the calling
script is expected to do that upfront just once, before calling one or
more of them).  In the early days of git, they showed the "diff --git"
header before they actually ask the xdiff machinery to produce patches,
and ended up showing only these headers if the real contents are the same
and the difference they noticed was only because the stat info cached in
the index did not match that of the working tree. It was too late for the
implementation to take the header that it already emitted back.

But 3e97c7c (No diff -b/-w output for all-whitespace changes, 2009-11-19)
introduced necessary logic to keep the meta-information headers in a
strbuf and delay their output until the xdiff machinery noticed actual
changes. This was primarily in order to generate patches that ignore
whitespaces. When operating under "-w" mode, we wouldn't know if the
header is needed until we actually look at the resulting patch, so it was
a sensible thing to do, but we did not realize that the same reasoning
applies to stat-dirty paths.

Later, 296c6bb2 generalized this machinery and introduced must_show_header
toggle.  This is turned on when the header must be shown even when there
is no patch to be produced, e.g. only the mode was changed, or the path
was renamed, without changing the contents.  However, when it did so, it
still kept the special case for the "-w" mode, which meant that the
plumbing would keep showing these phantom changes.

This corrects this historical inconsistency by allowing the plumbing to
omit paths that are only stat-dirty from its output in the same way as it
handles whitespace only changes under "-w" option.

The change in the behaviour can be seen in the updated test.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 diff.c                  |    2 +-
 t/t4011-diff-symlink.sh |    5 +----
 2 files changed, 2 insertions(+), 5 deletions(-)

diff --git a/diff.c b/diff.c
index c8e4366..0ecbf32 100644
--- a/diff.c
+++ b/diff.c
@@ -1972,7 +1972,7 @@ static void builtin_diff(const char *name_a,
 		struct emit_callback ecbdata;
 		const struct userdiff_funcname *pe;
 
-		if (!DIFF_XDL_TST(o, WHITESPACE_FLAGS) || must_show_header) {
+		if (must_show_header) {
 			fprintf(o->file, "%s", header.buf);
 			strbuf_reset(&header);
 		}
diff --git a/t/t4011-diff-symlink.sh b/t/t4011-diff-symlink.sh
index 6097e19..7547c6d 100755
--- a/t/t4011-diff-symlink.sh
+++ b/t/t4011-diff-symlink.sh
@@ -67,10 +67,7 @@ test_expect_success SYMLINKS 'diff removed symlink and file' '
 '
 
 test_expect_success SYMLINKS 'diff identical, but newly created symlink and file' '
-	cat >expected <<-\EOF &&
-	diff --git a/frotz b/frotz
-	diff --git a/nitfol b/nitfol
-	EOF
+	>expected &&
 	sleep 3 &&
 	rm -f frotz &&
 	echo xyzzy >nitfol3 &&
-- 
1.7.9.2.350.g74d65

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 4/4] diff --ignore-mode-change
  2012-03-01  2:14 [PATCH 0/4] "diff -p" patch header generation updates Junio C Hamano
                   ` (2 preceding siblings ...)
  2012-03-01  2:14 ` [PATCH 3/4] diff -p: squelch "diff --git" header for " Junio C Hamano
@ 2012-03-01  2:14 ` Junio C Hamano
  3 siblings, 0 replies; 10+ messages in thread
From: Junio C Hamano @ 2012-03-01  2:14 UTC (permalink / raw)
  To: git

It may be useful if you can view the diff while ignoring changes that only
touch the executable bit without changing the contents (e.g. a careless
imports of vendor drop from tarballs), and this teaches the diff machinery
to ignore them. A change that touches both contents and the executable bit
is not ignored.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 diff.c |   29 ++++++++++++++++++++++++++++-
 diff.h |    1 +
 2 files changed, 29 insertions(+), 1 deletion(-)

diff --git a/diff.c b/diff.c
index 0ecbf32..62fefba 100644
--- a/diff.c
+++ b/diff.c
@@ -1920,7 +1920,8 @@ static void builtin_diff(const char *name_a,
 		if (one->mode != two->mode) {
 			strbuf_addf(&header, "%s%sold mode %06o%s\n", line_prefix, set, one->mode, reset);
 			strbuf_addf(&header, "%s%snew mode %06o%s\n", line_prefix, set, two->mode, reset);
-			must_show_header = 1;
+			if (!DIFF_OPT_TST(o, IGNORE_MODE_CHANGE))
+				must_show_header = 1;
 		}
 		if (xfrm_msg)
 			strbuf_addstr(&header, xfrm_msg);
@@ -3166,6 +3167,8 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
 	}
 	else if (!strcmp(arg, "--no-renames"))
 		options->detect_rename = 0;
+	else if (!strcmp(arg, "--ignore-mode-change"))
+		DIFF_OPT_SET(options, IGNORE_MODE_CHANGE);
 	else if (!strcmp(arg, "--relative"))
 		DIFF_OPT_SET(options, RELATIVE_NAME);
 	else if (!prefixcmp(arg, "--relative=")) {
@@ -4191,10 +4194,34 @@ void diffcore_fix_diff_index(struct diff_options *options)
 	qsort(q->queue, q->nr, sizeof(q->queue[0]), diffnamecmp);
 }
 
+static void diffcore_ignore_mode_change(struct diff_options *diffopt)
+{
+	int i;
+	struct diff_queue_struct *q = &diff_queued_diff;
+	struct diff_queue_struct outq;
+	DIFF_QUEUE_CLEAR(&outq);
+
+	for (i = 0; i < q->nr; i++) {
+		struct diff_filepair *p = q->queue[i];
+
+		if (DIFF_FILE_VALID(p->one) &&
+		    DIFF_FILE_VALID(p->two) &&
+		    (p->one->sha1_valid && p->two->sha1_valid) &&
+		    !hashcmp(p->one->sha1, p->two->sha1))
+			diff_free_filepair(p); /* skip this */
+		else
+			diff_q(&outq, p);
+	}
+	free(q->queue);
+	*q = outq;
+}
+
 void diffcore_std(struct diff_options *options)
 {
 	if (options->skip_stat_unmatch)
 		diffcore_skip_stat_unmatch(options);
+	if (DIFF_OPT_TST(options, IGNORE_MODE_CHANGE))
+		diffcore_ignore_mode_change(options);
 	if (!options->found_follow) {
 		/* See try_to_follow_renames() in tree-diff.c */
 		if (options->break_opt != -1)
diff --git a/diff.h b/diff.h
index 0083d92..9f10f72 100644
--- a/diff.h
+++ b/diff.h
@@ -78,6 +78,7 @@ typedef struct strbuf *(*diff_prefix_fn_t)(struct diff_options *opt, void *data)
 #define DIFF_OPT_IGNORE_UNTRACKED_IN_SUBMODULES (1 << 25)
 #define DIFF_OPT_IGNORE_DIRTY_SUBMODULES (1 << 26)
 #define DIFF_OPT_OVERRIDE_SUBMODULE_CONFIG (1 << 27)
+#define DIFF_OPT_IGNORE_MODE_CHANGE  (1 << 30)
 
 #define DIFF_OPT_TST(opts, flag)    ((opts)->flags & DIFF_OPT_##flag)
 #define DIFF_OPT_SET(opts, flag)    ((opts)->flags |= DIFF_OPT_##flag)
-- 
1.7.9.2.350.g74d65

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH 2/4] t4011: illustrate "diff-index -p" on stat-dirty paths
  2012-03-01  2:14 ` [PATCH 2/4] t4011: illustrate "diff-index -p" on stat-dirty paths Junio C Hamano
@ 2012-03-01  9:05   ` Thomas Rast
  2012-03-01 16:18     ` Junio C Hamano
  2012-03-01 16:52     ` [PATCH 2/4 v2] " Junio C Hamano
  2012-03-01 10:05   ` [PATCH 2/4] " Zbigniew Jędrzejewski-Szmek
  1 sibling, 2 replies; 10+ messages in thread
From: Thomas Rast @ 2012-03-01  9:05 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git

Junio C Hamano <gitster@pobox.com> writes:

> The plumbing that looks at the working tree, i.e. "diff-index" and
> "diff-files", always emit the "diff --git a/path b/path" header lines
> without anything else for paths that are only stat-dirty (i.e. different
> only because the cached stat information in the index no longer matches
> that of the working tree, but the real contents are the same), when
> these commands are run with "-p" option to produce patches.
>
> Illustrate this current behaviour.  The new part that uses "-w" option
> demonstrates that we do not show any "diff --git" header for blobs whose
> true contents are different but compares the same when whitespaces are
> ignored, which is inconsistent with the behaviour for stat-dirty paths.
[...]
> -test_expect_success SYMLINKS 'diff identical, but newly created symlink' '
> +test_expect_success SYMLINKS 'diff identical, but newly created symlink and file' '
>  	cat >expected <<-\EOF &&
>  	diff --git a/frotz b/frotz
> +	diff --git a/nitfol b/nitfol
>  	EOF
> +	sleep 3 &&
> +	rm -f frotz &&
> +	echo xyzzy >nitfol3 &&
> +	mv nitfol3 nitfol &&
>  	ln -s xyzzy frotz &&
>  	git diff-index -M -p $tree >current &&
> +	compare_diff_patch expected current &&
> +
> +	>expected &&
> +	git diff-index -M -p -w $tree >current &&
>  	compare_diff_patch expected current
>  '

I find the last bit of the commit message rather confusing.  You appear
to be using -w here to diff the stat-dirty worktree nitfol 'xyzzy\n'
against the $tree:nitfol which is also 'xyzzy\n'.

If that analysis is correct, then

  we do not show any "diff --git" header for blobs whose true contents
  are different but compares the same when whitespaces are ignored

is not what is going on here; the blobs have exactly the same content.
The difference is that

* without -w, the code "knows" from the lstat() data that the files are
  different, prints a header, and then fails to find any differences;

* with -w, the code correctly holds off on printing anything since it
  will invariably have to inspect the contents beforehand.

So perhaps you can say

  Illustrate this current behaviour.  Also demonstrate that with the
  "-w" option, we (correctly) hold off showing a "diff --git" header
  until actual differences have been found.  This also suppresses the
  header for merely stat-dirty files, which is inconsistent.

-- 
Thomas Rast
trast@{inf,student}.ethz.ch

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 2/4] t4011: illustrate "diff-index -p" on stat-dirty paths
  2012-03-01  2:14 ` [PATCH 2/4] t4011: illustrate "diff-index -p" on stat-dirty paths Junio C Hamano
  2012-03-01  9:05   ` Thomas Rast
@ 2012-03-01 10:05   ` Zbigniew Jędrzejewski-Szmek
  2012-03-01 16:10     ` Junio C Hamano
  1 sibling, 1 reply; 10+ messages in thread
From: Zbigniew Jędrzejewski-Szmek @ 2012-03-01 10:05 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git

On 03/01/2012 03:14 AM, Junio C Hamano wrote:
> -test_expect_success SYMLINKS 'diff unchanged symlink'  '
> +test_expect_success SYMLINKS 'diff unchanged symlink and file'  '
>   	tree=$(git write-tree)&&
> -	git update-index frotz&&
> +	git update-index frotz nitfol&&
>   	test -z "$(git diff-index --name-only $tree)"
>   '
Hi,
why modify and extend an existing test instead of adding a new separate 
one? I think the test-suite should be getting more unittest-y, ie. 
checking minimal aspects of functionality, not less.

Zbyszek

> -test_expect_success SYMLINKS 'diff removed symlink' '
> +test_expect_success SYMLINKS 'diff removed symlink and file' '
>   	cat>expected<<-\EOF&&
>   	diff --git a/frotz b/frotz
>   	deleted file mode 120000
> @@ -44,22 +52,39 @@ test_expect_success SYMLINKS 'diff removed symlink' '
>   	@@ -1 +0,0 @@
>   	-xyzzy
>   	\ No newline at end of file
> +	diff --git a/nitfol b/nitfol
> +	deleted file mode 100644
> +	index 7c465af..0000000
> +	--- a/nitfol
> +	+++ /dev/null
> +	@@ -1 +0,0 @@
> +	-xyzzy
>   	EOF
>   	mv frotz frotz2&&
> +	mv nitfol nitfol2&&
>   	git diff-index -M -p $tree>current&&
>   	compare_diff_patch expected current
>   '

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 2/4] t4011: illustrate "diff-index -p" on stat-dirty paths
  2012-03-01 10:05   ` [PATCH 2/4] " Zbigniew Jędrzejewski-Szmek
@ 2012-03-01 16:10     ` Junio C Hamano
  0 siblings, 0 replies; 10+ messages in thread
From: Junio C Hamano @ 2012-03-01 16:10 UTC (permalink / raw)
  To: Zbigniew Jędrzejewski-Szmek; +Cc: git

Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> writes:

> On 03/01/2012 03:14 AM, Junio C Hamano wrote:
>> -test_expect_success SYMLINKS 'diff unchanged symlink'  '
>> +test_expect_success SYMLINKS 'diff unchanged symlink and file'  '
>>   	tree=$(git write-tree)&&
>> -	git update-index frotz&&
>> +	git update-index frotz nitfol&&
>>   	test -z "$(git diff-index --name-only $tree)"
>>   '
> why modify and extend an existing test instead of adding a new
> separate one?

If you are talking about assigning a new test number for a new script, it
is better to avoid it when you can.  If on the other hand you meant to add
a new "test_expect_success" block, yes, that is one of the right things to
consider when adding tests, and I tried it both ways.

The result was easier to read when done the way it was posted.

For this update, you could keep the later test that originally checked
symlink intact and add an identical check for regular file, but the thing
is, the behaviour change brought by the update in this series affect both
symlink and regular file comes from the same underlying mechanism, and
demonstrating the change in a single hunk that makes two phantom output
lines disappear was far easier to review than two hunks each of which
shows one phantom output line disapper.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 2/4] t4011: illustrate "diff-index -p" on stat-dirty paths
  2012-03-01  9:05   ` Thomas Rast
@ 2012-03-01 16:18     ` Junio C Hamano
  2012-03-01 16:52     ` [PATCH 2/4 v2] " Junio C Hamano
  1 sibling, 0 replies; 10+ messages in thread
From: Junio C Hamano @ 2012-03-01 16:18 UTC (permalink / raw)
  To: Thomas Rast; +Cc: Junio C Hamano, git

Thomas Rast <trast@inf.ethz.ch> writes:

> If that analysis is correct, then
>
>   we do not show any "diff --git" header for blobs whose true contents
>   are different but compares the same when whitespaces are ignored
>
> is not what is going on here; the blobs have exactly the same content.

True; an earlier draft actually had an 'echo " xyzzy" >nitfol' in there,
but it meant that it needed another annoying 'sleep 3' (I could have used
test-chmtime), so the test was updated but the above description stayed.

> The difference is that
>
> * without -w, the code "knows" from the lstat() data that the files are
>   different, prints a header, and then fails to find any differences;

Correct. Those quotes around "knows" are the most important ;-)

The code incorrectly thinks the stat dirtyness is all that it "knows";
even though it has a way to act on a better knowledge from the xdiff these
days, it does not utilize it.

> * with -w, the code correctly holds off on printing anything since it
>   will invariably have to inspect the contents beforehand.
>
> So perhaps you can say
>
>   Illustrate this current behaviour.  Also demonstrate that with the
>   "-w" option, we (correctly) hold off showing a "diff --git" header
>   until actual differences have been found.  This also suppresses the
>   header for merely stat-dirty files, which is inconsistent.

That is much better; thanks.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 2/4 v2] t4011: illustrate "diff-index -p" on stat-dirty paths
  2012-03-01  9:05   ` Thomas Rast
  2012-03-01 16:18     ` Junio C Hamano
@ 2012-03-01 16:52     ` Junio C Hamano
  1 sibling, 0 replies; 10+ messages in thread
From: Junio C Hamano @ 2012-03-01 16:52 UTC (permalink / raw)
  To: Thomas Rast; +Cc: git

The plumbing that looks at the working tree, i.e. "diff-index" and
"diff-files", always emit the "diff --git a/path b/path" header lines
without anything else for paths that are only stat-dirty (i.e. different
only because the cached stat information in the index no longer matches
that of the working tree, but the real contents are the same), when
these commands are run with "-p" option to produce patches.

Illustrate this current behaviour.  Also demonstrate that with the "-w"
option, we (correctly) hold off showing a "diff --git" header until actual
differences have been found.  This also suppresses the header for merely
stat-dirty files, which is inconsistent.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---

 * This time with test-chmtime to get rid of the annoying 3 second delay
   to invalidate the cached stat information.

 t/t4011-diff-symlink.sh |   46 +++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 39 insertions(+), 7 deletions(-)

diff --git a/t/t4011-diff-symlink.sh b/t/t4011-diff-symlink.sh
index cb47ec1..164f153 100755
--- a/t/t4011-diff-symlink.sh
+++ b/t/t4011-diff-symlink.sh
@@ -9,7 +9,7 @@ test_description='Test diff of symlinks.
 . ./test-lib.sh
 . "$TEST_DIRECTORY"/diff-lib.sh
 
-test_expect_success SYMLINKS 'diff new symlink' '
+test_expect_success SYMLINKS 'diff new symlink and file' '
 	cat >expected <<-\EOF &&
 	diff --git a/frotz b/frotz
 	new file mode 120000
@@ -19,22 +19,30 @@ test_expect_success SYMLINKS 'diff new symlink' '
 	@@ -0,0 +1 @@
 	+xyzzy
 	\ No newline at end of file
+	diff --git a/nitfol b/nitfol
+	new file mode 100644
+	index 0000000..7c465af
+	--- /dev/null
+	+++ b/nitfol
+	@@ -0,0 +1 @@
+	+xyzzy
 	EOF
 	ln -s xyzzy frotz &&
+	echo xyzzy >nitfol &&
 	git update-index &&
 	tree=$(git write-tree) &&
-	git update-index --add frotz &&
+	git update-index --add frotz nitfol &&
 	GIT_DIFF_OPTS=--unified=0 git diff-index -M -p $tree >current &&
 	compare_diff_patch expected current
 '
 
-test_expect_success SYMLINKS 'diff unchanged symlink'  '
+test_expect_success SYMLINKS 'diff unchanged symlink and file'  '
 	tree=$(git write-tree) &&
-	git update-index frotz &&
+	git update-index frotz nitfol &&
 	test -z "$(git diff-index --name-only $tree)"
 '
 
-test_expect_success SYMLINKS 'diff removed symlink' '
+test_expect_success SYMLINKS 'diff removed symlink and file' '
 	cat >expected <<-\EOF &&
 	diff --git a/frotz b/frotz
 	deleted file mode 120000
@@ -44,22 +52,38 @@ test_expect_success SYMLINKS 'diff removed symlink' '
 	@@ -1 +0,0 @@
 	-xyzzy
 	\ No newline at end of file
+	diff --git a/nitfol b/nitfol
+	deleted file mode 100644
+	index 7c465af..0000000
+	--- a/nitfol
+	+++ /dev/null
+	@@ -1 +0,0 @@
+	-xyzzy
 	EOF
 	mv frotz frotz2 &&
+	mv nitfol nitfol2 &&
 	git diff-index -M -p $tree >current &&
 	compare_diff_patch expected current
 '
 
-test_expect_success SYMLINKS 'diff identical, but newly created symlink' '
+test_expect_success SYMLINKS 'diff identical, but newly created symlink and file' '
 	cat >expected <<-\EOF &&
 	diff --git a/frotz b/frotz
+	diff --git a/nitfol b/nitfol
 	EOF
+	rm -f frotz nitfol &&
+	echo xyzzy >nitfol &&
+	test-chmtime +10 nitfol &&
 	ln -s xyzzy frotz &&
 	git diff-index -M -p $tree >current &&
+	compare_diff_patch expected current &&
+
+	>expected &&
+	git diff-index -M -p -w $tree >current &&
 	compare_diff_patch expected current
 '
 
-test_expect_success SYMLINKS 'diff different symlink' '
+test_expect_success SYMLINKS 'diff different symlink and file' '
 	cat >expected <<-\EOF &&
 	diff --git a/frotz b/frotz
 	index 7c465af..df1db54 120000
@@ -70,9 +94,17 @@ test_expect_success SYMLINKS 'diff different symlink' '
 	\ No newline at end of file
 	+yxyyz
 	\ No newline at end of file
+	diff --git a/nitfol b/nitfol
+	index 7c465af..df1db54 100644
+	--- a/nitfol
+	+++ b/nitfol
+	@@ -1 +1 @@
+	-xyzzy
+	+yxyyz
 	EOF
 	rm -f frotz &&
 	ln -s yxyyz frotz &&
+	echo yxyyz >nitfol &&
 	git diff-index -M -p $tree >current &&
 	compare_diff_patch expected current
 '
-- 
1.7.9.2.350.g74d65

^ permalink raw reply related	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2012-03-01 16:52 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-03-01  2:14 [PATCH 0/4] "diff -p" patch header generation updates Junio C Hamano
2012-03-01  2:14 ` [PATCH 1/4] t4011: modernise style Junio C Hamano
2012-03-01  2:14 ` [PATCH 2/4] t4011: illustrate "diff-index -p" on stat-dirty paths Junio C Hamano
2012-03-01  9:05   ` Thomas Rast
2012-03-01 16:18     ` Junio C Hamano
2012-03-01 16:52     ` [PATCH 2/4 v2] " Junio C Hamano
2012-03-01 10:05   ` [PATCH 2/4] " Zbigniew Jędrzejewski-Szmek
2012-03-01 16:10     ` Junio C Hamano
2012-03-01  2:14 ` [PATCH 3/4] diff -p: squelch "diff --git" header for " Junio C Hamano
2012-03-01  2:14 ` [PATCH 4/4] diff --ignore-mode-change Junio C Hamano

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).