(CommandList children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:test_description) op: Equal rhs: {(gitattributes)} spids: [4] ) ] spids: [4] ) (C {(.)} {(./test-lib.sh)}) (FuncDef name: attr_check body: (BraceGroup children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:path) op: Equal rhs: {(DQ ($ VSub_Number '$1'))} spids: [21] ) (assign_pair lhs: (LhsName name:expect) op: Equal rhs: {(DQ ($ VSub_Number '$2'))} spids: [26] ) ] spids: [21] ) (AndOr children: [ (SimpleCommand words: [ {(git)} {($ VSub_Number '$3')} {(check-attr)} {(test)} {(--)} {(DQ ($ VSub_Name '$path'))} ] redirects: [ (Redir op_id: Redir_Great fd: 16777215 arg_word: {(actual)} spids: [47] ) (Redir op_id:Redir_Great fd:2 arg_word:{(err)} spids:[50]) ] ) (AndOr children: [ (SimpleCommand words: [{(echo)} {(DQ ($ VSub_Name '$path') (': test: ') ($ VSub_Number '$2'))}] redirects: [ (Redir op_id: Redir_Great fd: 16777215 arg_word: {(expect)} spids: [64] ) ] ) (AndOr children: [ (C {(test_cmp)} {(expect)} {(actual)}) (C {(test_line_count)} {(Lit_Other '=')} {(0)} {(err)}) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] spids: [18] ) spids: [13 17] ) (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)}) ] )