Commits

Anonymous committed 6c65b5e Merge

Merge the attributes fix in from maint-1.6.6 branch

Signed-off-by: Junio C Hamano <gitster@pobox.com>

Comments (0)

Files changed (4)

Documentation/RelNotes/1.7.6.6.txt

+Git v1.7.6.6 Release Notes
+==========================
+
+Fixes since v1.7.6.5
+--------------------
+
+ * The code to look up attributes for paths reused entries from a wrong
+   directory when two paths in question are in adjacent directories and
+   the name of the one directory is a prefix of the other.
+
+Also contains minor fixes and documentation updates.

Documentation/config.txt

 	conflict hunks can be resolved automatically, should they be
 	encountered again.  By default, linkgit:git-rerere[1] is
 	enabled if there is an `rr-cache` directory under the
-	`$GIT_DIR`.
+	`$GIT_DIR`, e.g. if "rerere" was previously used in the
+	repository.
 
 sendemail.identity::
 	A configuration identity. When given, causes values in the
 
 static void bootstrap_attr_stack(void)
 {
-	if (!attr_stack) {
-		struct attr_stack *elem;
+	struct attr_stack *elem;
 
-		elem = read_attr_from_array(builtin_attr);
-		elem->origin = NULL;
-		elem->prev = attr_stack;
-		attr_stack = elem;
+	if (attr_stack)
+		return;
 
-		if (git_attr_system()) {
-			elem = read_attr_from_file(git_etc_gitattributes(), 1);
-			if (elem) {
-				elem->origin = NULL;
-				elem->prev = attr_stack;
-				attr_stack = elem;
-			}
-		}
+	elem = read_attr_from_array(builtin_attr);
+	elem->origin = NULL;
+	elem->prev = attr_stack;
+	attr_stack = elem;
 
-		if (git_attributes_file) {
-			elem = read_attr_from_file(git_attributes_file, 1);
-			if (elem) {
-				elem->origin = NULL;
-				elem->prev = attr_stack;
-				attr_stack = elem;
-			}
+	if (git_attr_system()) {
+		elem = read_attr_from_file(git_etc_gitattributes(), 1);
+		if (elem) {
+			elem->origin = NULL;
+			elem->prev = attr_stack;
+			attr_stack = elem;
 		}
+	}
 
-		if (!is_bare_repository() || direction == GIT_ATTR_INDEX) {
-			elem = read_attr(GITATTRIBUTES_FILE, 1);
-			elem->origin = xstrdup("");
+	if (git_attributes_file) {
+		elem = read_attr_from_file(git_attributes_file, 1);
+		if (elem) {
+			elem->origin = NULL;
 			elem->prev = attr_stack;
 			attr_stack = elem;
-			debug_push(elem);
 		}
+	}
 
-		elem = read_attr_from_file(git_path(INFOATTRIBUTES_FILE), 1);
-		if (!elem)
-			elem = xcalloc(1, sizeof(*elem));
-		elem->origin = NULL;
+	if (!is_bare_repository() || direction == GIT_ATTR_INDEX) {
+		elem = read_attr(GITATTRIBUTES_FILE, 1);
+		elem->origin = xstrdup("");
 		elem->prev = attr_stack;
 		attr_stack = elem;
+		debug_push(elem);
 	}
+
+	elem = read_attr_from_file(git_path(INFOATTRIBUTES_FILE), 1);
+	if (!elem)
+		elem = xcalloc(1, sizeof(*elem));
+	elem->origin = NULL;
+	elem->prev = attr_stack;
+	attr_stack = elem;
 }
 
 static void prepare_attr_stack(const char *path)
 
 	/*
 	 * Pop the ones from directories that are not the prefix of
-	 * the path we are checking.
+	 * the path we are checking. Break out of the loop when we see
+	 * the root one (whose origin is an empty string "") or the builtin
+	 * one (whose origin is NULL) without popping it.
 	 */
-	while (attr_stack && attr_stack->origin) {
+	while (attr_stack->origin) {
 		int namelen = strlen(attr_stack->origin);
 
 		elem = attr_stack;
 		if (namelen <= dirlen &&
-		    !strncmp(elem->origin, path, namelen))
+		    !strncmp(elem->origin, path, namelen) &&
+		    (!namelen || path[namelen] == '/'))
 			break;
 
 		debug_pop(elem);
 	 * Read from parent directories and push them down
 	 */
 	if (!is_bare_repository() || direction == GIT_ATTR_INDEX) {
+		/*
+		 * bootstrap_attr_stack() should have added, and the
+		 * above loop should have stopped before popping, the
+		 * root element whose attr_stack->origin is set to an
+		 * empty string.
+		 */
 		struct strbuf pathbuf = STRBUF_INIT;
 
+		assert(attr_stack->origin);
 		while (1) {
 			len = strlen(attr_stack->origin);
 			if (dirlen <= len)

t/t0003-attributes.sh

 
 '
 
+test_expect_success 'prefixes are not confused with leading directories' '
+	attr_check a_plus/g unspecified &&
+	cat >expect <<-\EOF &&
+	a/g: test: a/g
+	a_plus/g: test: unspecified
+	EOF
+	git check-attr test a/g a_plus/g >actual &&
+	test_cmp expect actual
+'
+
 test_expect_success 'core.attributesfile' '
 	attr_check global unspecified &&
 	git config core.attributesfile "$HOME/global-gitattributes" &&