{"thread":{"id":"23356","subject":"[PATCH v4 3/8] status: Added missing calls to diff_unmodified_pair() in format_callbacks.","startedAt":"2010-04-06T12:46:36Z","lastAt":"2010-04-16T15:30:16Z","messageCount":14,"participants":["Henrik Grubbström (Grubba)","Junio C Hamano","Henrik Grubbström"],"isPatch":true,"patchVersion":4,"patchTotal":8},"messages":[{"id":"138747","messageId":"cover.1270554878.git.grubba@grubba.org","threadId":"23356","inReplyTo":null,"subject":"[PATCH v4 0/8] Attribute and conversion patches","fromName":"Henrik Grubbström (Grubba)","fromEmail":"grubba@grubba.org","sentAt":"2010-04-06T12:46:36Z","receivedAt":"2010-04-06T12:46:36Z","isPatch":true,"sender":{"key":"grubba@grubba.org","avatar":"https://avatars.githubusercontent.com/u/1169458?v=4"},"body":"These are some patches that are needed to get the support for\nattributes and especially the 'ident' attribute to a useable\nstate.\n\nSince last time the 'ident'-specific patch \"Inhibit contraction of\nforeign $Id$ during stats.\" is gone, and replaced with the generic\n\"Filter files that have changed only due to conversion changes.\".\n\nHenrik Grubbström (Grubba) (8):\n  convert: Safer handling of $Id$ contraction.\n  convert: Keep foreign $Id$ on checkout.\n  status: Added missing calls to diff_unmodified_pair() in\n    format_callbacks.\n  diff: Filter files that have changed only due to conversion changes.\n  convert: Added core.refilteronadd feature.\n  attr: Fixed debug output for macro expansion.\n  attr: Allow multiple changes to an attribute on the same line.\n  attr: Expand macros immediately when encountered.\n\n Documentation/config.txt |   12 +++++++\n attr.c                   |   38 ++++++++++++++--------\n cache.h                  |    2 +\n config.c                 |   10 ++++++\n convert.c                |   28 ++++++++++++++++-\n diff.c                   |   42 +++++++++++++++++++++++++\n environment.c            |    2 +\n sha1_file.c              |   57 ++++++++++++++++++++++++++++++++++\n t/t0003-attributes.sh    |   15 +++++++++\n t/t0021-conversion.sh    |   76 ++++++++++++++++++++++++++++++++++++++++++----\n wt-status.c              |    4 ++\n 11 files changed, 264 insertions(+), 22 deletions(-)\n"},{"id":"138749","messageId":"e310bd4e1f1c797cc286044a4dbee0f12c1c90a0.1270554878.git.grubba@grubba.org","threadId":"23356","inReplyTo":"cover.1270554878.git.grubba@grubba.org","subject":"[PATCH v4 1/8] convert: Safer handling of $Id$ contraction.","fromName":"Henrik Grubbström (Grubba)","fromEmail":"grubba@grubba.org","sentAt":"2010-04-06T12:46:37Z","receivedAt":"2010-04-06T12:46:37Z","isPatch":true,"sender":{"key":"grubba@grubba.org","avatar":"https://avatars.githubusercontent.com/u/1169458?v=4"},"body":"The code to contract $Id:xxxxx$ strings could eat an arbitrary amount\nof source text if the terminating $ was lost. It now refuses to\ncontract $Id:xxxxx$ strings spanning multiple lines.\n\nSigned-off-by: Henrik Grubbström <grubba@grubba.org>\n---\nThe behaviour implemented by the patch is in line with what other\nVCSes that implement $Id$ do.\n\n convert.c             |   12 ++++++++++++\n t/t0021-conversion.sh |   16 ++++++++++------\n 2 files changed, 22 insertions(+), 6 deletions(-)\n\ndiff --git a/convert.c b/convert.c\nindex 4f8fcb7..239fa0a 100644\n--- a/convert.c\n+++ b/convert.c\n@@ -425,6 +425,8 @@ static int count_ident(const char *cp, unsigned long size)\n \t\t\t\tcnt++;\n \t\t\t\tbreak;\n \t\t\t}\n+\t\t\tif (ch == '\\n')\n+\t\t\t\tbreak;\n \t\t}\n \t}\n \treturn cnt;\n@@ -455,6 +457,11 @@ static int ident_to_git(const char *path, const char *src, size_t len,\n \t\t\tdollar = memchr(src + 3, '$', len - 3);\n \t\t\tif (!dollar)\n \t\t\t\tbreak;\n+\t\t\tif (memchr(src + 3, '\\n', dollar - src - 3)) {\n+\t\t\t\t/* Line break before the next dollar. */\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\n \t\t\tmemcpy(dst, \"Id$\", 3);\n \t\t\tdst += 3;\n \t\t\tlen -= dollar + 1 - src;\n@@ -514,6 +521,11 @@ static int ident_to_worktree(const char *path, const char *src, size_t len,\n \t\t\t\tbreak;\n \t\t\t}\n \n+\t\t\tif (memchr(src + 3, '\\n', dollar - src - 3)) {\n+\t\t\t\t/* Line break before the next dollar. */\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\n \t\t\tlen -= dollar + 1 - src;\n \t\t\tsrc  = dollar + 1;\n \t\t} else {\ndiff --git a/t/t0021-conversion.sh b/t/t0021-conversion.sh\nindex 6cb8d60..29438c5 100755\n--- a/t/t0021-conversion.sh\n+++ b/t/t0021-conversion.sh\n@@ -65,17 +65,21 @@ test_expect_success expanded_in_repo '\n \t\techo \"\\$Id:NoSpaceAtFront \\$\"\n \t\techo \"\\$Id:NoSpaceAtEitherEnd\\$\"\n \t\techo \"\\$Id: NoTerminatingSymbol\"\n+\t\techo \"\\$Id: Foreign Commit With Spaces \\$\"\n+\t\techo \"\\$Id: NoTerminatingSymbolAtEOF\"\n \t} > expanded-keywords &&\n \n \t{\n \t\techo \"File with expanded keywords\"\n-\t\techo \"\\$Id: 4f21723e7b15065df7de95bd46c8ba6fb1818f4c \\$\"\n-\t\techo \"\\$Id: 4f21723e7b15065df7de95bd46c8ba6fb1818f4c \\$\"\n-\t\techo \"\\$Id: 4f21723e7b15065df7de95bd46c8ba6fb1818f4c \\$\"\n-\t\techo \"\\$Id: 4f21723e7b15065df7de95bd46c8ba6fb1818f4c \\$\"\n-\t\techo \"\\$Id: 4f21723e7b15065df7de95bd46c8ba6fb1818f4c \\$\"\n-\t\techo \"\\$Id: 4f21723e7b15065df7de95bd46c8ba6fb1818f4c \\$\"\n+\t\techo \"\\$Id: fd0478f5f1486f3d5177d4c3f6eb2765e8fc56b9 \\$\"\n+\t\techo \"\\$Id: fd0478f5f1486f3d5177d4c3f6eb2765e8fc56b9 \\$\"\n+\t\techo \"\\$Id: fd0478f5f1486f3d5177d4c3f6eb2765e8fc56b9 \\$\"\n+\t\techo \"\\$Id: fd0478f5f1486f3d5177d4c3f6eb2765e8fc56b9 \\$\"\n+\t\techo \"\\$Id: fd0478f5f1486f3d5177d4c3f6eb2765e8fc56b9 \\$\"\n+\t\techo \"\\$Id: fd0478f5f1486f3d5177d4c3f6eb2765e8fc56b9 \\$\"\n \t\techo \"\\$Id: NoTerminatingSymbol\"\n+\t\techo \"\\$Id: fd0478f5f1486f3d5177d4c3f6eb2765e8fc56b9 \\$\"\n+\t\techo \"\\$Id: NoTerminatingSymbolAtEOF\"\n \t} > expected-output &&\n \n \tgit add expanded-keywords &&\n-- \n1.7.0.3.316.g33b5e\n"},{"id":"138743","messageId":"946653ea904dfd6d1770f350018697e75a02fb14.1270554878.git.grubba@grubba.org","threadId":"23356","inReplyTo":"cover.1270554878.git.grubba@grubba.org","subject":"[PATCH v4 2/8] convert: Keep foreign $Id$ on checkout.","fromName":"Henrik Grubbström (Grubba)","fromEmail":"grubba@grubba.org","sentAt":"2010-04-06T12:46:38Z","receivedAt":"2010-04-06T12:46:38Z","isPatch":true,"sender":{"key":"grubba@grubba.org","avatar":"https://avatars.githubusercontent.com/u/1169458?v=4"},"body":"If there are foreign $Id$ keywords in the repository, they are most\nlikely there for a reason. Let's keep them on checkout (which is also\nwhat the documentation indicates). Foreign $Id$ keywords are now\nrecognized by there being multiple space separated fields in $Id:xxxxx$.\n\nSigned-off-by: Henrik Grubbström <grubba@grubba.org>\n---\nThe typical use case is for repositories that have been converted\nfrom some other VCS, where it is desirable to keep the old identifiers\naround until there's some other reason to alter the file.\n\nNote that the comment about expanded Ids in the repository\nis obsoleted by the core.refilterOnDiff patch.\n\n convert.c             |   16 ++++++++++++++--\n t/t0021-conversion.sh |    2 +-\n 2 files changed, 15 insertions(+), 3 deletions(-)\n\ndiff --git a/convert.c b/convert.c\nindex 239fa0a..5a0b7fb 100644\n--- a/convert.c\n+++ b/convert.c\n@@ -477,7 +477,7 @@ static int ident_to_worktree(const char *path, const char *src, size_t len,\n                              struct strbuf *buf, int ident)\n {\n \tunsigned char sha1[20];\n-\tchar *to_free = NULL, *dollar;\n+\tchar *to_free = NULL, *dollar, *spc;\n \tint cnt;\n \n \tif (!ident)\n@@ -513,7 +513,10 @@ static int ident_to_worktree(const char *path, const char *src, size_t len,\n \t\t} else if (src[2] == ':') {\n \t\t\t/*\n \t\t\t * It's possible that an expanded Id has crept its way into the\n-\t\t\t * repository, we cope with that by stripping the expansion out\n+\t\t\t * repository, we cope with that by stripping the expansion out.\n+\t\t\t * This is probably not a good idea, since it will cause changes\n+\t\t\t * on checkout, which won't go away by stash, but let's keep it\n+\t\t\t * for git-style ids.\n \t\t\t */\n \t\t\tdollar = memchr(src + 3, '$', len - 3);\n \t\t\tif (!dollar) {\n@@ -526,6 +529,15 @@ static int ident_to_worktree(const char *path, const char *src, size_t len,\n \t\t\t\tcontinue;\n \t\t\t}\n \n+\t\t\tspc = memchr(src + 4, ' ', dollar - src - 4);\n+\t\t\tif (spc && spc < dollar-1) {\n+\t\t\t\t/* There are spaces in unexpected places.\n+\t\t\t\t * This is probably an id from some other\n+\t\t\t\t * versioning system. Keep it for now.\n+\t\t\t\t */\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\n \t\t\tlen -= dollar + 1 - src;\n \t\t\tsrc  = dollar + 1;\n \t\t} else {\ndiff --git a/t/t0021-conversion.sh b/t/t0021-conversion.sh\nindex 29438c5..828e35b 100755\n--- a/t/t0021-conversion.sh\n+++ b/t/t0021-conversion.sh\n@@ -78,7 +78,7 @@ test_expect_success expanded_in_repo '\n \t\techo \"\\$Id: fd0478f5f1486f3d5177d4c3f6eb2765e8fc56b9 \\$\"\n \t\techo \"\\$Id: fd0478f5f1486f3d5177d4c3f6eb2765e8fc56b9 \\$\"\n \t\techo \"\\$Id: NoTerminatingSymbol\"\n-\t\techo \"\\$Id: fd0478f5f1486f3d5177d4c3f6eb2765e8fc56b9 \\$\"\n+\t\techo \"\\$Id: Foreign Commit With Spaces \\$\"\n \t\techo \"\\$Id: NoTerminatingSymbolAtEOF\"\n \t} > expected-output &&\n \n-- \n1.7.0.3.316.g33b5e\n"},{"id":"138741","messageId":"5962221bef558d15183c9937863b38bc7ca41339.1270554878.git.grubba@grubba.org","threadId":"23356","inReplyTo":"cover.1270554878.git.grubba@grubba.org","subject":"[PATCH v4 3/8] status: Added missing calls to diff_unmodified_pair() in format_callbacks.","fromName":"Henrik Grubbström (Grubba)","fromEmail":"grubba@grubba.org","sentAt":"2010-04-06T12:46:39Z","receivedAt":"2010-04-06T12:46:39Z","isPatch":true,"sender":{"key":"grubba@grubba.org","avatar":"https://avatars.githubusercontent.com/u/1169458?v=4"},"body":"The diff_queue_struct provided by diff_flush() is raw, and needs to be\nfiltered through diff_unmodified_pair() before being used.\nThis is already done by most of the other functions operating on\ndiff_queue_struct called by diff_flush().\n\nSigned-off-by: Henrik Grubbström <grubba@grubba.org>\n---\nFor diff_modified_pair() to be able to do its job, it needs\nto be called...\n\n wt-status.c |    4 ++++\n 1 files changed, 4 insertions(+), 0 deletions(-)\n\ndiff --git a/wt-status.c b/wt-status.c\nindex 8ca59a2..e661225 100644\n--- a/wt-status.c\n+++ b/wt-status.c\n@@ -229,6 +229,8 @@ static void wt_status_collect_changed_cb(struct diff_queue_struct *q,\n \t\tstruct wt_status_change_data *d;\n \n \t\tp = q->queue[i];\n+\t\tif (diff_unmodified_pair(p))\n+\t\t\tcontinue;\n \t\tit = string_list_insert(p->one->path, &s->change);\n \t\td = it->util;\n \t\tif (!d) {\n@@ -276,6 +278,8 @@ static void wt_status_collect_updated_cb(struct diff_queue_struct *q,\n \t\tstruct wt_status_change_data *d;\n \n \t\tp = q->queue[i];\n+\t\tif (diff_unmodified_pair(p))\n+\t\t\tcontinue;\n \t\tit = string_list_insert(p->two->path, &s->change);\n \t\td = it->util;\n \t\tif (!d) {\n-- \n1.7.0.3.316.g33b5e\n"},{"id":"138744","messageId":"3daab2593b3f83971c6da6cfcd3d56046c84477a.1270554878.git.grubba@grubba.org","threadId":"23356","inReplyTo":"cover.1270554878.git.grubba@grubba.org","subject":"[PATCH v4 4/8] diff: Filter files that have changed only due to conversion changes.","fromName":"Henrik Grubbström (Grubba)","fromEmail":"grubba@grubba.org","sentAt":"2010-04-06T12:46:40Z","receivedAt":"2010-04-06T12:46:40Z","isPatch":true,"sender":{"key":"grubba@grubba.org","avatar":"https://avatars.githubusercontent.com/u/1169458?v=4"},"body":"When the conversion filter for a file is changed, files may get listed\nas modified even though the user has not made any changes to them.\nThis patch adds a configuration option 'core.refilterOnDiff', which\nperforms an extra renormalization pass to filter out such files.\n\nSigned-off-by: Henrik Grubbström <grubba@grubba.org>\n---\nThe typical reason to enable this option is when you have lots of files\nthat have been affected by a configuration change (eg crlf convention\nor ident expansion), but don't want to recommit the otherwise unchanged\nfiles just to get them on canonic form in the repository.\n\n Documentation/config.txt |    6 ++++++\n cache.h                  |    1 +\n config.c                 |    5 +++++\n diff.c                   |   42 ++++++++++++++++++++++++++++++++++++++++++\n environment.c            |    1 +\n t/t0021-conversion.sh    |   25 +++++++++++++++++++++++++\n 6 files changed, 80 insertions(+), 0 deletions(-)\n\ndiff --git a/Documentation/config.txt b/Documentation/config.txt\nindex 06b2f82..4eb3ab3 100644\n--- a/Documentation/config.txt\n+++ b/Documentation/config.txt\n@@ -535,6 +535,12 @@ core.sparseCheckout::\n \tEnable \"sparse checkout\" feature. See section \"Sparse checkout\" in\n \tlinkgit:git-read-tree[1] for more information.\n \n+core.refilterOnDiff::\n+\tEnable \"refilter on diff\" feature. This causes source files that\n+\thave only changed from the committed version as a side effect of\n+\ta conversion filter change to be filtered from the output of eg\n+\tlinkgit:git-status[1] and linkgit:git-diff[1].\n+\n add.ignore-errors::\n \tTells 'git add' to continue adding files when some files cannot be\n \tadded due to indexing errors. Equivalent to the '--ignore-errors'\ndiff --git a/cache.h b/cache.h\nindex 6dcb100..cd2bca4 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -552,6 +552,7 @@ extern int read_replace_refs;\n extern int fsync_object_files;\n extern int core_preload_index;\n extern int core_apply_sparse_checkout;\n+extern int core_refilter_on_diff;\n \n enum safe_crlf {\n \tSAFE_CRLF_FALSE = 0,\ndiff --git a/config.c b/config.c\nindex 6963fbe..4954797 100644\n--- a/config.c\n+++ b/config.c\n@@ -523,6 +523,11 @@ static int git_default_core_config(const char *var, const char *value)\n \t\treturn 0;\n \t}\n \n+\tif(!strcmp(var, \"core.refilterondiff\")) {\n+\t\tcore_refilter_on_diff = git_config_bool(var, value);\n+\t\treturn 0;\n+\t}\n+\n \t/* Add other config variables here and to Documentation/config.txt. */\n \treturn 0;\n }\ndiff --git a/diff.c b/diff.c\nindex 2daa732..b2d8e6d 100644\n--- a/diff.c\n+++ b/diff.c\n@@ -8,6 +8,8 @@\n #include \"delta.h\"\n #include \"xdiff-interface.h\"\n #include \"color.h\"\n+#include \"cache.h\"\n+#include \"object.h\"\n #include \"attr.h\"\n #include \"run-command.h\"\n #include \"utf8.h\"\n@@ -3097,6 +3099,46 @@ int diff_unmodified_pair(struct diff_filepair *p)\n \t\treturn 1; /* no change */\n \tif (!one->sha1_valid && !two->sha1_valid)\n \t\treturn 1; /* both look at the same file on the filesystem. */\n+\tif (one->dirty_submodule || two->dirty_submodule)\n+\t\treturn 0; /* Known to differ. */\n+\t/* The hashes differ, but this might be due to either of them\n+\t * not having been normalized (eg due to later .gitattributes\n+\t * changes.\n+\t */\n+\tif (core_refilter_on_diff) {\n+\t\tunsigned char one_sha1_norm[20];\n+\t\tunsigned char two_sha1_norm[20];\n+\t\tstruct strbuf nbuf = STRBUF_INIT;\n+\t\tunsigned long buflen = 0;\n+\t\tvoid *buf;\n+\n+\t\tdiff_fill_sha1_info(one);\n+\t\tdiff_fill_sha1_info(two);\n+\t\tmemcpy(one_sha1_norm, one->sha1, 20);\n+\t\tmemcpy(two_sha1_norm, two->sha1, 20);\n+\n+\t\tbuf = read_object_with_reference(one->sha1, typename(OBJ_BLOB),\n+\t\t\t\t\t\t &buflen, one_sha1_norm);\n+\t\tif (buf && convert_to_git(one->path, buf, buflen,\n+\t\t\t\t\t  &nbuf, safe_crlf))\n+\t\t\thash_sha1_file(nbuf.buf, nbuf.len,\n+\t\t\t\t       typename(OBJ_BLOB), one_sha1_norm);\n+\t\tif (buf)\n+\t\t\tfree(buf);\n+\n+\t\tbuf = read_object_with_reference(two->sha1, typename(OBJ_BLOB),\n+\t\t\t\t\t\t &buflen, two_sha1_norm);\n+\t\tif (buf && convert_to_git(two->path, buf, buflen,\n+\t\t\t\t\t  &nbuf, safe_crlf))\n+\t\t\thash_sha1_file(nbuf.buf, nbuf.len,\n+\t\t\t\t       typename(OBJ_BLOB), two_sha1_norm);\n+\t\tif (buf)\n+\t\t\tfree(buf);\n+\n+\t\tstrbuf_release(&nbuf);\n+\t\tif (!hashcmp(one_sha1_norm, two_sha1_norm))\n+\t\t\treturn 1; /* Same hash after normalization. */\n+\t}\n \treturn 0;\n }\n \ndiff --git a/environment.c b/environment.c\nindex 876c5e5..1b52bed 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -52,6 +52,7 @@ enum object_creation_mode object_creation_mode = OBJECT_CREATION_MODE;\n char *notes_ref_name;\n int grafts_replace_parents = 1;\n int core_apply_sparse_checkout;\n+int core_refilter_on_diff;\n \n /* Parallel index stat data preload? */\n int core_preload_index = 0;\ndiff --git a/t/t0021-conversion.sh b/t/t0021-conversion.sh\nindex 828e35b..48ae8bb 100755\n--- a/t/t0021-conversion.sh\n+++ b/t/t0021-conversion.sh\n@@ -93,4 +93,29 @@ test_expect_success expanded_in_repo '\n \tcmp expanded-keywords expected-output\n '\n \n+# Check that files containing keywords with proper markup aren't marked\n+# as modified on checkout when core.refilterOnDiff is set.\n+test_expect_success keywords_not_modified '\n+\t{\n+\t\techo \"File with foreign keywords\"\n+\t\techo \"\\$Id\\$\"\n+\t\techo \"\\$Id: NoTerminatingSymbol\"\n+\t\techo \"\\$Id: Foreign Commit With Spaces \\$\"\n+\t\techo \"\\$Id: GitCommitId \\$\"\n+\t\techo \"\\$Id: NoTerminatingSymbolAtEOF\"\n+\t} > expanded-keywords2 &&\n+\n+\tgit add expanded-keywords2 &&\n+\tgit commit -m \"File with keywords expanded\" &&\n+\n+\techo \"expanded-keywords2 ident\" >> .gitattributes &&\n+\n+\trm -f expanded-keywords2 &&\n+\tgit checkout -- expanded-keywords2 &&\n+\ttest \"x`git status --porcelain -- expanded-keywords2`\" = \\\n+             \"x M expanded-keywords2\" &&\n+\tgit config --add core.refilterondiff true &&\n+\ttest \"x`git status --porcelain -- expanded-keywords2`\" = x\n+'\n+\n test_done\n-- \n1.7.0.3.316.g33b5e\n"},{"id":"138746","messageId":"748069c7f90d80cc881d4be495b138f4f16a94f2.1270554878.git.grubba@grubba.org","threadId":"23356","inReplyTo":"cover.1270554878.git.grubba@grubba.org","subject":"[PATCH v4 5/8] convert: Added core.refilteronadd feature.","fromName":"Henrik Grubbström (Grubba)","fromEmail":"grubba@grubba.org","sentAt":"2010-04-06T12:46:41Z","receivedAt":"2010-04-06T12:46:41Z","isPatch":true,"sender":{"key":"grubba@grubba.org","avatar":"https://avatars.githubusercontent.com/u/1169458?v=4"},"body":"When having $Id$ tags in other versioning systems, it is customary\nto recalculate the tags in the source on commit or equvivalent.\nThis commit adds a configuration option to git that causes source\nfiles to pass through a conversion roundtrip when added to the index.\n\nSigned-off-by: Henrik Grubbström <grubba@grubba.org>\n---\n Documentation/config.txt |    6 +++++\n cache.h                  |    1 +\n config.c                 |    5 ++++\n environment.c            |    1 +\n sha1_file.c              |   57 ++++++++++++++++++++++++++++++++++++++++++++++\n t/t0021-conversion.sh    |   35 ++++++++++++++++++++++++++++\n 6 files changed, 105 insertions(+), 0 deletions(-)\n\ndiff --git a/Documentation/config.txt b/Documentation/config.txt\nindex 4eb3ab3..5225047 100644\n--- a/Documentation/config.txt\n+++ b/Documentation/config.txt\n@@ -535,6 +535,12 @@ core.sparseCheckout::\n \tEnable \"sparse checkout\" feature. See section \"Sparse checkout\" in\n \tlinkgit:git-read-tree[1] for more information.\n \n+core.refilterOnAdd::\n+\tEnable \"refilter on add\" feature. This causes source files to be\n+\tbehave as if they were checked out after a linkgit:git-add[1].\n+\tThis is typically usefull if eg the `ident` attribute is active,\n+\tin which case the $Id$ tags will be updated.\n+\n core.refilterOnDiff::\n \tEnable \"refilter on diff\" feature. This causes source files that\n \thave only changed from the committed version as a side effect of\ndiff --git a/cache.h b/cache.h\nindex cd2bca4..1bd8484 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -552,6 +552,7 @@ extern int read_replace_refs;\n extern int fsync_object_files;\n extern int core_preload_index;\n extern int core_apply_sparse_checkout;\n+extern int core_refilter_on_add;\n extern int core_refilter_on_diff;\n \n enum safe_crlf {\ndiff --git a/config.c b/config.c\nindex 4954797..d284897 100644\n--- a/config.c\n+++ b/config.c\n@@ -523,6 +523,11 @@ static int git_default_core_config(const char *var, const char *value)\n \t\treturn 0;\n \t}\n \n+\tif (!strcmp(var, \"core.refilteronadd\")) {\n+\t\tcore_refilter_on_add = git_config_bool(var, value);\n+\t\treturn 0;\n+\t}\n+\n \tif(!strcmp(var, \"core.refilterondiff\")) {\n \t\tcore_refilter_on_diff = git_config_bool(var, value);\n \t\treturn 0;\ndiff --git a/environment.c b/environment.c\nindex 1b52bed..4b4c966 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -52,6 +52,7 @@ enum object_creation_mode object_creation_mode = OBJECT_CREATION_MODE;\n char *notes_ref_name;\n int grafts_replace_parents = 1;\n int core_apply_sparse_checkout;\n+int core_refilter_on_add;\n int core_refilter_on_diff;\n \n /* Parallel index stat data preload? */\ndiff --git a/sha1_file.c b/sha1_file.c\nindex a08a9d0..2aa800e 100644\n--- a/sha1_file.c\n+++ b/sha1_file.c\n@@ -2466,6 +2466,54 @@ int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object,\n \treturn ret;\n }\n \n+static int refilter_fd(int fd, struct stat *st, const char *path)\n+{\n+\tint ret = -1;\n+\tsize_t size = xsize_t(st->st_size);\n+\tstruct strbuf gbuf = STRBUF_INIT;\n+\n+\tif (!S_ISREG(st->st_mode)) {\n+\t\tstruct strbuf sbuf = STRBUF_INIT;\n+\t\tif (strbuf_read(&sbuf, fd, 4096) >= 0)\n+\t\t\tret = convert_to_git(path, sbuf.buf, sbuf.len, &gbuf, safe_crlf);\n+\t\telse\n+\t\t\tret = -1;\n+\t\tstrbuf_release(&sbuf);\n+\t} else if (size) {\n+\t\tvoid *buf = xmmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);\n+\t\tret = convert_to_git(path, buf, size, &gbuf, safe_crlf);\n+\t\tmunmap(buf, size);\n+\t} else\n+\t\tret = -1;\n+\n+\tif (ret > 0) {\n+\t\t/* Something happened during conversion to git.\n+\t\t * Now convert it back, and save the result.\n+\t\t */\n+\t\tstruct strbuf obuf = STRBUF_INIT;\n+\n+\t\tlseek(fd, 0, SEEK_SET);\n+\n+\t\tif (convert_to_working_tree(path, gbuf.buf, gbuf.len, &obuf)) {\n+\t\t\tif (write_or_whine(fd, obuf.buf, obuf.len, path))\n+\t\t\t\tftruncate(fd, obuf.len);\n+\t\t\telse\n+\t\t\t\tret = -1;\n+\t\t} else {\n+\t\t\tif (write_or_whine(fd, gbuf.buf, gbuf.len, path))\n+\t\t\t\tftruncate(fd, gbuf.len);\n+\t\t\telse\n+\t\t\t\tret = -1;\n+\t\t}\n+\n+\t\tstrbuf_release(&obuf);\n+\t}\n+\tstrbuf_release(&gbuf);\n+\n+\tclose(fd);\n+\treturn ret;\n+}\n+\n int index_path(unsigned char *sha1, const char *path, struct stat *st, int write_object)\n {\n \tint fd;\n@@ -2480,6 +2528,15 @@ int index_path(unsigned char *sha1, const char *path, struct stat *st, int write\n \t\tif (index_fd(sha1, fd, st, write_object, OBJ_BLOB, path) < 0)\n \t\t\treturn error(\"%s: failed to insert into database\",\n \t\t\t\t     path);\n+\t\tif (write_object && core_refilter_on_add) {\n+\t\t\tfd = open(path, O_RDWR);\n+\t\t\tif (fd < 0)\n+\t\t\t\treturn error(\"open(\\\"%s\\\"): %s\", path,\n+\t\t\t\t\t     strerror(errno));\n+\t\t\tif (refilter_fd(fd, st, path) < 0)\n+\t\t\t\treturn error(\"%s: failed to refilter file\",\n+\t\t\t\t\t     path);\n+\t\t}\n \t\tbreak;\n \tcase S_IFLNK:\n \t\tif (strbuf_readlink(&sb, path, st->st_size)) {\ndiff --git a/t/t0021-conversion.sh b/t/t0021-conversion.sh\nindex 48ae8bb..9ddbde3 100755\n--- a/t/t0021-conversion.sh\n+++ b/t/t0021-conversion.sh\n@@ -118,4 +118,39 @@ test_expect_success keywords_not_modified '\n \ttest \"x`git status --porcelain -- expanded-keywords2`\" = x\n '\n \n+# Check that keywords are expanded on add when refilter is enabled.\n+test_expect_success expanded_on_add '\n+\tgit config --add core.refilteronadd true\n+\n+\techo \"expanded-keywords3 ident\" >> .gitattributes &&\n+\n+\t{\n+\t\techo \"File with keyword\"\n+\t\techo \"\\$Id\\$\"\n+\t} > expanded-keywords3 &&\n+\n+\t{\n+\t\techo \"File with keyword\"\n+\t\techo \"\\$Id: 0661580d6f976fe7cc1e4512f8db3f2ddb8d93cc \\$\"\n+\t} > expected-output3 &&\n+\n+\tgit add expanded-keywords3 &&\n+\n+\tcat expanded-keywords3 &&\n+\tcmp expanded-keywords3 expected-output3\n+'\n+\n+# Check that keywords are expanded on commit when refilter is enabled.\n+test_expect_success expanded_on_commit '\n+\t{\n+\t\techo \"File with keyword\"\n+\t\techo \"\\$Id\\$\"\n+\t} > expanded-keywords3 &&\n+\n+\tgit commit -m \"File with keyword\" expanded-keywords3 &&\n+\n+\tcat expanded-keywords3 &&\n+\tcmp expanded-keywords3 expected-output3\n+'\n+\n test_done\n-- \n1.7.0.3.316.g33b5e\n"},{"id":"138745","messageId":"11fd448fbc25ce76a1fb2eb52df6e260e34014ad.1270554878.git.grubba@grubba.org","threadId":"23356","inReplyTo":"cover.1270554878.git.grubba@grubba.org","subject":"[PATCH v4 6/8] attr: Fixed debug output for macro expansion.","fromName":"Henrik Grubbström (Grubba)","fromEmail":"grubba@grubba.org","sentAt":"2010-04-06T12:46:42Z","receivedAt":"2010-04-06T12:46:42Z","isPatch":true,"sender":{"key":"grubba@grubba.org","avatar":"https://avatars.githubusercontent.com/u/1169458?v=4"},"body":"When debug_set() was called during macro expansion, it\nreceived a pointer to a struct git_attr rather than a\nstring.\n\nSigned-off-by: Henrik Grubbström <grubba@grubba.org>\n---\n attr.c |    4 +++-\n 1 files changed, 3 insertions(+), 1 deletions(-)\n\ndiff --git a/attr.c b/attr.c\nindex f5346ed..5c6464e 100644\n--- a/attr.c\n+++ b/attr.c\n@@ -605,7 +605,9 @@ static int fill_one(const char *what, struct match_attr *a, int rem)\n \t\tconst char *v = a->state[i].setto;\n \n \t\tif (*n == ATTR__UNKNOWN) {\n-\t\t\tdebug_set(what, a->u.pattern, attr, v);\n+\t\t\tdebug_set(what,\n+\t\t\t\t  a->is_macro?a->u.attr->name:a->u.pattern,\n+\t\t\t\t  attr, v);\n \t\t\t*n = v;\n \t\t\trem--;\n \t\t}\n-- \n1.7.0.3.316.g33b5e\n"},{"id":"138742","messageId":"22e153d1e4258009990f41bd1add1a1d80baff6d.1270554878.git.grubba@grubba.org","threadId":"23356","inReplyTo":"cover.1270554878.git.grubba@grubba.org","subject":"[PATCH v4 7/8] attr: Allow multiple changes to an attribute on the same line.","fromName":"Henrik Grubbström (Grubba)","fromEmail":"grubba@grubba.org","sentAt":"2010-04-06T12:46:43Z","receivedAt":"2010-04-06T12:46:43Z","isPatch":true,"sender":{"key":"grubba@grubba.org","avatar":"https://avatars.githubusercontent.com/u/1169458?v=4"},"body":"When using macros it isn't inconceivable to have an attribute\nbeing set by a macro, and then being reset explicitly.\n\nSigned-off-by: Henrik Grubbström <grubba@grubba.org>\n---\nNB: Currently the tests in the testsuite patch will have the\nopposite meaning, which is probably not what the user expects,\nand is contrary to the documentation.\n\n attr.c                |    2 +-\n t/t0003-attributes.sh |    6 ++++++\n 2 files changed, 7 insertions(+), 1 deletions(-)\n\ndiff --git a/attr.c b/attr.c\nindex 5c6464e..968fb8b 100644\n--- a/attr.c\n+++ b/attr.c\n@@ -599,7 +599,7 @@ static int fill_one(const char *what, struct match_attr *a, int rem)\n \tstruct git_attr_check *check = check_all_attr;\n \tint i;\n \n-\tfor (i = 0; 0 < rem && i < a->num_attr; i++) {\n+\tfor (i = a->num_attr - 1; 0 < rem && 0 <= i; i--) {\n \t\tstruct git_attr *attr = a->state[i].attr;\n \t\tconst char **n = &(check[attr->attr_nr].value);\n \t\tconst char *v = a->state[i].setto;\ndiff --git a/t/t0003-attributes.sh b/t/t0003-attributes.sh\nindex 1c77192..bd9c8de 100755\n--- a/t/t0003-attributes.sh\n+++ b/t/t0003-attributes.sh\n@@ -22,6 +22,8 @@ test_expect_success 'setup' '\n \t(\n \t\techo \"f\ttest=f\"\n \t\techo \"a/i test=a/i\"\n+\t\techo \"onoff test -test\"\n+\t\techo \"offon -test test\"\n \t) >.gitattributes &&\n \t(\n \t\techo \"g test=a/g\" &&\n@@ -44,6 +46,8 @@ test_expect_success 'attribute test' '\n \tattr_check b/g unspecified &&\n \tattr_check a/b/h a/b/h &&\n \tattr_check a/b/d/g \"a/b/d/*\"\n+\tattr_check onoff unset\n+\tattr_check offon set\n \n '\n \n@@ -58,6 +62,8 @@ a/b/g: test: a/b/g\n b/g: test: unspecified\n a/b/h: test: a/b/h\n a/b/d/g: test: a/b/d/*\n+onoff: test: unset\n+offon: test: set\n EOF\n \n \tsed -e \"s/:.*//\" < expect | git check-attr --stdin test > actual &&\n-- \n1.7.0.3.316.g33b5e\n"},{"id":"138748","messageId":"81e89ac808ac41d2e6914635974fa45564f73279.1270554878.git.grubba@grubba.org","threadId":"23356","inReplyTo":"cover.1270554878.git.grubba@grubba.org","subject":"[PATCH v4 8/8] attr: Expand macros immediately when encountered.","fromName":"Henrik Grubbström (Grubba)","fromEmail":"grubba@grubba.org","sentAt":"2010-04-06T12:46:44Z","receivedAt":"2010-04-06T12:46:44Z","isPatch":true,"sender":{"key":"grubba@grubba.org","avatar":"https://avatars.githubusercontent.com/u/1169458?v=4"},"body":"When using macros it is otherwise hard to know whether an\nattribute set by the macro should override an already set\nattribute. Consider the following .gitattributes file:\n\n[attr]mybinary\tbinary -ident\n*\t\tident\nfoo.bin\t\tmybinary\nbar.bin\t\tmybinary ident\n\nWithout this patch both foo.bin and bar.bin will have\nthe ident attribute set, which is probably not what\nthe user expects. With this patch foo.bin will have an\nunset ident attribute, while bar.bin will have it set.\n\nSigned-off-by: Henrik Grubbström <grubba@grubba.org>\n---\nFYI: The use case I attempted was:\n\n *.c\t\t\tcrlf ident\n [attr]foreign_ident\t-ident block_commit=Remove-foreign_ident-attribute.\n src/version.c\t\tforeign_ident\n\nWhich currently causes src/version.c to have the ident attribute set.\n\n attr.c                |   32 ++++++++++++++++++++------------\n t/t0003-attributes.sh |    9 +++++++++\n 2 files changed, 29 insertions(+), 12 deletions(-)\n\ndiff --git a/attr.c b/attr.c\nindex 968fb8b..f90bb8e 100644\n--- a/attr.c\n+++ b/attr.c\n@@ -594,6 +594,8 @@ static int path_matches(const char *pathname, int pathlen,\n \treturn fnmatch(pattern, pathname + baselen, FNM_PATHNAME) == 0;\n }\n \n+static int macroexpand_one(int attr_nr, int rem);\n+\n static int fill_one(const char *what, struct match_attr *a, int rem)\n {\n \tstruct git_attr_check *check = check_all_attr;\n@@ -610,6 +612,7 @@ static int fill_one(const char *what, struct match_attr *a, int rem)\n \t\t\t\t  attr, v);\n \t\t\t*n = v;\n \t\t\trem--;\n+\t\t\trem = macroexpand_one(attr->attr_nr, rem);\n \t\t}\n \t}\n \treturn rem;\n@@ -631,19 +634,27 @@ static int fill(const char *path, int pathlen, struct attr_stack *stk, int rem)\n \treturn rem;\n }\n \n-static int macroexpand(struct attr_stack *stk, int rem)\n+static int macroexpand_one(int attr_nr, int rem)\n {\n+\tstruct attr_stack *stk;\n+\tstruct match_attr *a = NULL;\n \tint i;\n-\tstruct git_attr_check *check = check_all_attr;\n \n-\tfor (i = stk->num_matches - 1; 0 < rem && 0 <= i; i--) {\n-\t\tstruct match_attr *a = stk->attrs[i];\n-\t\tif (!a->is_macro)\n-\t\t\tcontinue;\n-\t\tif (check[a->u.attr->attr_nr].value != ATTR__TRUE)\n-\t\t\tcontinue;\n+\tif (check_all_attr[attr_nr].value != ATTR__TRUE)\n+\t\treturn rem;\n+\n+\tfor (stk = attr_stack; !a && stk; stk = stk->prev)\n+\t\tfor (i = stk->num_matches - 1; !a && 0 <= i; i--) {\n+\t\t\tstruct match_attr *ma = stk->attrs[i];\n+\t\t\tif (!ma->is_macro)\n+\t\t\t\tcontinue;\n+\t\t\tif (ma->u.attr->attr_nr == attr_nr)\n+\t\t\t\ta = ma;\n+\t\t}\n+\n+\tif (a)\n \t\trem = fill_one(\"expand\", a, rem);\n-\t}\n+\n \treturn rem;\n }\n \n@@ -668,9 +679,6 @@ int git_checkattr(const char *path, int num, struct git_attr_check *check)\n \tfor (stk = attr_stack; 0 < rem && stk; stk = stk->prev)\n \t\trem = fill(path, pathlen, stk, rem);\n \n-\tfor (stk = attr_stack; 0 < rem && stk; stk = stk->prev)\n-\t\trem = macroexpand(stk, rem);\n-\n \tfor (i = 0; i < num; i++) {\n \t\tconst char *value = check_all_attr[check[i].attr->attr_nr].value;\n \t\tif (value == ATTR__UNKNOWN)\ndiff --git a/t/t0003-attributes.sh b/t/t0003-attributes.sh\nindex bd9c8de..53bd7fc 100755\n--- a/t/t0003-attributes.sh\n+++ b/t/t0003-attributes.sh\n@@ -20,10 +20,12 @@ test_expect_success 'setup' '\n \n \tmkdir -p a/b/d a/c &&\n \t(\n+\t\techo \"[attr]notest !test\"\n \t\techo \"f\ttest=f\"\n \t\techo \"a/i test=a/i\"\n \t\techo \"onoff test -test\"\n \t\techo \"offon -test test\"\n+\t\techo \"no notest\"\n \t) >.gitattributes &&\n \t(\n \t\techo \"g test=a/g\" &&\n@@ -32,6 +34,7 @@ test_expect_success 'setup' '\n \t(\n \t\techo \"h test=a/b/h\" &&\n \t\techo \"d/* test=a/b/d/*\"\n+\t\techo \"d/yes notest\"\n \t) >a/b/.gitattributes\n \n '\n@@ -48,6 +51,9 @@ test_expect_success 'attribute test' '\n \tattr_check a/b/d/g \"a/b/d/*\"\n \tattr_check onoff unset\n \tattr_check offon set\n+\tattr_check no unspecified\n+\tattr_check a/b/d/no \"a/b/d/*\"\n+\tattr_check a/b/d/yes unspecified\n \n '\n \n@@ -64,6 +70,9 @@ a/b/h: test: a/b/h\n a/b/d/g: test: a/b/d/*\n onoff: test: unset\n offon: test: set\n+no: test: unspecified\n+a/b/d/no: test: a/b/d/*\n+a/b/d/yes: test: unspecified\n EOF\n \n \tsed -e \"s/:.*//\" < expect | git check-attr --stdin test > actual &&\n-- \n1.7.0.3.316.g33b5e\n"},{"id":"139210","messageId":"7vaatbueg5.fsf@alter.siamese.dyndns.org","threadId":"23356","inReplyTo":"5962221bef558d15183c9937863b38bc7ca41339.1270554878.git.grubba@grubba.org","subject":"Re: [PATCH v4 3/8] status: Added missing calls to diff_unmodified_pair() in format_callbacks.","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-04-10T22:31:54Z","receivedAt":"2010-04-10T22:31:54Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Henrik Grubbström (Grubba)\"  <grubba@grubba.org> writes:\n\n> The diff_queue_struct provided by diff_flush() is raw, and needs to be\n> filtered through diff_unmodified_pair() before being used.\n> This is already done by most of the other functions operating on\n> diff_queue_struct called by diff_flush().\n\nThat is true but only if you are letting the diff front-end to feed\nunmodified pairs to begin with, e.g. --find-copies-harder.  I don't think\nthe internal caller in wt-status does that.\n\nI don't think the patch is wrong nor it would hurt, but I am puzzled why\nyou needed this patch.\n\n>  wt-status.c |    4 ++++\n>  1 files changed, 4 insertions(+), 0 deletions(-)\n"},{"id":"139211","messageId":"7v39z3uefq.fsf@alter.siamese.dyndns.org","threadId":"23356","inReplyTo":"5962221bef558d15183c9937863b38bc7ca41339.1270554878.git.grubba@grubba.org","subject":"Re: [PATCH v4 3/8] status: Added missing calls to diff_unmodified_pair() in format_callbacks.","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-04-10T22:32:09Z","receivedAt":"2010-04-10T22:32:09Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Henrik Grubbström (Grubba)\"  <grubba@grubba.org> writes:\n\n> The diff_queue_struct provided by diff_flush() is raw, and needs to be\n> filtered through diff_unmodified_pair() before being used.\n> This is already done by most of the other functions operating on\n> diff_queue_struct called by diff_flush().\n\nThat is true but only if you are letting the diff front-end to feed\nunmodified pairs to begin with, e.g. --find-copies-harder.  I don't think\nthe internal caller in wt-status does that.\n\nI don't think the patch is wrong nor it would hurt, but I am puzzled why\nyou needed this patch.\n\n>  wt-status.c |    4 ++++\n>  1 files changed, 4 insertions(+), 0 deletions(-)\n"},{"id":"139213","messageId":"7vvdbzszmi.fsf@alter.siamese.dyndns.org","threadId":"23356","inReplyTo":"3daab2593b3f83971c6da6cfcd3d56046c84477a.1270554878.git.grubba@grubba.org","subject":"Re: [PATCH v4 4/8] diff: Filter files that have changed only due to conversion changes.","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-04-10T22:37:25Z","receivedAt":"2010-04-10T22:37:25Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Henrik Grubbström (Grubba)\"  <grubba@grubba.org> writes:\n\n> When the conversion filter for a file is changed, files may get listed\n> as modified even though the user has not made any changes to them.\n> This patch adds a configuration option 'core.refilterOnDiff', which\n> performs an extra renormalization pass to filter out such files.\n>\n> Signed-off-by: Henrik Grubbström <grubba@grubba.org>\n\nDoes this really have to be done for every invocation of diff?\n\nIt is a problem worthy of a clean solution that changing the filtering\noptions makes files that are not really different (from the end user's\npoint of view).\n\nBut the problem feels very similar to the issue that touching the inode\ninformation would make the cached stat information in the index invalid\nand plumbing commands such as \"diff-files\" would report phantom changes.\n\nAnd the way we solve the latter issue without undue overhead for all\ncommand invocations is with \"update-index --refresh\" (either run directly\nas a command inside Porcelain scripts that work with the plumbing, or\ninternally by calling refresh_cache() API in the C implementations of\nPorcelain commands).  Hence:\n\n\t$ cat Makefile >Makefile+\n        $ mv Makefile+ Makefile\n        $ git diff-files --name-only\n        Makefile\n        $ git update-index --refresh\n        $ git diff-files --name-only\n\nonce we spend cycles to revalidate the cached information in the index,\nsubsequent commands can trust the validity information without recomputing\nthe phantom differences that do not exist over and over.\n\nI wonder if we can solve this in a similar way.  Especially, because\nchanging filtering options like the core.crlf settings is a one-off event\nthat is done even rarely than \"touch Makefile\", it doesn't feel right to\nadd an extra configuration that makes people pay the penalty during\neveryday use just in case such a one-off event might have happened.\n\n> The typical reason to enable this option is when you have lots of files\n> that have been affected by a configuration change (eg crlf convention\n> or ident expansion), but don't want to recommit the otherwise unchanged\n> files just to get them on canonic form in the repository.\n\nOf course you do not want to re-commit.  If however these files that are\nunchanged from the end-user's point of view can be re-checked out safely,\nthen that would be similar to what \"update-index --refresh\" does for paths\nthat are stat-dirty.\n\n         \n"},{"id":"139325","messageId":"Pine.GSO.4.63.1004121453310.1164@shipon.roxen.com","threadId":"23356","inReplyTo":"7vaatbueg5.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH v4 3/8] status: Added missing calls to diff_unmodified_pair() in format_callbacks.","fromName":"Henrik Grubbström","fromEmail":"grubba@roxen.com","sentAt":"2010-04-12T13:00:03Z","receivedAt":"2010-04-12T13:00:03Z","isPatch":true,"sender":{"key":"grubba@roxen.com","avatar":null},"body":"On Sat, 10 Apr 2010, Junio C Hamano wrote:\n\n> \"Henrik Grubbström (Grubba)\"  <grubba@grubba.org> writes:\n>\n>> The diff_queue_struct provided by diff_flush() is raw, and needs to be\n>> filtered through diff_unmodified_pair() before being used.\n>> This is already done by most of the other functions operating on\n>> diff_queue_struct called by diff_flush().\n>\n> That is true but only if you are letting the diff front-end to feed\n> unmodified pairs to begin with, e.g. --find-copies-harder.  I don't think\n> the internal caller in wt-status does that.\n>\n> I don't think the patch is wrong nor it would hurt, but I am puzzled why\n> you needed this patch.\n\nWell, it's a prerequisite for the diff: Filter files that have changed...\npatch, albeit apparently not sufficient (yet).\n\n--\nHenrik Grubbström\t\t\t\t\tgrubba@grubba.org\nRoxen Internet Software AB\t\t\t\tgrubba@roxen.com"},{"id":"139668","messageId":"Pine.GSO.4.63.1004161723430.4423@shipon.roxen.com","threadId":"23356","inReplyTo":"7vvdbzszmi.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH v4 4/8] diff: Filter files that have changed only due to conversion changes.","fromName":"Henrik Grubbström","fromEmail":"grubba@roxen.com","sentAt":"2010-04-16T15:30:16Z","receivedAt":"2010-04-16T15:30:16Z","isPatch":true,"sender":{"key":"grubba@roxen.com","avatar":null},"body":"On Sat, 10 Apr 2010, Junio C Hamano wrote:\n\n> \"Henrik Grubbström (Grubba)\"  <grubba@grubba.org> writes:\n>\n>> When the conversion filter for a file is changed, files may get listed\n>> as modified even though the user has not made any changes to them.\n>> This patch adds a configuration option 'core.refilterOnDiff', which\n>> performs an extra renormalization pass to filter out such files.\n>>\n>> Signed-off-by: Henrik Grubbström <grubba@grubba.org>\n>\n> Does this really have to be done for every invocation of diff?\n>\n> But the problem feels very similar to the issue that touching the inode\n> information would make the cached stat information in the index invalid\n> and plumbing commands such as \"diff-files\" would report phantom changes.\n\nTrue, storing this information in the index is a much better approach.\n\n> Of course you do not want to re-commit.  If however these files that are\n> unchanged from the end-user's point of view can be re-checked out safely,\n> then that would be similar to what \"update-index --refresh\" does for paths\n> that are stat-dirty.\n\nI now have a tentative set of patches implementing this.\n\n--\nHenrik Grubbström\t\t\t\t\tgrubba@grubba.org\nRoxen Internet Software AB\t\t\t\tgrubba@roxen.com"}]}