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

[PATCH 2/2] attr.c: read .gitattributes from index as well.

From
Junio C Hamano <gitster@pobox.com>
Date
Aug 14, 2007, 08:41 UTC
Message-ID
<7vwsvycxup.fsf_-_@assigned-by-dhcp.cox.net>
In-Reply-To
<46BFFB1A.4070704@trolltech.com>

This makes .gitattributes files to be read from the index when they are not checked out to the work tree. This is in line with the way we always allowed low-level tools to operate in sparsely checked out work tree in a reasonable way.

It swaps the order of new file creation and converting the blob to work tree representation; otherwise when we are in the middle of checking out .gitattributes we would notice an empty but unwritten .gitattributes file in the work tree and will ignore the copy in the index.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 attr.c          |   61 ++++++++++++++++++++++++++++++++++++++++-
 entry.c         |   19 +++++++------
 t/t0020-crlf.sh |   81 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 150 insertions(+), 11 deletions(-)
diff --git a/attr.c b/attr.c
index 8d778f1..1293993 100644
--- a/attr.c
+++ b/attr.c
@@ -336,13 +336,70 @@ static struct attr_stack *read_attr_from_file(const char *path, int macro_ok)
 	return res;
 }
 
+static void *read_index_data(const char *path)
+{
+	int pos, len;
+	unsigned long sz;
+	enum object_type type;
+	void *data;
+
+	len = strlen(path);
+	pos = cache_name_pos(path, len);
+	if (pos < 0) {
+		/*
+		 * We might be in the middle of a merge, in which
+		 * case we would read stage #2 (ours).
+		 */
+		int i;
+		for (i = -pos - 1;
+		     (pos < 0 && i < active_nr &&
+		      !strcmp(active_cache[i]->name, path));
+		     i++)
+			if (ce_stage(active_cache[i]) == 2)
+				pos = i;
+	}
+	if (pos < 0)
+		return NULL;
+	data = read_sha1_file(active_cache[pos]->sha1, &type, &sz);
+	if (!data || type != OBJ_BLOB) {
+		free(data);
+		return NULL;
+	}
+	return data;
+}
+
 static struct attr_stack *read_attr(const char *path, int macro_ok)
 {
 	struct attr_stack *res;
+	char *buf, *sp;
+	int lineno = 0;
 
 	res = read_attr_from_file(path, macro_ok);
-	if (!res)
-		res = xcalloc(1, sizeof(*res));
+	if (res)
+		return res;
+
+	res = xcalloc(1, sizeof(*res));
+
+	/*
+	 * There is no checked out .gitattributes file there, but
+	 * we might have it in the index.  We allow operation in a
+	 * sparsely checked out work tree, so read from it.
+	 */
+	buf = read_index_data(path);
+	if (!buf)
+		return res;
+
+	for (sp = buf; *sp; ) {
+		char *ep;
+		int more;
+		for (ep = sp; *ep && *ep != '\n'; ep++)
+			;
+		more = (*ep == '\n');
+		*ep = '\0';
+		handle_attr_line(res, sp, path, ++lineno, macro_ok);
+		sp = ep + more;
+	}
+	free(buf);
 	return res;
 }
 
