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

[PATCH v4 4/8] diff: Filter files that have changed only due to conversion changes.

From
Henrik Grubbström (Grubba) <grubba@grubba.org>
Date
Apr 6, 2010, 12:46 UTC
Message-ID
<3daab2593b3f83971c6da6cfcd3d56046c84477a.1270554878.git.grubba@grubba.org>
In-Reply-To
<cover.1270554878.git.grubba@grubba.org>

When the conversion filter for a file is changed, files may get listed as modified even though the user has not made any changes to them. This patch adds a configuration option 'core.refilterOnDiff', which performs an extra renormalization pass to filter out such files.

Signed-off-by: Henrik Grubbström <grubba@grubba.org>
---
The typical reason to enable this option is when you have lots of files
that have been affected by a configuration change (eg crlf convention
or ident expansion), but don't want to recommit the otherwise unchanged
files just to get them on canonic form in the repository.
 Documentation/config.txt |    6 ++++++
 cache.h                  |    1 +
 config.c                 |    5 +++++
 diff.c                   |   42 ++++++++++++++++++++++++++++++++++++++++++
 environment.c            |    1 +
 t/t0021-conversion.sh    |   25 +++++++++++++++++++++++++
 6 files changed, 80 insertions(+), 0 deletions(-)
diff --git a/Documentation/config.txt b/Documentation/config.txt
index 06b2f82..4eb3ab3 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -535,6 +535,12 @@ core.sparseCheckout::
 	Enable "sparse checkout" feature. See section "Sparse checkout" in
 	linkgit:git-read-tree[1] for more information.
 
+core.refilterOnDiff::
+	Enable "refilter on diff" feature. This causes source files that
+	have only changed from the committed version as a side effect of
+	a conversion filter change to be filtered from the output of eg
+	linkgit:git-status[1] and linkgit:git-diff[1].
+
 add.ignore-errors::
 	Tells 'git add' to continue adding files when some files cannot be
 	added due to indexing errors. Equivalent to the '--ignore-errors'
diff --git a/cache.h b/cache.h
index 6dcb100..cd2bca4 100644
--- a/cache.h
+++ b/cache.h
@@ -552,6 +552,7 @@ extern int read_replace_refs;
 extern int fsync_object_files;
 extern int core_preload_index;
 extern int core_apply_sparse_checkout;
+extern int core_refilter_on_diff;
 
 enum safe_crlf {
 	SAFE_CRLF_FALSE = 0,
diff --git a/config.c b/config.c
index 6963fbe..4954797 100644
--- a/config.c
+++ b/config.c
@@ -523,6 +523,11 @@ static int git_default_core_config(const char *var, const char *value)
 		return 0;
 	}
 
+	if(!strcmp(var, "core.refilterondiff")) {
+		core_refilter_on_diff = git_config_bool(var, value);
+		return 0;
+	}
+
 	/* Add other config variables here and to Documentation/config.txt. */
 	return 0;
 }
diff --git a/diff.c b/diff.c
index 2daa732..b2d8e6d 100644
--- a/diff.c
+++ b/diff.c
@@ -8,6 +8,8 @@
 #include "delta.h"
 #include "xdiff-interface.h"
 #include "color.h"
+#include "cache.h"
+#include "object.h"
 #include "attr.h"
 #include "run-command.h"
 #include "utf8.h"
@@ -3097,6 +3099,46 @@ int diff_unmodified_pair(struct diff_filepair *p)
 		return 1; /* no change */
 	if (!one->sha1_valid && !two->sha1_valid)
 		return 1; /* both look at the same file on the filesystem. */
