Skip to content

Commit

Permalink
attr: don't confuse prefixes with leading directories
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: Jeff King <[email protected]>
Signed-off-by: Junio C Hamano <[email protected]>
  • Loading branch information
peff authored and gitster committed Jan 10, 2012
1 parent 07b88a0 commit 1afca44
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 1 deletion.
3 changes: 2 additions & 1 deletion attr.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
10 changes: 10 additions & 0 deletions t/t0003-attributes.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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" &&
Expand Down

0 comments on commit 1afca44

Please sign in to comment.