Merge the attributes fix in from maint-1.6.6 branch

Signed-off-by: Junio C Hamano <gitster@pobox.com>
diff --git a/attr.c b/attr.c
index 76b079f..96eda0e 100644
--- a/attr.c
+++ b/attr.c
@@ -495,47 +495,48 @@
 
 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 (!is_bare_repository() || direction == GIT_ATTR_INDEX) {
-			elem = read_attr(GITATTRIBUTES_FILE, 1);
-			elem->origin = xstrdup("");
+	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;
-			debug_push(elem);
 		}
+	}
 
-		elem = read_attr_from_file(git_path(INFOATTRIBUTES_FILE), 1);
-		if (!elem)
-			elem = xcalloc(1, sizeof(*elem));
-		elem->origin = NULL;
+	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 (!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)
@@ -575,14 +576,17 @@
 
 	/*
 	 * 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);
@@ -594,8 +598,15 @@
 	 * 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)