#!/bin/sh global test_description := ''basic work tree status reporting'' source ./test-lib.sh test_expect_success setup ' git config --global advice.statusuoption false && test_commit A && test_commit B oneside added && git checkout A^0 && test_commit C oneside created ' test_expect_success 'A/A conflict' ' git checkout B^0 && test_must_fail git merge C ' test_expect_success 'Report path with conflict' ' git diff --cached --name-status >actual && echo "U oneside" >expect && test_cmp expect actual ' test_expect_success 'Report new path with conflict' ' git diff --cached --name-status HEAD^ >actual && echo "U oneside" >expect && test_cmp expect actual ' test_expect_success 'M/D conflict does not segfault' ' cat >expect <..." as appropriate to mark resolution) deleted by us: foo no changes added to commit (use "git add" and/or "git commit -a") EOF mkdir mdconflict && ( cd mdconflict && git init && test_commit initial foo "" && test_commit modify foo foo && git checkout -b side HEAD^ && git rm foo && git commit -m delete && test_must_fail git merge master && test_must_fail git commit --dry-run >../actual && test_i18ncmp ../expect ../actual && git status >../actual && test_i18ncmp ../expect ../actual ) ' test_expect_success 'rename & unmerged setup' ' git rm -f -r . && cat "$TEST_DIRECTORY/README" >ONE && git add ONE && test_tick && git commit -m "One commit with ONE" && echo Modified >TWO && cat ONE >>TWO && cat ONE >>THREE && git add TWO THREE && sha1=$(git rev-parse :ONE) && git rm --cached ONE && ( echo "100644 $sha1 1 ONE" && echo "100644 $sha1 2 ONE" && echo "100644 $sha1 3 ONE" ) | git update-index --index-info && echo Further >>THREE ' test_expect_success 'rename & unmerged status' ' git status -suno >actual && cat >expect <<-EOF && UU ONE AM THREE A TWO EOF test_cmp expect actual ' test_expect_success 'git diff-index --cached shows 2 added + 1 unmerged' ' cat >expected <<-EOF && U ONE A THREE A TWO EOF git diff-index --cached --name-status HEAD >actual && test_cmp expected actual ' test_expect_success 'git diff-index --cached -M shows 2 added + 1 unmerged' ' cat >expected <<-EOF && U ONE A THREE A TWO EOF git diff-index --cached -M --name-status HEAD >actual && test_cmp expected actual ' test_expect_success 'git diff-index --cached -C shows 2 copies + 1 unmerged' ' cat >expected <<-EOF && U ONE C ONE THREE C ONE TWO EOF git diff-index --cached -C --name-status HEAD | sed "s/^C[0-9]*/C/g" >actual && test_cmp expected actual ' test_expect_success 'status when conflicts with add and rm advice (deleted by them)' ' git reset --hard && git checkout master && test_commit init main.txt init && git checkout -b second_branch && git rm main.txt && git commit -m "main.txt deleted on second_branch" && test_commit second conflict.txt second && git checkout master && test_commit on_second main.txt on_second && test_commit master conflict.txt master && test_must_fail git merge second_branch && cat >expected <<\EOF && On branch master You have unmerged paths. (fix conflicts and run "git commit") (use "git merge --abort" to abort the merge) Unmerged paths: (use "git add/rm ..." as appropriate to mark resolution) both added: conflict.txt deleted by them: main.txt no changes added to commit (use "git add" and/or "git commit -a") EOF git status --untracked-files=no >actual && test_i18ncmp expected actual ' test_expect_success 'prepare for conflicts' ' git reset --hard && git checkout -b conflict && test_commit one main.txt one && git branch conflict_second && git mv main.txt sub_master.txt && git commit -m "main.txt renamed in sub_master.txt" && git checkout conflict_second && git mv main.txt sub_second.txt && git commit -m "main.txt renamed in sub_second.txt" ' test_expect_success 'status when conflicts with add and rm advice (both deleted)' ' test_must_fail git merge conflict && cat >expected <<\EOF && On branch conflict_second You have unmerged paths. (fix conflicts and run "git commit") (use "git merge --abort" to abort the merge) Unmerged paths: (use "git add/rm ..." as appropriate to mark resolution) both deleted: main.txt added by them: sub_master.txt added by us: sub_second.txt no changes added to commit (use "git add" and/or "git commit -a") EOF git status --untracked-files=no >actual && test_i18ncmp expected actual ' test_expect_success 'status when conflicts with only rm advice (both deleted)' ' git reset --hard conflict_second && test_must_fail git merge conflict && git add sub_master.txt && git add sub_second.txt && cat >expected <<\EOF && On branch conflict_second You have unmerged paths. (fix conflicts and run "git commit") (use "git merge --abort" to abort the merge) Changes to be committed: new file: sub_master.txt Unmerged paths: (use "git rm ..." to mark resolution) both deleted: main.txt Untracked files not listed (use -u option to show untracked files) EOF git status --untracked-files=no >actual && test_i18ncmp expected actual && git reset --hard && git checkout master ' test_expect_success 'status --branch with detached HEAD' ' git reset --hard && git checkout master^0 && git status --branch --porcelain >actual && cat >expected <<-EOF && ## HEAD (no branch) ?? .gitconfig ?? actual ?? expect ?? expected ?? mdconflict/ EOF test_i18ncmp expected actual ' ## Duplicate the above test and verify --porcelain=v1 arg parsing. test_expect_success 'status --porcelain=v1 --branch with detached HEAD' ' git reset --hard && git checkout master^0 && git status --branch --porcelain=v1 >actual && cat >expected <<-EOF && ## HEAD (no branch) ?? .gitconfig ?? actual ?? expect ?? expected ?? mdconflict/ EOF test_i18ncmp expected actual ' ## Verify parser error on invalid --porcelain argument. test_expect_success 'status --porcelain=bogus' ' test_must_fail git status --porcelain=bogus ' test_done (CommandList children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:test_description) op: Equal rhs: {(SQ <"basic work tree status reporting">)} spids: [4] ) ] spids: [4] ) (C {(.)} {(./test-lib.sh)}) (C {(test_expect_success)} {(setup)} { (SQ <"\n"> <"\tgit config --global advice.statusuoption false &&\n"> <"\ttest_commit A &&\n"> <"\ttest_commit B oneside added &&\n"> <"\tgit checkout A^0 &&\n"> <"\ttest_commit C oneside created\n"> ) } ) (C {(test_expect_success)} {(SQ <"A/A conflict">)} {(SQ <"\n"> <"\tgit checkout B^0 &&\n"> <"\ttest_must_fail git merge C\n">)} ) (C {(test_expect_success)} {(SQ <"Report path with conflict">)} { (SQ <"\n"> <"\tgit diff --cached --name-status >actual &&\n"> <"\techo \"U\toneside\" >expect &&\n"> <"\ttest_cmp expect actual\n"> ) } ) (C {(test_expect_success)} {(SQ <"Report new path with conflict">)} { (SQ <"\n"> <"\tgit diff --cached --name-status HEAD^ >actual &&\n"> <"\techo \"U\toneside\" >expect &&\n"> <"\ttest_cmp expect actual\n"> ) } ) (C {(test_expect_success)} {(SQ <"M/D conflict does not segfault">)} { (SQ <"\n"> <"\tcat >expect < <"On branch side\n"> <"You have unmerged paths.\n"> <" (fix conflicts and run \"git commit\")\n"> <" (use \"git merge --abort\" to abort the merge)\n"> <"\n"> <"Unmerged paths:\n"> <" (use \"git add/rm ...\" as appropriate to mark resolution)\n"> <"\n"> <"\tdeleted by us: foo\n"> <"\n"> <"no changes added to commit (use \"git add\" and/or \"git commit -a\")\n"> <"EOF\n"> <"\tmkdir mdconflict &&\n"> <"\t(\n"> <"\t\tcd mdconflict &&\n"> <"\t\tgit init &&\n"> <"\t\ttest_commit initial foo \"\" &&\n"> <"\t\ttest_commit modify foo foo &&\n"> <"\t\tgit checkout -b side HEAD^ &&\n"> <"\t\tgit rm foo &&\n"> <"\t\tgit commit -m delete &&\n"> <"\t\ttest_must_fail git merge master &&\n"> <"\t\ttest_must_fail git commit --dry-run >../actual &&\n"> <"\t\ttest_i18ncmp ../expect ../actual &&\n"> <"\t\tgit status >../actual &&\n"> <"\t\ttest_i18ncmp ../expect ../actual\n"> <"\t)\n"> ) } ) (C {(test_expect_success)} {(SQ <"rename & unmerged setup">)} { (SQ <"\n"> <"\tgit rm -f -r . &&\n"> <"\tcat \"$TEST_DIRECTORY/README\" >ONE &&\n"> <"\tgit add ONE &&\n"> <"\ttest_tick &&\n"> <"\tgit commit -m \"One commit with ONE\" &&\n"> <"\n"> <"\techo Modified >TWO &&\n"> <"\tcat ONE >>TWO &&\n"> <"\tcat ONE >>THREE &&\n"> <"\tgit add TWO THREE &&\n"> <"\tsha1=$(git rev-parse :ONE) &&\n"> <"\tgit rm --cached ONE &&\n"> <"\t(\n"> <"\t\techo \"100644 $sha1 1\tONE\" &&\n"> <"\t\techo \"100644 $sha1 2\tONE\" &&\n"> <"\t\techo \"100644 $sha1 3\tONE\"\n"> <"\t) | git update-index --index-info &&\n"> <"\techo Further >>THREE\n"> ) } ) (C {(test_expect_success)} {(SQ <"rename & unmerged status">)} { (SQ <"\n"> <"\tgit status -suno >actual &&\n"> <"\tcat >expect <<-EOF &&\n"> <"\tUU ONE\n"> <"\tAM THREE\n"> <"\tA TWO\n"> <"\tEOF\n"> <"\ttest_cmp expect actual\n"> ) } ) (C {(test_expect_success)} {(SQ <"git diff-index --cached shows 2 added + 1 unmerged">)} { (SQ <"\n"> <"\tcat >expected <<-EOF &&\n"> <"\tU\tONE\n"> <"\tA\tTHREE\n"> <"\tA\tTWO\n"> <"\tEOF\n"> <"\tgit diff-index --cached --name-status HEAD >actual &&\n"> <"\ttest_cmp expected actual\n"> ) } ) (C {(test_expect_success)} {(SQ <"git diff-index --cached -M shows 2 added + 1 unmerged">)} { (SQ <"\n"> <"\tcat >expected <<-EOF &&\n"> <"\tU\tONE\n"> <"\tA\tTHREE\n"> <"\tA\tTWO\n"> <"\tEOF\n"> <"\tgit diff-index --cached -M --name-status HEAD >actual &&\n"> <"\ttest_cmp expected actual\n"> ) } ) (C {(test_expect_success)} {(SQ <"git diff-index --cached -C shows 2 copies + 1 unmerged">)} { (SQ <"\n"> <"\tcat >expected <<-EOF &&\n"> <"\tU\tONE\n"> <"\tC\tONE\tTHREE\n"> <"\tC\tONE\tTWO\n"> <"\tEOF\n"> <"\tgit diff-index --cached -C --name-status HEAD |\n"> <"\tsed \"s/^C[0-9]*/C/g\" >actual &&\n"> <"\ttest_cmp expected actual\n"> ) } ) (C {(test_expect_success)} {(SQ <"status when conflicts with add and rm advice (deleted by them)">)} { (SQ <"\n"> <"\tgit reset --hard &&\n"> <"\tgit checkout master &&\n"> <"\ttest_commit init main.txt init &&\n"> <"\tgit checkout -b second_branch &&\n"> <"\tgit rm main.txt &&\n"> <"\tgit commit -m \"main.txt deleted on second_branch\" &&\n"> <"\ttest_commit second conflict.txt second &&\n"> <"\tgit checkout master &&\n"> <"\ttest_commit on_second main.txt on_second &&\n"> <"\ttest_commit master conflict.txt master &&\n"> <"\ttest_must_fail git merge second_branch &&\n"> <"\tcat >expected <<\\EOF &&\n"> <"On branch master\n"> <"You have unmerged paths.\n"> <" (fix conflicts and run \"git commit\")\n"> <" (use \"git merge --abort\" to abort the merge)\n"> <"\n"> <"Unmerged paths:\n"> <" (use \"git add/rm ...\" as appropriate to mark resolution)\n"> <"\n"> <"\tboth added: conflict.txt\n"> <"\tdeleted by them: main.txt\n"> <"\n"> <"no changes added to commit (use \"git add\" and/or \"git commit -a\")\n"> <"EOF\n"> <"\tgit status --untracked-files=no >actual &&\n"> <"\ttest_i18ncmp expected actual\n"> ) } ) (C {(test_expect_success)} {(SQ <"prepare for conflicts">)} { (SQ <"\n"> <"\tgit reset --hard &&\n"> <"\tgit checkout -b conflict &&\n"> <"\ttest_commit one main.txt one &&\n"> <"\tgit branch conflict_second &&\n"> <"\tgit mv main.txt sub_master.txt &&\n"> <"\tgit commit -m \"main.txt renamed in sub_master.txt\" &&\n"> <"\tgit checkout conflict_second &&\n"> <"\tgit mv main.txt sub_second.txt &&\n"> <"\tgit commit -m \"main.txt renamed in sub_second.txt\"\n"> ) } ) (C {(test_expect_success)} {(SQ <"status when conflicts with add and rm advice (both deleted)">)} { (SQ <"\n"> <"\ttest_must_fail git merge conflict &&\n"> <"\tcat >expected <<\\EOF &&\n"> <"On branch conflict_second\n"> <"You have unmerged paths.\n"> <" (fix conflicts and run \"git commit\")\n"> <" (use \"git merge --abort\" to abort the merge)\n"> <"\n"> <"Unmerged paths:\n"> <" (use \"git add/rm ...\" as appropriate to mark resolution)\n"> <"\n"> <"\tboth deleted: main.txt\n"> <"\tadded by them: sub_master.txt\n"> <"\tadded by us: sub_second.txt\n"> <"\n"> <"no changes added to commit (use \"git add\" and/or \"git commit -a\")\n"> <"EOF\n"> <"\tgit status --untracked-files=no >actual &&\n"> <"\ttest_i18ncmp expected actual\n"> ) } ) (C {(test_expect_success)} {(SQ <"status when conflicts with only rm advice (both deleted)">)} { (SQ <"\n"> <"\tgit reset --hard conflict_second &&\n"> <"\ttest_must_fail git merge conflict &&\n"> <"\tgit add sub_master.txt &&\n"> <"\tgit add sub_second.txt &&\n"> <"\tcat >expected <<\\EOF &&\n"> <"On branch conflict_second\n"> <"You have unmerged paths.\n"> <" (fix conflicts and run \"git commit\")\n"> <" (use \"git merge --abort\" to abort the merge)\n"> <"\n"> <"Changes to be committed:\n"> <"\n"> <"\tnew file: sub_master.txt\n"> <"\n"> <"Unmerged paths:\n"> <" (use \"git rm ...\" to mark resolution)\n"> <"\n"> <"\tboth deleted: main.txt\n"> <"\n"> <"Untracked files not listed (use -u option to show untracked files)\n"> <"EOF\n"> <"\tgit status --untracked-files=no >actual &&\n"> <"\ttest_i18ncmp expected actual &&\n"> <"\tgit reset --hard &&\n"> <"\tgit checkout master\n"> ) } ) (C {(test_expect_success)} {(SQ <"status --branch with detached HEAD">)} { (SQ <"\n"> <"\tgit reset --hard &&\n"> <"\tgit checkout master^0 &&\n"> <"\tgit status --branch --porcelain >actual &&\n"> <"\tcat >expected <<-EOF &&\n"> <"\t## HEAD (no branch)\n"> <"\t?? .gitconfig\n"> <"\t?? actual\n"> <"\t?? expect\n"> <"\t?? expected\n"> <"\t?? mdconflict/\n"> <"\tEOF\n"> <"\ttest_i18ncmp expected actual\n"> ) } ) (C {(test_expect_success)} {(SQ <"status --porcelain=v1 --branch with detached HEAD">)} { (SQ <"\n"> <"\tgit reset --hard &&\n"> <"\tgit checkout master^0 &&\n"> <"\tgit status --branch --porcelain=v1 >actual &&\n"> <"\tcat >expected <<-EOF &&\n"> <"\t## HEAD (no branch)\n"> <"\t?? .gitconfig\n"> <"\t?? actual\n"> <"\t?? expect\n"> <"\t?? expected\n"> <"\t?? mdconflict/\n"> <"\tEOF\n"> <"\ttest_i18ncmp expected actual\n"> ) } ) (C {(test_expect_success)} {(SQ <"status --porcelain=bogus">)} {(SQ <"\n"> <"\ttest_must_fail git status --porcelain=bogus\n">)} ) (C {(test_done)}) ] )