+	if (one->dirty_submodule || two->dirty_submodule)
+		return 0; /* Known to differ. */
+	/* The hashes differ, but this might be due to either of them
+	 * not having been normalized (eg due to later .gitattributes
+	 * changes.
+	 */
+	if (core_refilter_on_diff) {
+		unsigned char one_sha1_norm[20];
+		unsigned char two_sha1_norm[20];
+		struct strbuf nbuf = STRBUF_INIT;
+		unsigned long buflen = 0;
+		void *buf;
+
+		diff_fill_sha1_info(one);
+		diff_fill_sha1_info(two);
+		memcpy(one_sha1_norm, one->sha1, 20);
+		memcpy(two_sha1_norm, two->sha1, 20);
+
+		buf = read_object_with_reference(one->sha1, typename(OBJ_BLOB),
+						 &buflen, one_sha1_norm);
+		if (buf && convert_to_git(one->path, buf, buflen,
+					  &nbuf, safe_crlf))
+			hash_sha1_file(nbuf.buf, nbuf.len,
+				       typename(OBJ_BLOB), one_sha1_norm);
+		if (buf)
+			free(buf);
+
+		buf = read_object_with_reference(two->sha1, typename(OBJ_BLOB),
+						 &buflen, two_sha1_norm);
+		if (buf && convert_to_git(two->path, buf, buflen,
+					  &nbuf, safe_crlf))
+			hash_sha1_file(nbuf.buf, nbuf.len,
+				       typename(OBJ_BLOB), two_sha1_norm);
+		if (buf)
+			free(buf);
+
+		strbuf_release(&nbuf);
+		if (!hashcmp(one_sha1_norm, two_sha1_norm))
+			return 1; /* Same hash after normalization. */
+	}
 	return 0;
 }
 
diff --git a/environment.c b/environment.c
index 876c5e5..1b52bed 100644
--- a/environment.c
+++ b/environment.c
@@ -52,6 +52,7 @@ enum object_creation_mode object_creation_mode = OBJECT_CREATION_MODE;
 char *notes_ref_name;
 int grafts_replace_parents = 1;
 int core_apply_sparse_checkout;
+int core_refilter_on_diff;
 
 /* Parallel index stat data preload? */
 int core_preload_index = 0;
diff --git a/t/t0021-conversion.sh b/t/t0021-conversion.sh
index 828e35b..48ae8bb 100755
--- a/t/t0021-conversion.sh
+++ b/t/t0021-conversion.sh
@@ -93,4 +93,29 @@ test_expect_success expanded_in_repo '
 	cmp expanded-keywords expected-output
 '
 
+# Check that files containing keywords with proper markup aren't marked
+# as modified on checkout when core.refilterOnDiff is set.
+test_expect_success keywords_not_modified '
+	{
+		echo "File with foreign keywords"
+		echo "\$Id\$"
+		echo "\$Id: NoTerminatingSymbol"
+		echo "\$Id: Foreign Commit With Spaces \$"
+		echo "\$Id: GitCommitId \$"
+		echo "\$Id: NoTerminatingSymbolAtEOF"
+	} > expanded-keywords2 &&
+
+	git add expanded-keywords2 &&
+	git commit -m "File with keywords expanded" &&
+
+	echo "expanded-keywords2 ident" >> .gitattributes &&
+
+	rm -f expanded-keywords2 &&
+	git checkout -- expanded-keywords2 &&
+	test "x`git status --porcelain -- expanded-keywords2`" = \
+             "x M expanded-keywords2" &&
+	git config --add core.refilterondiff true &&
+	test "x`git status --porcelain -- expanded-keywords2`" = x
+'
+
 test_done
-- 
1.7.0.3.316.g33b5e
Previous: Junio C HamanoNext: Junio C Hamano
Message 8 of 14 in “Attribute and conversion patches”
  1. 0/8 Attribute and conversion patchesHenrik Grubbström (Grubba), Apr 6, 2010
  2. 1/8 convert: Safer handling of $Id$ contraction.Henrik Grubbström (Grubba), Apr 6, 2010
  3. 2/8 convert: Keep foreign $Id$ on checkout.Henrik Grubbström (Grubba), Apr 6, 2010
  4. 3/8 status: Added missing calls to diff_unmodified_pair() in format_callbacks.Henrik Grubbström (Grubba), Apr 6, 2010
  5. Junio C HamanoApr 10, 2010
  6. Henrik GrubbströmApr 12, 2010
  7. Junio C HamanoApr 10, 2010
  8. 4/8 diff: Filter files that have changed only due to conversion changes.Henrik Grubbström (Grubba), Apr 6, 2010
  9. Junio C HamanoApr 10, 2010
  10. Henrik GrubbströmApr 16, 2010
  11. 5/8 convert: Added core.refilteronadd feature.Henrik Grubbström (Grubba), Apr 6, 2010
  12. 6/8 attr: Fixed debug output for macro expansion.Henrik Grubbström (Grubba), Apr 6, 2010
  13. 7/8 attr: Allow multiple changes to an attribute on the same line.Henrik Grubbström (Grubba), Apr 6, 2010
  14. 8/8 attr: Expand macros immediately when encountered.Henrik Grubbström (Grubba), Apr 6, 2010

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.