summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff King <peff@peff.net>2012-01-10 13:08:21 -0500
committerJunio C Hamano <gitster@pobox.com>2012-01-10 11:25:40 -0800
commit1afca444953639fef53f3e5520202971505d77b9 (patch)
tree69371ec4d16eb3440be5b6b6fd4c462c9e9f20f9
parent07b88a00c0caac055a9f52167523248a75711842 (diff)
downloadgit-1afca444953639fef53f3e5520202971505d77b9.tar.gz
attr: don't confuse prefixes with leading directories
When we prepare the attribute stack for a lookup on a path, we start with the cached stack from the previous lookup (because it is common to do several lookups in the same directory hierarchy). So the first thing we must do in preparing the stack is to pop any entries that point to directories we are no longer interested in. For example, if our stack contains gitattributes for: foo/bar/baz foo/bar foo but we want to do a lookup in "foo/bar/bleep", then we want to pop the top element, but retain the others. To do this we walk down the stack from the top, popping elements that do not match our lookup directory. However, the test do this simply checked strncmp, meaning we would mistake "foo/bar/baz" as a leading directory of "foo/bar/baz_plus". We must also check that the character after our match is '/', meaning we matched the whole path component. There are two special cases to consider: 1. The top of our attr stack has the empty path. So we must not check for '/', but rather special-case the empty path, which always matches. 2. Typically when matching paths in this way, you would also need to check for a full string match (i.e., the character after is '\0'). We don't need to do so in this case, though, because our path string is actually just the directory component of the path to a file (i.e., we know that it terminates with "/", because the filename comes after that). Helped-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rw-r--r--attr.c3
-rwxr-xr-xt/t0003-attributes.sh10
2 files changed, 12 insertions, 1 deletions
diff --git a/attr.c b/attr.c
index f6b3f7e850..924b4408d5 100644
--- a/attr.c
+++ b/attr.c
@@ -573,7 +573,8 @@ static void prepare_attr_stack(const char *path, int dirlen)
elem = attr_stack;
if (namelen <= dirlen &&
- !strncmp(elem->origin, path, namelen))
+ !strncmp(elem->origin, path, namelen) &&
+ (!namelen || path[namelen] == '/'))
break;
debug_pop(elem);
diff --git a/t/t0003-attributes.sh b/t/t0003-attributes.sh
index ebbc7554a7..61b5a2eba6 100755
--- a/t/t0003-attributes.sh
+++ b/t/t0003-attributes.sh
@@ -60,6 +60,16 @@ test_expect_success 'attribute test' '
'
+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" &&