2008-02-07 16:02:08 +08:00
|
|
|
#!/bin/sh
|
|
|
|
|
|
|
|
test_description=gitattributes
|
|
|
|
|
|
|
|
. ./test-lib.sh
|
|
|
|
|
|
|
|
attr_check () {
|
2011-09-23 07:34:05 +08:00
|
|
|
path="$1" expect="$2"
|
2008-02-07 16:02:08 +08:00
|
|
|
|
2011-10-11 23:53:31 +08:00
|
|
|
git $3 check-attr test -- "$path" >actual 2>err &&
|
2008-02-07 16:02:08 +08:00
|
|
|
echo "$path: test: $2" >expect &&
|
2011-08-04 12:47:43 +08:00
|
|
|
test_cmp expect actual &&
|
|
|
|
test_line_count = 0 err
|
2008-02-07 16:02:08 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
test_expect_success 'setup' '
|
2011-08-04 12:47:45 +08:00
|
|
|
mkdir -p a/b/d a/c b &&
|
2008-02-07 16:02:08 +08:00
|
|
|
(
|
2010-04-06 20:46:44 +08:00
|
|
|
echo "[attr]notest !test"
|
2008-02-07 16:02:08 +08:00
|
|
|
echo "f test=f"
|
2008-04-23 02:19:12 +08:00
|
|
|
echo "a/i test=a/i"
|
2010-04-06 20:46:43 +08:00
|
|
|
echo "onoff test -test"
|
|
|
|
echo "offon -test test"
|
2010-04-06 20:46:44 +08:00
|
|
|
echo "no notest"
|
2011-10-11 23:53:31 +08:00
|
|
|
echo "A/e/F test=A/e/F"
|
2008-02-07 16:02:08 +08:00
|
|
|
) >.gitattributes &&
|
|
|
|
(
|
|
|
|
echo "g test=a/g" &&
|
|
|
|
echo "b/g test=a/b/g"
|
|
|
|
) >a/.gitattributes &&
|
|
|
|
(
|
|
|
|
echo "h test=a/b/h" &&
|
|
|
|
echo "d/* test=a/b/d/*"
|
2010-04-06 20:46:44 +08:00
|
|
|
echo "d/yes notest"
|
2011-08-04 12:36:15 +08:00
|
|
|
) >a/b/.gitattributes &&
|
2010-09-01 06:42:43 +08:00
|
|
|
(
|
|
|
|
echo "global test=global"
|
2011-08-04 12:36:31 +08:00
|
|
|
) >"$HOME"/global-gitattributes &&
|
2011-09-23 07:34:05 +08:00
|
|
|
cat <<-EOF >expect-all
|
|
|
|
f: test: f
|
|
|
|
a/f: test: f
|
|
|
|
a/c/f: test: f
|
|
|
|
a/g: test: a/g
|
|
|
|
a/b/g: test: a/b/g
|
|
|
|
b/g: test: unspecified
|
|
|
|
a/b/h: test: a/b/h
|
|
|
|
a/b/d/g: test: a/b/d/*
|
|
|
|
onoff: test: unset
|
|
|
|
offon: test: set
|
|
|
|
no: notest: set
|
|
|
|
no: test: unspecified
|
|
|
|
a/b/d/no: notest: set
|
|
|
|
a/b/d/no: test: a/b/d/*
|
|
|
|
a/b/d/yes: notest: set
|
|
|
|
a/b/d/yes: test: unspecified
|
|
|
|
EOF
|
2008-02-07 16:02:08 +08:00
|
|
|
'
|
|
|
|
|
2011-08-04 12:36:14 +08:00
|
|
|
test_expect_success 'command line checks' '
|
2011-08-04 12:36:16 +08:00
|
|
|
test_must_fail git check-attr &&
|
|
|
|
test_must_fail git check-attr -- &&
|
2011-08-04 12:36:29 +08:00
|
|
|
test_must_fail git check-attr test &&
|
|
|
|
test_must_fail git check-attr test -- &&
|
2011-08-04 12:36:16 +08:00
|
|
|
test_must_fail git check-attr -- f &&
|
|
|
|
echo "f" | test_must_fail git check-attr --stdin &&
|
|
|
|
echo "f" | test_must_fail git check-attr --stdin -- f &&
|
|
|
|
echo "f" | test_must_fail git check-attr --stdin test -- f &&
|
2011-08-04 12:36:14 +08:00
|
|
|
test_must_fail git check-attr "" -- f
|
|
|
|
'
|
|
|
|
|
2008-02-07 16:02:08 +08:00
|
|
|
test_expect_success 'attribute test' '
|
|
|
|
attr_check f f &&
|
|
|
|
attr_check a/f f &&
|
|
|
|
attr_check a/c/f f &&
|
|
|
|
attr_check a/g a/g &&
|
|
|
|
attr_check a/b/g a/b/g &&
|
|
|
|
attr_check b/g unspecified &&
|
|
|
|
attr_check a/b/h a/b/h &&
|
2010-08-29 02:18:36 +08:00
|
|
|
attr_check a/b/d/g "a/b/d/*" &&
|
|
|
|
attr_check onoff unset &&
|
|
|
|
attr_check offon set &&
|
|
|
|
attr_check no unspecified &&
|
|
|
|
attr_check a/b/d/no "a/b/d/*" &&
|
2010-04-06 20:46:44 +08:00
|
|
|
attr_check a/b/d/yes unspecified
|
2008-02-07 16:02:08 +08:00
|
|
|
'
|
|
|
|
|
2011-10-11 23:53:31 +08:00
|
|
|
test_expect_success 'attribute matching is case sensitive when core.ignorecase=0' '
|
|
|
|
|
|
|
|
test_must_fail attr_check F f "-c core.ignorecase=0" &&
|
|
|
|
test_must_fail attr_check a/F f "-c core.ignorecase=0" &&
|
|
|
|
test_must_fail attr_check a/c/F f "-c core.ignorecase=0" &&
|
|
|
|
test_must_fail attr_check a/G a/g "-c core.ignorecase=0" &&
|
|
|
|
test_must_fail attr_check a/B/g a/b/g "-c core.ignorecase=0" &&
|
|
|
|
test_must_fail attr_check a/b/G a/b/g "-c core.ignorecase=0" &&
|
|
|
|
test_must_fail attr_check a/b/H a/b/h "-c core.ignorecase=0" &&
|
|
|
|
test_must_fail attr_check a/b/D/g "a/b/d/*" "-c core.ignorecase=0" &&
|
|
|
|
test_must_fail attr_check oNoFf unset "-c core.ignorecase=0" &&
|
|
|
|
test_must_fail attr_check oFfOn set "-c core.ignorecase=0" &&
|
|
|
|
attr_check NO unspecified "-c core.ignorecase=0" &&
|
|
|
|
test_must_fail attr_check a/b/D/NO "a/b/d/*" "-c core.ignorecase=0" &&
|
|
|
|
attr_check a/b/d/YES a/b/d/* "-c core.ignorecase=0" &&
|
|
|
|
test_must_fail attr_check a/E/f "A/e/F" "-c core.ignorecase=0"
|
|
|
|
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'attribute matching is case insensitive when core.ignorecase=1' '
|
|
|
|
|
|
|
|
attr_check F f "-c core.ignorecase=1" &&
|
|
|
|
attr_check a/F f "-c core.ignorecase=1" &&
|
|
|
|
attr_check a/c/F f "-c core.ignorecase=1" &&
|
|
|
|
attr_check a/G a/g "-c core.ignorecase=1" &&
|
|
|
|
attr_check a/B/g a/b/g "-c core.ignorecase=1" &&
|
|
|
|
attr_check a/b/G a/b/g "-c core.ignorecase=1" &&
|
|
|
|
attr_check a/b/H a/b/h "-c core.ignorecase=1" &&
|
|
|
|
attr_check a/b/D/g "a/b/d/*" "-c core.ignorecase=1" &&
|
|
|
|
attr_check oNoFf unset "-c core.ignorecase=1" &&
|
|
|
|
attr_check oFfOn set "-c core.ignorecase=1" &&
|
|
|
|
attr_check NO unspecified "-c core.ignorecase=1" &&
|
|
|
|
attr_check a/b/D/NO "a/b/d/*" "-c core.ignorecase=1" &&
|
|
|
|
attr_check a/b/d/YES unspecified "-c core.ignorecase=1" &&
|
|
|
|
attr_check a/E/f "A/e/F" "-c core.ignorecase=1"
|
|
|
|
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'check whether FS is case-insensitive' '
|
|
|
|
mkdir junk &&
|
|
|
|
echo good >junk/CamelCase &&
|
|
|
|
echo bad >junk/camelcase &&
|
|
|
|
if test "$(cat junk/CamelCase)" != good
|
|
|
|
then
|
|
|
|
test_set_prereq CASE_INSENSITIVE_FS
|
|
|
|
fi
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success CASE_INSENSITIVE_FS 'additional case insensitivity tests' '
|
|
|
|
test_must_fail attr_check a/B/D/g "a/b/d/*" "-c core.ignorecase=0" &&
|
|
|
|
test_must_fail attr_check A/B/D/NO "a/b/d/*" "-c core.ignorecase=0" &&
|
|
|
|
attr_check A/b/h a/b/h "-c core.ignorecase=1" &&
|
|
|
|
attr_check a/B/D/g "a/b/d/*" "-c core.ignorecase=1" &&
|
|
|
|
attr_check A/B/D/NO "a/b/d/*" "-c core.ignorecase=1"
|
|
|
|
'
|
|
|
|
|
2011-08-04 12:47:46 +08:00
|
|
|
test_expect_success 'unnormalized paths' '
|
2011-08-04 12:47:44 +08:00
|
|
|
attr_check ./f f &&
|
|
|
|
attr_check ./a/g a/g &&
|
|
|
|
attr_check a/./g a/g &&
|
|
|
|
attr_check a/c/../b/g a/b/g
|
|
|
|
'
|
|
|
|
|
2011-08-04 12:47:46 +08:00
|
|
|
test_expect_success 'relative paths' '
|
2011-08-04 12:47:45 +08:00
|
|
|
(cd a && attr_check ../f f) &&
|
|
|
|
(cd a && attr_check f f) &&
|
|
|
|
(cd a && attr_check i a/i) &&
|
|
|
|
(cd a && attr_check g a/g) &&
|
|
|
|
(cd a && attr_check b/g a/b/g) &&
|
|
|
|
(cd b && attr_check ../a/f f) &&
|
|
|
|
(cd b && attr_check ../a/g a/g) &&
|
|
|
|
(cd b && attr_check ../a/b/g a/b/g)
|
|
|
|
'
|
|
|
|
|
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>
2012-01-11 02:08:21 +08:00
|
|
|
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
|
|
|
|
'
|
|
|
|
|
2010-09-01 06:42:43 +08:00
|
|
|
test_expect_success 'core.attributesfile' '
|
|
|
|
attr_check global unspecified &&
|
|
|
|
git config core.attributesfile "$HOME/global-gitattributes" &&
|
|
|
|
attr_check global global &&
|
|
|
|
git config core.attributesfile "~/global-gitattributes" &&
|
|
|
|
attr_check global global &&
|
2011-09-23 07:34:05 +08:00
|
|
|
echo "global test=precedence" >>.gitattributes &&
|
2010-09-01 06:42:43 +08:00
|
|
|
attr_check global precedence
|
|
|
|
'
|
|
|
|
|
2008-10-07 08:16:52 +08:00
|
|
|
test_expect_success 'attribute test: read paths from stdin' '
|
2011-09-23 07:34:05 +08:00
|
|
|
grep -v notest <expect-all >expect &&
|
|
|
|
sed -e "s/:.*//" <expect | git check-attr --stdin test >actual &&
|
2008-10-07 08:16:52 +08:00
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
|
2011-08-04 12:36:30 +08:00
|
|
|
test_expect_success 'attribute test: --all option' '
|
2011-09-23 05:44:20 +08:00
|
|
|
grep -v unspecified <expect-all | sort >specified-all &&
|
|
|
|
sed -e "s/:.*//" <expect-all | uniq >stdin-all &&
|
|
|
|
git check-attr --stdin --all <stdin-all | sort >actual &&
|
|
|
|
test_cmp specified-all actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'attribute test: --cached option' '
|
|
|
|
: >empty &&
|
|
|
|
git check-attr --cached --stdin --all <stdin-all | sort >actual &&
|
|
|
|
test_cmp empty actual &&
|
|
|
|
git add .gitattributes a/.gitattributes a/b/.gitattributes &&
|
|
|
|
git check-attr --cached --stdin --all <stdin-all | sort >actual &&
|
|
|
|
test_cmp specified-all actual
|
2011-08-04 12:36:30 +08:00
|
|
|
'
|
|
|
|
|
2008-04-23 02:19:12 +08:00
|
|
|
test_expect_success 'root subdir attribute test' '
|
|
|
|
attr_check a/i a/i &&
|
|
|
|
attr_check subdir/a/i unspecified
|
|
|
|
'
|
|
|
|
|
2008-06-08 23:16:11 +08:00
|
|
|
test_expect_success 'setup bare' '
|
|
|
|
git clone --bare . bare.git &&
|
|
|
|
cd bare.git
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'bare repository: check that .gitattribute is ignored' '
|
|
|
|
(
|
|
|
|
echo "f test=f"
|
|
|
|
echo "a/i test=a/i"
|
|
|
|
) >.gitattributes &&
|
|
|
|
attr_check f unspecified &&
|
|
|
|
attr_check a/f unspecified &&
|
|
|
|
attr_check a/c/f unspecified &&
|
|
|
|
attr_check a/i unspecified &&
|
|
|
|
attr_check subdir/a/i unspecified
|
|
|
|
'
|
|
|
|
|
2011-09-23 05:44:20 +08:00
|
|
|
test_expect_success 'bare repository: check that --cached honors index' '
|
|
|
|
GIT_INDEX_FILE=../.git/index \
|
|
|
|
git check-attr --cached --stdin --all <../stdin-all |
|
|
|
|
sort >actual &&
|
|
|
|
test_cmp ../specified-all actual
|
|
|
|
'
|
|
|
|
|
2008-06-08 23:16:11 +08:00
|
|
|
test_expect_success 'bare repository: test info/attributes' '
|
|
|
|
(
|
|
|
|
echo "f test=f"
|
|
|
|
echo "a/i test=a/i"
|
|
|
|
) >info/attributes &&
|
|
|
|
attr_check f f &&
|
|
|
|
attr_check a/f f &&
|
|
|
|
attr_check a/c/f f &&
|
|
|
|
attr_check a/i a/i &&
|
|
|
|
attr_check subdir/a/i unspecified
|
|
|
|
'
|
|
|
|
|
2008-02-07 16:02:08 +08:00
|
|
|
test_done
|