(command.CommandList children: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name left:<Id.Lit_VarLike 'test_description='> name:test_description) op: assign_op.Equal rhs: {<gitattributes>} spids: [4] ) ] redirects: [] ) (C {<.>} {<'./test-lib.sh'>}) (command.ShFunction name: attr_check body: (BraceGroup left: <Id.Lit_LBrace '{'> children: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name left:<Id.Lit_VarLike 'path='> name:path) op: assign_op.Equal rhs: {(DQ ($ Id.VSub_Number 1))} spids: [21] ) (assign_pair lhs: (sh_lhs_expr.Name left:<Id.Lit_VarLike 'expect='> name:expect) op: assign_op.Equal rhs: {(DQ ($ Id.VSub_Number 2))} spids: [26] ) ] redirects: [] ) (command.AndOr ops: [Id.Op_DAmp Id.Op_DAmp Id.Op_DAmp] children: [ (command.Simple words: [ {<git>} {($ Id.VSub_Number 3)} {<check-attr>} {<test>} {<-->} {(DQ ($ Id.VSub_DollarName path))} ] redirects: [ (redir op: <Id.Redir_Great '>'> loc: (redir_loc.Fd fd:1) arg: {<actual>} ) (redir op: <Id.Redir_Great '2>'> loc: (redir_loc.Fd fd:2) arg: {<err>} ) ] more_env: [] do_fork: T ) (command.Simple words: [{<echo>} {(DQ ($ Id.VSub_DollarName path) <': test: '> ($ Id.VSub_Number 2))}] redirects: [(redir op:<Id.Redir_Great '>'> loc:(redir_loc.Fd fd:1) arg:{<expect>})] more_env: [] do_fork: T ) (C {<test_cmp>} {<expect>} {<actual>}) (C {<test_line_count>} {<Id.Lit_Equals '='>} {<0>} {<err>}) ] ) ] redirects: [] right: <Id.Lit_RBrace '}'> ) ) (C {<test_expect_success>} {(SQ <setup>)} { (SQ <'\n'> <'\tmkdir -p a/b/d a/c b &&\n'> <'\t(\n'> <'\t\techo "[attr]notest !test"\n'> <'\t\techo "f\ttest=f"\n'> <'\t\techo "a/i test=a/i"\n'> <'\t\techo "onoff test -test"\n'> <'\t\techo "offon -test test"\n'> <'\t\techo "no notest"\n'> <'\t\techo "A/e/F test=A/e/F"\n'> <'\t) >.gitattributes &&\n'> <'\t(\n'> <'\t\techo "g test=a/g" &&\n'> <'\t\techo "b/g test=a/b/g"\n'> <'\t) >a/.gitattributes &&\n'> <'\t(\n'> <'\t\techo "h test=a/b/h" &&\n'> <'\t\techo "d/* test=a/b/d/*"\n'> <'\t\techo "d/yes notest"\n'> <'\t) >a/b/.gitattributes &&\n'> <'\t(\n'> <'\t\techo "global test=global"\n'> <'\t) >"$HOME"/global-gitattributes &&\n'> <'\tcat <<-EOF >expect-all\n'> <'\tf: test: f\n'> <'\ta/f: test: f\n'> <'\ta/c/f: test: f\n'> <'\ta/g: test: a/g\n'> <'\ta/b/g: test: a/b/g\n'> <'\tb/g: test: unspecified\n'> <'\ta/b/h: test: a/b/h\n'> <'\ta/b/d/g: test: a/b/d/*\n'> <'\tonoff: test: unset\n'> <'\toffon: test: set\n'> <'\tno: notest: set\n'> <'\tno: test: unspecified\n'> <'\ta/b/d/no: notest: set\n'> <'\ta/b/d/no: test: a/b/d/*\n'> <'\ta/b/d/yes: notest: set\n'> <'\ta/b/d/yes: test: unspecified\n'> <'\tEOF\n'> ) } ) (C {<test_expect_success>} {(SQ <'command line checks'>)} { (SQ <'\n'> <'\ttest_must_fail git check-attr &&\n'> <'\ttest_must_fail git check-attr -- &&\n'> <'\ttest_must_fail git check-attr test &&\n'> <'\ttest_must_fail git check-attr test -- &&\n'> <'\ttest_must_fail git check-attr -- f &&\n'> <'\techo "f" | test_must_fail git check-attr --stdin &&\n'> <'\techo "f" | test_must_fail git check-attr --stdin -- f &&\n'> <'\techo "f" | test_must_fail git check-attr --stdin test -- f &&\n'> <'\ttest_must_fail git check-attr "" -- f\n'> ) } ) (C {<test_expect_success>} {(SQ <'attribute test'>)} { (SQ <'\n'> <'\tattr_check f f &&\n'> <'\tattr_check a/f f &&\n'> <'\tattr_check a/c/f f &&\n'> <'\tattr_check a/g a/g &&\n'> <'\tattr_check a/b/g a/b/g &&\n'> <'\tattr_check b/g unspecified &&\n'> <'\tattr_check a/b/h a/b/h &&\n'> <'\tattr_check a/b/d/g "a/b/d/*" &&\n'> <'\tattr_check onoff unset &&\n'> <'\tattr_check offon set &&\n'> <'\tattr_check no unspecified &&\n'> <'\tattr_check a/b/d/no "a/b/d/*" &&\n'> <'\tattr_check a/b/d/yes unspecified\n'> ) } ) (C {<test_expect_success>} {(SQ <'attribute matching is case sensitive when core.ignorecase=0'>)} { (SQ <'\n'> <'\n'> <'\ttest_must_fail attr_check F f "-c core.ignorecase=0" &&\n'> <'\ttest_must_fail attr_check a/F f "-c core.ignorecase=0" &&\n'> <'\ttest_must_fail attr_check a/c/F f "-c core.ignorecase=0" &&\n'> <'\ttest_must_fail attr_check a/G a/g "-c core.ignorecase=0" &&\n'> <'\ttest_must_fail attr_check a/B/g a/b/g "-c core.ignorecase=0" &&\n'> <'\ttest_must_fail attr_check a/b/G a/b/g "-c core.ignorecase=0" &&\n'> <'\ttest_must_fail attr_check a/b/H a/b/h "-c core.ignorecase=0" &&\n'> <'\ttest_must_fail attr_check a/b/D/g "a/b/d/*" "-c core.ignorecase=0" &&\n'> <'\ttest_must_fail attr_check oNoFf unset "-c core.ignorecase=0" &&\n'> <'\ttest_must_fail attr_check oFfOn set "-c core.ignorecase=0" &&\n'> <'\tattr_check NO unspecified "-c core.ignorecase=0" &&\n'> <'\ttest_must_fail attr_check a/b/D/NO "a/b/d/*" "-c core.ignorecase=0" &&\n'> <'\tattr_check a/b/d/YES a/b/d/* "-c core.ignorecase=0" &&\n'> <'\ttest_must_fail attr_check a/E/f "A/e/F" "-c core.ignorecase=0"\n'> <'\n'> ) } ) (C {<test_expect_success>} {(SQ <'attribute matching is case insensitive when core.ignorecase=1'>)} { (SQ <'\n'> <'\n'> <'\tattr_check F f "-c core.ignorecase=1" &&\n'> <'\tattr_check a/F f "-c core.ignorecase=1" &&\n'> <'\tattr_check a/c/F f "-c core.ignorecase=1" &&\n'> <'\tattr_check a/G a/g "-c core.ignorecase=1" &&\n'> <'\tattr_check a/B/g a/b/g "-c core.ignorecase=1" &&\n'> <'\tattr_check a/b/G a/b/g "-c core.ignorecase=1" &&\n'> <'\tattr_check a/b/H a/b/h "-c core.ignorecase=1" &&\n'> <'\tattr_check a/b/D/g "a/b/d/*" "-c core.ignorecase=1" &&\n'> <'\tattr_check oNoFf unset "-c core.ignorecase=1" &&\n'> <'\tattr_check oFfOn set "-c core.ignorecase=1" &&\n'> <'\tattr_check NO unspecified "-c core.ignorecase=1" &&\n'> <'\tattr_check a/b/D/NO "a/b/d/*" "-c core.ignorecase=1" &&\n'> <'\tattr_check a/b/d/YES unspecified "-c core.ignorecase=1" &&\n'> <'\tattr_check a/E/f "A/e/F" "-c core.ignorecase=1"\n'> <'\n'> ) } ) (C {<test_expect_success>} {<CASE_INSENSITIVE_FS>} {(SQ <'additional case insensitivity tests'>)} { (SQ <'\n'> <'\ttest_must_fail attr_check a/B/D/g "a/b/d/*" "-c core.ignorecase=0" &&\n'> <'\ttest_must_fail attr_check A/B/D/NO "a/b/d/*" "-c core.ignorecase=0" &&\n'> <'\tattr_check A/b/h a/b/h "-c core.ignorecase=1" &&\n'> <'\tattr_check a/B/D/g "a/b/d/*" "-c core.ignorecase=1" &&\n'> <'\tattr_check A/B/D/NO "a/b/d/*" "-c core.ignorecase=1"\n'> ) } ) (C {<test_expect_success>} {(SQ <'unnormalized paths'>)} { (SQ <'\n'> <'\tattr_check ./f f &&\n'> <'\tattr_check ./a/g a/g &&\n'> <'\tattr_check a/./g a/g &&\n'> <'\tattr_check a/c/../b/g a/b/g\n'> ) } ) (C {<test_expect_success>} {(SQ <'relative paths'>)} { (SQ <'\n'> <'\t(cd a && attr_check ../f f) &&\n'> <'\t(cd a && attr_check f f) &&\n'> <'\t(cd a && attr_check i a/i) &&\n'> <'\t(cd a && attr_check g a/g) &&\n'> <'\t(cd a && attr_check b/g a/b/g) &&\n'> <'\t(cd b && attr_check ../a/f f) &&\n'> <'\t(cd b && attr_check ../a/g a/g) &&\n'> <'\t(cd b && attr_check ../a/b/g a/b/g)\n'> ) } ) (C {<test_expect_success>} {(SQ <'prefixes are not confused with leading directories'>)} { (SQ <'\n'> <'\tattr_check a_plus/g unspecified &&\n'> <'\tcat >expect <<-\\EOF &&\n'> <'\ta/g: test: a/g\n'> <'\ta_plus/g: test: unspecified\n'> <'\tEOF\n'> <'\tgit check-attr test a/g a_plus/g >actual &&\n'> <'\ttest_cmp expect actual\n'> ) } ) (C {<test_expect_success>} {(SQ <core.attributesfile>)} { (SQ <'\n'> <'\tattr_check global unspecified &&\n'> <'\tgit config core.attributesfile "$HOME/global-gitattributes" &&\n'> <'\tattr_check global global &&\n'> <'\tgit config core.attributesfile "~/global-gitattributes" &&\n'> <'\tattr_check global global &&\n'> <'\techo "global test=precedence" >>.gitattributes &&\n'> <'\tattr_check global precedence\n'> ) } ) (C {<test_expect_success>} {(SQ <'attribute test: read paths from stdin'>)} { (SQ <'\n'> <'\tgrep -v notest <expect-all >expect &&\n'> <'\tsed -e "s/:.*//" <expect | git check-attr --stdin test >actual &&\n'> <'\ttest_cmp expect actual\n'> ) } ) (C {<test_expect_success>} {(SQ <'attribute test: --all option'>)} { (SQ <'\n'> <'\tgrep -v unspecified <expect-all | sort >specified-all &&\n'> <'\tsed -e "s/:.*//" <expect-all | uniq >stdin-all &&\n'> <'\tgit check-attr --stdin --all <stdin-all | sort >actual &&\n'> <'\ttest_cmp specified-all actual\n'> ) } ) (C {<test_expect_success>} {(SQ <'attribute test: --cached option'>)} { (SQ <'\n'> <'\t: >empty &&\n'> <'\tgit check-attr --cached --stdin --all <stdin-all | sort >actual &&\n'> <'\ttest_cmp empty actual &&\n'> <'\tgit add .gitattributes a/.gitattributes a/b/.gitattributes &&\n'> <'\tgit check-attr --cached --stdin --all <stdin-all | sort >actual &&\n'> <'\ttest_cmp specified-all actual\n'> ) } ) (C {<test_expect_success>} {(SQ <'root subdir attribute test'>)} {(SQ <'\n'> <'\tattr_check a/i a/i &&\n'> <'\tattr_check subdir/a/i unspecified\n'>)} ) (C {<test_expect_success>} {(SQ <'negative patterns'>)} {(SQ <'\n'> <'\techo "!f test=bar" >.gitattributes &&\n'> <'\tgit check-attr test -- '>) (DQ <'\''>) (SQ <'!f'>) (DQ <'\''>) (SQ <' 2>errors &&\n'> <'\ttest_i18ngrep "Negative patterns are ignored" errors\n'>) } ) (C {<test_expect_success>} {(SQ <'patterns starting with exclamation'>)} {(SQ <'\n'> <'\techo "\\!f test=foo" >.gitattributes &&\n'> <'\tattr_check "!f" foo\n'>)} ) (C {<test_expect_success>} {(SQ <'"**" test'>)} { (SQ <'\n'> <'\techo "**/f foo=bar" >.gitattributes &&\n'> <'\tcat <<\\EOF >expect &&\n'> <'f: foo: bar\n'> <'a/f: foo: bar\n'> <'a/b/f: foo: bar\n'> <'a/b/c/f: foo: bar\n'> <'EOF\n'> <'\tgit check-attr foo -- "f" >actual 2>err &&\n'> <'\tgit check-attr foo -- "a/f" >>actual 2>>err &&\n'> <'\tgit check-attr foo -- "a/b/f" >>actual 2>>err &&\n'> <'\tgit check-attr foo -- "a/b/c/f" >>actual 2>>err &&\n'> <'\ttest_cmp expect actual &&\n'> <'\ttest_line_count = 0 err\n'> ) } ) (C {<test_expect_success>} {(SQ <'"**" with no slashes test'>)} { (SQ <'\n'> <'\techo "a**f foo=bar" >.gitattributes &&\n'> <'\tgit check-attr foo -- "f" >actual &&\n'> <'\tcat <<\\EOF >expect &&\n'> <'f: foo: unspecified\n'> <'af: foo: bar\n'> <'axf: foo: bar\n'> <'a/f: foo: unspecified\n'> <'a/b/f: foo: unspecified\n'> <'a/b/c/f: foo: unspecified\n'> <'EOF\n'> <'\tgit check-attr foo -- "f" >actual 2>err &&\n'> <'\tgit check-attr foo -- "af" >>actual 2>err &&\n'> <'\tgit check-attr foo -- "axf" >>actual 2>err &&\n'> <'\tgit check-attr foo -- "a/f" >>actual 2>>err &&\n'> <'\tgit check-attr foo -- "a/b/f" >>actual 2>>err &&\n'> <'\tgit check-attr foo -- "a/b/c/f" >>actual 2>>err &&\n'> <'\ttest_cmp expect actual &&\n'> <'\ttest_line_count = 0 err\n'> ) } ) (C {<test_expect_success>} {(SQ <'using --git-dir and --work-tree'>)} { (SQ <'\n'> <'\tmkdir unreal real &&\n'> <'\tgit init real &&\n'> <'\techo "file test=in-real" >real/.gitattributes &&\n'> <'\t(\n'> <'\t\tcd unreal &&\n'> <'\t\tattr_check file in-real "--git-dir ../real/.git --work-tree ../real"\n'> <'\t)\n'> ) } ) (C {<test_expect_success>} {(SQ <'setup bare'>)} {(SQ <'\n'> <'\tgit clone --bare . bare.git\n'>)}) (C {<test_expect_success>} {(SQ <'bare repository: check that .gitattribute is ignored'>)} { (SQ <'\n'> <'\t(\n'> <'\t\tcd bare.git &&\n'> <'\t\t(\n'> <'\t\t\techo "f\ttest=f"\n'> <'\t\t\techo "a/i test=a/i"\n'> <'\t\t) >.gitattributes &&\n'> <'\t\tattr_check f unspecified &&\n'> <'\t\tattr_check a/f unspecified &&\n'> <'\t\tattr_check a/c/f unspecified &&\n'> <'\t\tattr_check a/i unspecified &&\n'> <'\t\tattr_check subdir/a/i unspecified\n'> <'\t)\n'> ) } ) (C {<test_expect_success>} {(SQ <'bare repository: check that --cached honors index'>)} { (SQ <'\n'> <'\t(\n'> <'\t\tcd bare.git &&\n'> <'\t\tGIT_INDEX_FILE=../.git/index \\\n'> <'\t\tgit check-attr --cached --stdin --all <../stdin-all |\n'> <'\t\tsort >actual &&\n'> <'\t\ttest_cmp ../specified-all actual\n'> <'\t)\n'> ) } ) (C {<test_expect_success>} {(SQ <'bare repository: test info/attributes'>)} { (SQ <'\n'> <'\t(\n'> <'\t\tcd bare.git &&\n'> <'\t\t(\n'> <'\t\t\techo "f\ttest=f"\n'> <'\t\t\techo "a/i test=a/i"\n'> <'\t\t) >info/attributes &&\n'> <'\t\tattr_check f f &&\n'> <'\t\tattr_check a/f f &&\n'> <'\t\tattr_check a/c/f f &&\n'> <'\t\tattr_check a/i a/i &&\n'> <'\t\tattr_check subdir/a/i unspecified\n'> <'\t)\n'> ) } ) (C {<test_done>}) ] )