diff options
Diffstat (limited to 't/t0003-attributes.sh')
-rwxr-xr-x | t/t0003-attributes.sh | 362 |
1 files changed, 327 insertions, 35 deletions
diff --git a/t/t0003-attributes.sh b/t/t0003-attributes.sh index 71e63d8..774b52c 100755 --- a/t/t0003-attributes.sh +++ b/t/t0003-attributes.sh @@ -2,35 +2,72 @@ test_description=gitattributes +TEST_PASSES_SANITIZE_LEAK=true +TEST_CREATE_REPO_NO_TEMPLATE=1 . ./test-lib.sh +attr_check_basic () { + path="$1" expect="$2" git_opts="$3" && + + git $git_opts check-attr test -- "$path" >actual 2>err && + echo "$path: test: $expect" >expect && + test_cmp expect actual +} + attr_check () { - path="$1" expect="$2" + attr_check_basic "$@" && + test_must_be_empty err +} - git $3 check-attr test -- "$path" >actual 2>err && - echo "$path: test: $2" >expect && - test_cmp expect actual && - test_line_count = 0 err +attr_check_object_mode_basic () { + path="$1" && + expect="$2" && + check_opts="$3" && + git check-attr $check_opts builtin_objectmode -- "$path" >actual 2>err && + echo "$path: builtin_objectmode: $expect" >expect && + test_cmp expect actual } -attr_check_quote () { +attr_check_object_mode () { + attr_check_object_mode_basic "$@" && + test_must_be_empty err +} - path="$1" - quoted_path="$2" - expect="$3" +attr_check_quote () { + path="$1" quoted_path="$2" expect="$3" && git check-attr test -- "$path" >actual && echo "\"$quoted_path\": test: $expect" >expect && test_cmp expect actual +} + +attr_check_source () { + path="$1" expect="$2" source="$3" git_opts="$4" && + echo "$path: test: $expect" >expect && + + git $git_opts check-attr --source $source test -- "$path" >actual 2>err && + test_cmp expect actual && + test_must_be_empty err && + + git $git_opts --attr-source="$source" check-attr test -- "$path" >actual 2>err && + test_cmp expect actual && + test_must_be_empty err + + git $git_opts -c "attr.tree=$source" check-attr test -- "$path" >actual 2>err && + test_cmp expect actual && + test_must_be_empty err + + GIT_ATTR_SOURCE="$source" git $git_opts check-attr test -- "$path" >actual 2>err && + test_cmp expect actual && + test_must_be_empty err } test_expect_success 'open-quoted pathname' ' echo "\"a test=a" >.gitattributes && - test_must_fail attr_check a a + attr_check a unspecified ' - test_expect_success 'setup' ' mkdir -p a/b/d a/c b && ( @@ -77,12 +114,23 @@ test_expect_success 'setup' ' EOF ' +test_expect_success 'setup branches' ' + mkdir -p foo/bar && + test_commit --printf "add .gitattributes" foo/bar/.gitattributes \ + "f test=f\na/i test=n\n" tag-1 && + test_commit --printf "add .gitattributes" foo/bar/.gitattributes \ + "g test=g\na/i test=m\n" tag-2 && + rm foo/bar/.gitattributes +' + test_expect_success 'command line checks' ' test_must_fail git check-attr && test_must_fail git check-attr -- && test_must_fail git check-attr test && test_must_fail git check-attr test -- && test_must_fail git check-attr -- f && + test_must_fail git check-attr --source && + test_must_fail git check-attr --source not-a-valid-ref && 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 && @@ -112,20 +160,20 @@ test_expect_success 'attribute test' ' 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 F unspecified "-c core.ignorecase=0" && + attr_check a/F unspecified "-c core.ignorecase=0" && + attr_check a/c/F unspecified "-c core.ignorecase=0" && + attr_check a/G unspecified "-c core.ignorecase=0" && + attr_check a/B/g a/g "-c core.ignorecase=0" && + attr_check a/b/G unspecified "-c core.ignorecase=0" && + attr_check a/b/H unspecified "-c core.ignorecase=0" && + attr_check a/b/D/g a/g "-c core.ignorecase=0" && + attr_check oNoFf unspecified "-c core.ignorecase=0" && + attr_check oFfOn unspecified "-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/NO unspecified "-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" + attr_check a/E/f f "-c core.ignorecase=0" ' @@ -149,8 +197,8 @@ test_expect_success 'attribute matching is case insensitive when core.ignorecase ' 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/D/g a/g "-c core.ignorecase=0" && + attr_check A/B/D/NO unspecified "-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" @@ -200,18 +248,24 @@ test_expect_success 'attribute test: read paths from stdin' ' test_cmp expect actual ' -test_expect_success 'attribute test: --all option' ' +test_expect_success 'setup --all option' ' 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 && + sed -e "s/:.*//" <expect-all | uniq >stdin-all +' + +test_expect_success 'attribute test: --all option' ' + git check-attr --stdin --all <stdin-all >tmp && + sort tmp >actual && test_cmp specified-all actual ' test_expect_success 'attribute test: --cached option' ' - git check-attr --cached --stdin --all <stdin-all | sort >actual && + git check-attr --cached --stdin --all <stdin-all >tmp && + sort tmp >actual && test_must_be_empty actual && git add .gitattributes a/.gitattributes a/b/.gitattributes && - git check-attr --cached --stdin --all <stdin-all | sort >actual && + git check-attr --cached --stdin --all <stdin-all >tmp && + sort tmp >actual && test_cmp specified-all actual ' @@ -223,7 +277,7 @@ test_expect_success 'root subdir attribute test' ' test_expect_success 'negative patterns' ' echo "!f test=bar" >.gitattributes && git check-attr test -- '"'"'!f'"'"' 2>errors && - test_i18ngrep "Negative patterns are ignored" errors + test_grep "Negative patterns are ignored" errors ' test_expect_success 'patterns starting with exclamation' ' @@ -244,7 +298,7 @@ EOF git check-attr foo -- "a/b/f" >>actual 2>>err && git check-attr foo -- "a/b/c/f" >>actual 2>>err && test_cmp expect actual && - test_line_count = 0 err + test_must_be_empty err ' test_expect_success '"**" with no slashes test' ' @@ -265,7 +319,7 @@ EOF git check-attr foo -- "a/b/f" >>actual 2>>err && git check-attr foo -- "a/b/c/f" >>actual 2>>err && test_cmp expect actual && - test_line_count = 0 err + test_must_be_empty err ' test_expect_success 'using --git-dir and --work-tree' ' @@ -278,8 +332,17 @@ test_expect_success 'using --git-dir and --work-tree' ' ) ' +test_expect_success 'using --source' ' + attr_check_source foo/bar/f f tag-1 && + attr_check_source foo/bar/a/i n tag-1 && + attr_check_source foo/bar/f unspecified tag-2 && + attr_check_source foo/bar/a/i m tag-2 && + attr_check_source foo/bar/g g tag-2 && + attr_check_source foo/bar/g unspecified tag-1 +' + test_expect_success 'setup bare' ' - git clone --bare . bare.git + git clone --template= --bare . bare.git ' test_expect_success 'bare repository: check that .gitattribute is ignored' ' @@ -297,6 +360,86 @@ test_expect_success 'bare repository: check that .gitattribute is ignored' ' ) ' +bad_attr_source_err="fatal: bad --attr-source or GIT_ATTR_SOURCE" + +test_expect_success '--attr-source is bad' ' + test_when_finished rm -rf empty && + git init empty && + ( + cd empty && + echo "$bad_attr_source_err" >expect_err && + test_must_fail git --attr-source=HEAD check-attr test -- f/path 2>err && + test_cmp expect_err err + ) +' + +test_expect_success 'attr.tree when HEAD is unborn' ' + test_when_finished rm -rf empty && + git init empty && + ( + cd empty && + echo "f/path: test: unspecified" >expect && + git -c attr.tree=HEAD check-attr test -- f/path >actual 2>err && + test_must_be_empty err && + test_cmp expect actual + ) +' + +test_expect_success 'bad attr source defaults to reading .gitattributes file' ' + test_when_finished rm -rf empty && + git init empty && + ( + cd empty && + echo "f/path test=val" >.gitattributes && + echo "f/path: test: val" >expect && + git -c attr.tree=HEAD check-attr test -- f/path >actual 2>err && + test_must_be_empty err && + test_cmp expect actual + ) +' + +test_expect_success 'bare repo defaults to reading .gitattributes from HEAD' ' + test_when_finished rm -rf test bare_with_gitattribute && + git init test && + test_commit -C test gitattributes .gitattributes "f/path test=val" && + git clone --bare test bare_with_gitattribute && + echo "f/path: test: val" >expect && + git -C bare_with_gitattribute check-attr test -- f/path >actual && + test_cmp expect actual +' + +test_expect_success 'precedence of --attr-source, GIT_ATTR_SOURCE, then attr.tree' ' + test_when_finished rm -rf empty && + git init empty && + ( + cd empty && + git checkout -b attr-source && + test_commit "val1" .gitattributes "f/path test=val1" && + git checkout -b attr-tree && + test_commit "val2" .gitattributes "f/path test=val2" && + git checkout attr-source && + echo "f/path: test: val1" >expect && + GIT_ATTR_SOURCE=attr-source git -c attr.tree=attr-tree --attr-source=attr-source \ + check-attr test -- f/path >actual && + test_cmp expect actual && + GIT_ATTR_SOURCE=attr-source git -c attr.tree=attr-tree \ + check-attr test -- f/path >actual && + test_cmp expect actual + ) +' + +test_expect_success 'bare repository: with --source' ' + ( + cd bare.git && + attr_check_source foo/bar/f f tag-1 && + attr_check_source foo/bar/a/i n tag-1 && + attr_check_source foo/bar/f unspecified tag-2 && + attr_check_source foo/bar/a/i m tag-2 && + attr_check_source foo/bar/g g tag-2 && + attr_check_source foo/bar/g unspecified tag-1 + ) +' + test_expect_success 'bare repository: check that --cached honors index' ' ( cd bare.git && @@ -310,6 +453,7 @@ test_expect_success 'bare repository: check that --cached honors index' ' test_expect_success 'bare repository: test info/attributes' ' ( cd bare.git && + mkdir info && ( echo "f test=f" && echo "a/i test=a/i" @@ -334,7 +478,6 @@ test_expect_success 'binary macro expanded by -a' ' test_cmp expect actual ' - test_expect_success 'query binary macro directly' ' echo "file binary" >.gitattributes && echo file: binary: set >expect && @@ -342,4 +485,153 @@ test_expect_success 'query binary macro directly' ' test_cmp expect actual ' +test_expect_success SYMLINKS 'set up symlink tests' ' + echo "* test" >attr && + rm -f .gitattributes +' + +test_expect_success SYMLINKS 'symlinks respected in core.attributesFile' ' + test_when_finished "rm symlink" && + ln -s attr symlink && + test_config core.attributesFile "$(pwd)/symlink" && + attr_check file set +' + +test_expect_success SYMLINKS 'symlinks respected in info/attributes' ' + test_when_finished "rm .git/info/attributes" && + mkdir .git/info && + ln -s ../../attr .git/info/attributes && + attr_check file set +' + +test_expect_success SYMLINKS 'symlinks not respected in-tree' ' + test_when_finished "rm -rf .gitattributes subdir" && + ln -s attr .gitattributes && + mkdir subdir && + ln -s ../attr subdir/.gitattributes && + attr_check_basic subdir/file unspecified && + test_grep "unable to access.*gitattributes" err +' + +test_expect_success 'large attributes line ignored in tree' ' + test_when_finished "rm .gitattributes" && + printf "path %02043d" 1 >.gitattributes && + git check-attr --all path >actual 2>err && + echo "warning: ignoring overly long attributes line 1" >expect && + test_cmp expect err && + test_must_be_empty actual +' + +test_expect_success 'large attributes line ignores trailing content in tree' ' + test_when_finished "rm .gitattributes" && + # older versions of Git broke lines at 2048 bytes; the 2045 bytes + # of 0-padding here is accounting for the three bytes of "a 1", which + # would knock "trailing" to the "next" line, where it would be + # erroneously parsed. + printf "a %02045dtrailing attribute\n" 1 >.gitattributes && + git check-attr --all trailing >actual 2>err && + echo "warning: ignoring overly long attributes line 1" >expect && + test_cmp expect err && + test_must_be_empty actual +' + +test_expect_success EXPENSIVE 'large attributes file ignored in tree' ' + test_when_finished "rm .gitattributes" && + dd if=/dev/zero of=.gitattributes bs=1048576 count=101 2>/dev/null && + git check-attr --all path >/dev/null 2>err && + echo "warning: ignoring overly large gitattributes file ${SQ}.gitattributes${SQ}" >expect && + test_cmp expect err +' + +test_expect_success 'large attributes line ignored in index' ' + test_when_finished "git update-index --remove .gitattributes" && + blob=$(printf "path %02043d" 1 | git hash-object -w --stdin) && + git update-index --add --cacheinfo 100644,$blob,.gitattributes && + git check-attr --cached --all path >actual 2>err && + echo "warning: ignoring overly long attributes line 1" >expect && + test_cmp expect err && + test_must_be_empty actual +' + +test_expect_success 'large attributes line ignores trailing content in index' ' + test_when_finished "git update-index --remove .gitattributes" && + blob=$(printf "a %02045dtrailing attribute\n" 1 | git hash-object -w --stdin) && + git update-index --add --cacheinfo 100644,$blob,.gitattributes && + git check-attr --cached --all trailing >actual 2>err && + echo "warning: ignoring overly long attributes line 1" >expect && + test_cmp expect err && + test_must_be_empty actual +' + +test_expect_success EXPENSIVE 'large attributes file ignored in index' ' + test_when_finished "git update-index --remove .gitattributes" && + blob=$(dd if=/dev/zero bs=1048576 count=101 2>/dev/null | git hash-object -w --stdin) && + git update-index --add --cacheinfo 100644,$blob,.gitattributes && + git check-attr --cached --all path >/dev/null 2>err && + echo "warning: ignoring overly large gitattributes blob ${SQ}.gitattributes${SQ}" >expect && + test_cmp expect err +' + +test_expect_success 'builtin object mode attributes work (dir and regular paths)' ' + >normal && + attr_check_object_mode normal 100644 && + mkdir dir && + attr_check_object_mode dir 040000 +' + +test_expect_success POSIXPERM 'builtin object mode attributes work (executable)' ' + >exec && + chmod +x exec && + attr_check_object_mode exec 100755 +' + +test_expect_success SYMLINKS 'builtin object mode attributes work (symlinks)' ' + ln -s to_sym sym && + attr_check_object_mode sym 120000 +' + +test_expect_success 'native object mode attributes work with --cached' ' + >normal && + git add normal && + empty_blob=$(git rev-parse :normal) && + git update-index --index-info <<-EOF && + 100755 $empty_blob 0 exec + 120000 $empty_blob 0 symlink + EOF + attr_check_object_mode normal 100644 --cached && + attr_check_object_mode exec 100755 --cached && + attr_check_object_mode symlink 120000 --cached +' + +test_expect_success 'check object mode attributes work for submodules' ' + mkdir sub && + ( + cd sub && + git init && + mv .git .real && + echo "gitdir: .real" >.git && + test_commit first + ) && + attr_check_object_mode sub 160000 && + attr_check_object_mode sub unspecified --cached && + git add sub && + attr_check_object_mode sub 160000 --cached +' + +test_expect_success 'we do not allow user defined builtin_* attributes' ' + echo "foo* builtin_foo" >.gitattributes && + git add .gitattributes 2>actual && + echo "builtin_foo is not a valid attribute name: .gitattributes:1" >expect && + test_cmp expect actual +' + +test_expect_success 'user defined builtin_objectmode values are ignored' ' + echo "foo* builtin_objectmode=12345" >.gitattributes && + git add .gitattributes && + >foo_1 && + attr_check_object_mode_basic foo_1 100644 && + echo "builtin_objectmode is not a valid attribute name: .gitattributes:1" >expect && + test_cmp expect err +' + test_done |