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

[PATCH 3/4] convert: Inhibit contraction of foreign $Id$ during stats.

From
Henrik Grubbström (Grubba) <grubba@grubba.org>
Date
Mar 15, 2010, 15:30 UTC
Message-ID
<baa3d958d4885348d3d5a4c30305fce0f026d85c.1268664693.git.grubba@grubba.org>
In-Reply-To
<cff48594f97960444a3cd642dafd7fd4905e6891.1268664693.git.grubba@grubba.org>

Files containing foreign $Id$'s were reported as modified directly on checkout, which ment that it was difficult to keep a clean working tree when handling commits with files containing such. convert_to_git() now takes one more mode parameter for controlling this.

Signed-off-by: Henrik Grubbström <grubba@grubba.org>
---
 builtin/apply.c       |    2 +-
 builtin/blame.c       |    2 +-
 cache.h               |    8 +++++++-
 combine-diff.c        |    2 +-
 convert.c             |   24 ++++++++++++++++++++----
 diff.c                |    2 +-
 sha1_file.c           |    3 ++-
 t/t0021-conversion.sh |   21 +++++++++++++++++++++
 8 files changed, 54 insertions(+), 10 deletions(-)
diff --git a/builtin/apply.c b/builtin/apply.c
index 3af4ae0..25adef8 100644
--- a/builtin/apply.c
+++ b/builtin/apply.c
@@ -1759,7 +1759,7 @@ static int read_old_data(struct stat *st, const char *path, struct strbuf *buf)
 	case S_IFREG:
 		if (strbuf_read_file(buf, path, st->st_size) != st->st_size)
 			return error("unable to open or read %s", path);
-		convert_to_git(path, buf->buf, buf->len, buf, 0);
+		convert_to_git(path, buf->buf, buf->len, buf, 0, 0);
 		return 0;
 	default:
 		return -1;
diff --git a/builtin/blame.c b/builtin/blame.c
index fc15863..16f7f00 100644
--- a/builtin/blame.c
+++ b/builtin/blame.c
@@ -2050,7 +2050,7 @@ static struct commit *fake_working_tree_commit(const char *path, const char *con
 		if (strbuf_read(&buf, 0, 0) < 0)
 			die_errno("failed to read from stdin");
 	}
-	convert_to_git(path, buf.buf, buf.len, &buf, 0);
+	convert_to_git(path, buf.buf, buf.len, &buf, 0, 0);
 	origin->file.ptr = buf.buf;
 	origin->file.size = buf.len;
 	pretend_sha1_file(buf.buf, buf.len, OBJ_BLOB, origin->blob_sha1);
diff --git a/cache.h b/cache.h
index 89f6a40..b62c462 100644
--- a/cache.h
+++ b/cache.h
@@ -556,6 +556,11 @@ enum safe_crlf {
 	SAFE_CRLF_WARN = 2,
 };
 
+enum ident_mode {
+	IDENT_MODE_FALSE = 0,
+	IDENT_MODE_KEEP_FOREIGN = 1,
+};
+
 extern enum safe_crlf safe_crlf;
 
 enum branch_track {
@@ -1010,7 +1015,8 @@ extern void trace_argv_printf(const char **argv, const char *format, ...);
 /* convert.c */
 /* returns 1 if *dst was used */
 extern int convert_to_git(const char *path, const char *src, size_t len,
-                          struct strbuf *dst, enum safe_crlf checksafe);
+			  struct strbuf *dst, enum safe_crlf checksafe,
+			  enum ident_mode identmode);
 extern int convert_to_working_tree(const char *path, const char *src, size_t len, struct strbuf *dst);
 
 /* add */
