Merge the attributes fix in from maint-1.6.7 branch

Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Junio C Hamano 2012-01-10 14:24:01 -08:00
commit 55dcc2ebad
5 changed files with 79 additions and 35 deletions

View File

@ -0,0 +1,11 @@
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.

View File

@ -0,0 +1,11 @@
Git v1.7.7.6 Release Notes
==========================
Fixes since v1.7.7.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.

View File

@ -1740,7 +1740,8 @@ rerere.enabled::
conflict hunks can be resolved automatically, should they be conflict hunks can be resolved automatically, should they be
encountered again. By default, linkgit:git-rerere[1] is encountered again. By default, linkgit:git-rerere[1] is
enabled if there is an `rr-cache` directory under the 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:: sendemail.identity::
A configuration identity. When given, causes values in the A configuration identity. When given, causes values in the

79
attr.c
View File

@ -495,47 +495,48 @@ static int git_attr_system(void)
static void bootstrap_attr_stack(void) static void bootstrap_attr_stack(void)
{ {
if (!attr_stack) { struct attr_stack *elem;
struct attr_stack *elem;
elem = read_attr_from_array(builtin_attr); if (attr_stack)
elem->origin = NULL; return;
elem->prev = attr_stack;
attr_stack = elem;
if (git_attr_system()) { elem = read_attr_from_array(builtin_attr);
elem = read_attr_from_file(git_etc_gitattributes(), 1); elem->origin = NULL;
if (elem) { elem->prev = attr_stack;
elem->origin = NULL; attr_stack = elem;
elem->prev = attr_stack;
attr_stack = elem;
}
}
if (git_attributes_file) { if (git_attr_system()) {
elem = read_attr_from_file(git_attributes_file, 1); elem = read_attr_from_file(git_etc_gitattributes(), 1);
if (elem) { if (elem) {
elem->origin = NULL; 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; elem->prev = attr_stack;
attr_stack = elem; attr_stack = elem;
debug_push(elem);
} }
}
elem = read_attr_from_file(git_path(INFOATTRIBUTES_FILE), 1); if (git_attributes_file) {
if (!elem) elem = read_attr_from_file(git_attributes_file, 1);
elem = xcalloc(1, sizeof(*elem)); if (elem) {
elem->origin = NULL; 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; elem->prev = attr_stack;
attr_stack = elem; 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) static void prepare_attr_stack(const char *path)
@ -575,14 +576,17 @@ static void prepare_attr_stack(const char *path)
/* /*
* Pop the ones from directories that are not the prefix of * 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); int namelen = strlen(attr_stack->origin);
elem = attr_stack; elem = attr_stack;
if (namelen <= dirlen && if (namelen <= dirlen &&
!strncmp(elem->origin, path, namelen)) !strncmp(elem->origin, path, namelen) &&
(!namelen || path[namelen] == '/'))
break; break;
debug_pop(elem); debug_pop(elem);
@ -594,8 +598,15 @@ static void prepare_attr_stack(const char *path)
* Read from parent directories and push them down * Read from parent directories and push them down
*/ */
if (!is_bare_repository() || direction == GIT_ATTR_INDEX) { 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; struct strbuf pathbuf = STRBUF_INIT;
assert(attr_stack->origin);
while (1) { while (1) {
len = strlen(attr_stack->origin); len = strlen(attr_stack->origin);
if (dirlen <= len) if (dirlen <= len)

View File

@ -159,6 +159,16 @@ test_expect_success 'relative paths' '
(cd b && attr_check ../a/b/g a/b/g) (cd b && attr_check ../a/b/g a/b/g)
' '
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' ' test_expect_success 'core.attributesfile' '
attr_check global unspecified && attr_check global unspecified &&
git config core.attributesfile "$HOME/global-gitattributes" && git config core.attributesfile "$HOME/global-gitattributes" &&