{"thread":{"id":"23023","subject":"[PATCH 0/4] ident attribute related patches (resend w/ testsuite)","startedAt":"2010-03-15T15:30:40Z","lastAt":"2010-03-15T18:32:06Z","messageCount":10,"participants":["Henrik Grubbström (Grubba)","Bert Wesarg","René Scharfe","Henrik Grubbström"],"isPatch":true,"patchVersion":1,"patchTotal":4},"messages":[{"id":"136833","messageId":"cover.1268664693.git.grubba@grubba.org","threadId":"23023","inReplyTo":null,"subject":"[PATCH 0/4] ident attribute related patches (resend w/ testsuite)","fromName":"Henrik Grubbström (Grubba)","fromEmail":"grubba@grubba.org","sentAt":"2010-03-15T15:30:40Z","receivedAt":"2010-03-15T15:30:40Z","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 the\n'ident' attribute to a useable state.\n\nSince last time, some issues that caused the the existing testsuite to\nfail have been fixed, and the testsuite has been extended to test the\nissues fixed by the patches.\n\nHenrik GrubbstrÃ¶m (Grubba) (4):\n  convert: Safer handling of $Id$ contraction.\n  convert: Keep foreign $Id$ on checkout.\n  convert: Inhibit contraction of foreign $Id$ during stats.\n  convert: Added core.refilteronadd feature.\n\n Documentation/config.txt |    6 ++++\n builtin/apply.c          |    2 +-\n builtin/blame.c          |    2 +-\n cache.h                  |    9 +++++-\n combine-diff.c           |    2 +-\n config.c                 |    5 +++\n convert.c                |   53 ++++++++++++++++++++++++++++++----\n diff.c                   |    2 +-\n environment.c            |    1 +\n sha1_file.c              |   60 +++++++++++++++++++++++++++++++++++++-\n t/t0021-conversion.sh    |   72 ++++++++++++++++++++++++++++++++++++++++++----\n 11 files changed, 196 insertions(+), 18 deletions(-)\n"},{"id":"136834","messageId":"be7e603837d8f55461c4d654fb07bd61c97b70e6.1268664693.git.grubba@grubba.org","threadId":"23023","inReplyTo":"cover.1268664693.git.grubba@grubba.org","subject":"[PATCH 1/4] convert: Safer handling of $Id$ contraction.","fromName":"Henrik Grubbström (Grubba)","fromEmail":"grubba@grubba.org","sentAt":"2010-03-15T15:30:41Z","receivedAt":"2010-03-15T15:30:41Z","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             |   17 +++++++++++++++--\n t/t0021-conversion.sh |   16 ++++++++++------\n 2 files changed, 25 insertions(+), 8 deletions(-)\n\ndiff --git a/convert.c b/convert.c\nindex 4f8fcb7..91207ab 100644\n--- a/convert.c\n+++ b/convert.c\n@@ -425,6 +425,7 @@ 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') break;\n \t\t}\n \t}\n \treturn cnt;\n@@ -433,7 +434,7 @@ static int count_ident(const char *cp, unsigned long size)\n static int ident_to_git(const char *path, const char *src, size_t len,\n                         struct strbuf *buf, int ident)\n {\n-\tchar *dst, *dollar;\n+\tchar *dst, *dollar, *nl;\n \n \tif (!ident || !count_ident(src, len))\n \t\treturn 0;\n@@ -455,6 +456,12 @@ 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\tnl = memchr(src + 3, '\\n', len - 3);\n+\t\t\tif (nl && nl < dollar) {\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@@ -470,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, *nl;\n \tint cnt;\n \n \tif (!ident)\n@@ -514,6 +521,12 @@ 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\tnl = memchr(src + 3, '\\n', len - 3);\n+\t\t\tif (nl && nl < dollar) {\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..a21a8d2 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.6.4.122.g6ffd7\n"},{"id":"136835","messageId":"cff48594f97960444a3cd642dafd7fd4905e6891.1268664693.git.grubba@grubba.org","threadId":"23023","inReplyTo":"be7e603837d8f55461c4d654fb07bd61c97b70e6.1268664693.git.grubba@grubba.org","subject":"[PATCH 2/4] convert: Keep foreign $Id$ on checkout.","fromName":"Henrik Grubbström (Grubba)","fromEmail":"grubba@grubba.org","sentAt":"2010-03-15T15:30:42Z","receivedAt":"2010-03-15T15:30:42Z","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\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 91207ab..4165385 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, *nl;\n+\tchar *to_free = NULL, *dollar, *nl, *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@@ -527,6 +530,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, ' ', len - 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 a21a8d2..248efcc 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.6.4.122.g6ffd7\n"},{"id":"136836","messageId":"baa3d958d4885348d3d5a4c30305fce0f026d85c.1268664693.git.grubba@grubba.org","threadId":"23023","inReplyTo":"cff48594f97960444a3cd642dafd7fd4905e6891.1268664693.git.grubba@grubba.org","subject":"[PATCH 3/4] convert: Inhibit contraction of foreign $Id$ during stats.","fromName":"Henrik Grubbström (Grubba)","fromEmail":"grubba@grubba.org","sentAt":"2010-03-15T15:30:43Z","receivedAt":"2010-03-15T15:30:43Z","isPatch":true,"sender":{"key":"grubba@grubba.org","avatar":"https://avatars.githubusercontent.com/u/1169458?v=4"},"body":"Files containing foreign $Id$'s were reported as modified directly\non checkout, which ment that it was difficult to keep a clean working\ntree when handling commits with files containing such. convert_to_git()\nnow takes one more mode parameter for controlling this.\n\nSigned-off-by: Henrik Grubbström <grubba@grubba.org>\n---\n builtin/apply.c       |    2 +-\n builtin/blame.c       |    2 +-\n cache.h               |    8 +++++++-\n combine-diff.c        |    2 +-\n convert.c             |   24 ++++++++++++++++++++----\n diff.c                |    2 +-\n sha1_file.c           |    3 ++-\n t/t0021-conversion.sh |   21 +++++++++++++++++++++\n 8 files changed, 54 insertions(+), 10 deletions(-)\n\ndiff --git a/builtin/apply.c b/builtin/apply.c\nindex 3af4ae0..25adef8 100644\n--- a/builtin/apply.c\n+++ b/builtin/apply.c\n@@ -1759,7 +1759,7 @@ static int read_old_data(struct stat *st, const char *path, struct strbuf *buf)\n \tcase S_IFREG:\n \t\tif (strbuf_read_file(buf, path, st->st_size) != st->st_size)\n \t\t\treturn error(\"unable to open or read %s\", path);\n-\t\tconvert_to_git(path, buf->buf, buf->len, buf, 0);\n+\t\tconvert_to_git(path, buf->buf, buf->len, buf, 0, 0);\n \t\treturn 0;\n \tdefault:\n \t\treturn -1;\ndiff --git a/builtin/blame.c b/builtin/blame.c\nindex fc15863..16f7f00 100644\n--- a/builtin/blame.c\n+++ b/builtin/blame.c\n@@ -2050,7 +2050,7 @@ static struct commit *fake_working_tree_commit(const char *path, const char *con\n \t\tif (strbuf_read(&buf, 0, 0) < 0)\n \t\t\tdie_errno(\"failed to read from stdin\");\n \t}\n-\tconvert_to_git(path, buf.buf, buf.len, &buf, 0);\n+\tconvert_to_git(path, buf.buf, buf.len, &buf, 0, 0);\n \torigin->file.ptr = buf.buf;\n \torigin->file.size = buf.len;\n \tpretend_sha1_file(buf.buf, buf.len, OBJ_BLOB, origin->blob_sha1);\ndiff --git a/cache.h b/cache.h\nindex 89f6a40..b62c462 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -556,6 +556,11 @@ enum safe_crlf {\n \tSAFE_CRLF_WARN = 2,\n };\n \n+enum ident_mode {\n+\tIDENT_MODE_FALSE = 0,\n+\tIDENT_MODE_KEEP_FOREIGN = 1,\n+};\n+\n extern enum safe_crlf safe_crlf;\n \n enum branch_track {\n@@ -1010,7 +1015,8 @@ extern void trace_argv_printf(const char **argv, const char *format, ...);\n /* convert.c */\n /* returns 1 if *dst was used */\n extern int convert_to_git(const char *path, const char *src, size_t len,\n-                          struct strbuf *dst, enum safe_crlf checksafe);\n+\t\t\t  struct strbuf *dst, enum safe_crlf checksafe,\n+\t\t\t  enum ident_mode identmode);\n extern int convert_to_working_tree(const char *path, const char *src, size_t len, struct strbuf *dst);\n \n /* add */\ndiff --git a/combine-diff.c b/combine-diff.c\nindex 6162691..8c9320a 100644\n--- a/combine-diff.c\n+++ b/combine-diff.c\n@@ -758,7 +758,7 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent,\n \t\t\tif (is_file) {\n \t\t\t\tstruct strbuf buf = STRBUF_INIT;\n \n-\t\t\t\tif (convert_to_git(elem->path, result, len, &buf, safe_crlf)) {\n+\t\t\t\tif (convert_to_git(elem->path, result, len, &buf, safe_crlf, 0)) {\n \t\t\t\t\tfree(result);\n \t\t\t\t\tresult = strbuf_detach(&buf, &len);\n \t\t\t\t\tresult_size = len;\ndiff --git a/convert.c b/convert.c\nindex 4165385..ab2e98e 100644\n--- a/convert.c\n+++ b/convert.c\n@@ -432,9 +432,10 @@ static int count_ident(const char *cp, unsigned long size)\n }\n \n static int ident_to_git(const char *path, const char *src, size_t len,\n-                        struct strbuf *buf, int ident)\n+\t\t\tstruct strbuf *buf, int ident,\n+\t\t\tenum ident_mode identmode)\n {\n-\tchar *dst, *dollar, *nl;\n+\tchar *dst, *dollar, *nl, *spc;\n \n \tif (!ident || !count_ident(src, len))\n \t\treturn 0;\n@@ -462,6 +463,20 @@ static int ident_to_git(const char *path, const char *src, size_t len,\n \t\t\t\tcontinue;\n \t\t\t}\n \n+\t\t\tif ((identmode == IDENT_MODE_KEEP_FOREIGN) && len > 5) {\n+\t\t\t\tspc = memchr(src + 4, ' ', len - 4);\n+\t\t\t\tif (spc && spc < dollar-1) {\n+\t\t\t\t\t/* Foreign id.\n+\t\t\t\t\t * Contraction of these is inhibited\n+\t\t\t\t\t * during status operations to avoid\n+\t\t\t\t\t * all files containing such being\n+\t\t\t\t\t * marked as modified on checkout.\n+\t\t\t\t\t * cf sha1_file.c:index_mem().\n+\t\t\t\t\t */\n+\t\t\t\t\tcontinue;\n+\t\t\t\t}\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@@ -594,7 +609,8 @@ static int git_path_check_ident(const char *path, struct git_attr_check *check)\n }\n \n int convert_to_git(const char *path, const char *src, size_t len,\n-                   struct strbuf *dst, enum safe_crlf checksafe)\n+\t\t   struct strbuf *dst, enum safe_crlf checksafe,\n+\t\t   enum ident_mode identmode)\n {\n \tstruct git_attr_check check[3];\n \tint crlf = CRLF_GUESS;\n@@ -621,7 +637,7 @@ int convert_to_git(const char *path, const char *src, size_t len,\n \t\tsrc = dst->buf;\n \t\tlen = dst->len;\n \t}\n-\treturn ret | ident_to_git(path, src, len, dst, ident);\n+\treturn ret | ident_to_git(path, src, len, dst, ident, identmode);\n }\n \n int convert_to_working_tree(const char *path, const char *src, size_t len, struct strbuf *dst)\ndiff --git a/diff.c b/diff.c\nindex dfdfa1a..dd464bc 100644\n--- a/diff.c\n+++ b/diff.c\n@@ -2113,7 +2113,7 @@ int diff_populate_filespec(struct diff_filespec *s, int size_only)\n \t\t/*\n \t\t * Convert from working tree format to canonical git format\n \t\t */\n-\t\tif (convert_to_git(s->path, s->data, s->size, &buf, safe_crlf)) {\n+\t\tif (convert_to_git(s->path, s->data, s->size, &buf, safe_crlf, 0)) {\n \t\t\tsize_t size = 0;\n \t\t\tmunmap(s->data, s->size);\n \t\t\ts->should_munmap = 0;\ndiff --git a/sha1_file.c b/sha1_file.c\nindex a08a9d0..992b624 100644\n--- a/sha1_file.c\n+++ b/sha1_file.c\n@@ -2417,7 +2417,8 @@ static int index_mem(unsigned char *sha1, void *buf, size_t size,\n \tif ((type == OBJ_BLOB) && path) {\n \t\tstruct strbuf nbuf = STRBUF_INIT;\n \t\tif (convert_to_git(path, buf, size, &nbuf,\n-\t\t                   write_object ? safe_crlf : 0)) {\n+\t\t\t\t   write_object ? safe_crlf : 0,\n+\t\t\t\t   write_object ? 0 : IDENT_MODE_KEEP_FOREIGN)) {\n \t\t\tbuf = strbuf_detach(&nbuf, &size);\n \t\t\tre_allocated = 1;\n \t\t}\ndiff --git a/t/t0021-conversion.sh b/t/t0021-conversion.sh\nindex 248efcc..57812b6 100755\n--- a/t/t0021-conversion.sh\n+++ b/t/t0021-conversion.sh\n@@ -93,4 +93,25 @@ 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.\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: 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`\" = x\n+'\n+\n test_done\n-- \n1.6.4.122.g6ffd7\n"},{"id":"136837","messageId":"647b1f10334c85789dcf7ce00844f32044469adc.1268664693.git.grubba@grubba.org","threadId":"23023","inReplyTo":"baa3d958d4885348d3d5a4c30305fce0f026d85c.1268664693.git.grubba@grubba.org","subject":"[PATCH 4/4] convert: Added core.refilteronadd feature.","fromName":"Henrik Grubbström (Grubba)","fromEmail":"grubba@grubba.org","sentAt":"2010-03-15T15:30:44Z","receivedAt":"2010-03-15T15:30:44Z","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 c80262b..a38b23e 100644\n--- a/Documentation/config.txt\n+++ b/Documentation/config.txt\n@@ -533,6 +533,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 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 b62c462..8cff256 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -549,6 +549,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 \n enum safe_crlf {\n \tSAFE_CRLF_FALSE = 0,\ndiff --git a/config.c b/config.c\nindex 6963fbe..b1db505 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 \t/* Add other config variables here and to Documentation/config.txt. */\n \treturn 0;\n }\ndiff --git a/environment.c b/environment.c\nindex 876c5e5..25e1e47 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 \n /* Parallel index stat data preload? */\n int core_preload_index = 0;\ndiff --git a/sha1_file.c b/sha1_file.c\nindex 992b624..d7cc3ad 100644\n--- a/sha1_file.c\n+++ b/sha1_file.c\n@@ -2467,6 +2467,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, 0);\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, 0);\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@@ -2481,6 +2529,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 57812b6..9d98072 100755\n--- a/t/t0021-conversion.sh\n+++ b/t/t0021-conversion.sh\n@@ -114,4 +114,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.6.4.122.g6ffd7\n"},{"id":"136838","messageId":"36ca99e91003150839r3b159befr9086fa47eec61a8d@mail.gmail.com","threadId":"23023","inReplyTo":"be7e603837d8f55461c4d654fb07bd61c97b70e6.1268664693.git.grubba@grubba.org","subject":"Re: [PATCH 1/4] convert: Safer handling of $Id$ contraction.","fromName":"Bert Wesarg","fromEmail":"bert.wesarg@googlemail.com","sentAt":"2010-03-15T15:39:35Z","receivedAt":"2010-03-15T15:39:35Z","isPatch":true,"sender":{"key":"bert.wesarg@googlemail.com","avatar":"https://avatars.githubusercontent.com/u/111934?v=4"},"body":"2010/3/15 Henrik Grubbström (Grubba) <grubba@grubba.org>:\n> diff --git a/t/t0021-conversion.sh b/t/t0021-conversion.sh\n> index 6cb8d60..a21a8d2 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>                echo \"\\$Id:NoSpaceAtFront \\$\"\n>                echo \"\\$Id:NoSpaceAtEitherEnd\\$\"\n>                echo \"\\$Id: NoTerminatingSymbol\"\n> +               echo \"\\$Id: Foreign Commit With Spaces $\"\n\nMissing \\ for second $.\n\n> +               echo \"\\$Id: NoTerminatingSymbolAtEOF\"\n>        } > expanded-keywords &&\n>\n>        {\n>                echo \"File with expanded keywords\"\n> -               echo \"\\$Id: 4f21723e7b15065df7de95bd46c8ba6fb1818f4c \\$\"\n> -               echo \"\\$Id: 4f21723e7b15065df7de95bd46c8ba6fb1818f4c \\$\"\n> -               echo \"\\$Id: 4f21723e7b15065df7de95bd46c8ba6fb1818f4c \\$\"\n> -               echo \"\\$Id: 4f21723e7b15065df7de95bd46c8ba6fb1818f4c \\$\"\n> -               echo \"\\$Id: 4f21723e7b15065df7de95bd46c8ba6fb1818f4c \\$\"\n> -               echo \"\\$Id: 4f21723e7b15065df7de95bd46c8ba6fb1818f4c \\$\"\n> +               echo \"\\$Id: fd0478f5f1486f3d5177d4c3f6eb2765e8fc56b9 \\$\"\n> +               echo \"\\$Id: fd0478f5f1486f3d5177d4c3f6eb2765e8fc56b9 \\$\"\n> +               echo \"\\$Id: fd0478f5f1486f3d5177d4c3f6eb2765e8fc56b9 \\$\"\n> +               echo \"\\$Id: fd0478f5f1486f3d5177d4c3f6eb2765e8fc56b9 \\$\"\n> +               echo \"\\$Id: fd0478f5f1486f3d5177d4c3f6eb2765e8fc56b9 \\$\"\n> +               echo \"\\$Id: fd0478f5f1486f3d5177d4c3f6eb2765e8fc56b9 \\$\"\n>                echo \"\\$Id: NoTerminatingSymbol\"\n> +               echo \"\\$Id: fd0478f5f1486f3d5177d4c3f6eb2765e8fc56b9 $\"\n\nDitto.\n\n> +               echo \"\\$Id: NoTerminatingSymbolAtEOF\"\n>        } > expected-output &&\n>\n>        git add expanded-keywords &&\n"},{"id":"136839","messageId":"36ca99e91003150842q6a39a48dl2e88254fd636556d@mail.gmail.com","threadId":"23023","inReplyTo":"baa3d958d4885348d3d5a4c30305fce0f026d85c.1268664693.git.grubba@grubba.org","subject":"Re: [PATCH 3/4] convert: Inhibit contraction of foreign $Id$ during stats.","fromName":"Bert Wesarg","fromEmail":"bert.wesarg@googlemail.com","sentAt":"2010-03-15T15:42:48Z","receivedAt":"2010-03-15T15:42:48Z","isPatch":true,"sender":{"key":"bert.wesarg@googlemail.com","avatar":"https://avatars.githubusercontent.com/u/111934?v=4"},"body":"2010/3/15 Henrik Grubbström (Grubba) <grubba@grubba.org>:\n> diff --git a/builtin/apply.c b/builtin/apply.c\n> index 3af4ae0..25adef8 100644\n> --- a/builtin/apply.c\n> +++ b/builtin/apply.c\n> @@ -1759,7 +1759,7 @@ static int read_old_data(struct stat *st, const char *path, struct strbuf *buf)\n>        case S_IFREG:\n>                if (strbuf_read_file(buf, path, st->st_size) != st->st_size)\n>                        return error(\"unable to open or read %s\", path);\n> -               convert_to_git(path, buf->buf, buf->len, buf, 0);\n> +               convert_to_git(path, buf->buf, buf->len, buf, 0, 0);\n\nSo this new 0 should be ...\n\n>                return 0;\n>        default:\n>                return -1;\n> diff --git a/builtin/blame.c b/builtin/blame.c\n> index fc15863..16f7f00 100644\n> --- a/builtin/blame.c\n> +++ b/builtin/blame.c\n> @@ -2050,7 +2050,7 @@ static struct commit *fake_working_tree_commit(const char *path, const char *con\n>                if (strbuf_read(&buf, 0, 0) < 0)\n>                        die_errno(\"failed to read from stdin\");\n>        }\n> -       convert_to_git(path, buf.buf, buf.len, &buf, 0);\n> +       convert_to_git(path, buf.buf, buf.len, &buf, 0, 0);\n\n... (and this one too) ...\n\n>        origin->file.ptr = buf.buf;\n>        origin->file.size = buf.len;\n>        pretend_sha1_file(buf.buf, buf.len, OBJ_BLOB, origin->blob_sha1);\n> diff --git a/cache.h b/cache.h\n> index 89f6a40..b62c462 100644\n> --- a/cache.h\n> +++ b/cache.h\n> @@ -556,6 +556,11 @@ enum safe_crlf {\n>        SAFE_CRLF_WARN = 2,\n>  };\n>\n> +enum ident_mode {\n> +       IDENT_MODE_FALSE = 0,\n\n... this?\n\n> +       IDENT_MODE_KEEP_FOREIGN = 1,\n> +};\n> +\n>  extern enum safe_crlf safe_crlf;\n>\n>  enum branch_track {\n"},{"id":"136859","messageId":"4B9E7966.4060300@lsrfire.ath.cx","threadId":"23023","inReplyTo":"be7e603837d8f55461c4d654fb07bd61c97b70e6.1268664693.git.grubba@grubba.org","subject":"Re: [PATCH 1/4] convert: Safer handling of $Id$ contraction.","fromName":"René Scharfe","fromEmail":"rene.scharfe@lsrfire.ath.cx","sentAt":"2010-03-15T18:16:06Z","receivedAt":"2010-03-15T18:16:06Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Am 15.03.2010 16:30, schrieb Henrik Grubbström (Grubba):\n> The code to contract $Id:xxxxx$ strings could eat an arbitrary amount\n> of source text if the terminating $ was lost. It now refuses to\n> contract $Id:xxxxx$ strings spanning multiple lines.\n> \n> Signed-off-by: Henrik Grubbström <grubba@grubba.org>\n> ---\n> The behaviour implemented by the patch is in line with what other\n> VCSes that implement $Id$ do.\n> \n>  convert.c             |   17 +++++++++++++++--\n>  t/t0021-conversion.sh |   16 ++++++++++------\n>  2 files changed, 25 insertions(+), 8 deletions(-)\n> \n> diff --git a/convert.c b/convert.c\n> index 4f8fcb7..91207ab 100644\n> --- a/convert.c\n> +++ b/convert.c\n> @@ -425,6 +425,7 @@ 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') break;\n\nStyle:\n\n\t\t\tif (ch == '\\n')\n\t\t\t\tbreak;\n\n>  \t\t}\n>  \t}\n>  \treturn cnt;\n> @@ -433,7 +434,7 @@ static int count_ident(const char *cp, unsigned long size)\n>  static int ident_to_git(const char *path, const char *src, size_t len,\n>                          struct strbuf *buf, int ident)\n>  {\n> -\tchar *dst, *dollar;\n> +\tchar *dst, *dollar, *nl;\n>  \n>  \tif (!ident || !count_ident(src, len))\n>  \t\treturn 0;\n> @@ -455,6 +456,12 @@ 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\tnl = memchr(src + 3, '\\n', len - 3);\n> +\t\t\tif (nl && nl < dollar) {\n> +\t\t\t\t/* Line break before the next dollar. */\n> +\t\t\t\tcontinue;\n> +\t\t\t}\n> +\n\nYou only need to search up to the previously found dollar sign here:\n\n\t\t\tif (memchr(src + 3, '\\n', dollar - src - 3))\n\t\t\t\tcontinue;\n\n>  \t\t\tmemcpy(dst, \"Id$\", 3);\n>  \t\t\tdst += 3;\n>  \t\t\tlen -= dollar + 1 - src;\n> @@ -470,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, *nl;\n>  \tint cnt;\n>  \n>  \tif (!ident)\n> @@ -514,6 +521,12 @@ 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\tnl = memchr(src + 3, '\\n', len - 3);\n> +\t\t\tif (nl && nl < dollar) {\n> +\t\t\t\t/* Line break before the next dollar. */\n> +\t\t\t\tcontinue;\n> +\t\t\t}\n> +\n\nDitto.\n\nRené\n"},{"id":"136861","messageId":"Pine.GSO.4.63.1003151915470.1164@shipon.roxen.com","threadId":"23023","inReplyTo":"36ca99e91003150839r3b159befr9086fa47eec61a8d@mail.gmail.com","subject":"Re: [PATCH 1/4] convert: Safer handling of $Id$ contraction.","fromName":"Henrik Grubbström","fromEmail":"grubba@roxen.com","sentAt":"2010-03-15T18:21:55Z","receivedAt":"2010-03-15T18:21:55Z","isPatch":true,"sender":{"key":"grubba@roxen.com","avatar":null},"body":"On Mon, 15 Mar 2010, Bert Wesarg wrote:\n\n> 2010/3/15 Henrik Grubbström (Grubba) <grubba@grubba.org>:\n>> diff --git a/t/t0021-conversion.sh b/t/t0021-conversion.sh\n[...]\n>> +               echo \"\\$Id: Foreign Commit With Spaces $\"\n>\n> Missing \\ for second $.\n[...]\n>> +               echo \"\\$Id: fd0478f5f1486f3d5177d4c3f6eb2765e8fc56b9 $\"\n>\n> Ditto.\n\nThanks. It seems like bash and /bin/sh on Solaris don't care, but it's \nprobably not a portable behaviour.\n\n--\nHenrik Grubbström\t\t\t\t\tgrubba@grubba.org\nRoxen Internet Software AB\t\t\t\tgrubba@roxen.com"},{"id":"136863","messageId":"Pine.GSO.4.63.1003151923290.1164@shipon.roxen.com","threadId":"23023","inReplyTo":"36ca99e91003150842q6a39a48dl2e88254fd636556d@mail.gmail.com","subject":"Re: [PATCH 3/4] convert: Inhibit contraction of foreign $Id$ during stats.","fromName":"Henrik Grubbström","fromEmail":"grubba@roxen.com","sentAt":"2010-03-15T18:32:06Z","receivedAt":"2010-03-15T18:32:06Z","isPatch":true,"sender":{"key":"grubba@roxen.com","avatar":null},"body":"On Mon, 15 Mar 2010, Bert Wesarg wrote:\n\n> 2010/3/15 Henrik Grubbström (Grubba) <grubba@grubba.org>:\n>> diff --git a/builtin/apply.c b/builtin/apply.c\n>> index 3af4ae0..25adef8 100644\n>> --- a/builtin/apply.c\n>> +++ b/builtin/apply.c\n[...]\n>> -               convert_to_git(path, buf->buf, buf->len, buf, 0);\n>> +               convert_to_git(path, buf->buf, buf->len, buf, 0, 0);\n>\n> So this new 0 should be ...\n>\n[...]\n>> @@ -556,6 +556,11 @@ enum safe_crlf {\n>>        SAFE_CRLF_WARN = 2,\n>>  };\n>>\n>> +enum ident_mode {\n>> +       IDENT_MODE_FALSE = 0,\n>\n> ... this?\n\nCorrect. I followed the style for the preceeding parameter (ie the other \nzero), which maps to enum safe_crlf SAFE_CRLF_FALSE. I agree that using \nthe enum constants here instead of the plain zeros could perhaps be more \nreadable, but that should be a separate patch.\n\n--\nHenrik Grubbström\t\t\t\t\tgrubba@grubba.org\nRoxen Internet Software AB\t\t\t\tgrubba@roxen.com"}]}