diff --git a/entry.c b/entry.c
index 0625112..fc3a506 100644
--- a/entry.c
+++ b/entry.c
@@ -112,6 +112,16 @@ static int write_entry(struct cache_entry *ce, char *path, const struct checkout
 		if (!new)
 			return error("git-checkout-index: unable to read sha1 file of %s (%s)",
 				path, sha1_to_hex(ce->sha1));
+
+		/*
+		 * Convert from git internal format to working tree format
+		 */
+		buf = convert_to_working_tree(ce->name, new, &size);
+		if (buf) {
+			free(new);
+			new = buf;
+		}
+
 		if (to_tempfile) {
 			strcpy(path, ".merge_file_XXXXXX");
 			fd = mkstemp(path);
@@ -123,15 +133,6 @@ static int write_entry(struct cache_entry *ce, char *path, const struct checkout
 				path, strerror(errno));
 		}
 
-		/*
-		 * Convert from git internal format to working tree format
-		 */
-		buf = convert_to_working_tree(ce->name, new, &size);
-		if (buf) {
-			free(new);
-			new = buf;
-		}
-
 		wrote = write_in_full(fd, new, size);
 		close(fd);
 		free(new);
diff --git a/t/t0020-crlf.sh b/t/t0020-crlf.sh
index fe1dfd0..0807d9f 100755
--- a/t/t0020-crlf.sh
+++ b/t/t0020-crlf.sh
@@ -290,4 +290,85 @@ test_expect_success '.gitattributes says two and three are text' '
 	fi
 '
 
+test_expect_success 'in-tree .gitattributes (1)' '
+
+	echo "one -crlf" >>.gitattributes &&
+	git add .gitattributes &&
+	git commit -m "Add .gitattributes" &&
+
+	rm -rf tmp one dir .gitattributes patch.file three &&
+	git read-tree --reset -u HEAD &&
+
+	if remove_cr one >/dev/null
+	then
+		echo "Eh? one should not have CRLF"
+		false
+	else
+		: happy
+	fi &&
+	remove_cr three >/dev/null || {
+		echo "Eh? three should still have CRLF"
+		false
+	}
+'
+
+test_expect_success 'in-tree .gitattributes (2)' '
+
+	rm -rf tmp one dir .gitattributes patch.file three &&
+	git read-tree --reset HEAD &&
+	git checkout-index -f -q -u -a &&
+
+	if remove_cr one >/dev/null
+	then
+		echo "Eh? one should not have CRLF"
+		false
+	else
+		: happy
+	fi &&
+	remove_cr three >/dev/null || {
+		echo "Eh? three should still have CRLF"
+		false
+	}
+'
+
+test_expect_success 'in-tree .gitattributes (3)' '
+
+	rm -rf tmp one dir .gitattributes patch.file three &&
+	git read-tree --reset HEAD &&
+	git checkout-index -u .gitattributes &&
+	git checkout-index -u one dir/two three &&
+
+	if remove_cr one >/dev/null
+	then
+		echo "Eh? one should not have CRLF"
+		false
+	else
+		: happy
+	fi &&
+	remove_cr three >/dev/null || {
+		echo "Eh? three should still have CRLF"
+		false
+	}
+'
+
+test_expect_success 'in-tree .gitattributes (4)' '
+
+	rm -rf tmp one dir .gitattributes patch.file three &&
+	git read-tree --reset HEAD &&
+	git checkout-index -u one dir/two three &&
+	git checkout-index -u .gitattributes &&
+
+	if remove_cr one >/dev/null
+	then
+		echo "Eh? one should not have CRLF"
+		false
+	else
+		: happy
+	fi &&
+	remove_cr three >/dev/null || {
+		echo "Eh? three should still have CRLF"
+		false
+	}
+'
+
 test_done
-- 
1.5.3.rc4.89.g18078
Previous: Junio C HamanoNext: Steffen Prohaska
Message 14 of 20 in “attr: fix attribute handling if .gitattributes is involved”
  1. 1/2 attr: fix attribute handling if .gitattributes is involvedSteffen Prohaska, Aug 12, 2007
  2. 2/2 checkout: fix attribute handling in checkout allSteffen Prohaska, Aug 12, 2007
  3. Junio C HamanoAug 12, 2007
  4. Steffen ProhaskaAug 12, 2007
  5. Junio C HamanoAug 13, 2007
  6. Marius Storm-OlsenAug 13, 2007
  7. Steffen ProhaskaAug 13, 2007
  8. Marius Storm-OlsenAug 13, 2007
  9. Steffen ProhaskaAug 13, 2007
  10. Marius Storm-OlsenAug 13, 2007
  11. Steffen ProhaskaAug 13, 2007
  12. Dmitry KakurinAug 13, 2007
  13. 1/2 attr.c: refactoringJunio C Hamano, Aug 14, 2007
  14. 2/2 attr.c: read .gitattributes from index as well.Junio C Hamano, Aug 14, 2007
  15. Steffen ProhaskaAug 13, 2007
  16. Johannes SchindelinAug 13, 2007
  17. David KastrupAug 13, 2007
  18. git-update-ref bug? (was: [PATCH 2/2] checkout: fix attribute handling in checkout all)David Kastrup, Aug 13, 2007
  19. Junio C HamanoAug 13, 2007
  20. Brian DowningAug 13, 2007

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.