diff --git a/combine-diff.c b/combine-diff.c
index 6162691..8c9320a 100644
--- a/combine-diff.c
+++ b/combine-diff.c
@@ -758,7 +758,7 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
 			if (is_file) {
 				struct strbuf buf = STRBUF_INIT;
 
-				if (convert_to_git(elem->path, result, len, &buf, safe_crlf)) {
+				if (convert_to_git(elem->path, result, len, &buf, safe_crlf, 0)) {
 					free(result);
 					result = strbuf_detach(&buf, &len);
 					result_size = len;
diff --git a/convert.c b/convert.c
index 4165385..ab2e98e 100644
--- a/convert.c
+++ b/convert.c
@@ -432,9 +432,10 @@ static int count_ident(const char *cp, unsigned long size)
 }
 
 static int ident_to_git(const char *path, const char *src, size_t len,
-                        struct strbuf *buf, int ident)
+			struct strbuf *buf, int ident,
+			enum ident_mode identmode)
 {
-	char *dst, *dollar, *nl;
+	char *dst, *dollar, *nl, *spc;
 
 	if (!ident || !count_ident(src, len))
 		return 0;
@@ -462,6 +463,20 @@ static int ident_to_git(const char *path, const char *src, size_t len,
 				continue;
 			}
 
+			if ((identmode == IDENT_MODE_KEEP_FOREIGN) && len > 5) {
+				spc = memchr(src + 4, ' ', len - 4);
+				if (spc && spc < dollar-1) {
+					/* Foreign id.
+					 * Contraction of these is inhibited
+					 * during status operations to avoid
+					 * all files containing such being
+					 * marked as modified on checkout.
+					 * cf sha1_file.c:index_mem().
+					 */
+					continue;
+				}
+			}
+
 			memcpy(dst, "Id$", 3);
 			dst += 3;
 			len -= dollar + 1 - src;
@@ -594,7 +609,8 @@ static int git_path_check_ident(const char *path, struct git_attr_check *check)
 }
 
 int convert_to_git(const char *path, const char *src, size_t len,
-                   struct strbuf *dst, enum safe_crlf checksafe)
+		   struct strbuf *dst, enum safe_crlf checksafe,
+		   enum ident_mode identmode)
 {
 	struct git_attr_check check[3];
 	int crlf = CRLF_GUESS;
@@ -621,7 +637,7 @@ int convert_to_git(const char *path, const char *src, size_t len,
 		src = dst->buf;
 		len = dst->len;
 	}
-	return ret | ident_to_git(path, src, len, dst, ident);
+	return ret | ident_to_git(path, src, len, dst, ident, identmode);
 }
 
 int convert_to_working_tree(const char *path, const char *src, size_t len, struct strbuf *dst)
diff --git a/diff.c b/diff.c
index dfdfa1a..dd464bc 100644
--- a/diff.c
+++ b/diff.c
@@ -2113,7 +2113,7 @@ int diff_populate_filespec(struct diff_filespec *s, int size_only)
 		/*
 		 * Convert from working tree format to canonical git format
 		 */
-		if (convert_to_git(s->path, s->data, s->size, &buf, safe_crlf)) {
+		if (convert_to_git(s->path, s->data, s->size, &buf, safe_crlf, 0)) {
 			size_t size = 0;
 			munmap(s->data, s->size);
 			s->should_munmap = 0;
diff --git a/sha1_file.c b/sha1_file.c
index a08a9d0..992b624 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -2417,7 +2417,8 @@ static int index_mem(unsigned char *sha1, void *buf, size_t size,
 	if ((type == OBJ_BLOB) && path) {
 		struct strbuf nbuf = STRBUF_INIT;
 		if (convert_to_git(path, buf, size, &nbuf,
-		                   write_object ? safe_crlf : 0)) {
+				   write_object ? safe_crlf : 0,
+				   write_object ? 0 : IDENT_MODE_KEEP_FOREIGN)) {
 			buf = strbuf_detach(&nbuf, &size);
 			re_allocated = 1;
 		}
diff --git a/t/t0021-conversion.sh b/t/t0021-conversion.sh
index 248efcc..57812b6 100755
--- a/t/t0021-conversion.sh
+++ b/t/t0021-conversion.sh
@@ -93,4 +93,25 @@ 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.
+test_expect_success keywords_not_modified '
+	{
+		echo "File with foreign keywords"
+		echo "\$Id\$"
+		echo "\$Id: NoTerminatingSymbol"
+		echo "\$Id: Foreign Commit With Spaces $"
+		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
+'
+
 test_done
-- 
1.6.4.122.g6ffd7
Previous: Henrik Grubbström (Grubba)Next: Henrik Grubbström (Grubba)
Message 4 of 10 in “ident attribute related patches (resend w/ testsuite)”
  1. 0/4 ident attribute related patches (resend w/ testsuite)Henrik Grubbström (Grubba), Mar 15, 2010
  2. 1/4 convert: Safer handling of $Id$ contraction.Henrik Grubbström (Grubba), Mar 15, 2010
  3. 2/4 convert: Keep foreign $Id$ on checkout.Henrik Grubbström (Grubba), Mar 15, 2010
  4. 3/4 convert: Inhibit contraction of foreign $Id$ during stats.Henrik Grubbström (Grubba), Mar 15, 2010
  5. 4/4 convert: Added core.refilteronadd feature.Henrik Grubbström (Grubba), Mar 15, 2010
  6. Bert WesargMar 15, 2010
  7. Henrik GrubbströmMar 15, 2010
  8. Bert WesargMar 15, 2010
  9. Henrik GrubbströmMar 15, 2010
  10. René ScharfeMar 15, 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.