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

Subsystems: the rest

DORMANTno replies

6 messages, 3 authors, 2016-06-15 · open the first message on its own page

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

From: Junio C Hamano <hidden>
Date: 2016-06-15 22:43:29

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 <redacted>
---
 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

[PATCH] Add read_cache to builtin-check-attr

From: Brian Downing <hidden>
Date: 2016-06-15 22:43:29

We can now read .gitattributes files out of the index, but the index
must be loaded for this to work.

Signed-off-by: Brian Downing <redacted>
---
 builtin-check-attr.c |    5 +++++
 1 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/builtin-check-attr.c b/builtin-check-attr.c
index 9d77f76..d949733 100644
--- a/builtin-check-attr.c
+++ b/builtin-check-attr.c
@@ -1,4 +1,5 @@
 #include "builtin.h"
+#include "cache.h"
 #include "attr.h"
 #include "quote.h"
 
@@ -10,6 +11,10 @@ int cmd_check_attr(int argc, const char **argv, const char *prefix)
 	struct git_attr_check *check;
 	int cnt, i, doubledash;
 
+	if (read_cache() < 0) {
+		die("invalid cache");
+	}
+
 	doubledash = -1;
 	for (i = 1; doubledash < 0 && i < argc; i++) {
 		if (!strcmp(argv[i], "--"))
-- 
1.5.3.GIT

Re: [PATCH] Add read_cache to builtin-check-attr

From: Brian Downing <hidden>
Date: 2016-06-15 22:43:29

On Tue, Aug 14, 2007 at 08:18:38AM -0500, Brian Downing wrote:
We can now read .gitattributes files out of the index, but the index
must be loaded for this to work.
This was supposed to be In-Reply-To Junio's patch, "attr.c: read
.gitattributes from index as well."  It's not much use without it.

-bcd

Re: [PATCH] Add read_cache to builtin-check-attr

From: Johannes Schindelin <hidden>
Date: 2016-06-15 22:43:29

Hi,

On Tue, 14 Aug 2007, Brian Downing wrote:
On Tue, Aug 14, 2007 at 08:18:38AM -0500, Brian Downing wrote:
quoted
We can now read .gitattributes files out of the index, but the index
must be loaded for this to work.
This was supposed to be In-Reply-To Junio's patch, "attr.c: read
.gitattributes from index as well."  It's not much use without it.
Shouldn't read_cache() be _only_ called if

- it has not been read yet, and
- .gitattributes was not found in the work tree?

IOW check-attr is the wrong place for your patch IMHO.

Ciao,
Dscho

Re: [PATCH] Add read_cache to builtin-check-attr

From: Brian Downing <hidden>
Date: 2016-06-15 22:43:29

On Tue, Aug 14, 2007 at 03:08:52PM +0100, Johannes Schindelin wrote:
Shouldn't read_cache() be _only_ called if

- it has not been read yet, and
- .gitattributes was not found in the work tree?

IOW check-attr is the wrong place for your patch IMHO.
I admit I just cargo-culted what builtin-checkout-index did upon starting.
Off the cuff, though, I don't see how the cache could ever already be
loaded upon the start of cmd_check_attr, and the way the attr.c code is
written, the cache be loaded when we check attributes or it will default
to the old behavior (only checking the working directory.)

What would you suggest here?

-bcd

Re: [PATCH] Add read_cache to builtin-check-attr

From: Johannes Schindelin <hidden>
Date: 2016-06-15 22:43:29

Hi,

On Tue, 14 Aug 2007, Brian Downing wrote:
On Tue, Aug 14, 2007 at 03:08:52PM +0100, Johannes Schindelin wrote:
quoted
Shouldn't read_cache() be _only_ called if

- it has not been read yet, and
- .gitattributes was not found in the work tree?

IOW check-attr is the wrong place for your patch IMHO.
I admit I just cargo-culted what builtin-checkout-index did upon starting.
Off the cuff, though, I don't see how the cache could ever already be
loaded upon the start of cmd_check_attr,
Right.  I was talking more about read_cache() being called later anyway, 
so you do not have to read the cache if a .gitattributes is there and you 
do not need the index to begin with.
and the way the attr.c code is
written, the cache be loaded when we check attributes or it will default
to the old behavior (only checking the working directory.)
Why not just make sure that the index is read in read_index_data()?  
Something like

	/* read index if that was not already done yet */
	if (!istate->mmap)
		read_index(&istate);

(Yes, I know that read_index() calls read_index_from(), which in turn 
checks that, but read_attr() is called possibly pretty often, right?  So 
we might just as well spare a few cycles here.)

Ciao,
Dscho
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help