Merge branch 'lk/more-helpful-status-hints'
Give finer classification to various states of paths in conflicted state and offer advice messages in the "git status" output.
This commit is contained in:
@ -159,9 +159,10 @@ advice.*::
|
|||||||
specified a refspec that isn't your current branch) and
|
specified a refspec that isn't your current branch) and
|
||||||
it resulted in a non-fast-forward error.
|
it resulted in a non-fast-forward error.
|
||||||
statusHints::
|
statusHints::
|
||||||
Directions on how to stage/unstage/add shown in the
|
Show directions on how to proceed from the current
|
||||||
output of linkgit:git-status[1] and the template shown
|
state in the output of linkgit:git-status[1] and in
|
||||||
when writing commit messages.
|
the template shown when writing commit messages in
|
||||||
|
linkgit:git-commit[1].
|
||||||
commitBeforeMerge::
|
commitBeforeMerge::
|
||||||
Advice shown when linkgit:git-merge[1] refuses to
|
Advice shown when linkgit:git-merge[1] refuses to
|
||||||
merge to avoid overwriting local changes.
|
merge to avoid overwriting local changes.
|
||||||
|
@ -30,6 +30,9 @@ test_expect_success 'Report new path with conflict' '
|
|||||||
|
|
||||||
cat >expect <<EOF
|
cat >expect <<EOF
|
||||||
# On branch side
|
# On branch side
|
||||||
|
# You have unmerged paths.
|
||||||
|
# (fix conflicts and run "git commit")
|
||||||
|
#
|
||||||
# Unmerged paths:
|
# Unmerged paths:
|
||||||
# (use "git add/rm <file>..." as appropriate to mark resolution)
|
# (use "git add/rm <file>..." as appropriate to mark resolution)
|
||||||
#
|
#
|
||||||
@ -118,4 +121,97 @@ test_expect_success 'git diff-index --cached -C shows 2 copies + 1 unmerged' '
|
|||||||
test_cmp expected 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")
|
||||||
|
#
|
||||||
|
# Unmerged paths:
|
||||||
|
# (use "git add/rm <file>..." 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")
|
||||||
|
#
|
||||||
|
# Unmerged paths:
|
||||||
|
# (use "git add/rm <file>..." 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")
|
||||||
|
#
|
||||||
|
# Changes to be committed:
|
||||||
|
#
|
||||||
|
# new file: sub_master.txt
|
||||||
|
#
|
||||||
|
# Unmerged paths:
|
||||||
|
# (use "git rm <file>..." 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_done
|
test_done
|
||||||
|
649
t/t7512-status-help.sh
Executable file
649
t/t7512-status-help.sh
Executable file
@ -0,0 +1,649 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# Copyright (c) 2012 Valentin Duperray, Lucien Kong, Franck Jonas,
|
||||||
|
# Thomas Nguy, Khoi Nguyen
|
||||||
|
# Grenoble INP Ensimag
|
||||||
|
#
|
||||||
|
|
||||||
|
test_description='git status advices'
|
||||||
|
|
||||||
|
. ./test-lib.sh
|
||||||
|
|
||||||
|
. "$TEST_DIRECTORY"/lib-rebase.sh
|
||||||
|
|
||||||
|
set_fake_editor
|
||||||
|
|
||||||
|
test_expect_success 'prepare for conflicts' '
|
||||||
|
test_commit init main.txt init &&
|
||||||
|
git branch conflicts &&
|
||||||
|
test_commit on_master main.txt on_master &&
|
||||||
|
git checkout conflicts &&
|
||||||
|
test_commit on_conflicts main.txt on_conflicts
|
||||||
|
'
|
||||||
|
|
||||||
|
|
||||||
|
test_expect_success 'status when conflicts unresolved' '
|
||||||
|
test_must_fail git merge master &&
|
||||||
|
cat >expected <<-\EOF &&
|
||||||
|
# On branch conflicts
|
||||||
|
# You have unmerged paths.
|
||||||
|
# (fix conflicts and run "git commit")
|
||||||
|
#
|
||||||
|
# Unmerged paths:
|
||||||
|
# (use "git add <file>..." to mark resolution)
|
||||||
|
#
|
||||||
|
# both modified: 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 'status when conflicts resolved before commit' '
|
||||||
|
git reset --hard conflicts &&
|
||||||
|
test_must_fail git merge master &&
|
||||||
|
echo one >main.txt &&
|
||||||
|
git add main.txt &&
|
||||||
|
cat >expected <<-\EOF &&
|
||||||
|
# On branch conflicts
|
||||||
|
# All conflicts fixed but you are still merging.
|
||||||
|
# (use "git commit" to conclude merge)
|
||||||
|
#
|
||||||
|
# Changes to be committed:
|
||||||
|
#
|
||||||
|
# modified: main.txt
|
||||||
|
#
|
||||||
|
# Untracked files not listed (use -u option to show untracked files)
|
||||||
|
EOF
|
||||||
|
git status --untracked-files=no >actual &&
|
||||||
|
test_i18ncmp expected actual
|
||||||
|
'
|
||||||
|
|
||||||
|
|
||||||
|
test_expect_success 'prepare for rebase conflicts' '
|
||||||
|
git reset --hard master &&
|
||||||
|
git checkout -b rebase_conflicts &&
|
||||||
|
test_commit one_rebase main.txt one &&
|
||||||
|
test_commit two_rebase main.txt two &&
|
||||||
|
test_commit three_rebase main.txt three
|
||||||
|
'
|
||||||
|
|
||||||
|
|
||||||
|
test_expect_success 'status when rebase in progress before resolving conflicts' '
|
||||||
|
test_when_finished "git rebase --abort" &&
|
||||||
|
test_must_fail git rebase HEAD^ --onto HEAD^^ &&
|
||||||
|
cat >expected <<-\EOF &&
|
||||||
|
# Not currently on any branch.
|
||||||
|
# You are currently rebasing.
|
||||||
|
# (fix conflicts and then run "git rebase --continue")
|
||||||
|
# (use "git rebase --skip" to skip this patch)
|
||||||
|
# (use "git rebase --abort" to check out the original branch)
|
||||||
|
#
|
||||||
|
# Unmerged paths:
|
||||||
|
# (use "git reset HEAD <file>..." to unstage)
|
||||||
|
# (use "git add <file>..." to mark resolution)
|
||||||
|
#
|
||||||
|
# both modified: 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 'status when rebase in progress before rebase --continue' '
|
||||||
|
git reset --hard rebase_conflicts &&
|
||||||
|
test_when_finished "git rebase --abort" &&
|
||||||
|
test_must_fail git rebase HEAD^ --onto HEAD^^ &&
|
||||||
|
echo three >main.txt &&
|
||||||
|
git add main.txt &&
|
||||||
|
cat >expected <<-\EOF &&
|
||||||
|
# Not currently on any branch.
|
||||||
|
# You are currently rebasing.
|
||||||
|
# (all conflicts fixed: run "git rebase --continue")
|
||||||
|
#
|
||||||
|
# Changes to be committed:
|
||||||
|
# (use "git reset HEAD <file>..." to unstage)
|
||||||
|
#
|
||||||
|
# modified: main.txt
|
||||||
|
#
|
||||||
|
# Untracked files not listed (use -u option to show untracked files)
|
||||||
|
EOF
|
||||||
|
git status --untracked-files=no >actual &&
|
||||||
|
test_i18ncmp expected actual
|
||||||
|
'
|
||||||
|
|
||||||
|
|
||||||
|
test_expect_success 'prepare for rebase_i_conflicts' '
|
||||||
|
git reset --hard master &&
|
||||||
|
git checkout -b rebase_i_conflicts &&
|
||||||
|
test_commit one_unmerge main.txt one_unmerge &&
|
||||||
|
git branch rebase_i_conflicts_second &&
|
||||||
|
test_commit one_master main.txt one_master &&
|
||||||
|
git checkout rebase_i_conflicts_second &&
|
||||||
|
test_commit one_second main.txt one_second
|
||||||
|
'
|
||||||
|
|
||||||
|
|
||||||
|
test_expect_success 'status during rebase -i when conflicts unresolved' '
|
||||||
|
test_when_finished "git rebase --abort" &&
|
||||||
|
test_must_fail git rebase -i rebase_i_conflicts &&
|
||||||
|
cat >expected <<-\EOF &&
|
||||||
|
# Not currently on any branch.
|
||||||
|
# You are currently rebasing.
|
||||||
|
# (fix conflicts and then run "git rebase --continue")
|
||||||
|
# (use "git rebase --skip" to skip this patch)
|
||||||
|
# (use "git rebase --abort" to check out the original branch)
|
||||||
|
#
|
||||||
|
# Unmerged paths:
|
||||||
|
# (use "git reset HEAD <file>..." to unstage)
|
||||||
|
# (use "git add <file>..." to mark resolution)
|
||||||
|
#
|
||||||
|
# both modified: 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 'status during rebase -i after resolving conflicts' '
|
||||||
|
git reset --hard rebase_i_conflicts_second &&
|
||||||
|
test_when_finished "git rebase --abort" &&
|
||||||
|
test_must_fail git rebase -i rebase_i_conflicts &&
|
||||||
|
git add main.txt &&
|
||||||
|
cat >expected <<-\EOF &&
|
||||||
|
# Not currently on any branch.
|
||||||
|
# You are currently rebasing.
|
||||||
|
# (all conflicts fixed: run "git rebase --continue")
|
||||||
|
#
|
||||||
|
# Changes to be committed:
|
||||||
|
# (use "git reset HEAD <file>..." to unstage)
|
||||||
|
#
|
||||||
|
# modified: main.txt
|
||||||
|
#
|
||||||
|
# Untracked files not listed (use -u option to show untracked files)
|
||||||
|
EOF
|
||||||
|
git status --untracked-files=no >actual &&
|
||||||
|
test_i18ncmp expected actual
|
||||||
|
'
|
||||||
|
|
||||||
|
|
||||||
|
test_expect_success 'status when rebasing -i in edit mode' '
|
||||||
|
git reset --hard master &&
|
||||||
|
git checkout -b rebase_i_edit &&
|
||||||
|
test_commit one_rebase_i main.txt one &&
|
||||||
|
test_commit two_rebase_i main.txt two &&
|
||||||
|
test_commit three_rebase_i main.txt three &&
|
||||||
|
FAKE_LINES="1 edit 2" &&
|
||||||
|
export FAKE_LINES &&
|
||||||
|
test_when_finished "git rebase --abort" &&
|
||||||
|
git rebase -i HEAD~2 &&
|
||||||
|
cat >expected <<-\EOF &&
|
||||||
|
# Not currently on any branch.
|
||||||
|
# You are currently editing a commit during a rebase.
|
||||||
|
# (use "git commit --amend" to amend the current commit)
|
||||||
|
# (use "git rebase --continue" once you are satisfied with your changes)
|
||||||
|
#
|
||||||
|
nothing to commit (use -u to show untracked files)
|
||||||
|
EOF
|
||||||
|
git status --untracked-files=no >actual &&
|
||||||
|
test_i18ncmp expected actual
|
||||||
|
'
|
||||||
|
|
||||||
|
|
||||||
|
test_expect_success 'status when splitting a commit' '
|
||||||
|
git reset --hard master &&
|
||||||
|
git checkout -b split_commit &&
|
||||||
|
test_commit one_split main.txt one &&
|
||||||
|
test_commit two_split main.txt two &&
|
||||||
|
test_commit three_split main.txt three &&
|
||||||
|
test_commit four_split main.txt four &&
|
||||||
|
FAKE_LINES="1 edit 2 3" &&
|
||||||
|
export FAKE_LINES &&
|
||||||
|
test_when_finished "git rebase --abort" &&
|
||||||
|
git rebase -i HEAD~3 &&
|
||||||
|
git reset HEAD^ &&
|
||||||
|
cat >expected <<-\EOF &&
|
||||||
|
# Not currently on any branch.
|
||||||
|
# You are currently splitting a commit during a rebase.
|
||||||
|
# (Once your working directory is clean, run "git rebase --continue")
|
||||||
|
#
|
||||||
|
# Changes not staged for commit:
|
||||||
|
# (use "git add <file>..." to update what will be committed)
|
||||||
|
# (use "git checkout -- <file>..." to discard changes in working directory)
|
||||||
|
#
|
||||||
|
# modified: 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 'status after editing the last commit with --amend during a rebase -i' '
|
||||||
|
git reset --hard master &&
|
||||||
|
git checkout -b amend_last &&
|
||||||
|
test_commit one_amend main.txt one &&
|
||||||
|
test_commit two_amend main.txt two &&
|
||||||
|
test_commit three_amend main.txt three &&
|
||||||
|
test_commit four_amend main.txt four &&
|
||||||
|
FAKE_LINES="1 2 edit 3" &&
|
||||||
|
export FAKE_LINES &&
|
||||||
|
test_when_finished "git rebase --abort" &&
|
||||||
|
git rebase -i HEAD~3 &&
|
||||||
|
git commit --amend -m "foo" &&
|
||||||
|
cat >expected <<-\EOF &&
|
||||||
|
# Not currently on any branch.
|
||||||
|
# You are currently editing a commit during a rebase.
|
||||||
|
# (use "git commit --amend" to amend the current commit)
|
||||||
|
# (use "git rebase --continue" once you are satisfied with your changes)
|
||||||
|
#
|
||||||
|
nothing to commit (use -u to show untracked files)
|
||||||
|
EOF
|
||||||
|
git status --untracked-files=no >actual &&
|
||||||
|
test_i18ncmp expected actual
|
||||||
|
'
|
||||||
|
|
||||||
|
|
||||||
|
test_expect_success 'prepare for several edits' '
|
||||||
|
git reset --hard master &&
|
||||||
|
git checkout -b several_edits &&
|
||||||
|
test_commit one_edits main.txt one &&
|
||||||
|
test_commit two_edits main.txt two &&
|
||||||
|
test_commit three_edits main.txt three &&
|
||||||
|
test_commit four_edits main.txt four
|
||||||
|
'
|
||||||
|
|
||||||
|
|
||||||
|
test_expect_success 'status: (continue first edit) second edit' '
|
||||||
|
FAKE_LINES="edit 1 edit 2 3" &&
|
||||||
|
export FAKE_LINES &&
|
||||||
|
test_when_finished "git rebase --abort" &&
|
||||||
|
git rebase -i HEAD~3 &&
|
||||||
|
git rebase --continue &&
|
||||||
|
cat >expected <<-\EOF &&
|
||||||
|
# Not currently on any branch.
|
||||||
|
# You are currently editing a commit during a rebase.
|
||||||
|
# (use "git commit --amend" to amend the current commit)
|
||||||
|
# (use "git rebase --continue" once you are satisfied with your changes)
|
||||||
|
#
|
||||||
|
nothing to commit (use -u to show untracked files)
|
||||||
|
EOF
|
||||||
|
git status --untracked-files=no >actual &&
|
||||||
|
test_i18ncmp expected actual
|
||||||
|
'
|
||||||
|
|
||||||
|
|
||||||
|
test_expect_success 'status: (continue first edit) second edit and split' '
|
||||||
|
git reset --hard several_edits &&
|
||||||
|
FAKE_LINES="edit 1 edit 2 3" &&
|
||||||
|
export FAKE_LINES &&
|
||||||
|
test_when_finished "git rebase --abort" &&
|
||||||
|
git rebase -i HEAD~3 &&
|
||||||
|
git rebase --continue &&
|
||||||
|
git reset HEAD^ &&
|
||||||
|
cat >expected <<-\EOF &&
|
||||||
|
# Not currently on any branch.
|
||||||
|
# You are currently splitting a commit during a rebase.
|
||||||
|
# (Once your working directory is clean, run "git rebase --continue")
|
||||||
|
#
|
||||||
|
# Changes not staged for commit:
|
||||||
|
# (use "git add <file>..." to update what will be committed)
|
||||||
|
# (use "git checkout -- <file>..." to discard changes in working directory)
|
||||||
|
#
|
||||||
|
# modified: 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 'status: (continue first edit) second edit and amend' '
|
||||||
|
git reset --hard several_edits &&
|
||||||
|
FAKE_LINES="edit 1 edit 2 3" &&
|
||||||
|
export FAKE_LINES &&
|
||||||
|
test_when_finished "git rebase --abort" &&
|
||||||
|
git rebase -i HEAD~3 &&
|
||||||
|
git rebase --continue &&
|
||||||
|
git commit --amend -m "foo" &&
|
||||||
|
cat >expected <<-\EOF &&
|
||||||
|
# Not currently on any branch.
|
||||||
|
# You are currently editing a commit during a rebase.
|
||||||
|
# (use "git commit --amend" to amend the current commit)
|
||||||
|
# (use "git rebase --continue" once you are satisfied with your changes)
|
||||||
|
#
|
||||||
|
nothing to commit (use -u to show untracked files)
|
||||||
|
EOF
|
||||||
|
git status --untracked-files=no >actual &&
|
||||||
|
test_i18ncmp expected actual
|
||||||
|
'
|
||||||
|
|
||||||
|
|
||||||
|
test_expect_success 'status: (amend first edit) second edit' '
|
||||||
|
git reset --hard several_edits &&
|
||||||
|
FAKE_LINES="edit 1 edit 2 3" &&
|
||||||
|
export FAKE_LINES &&
|
||||||
|
test_when_finished "git rebase --abort" &&
|
||||||
|
git rebase -i HEAD~3 &&
|
||||||
|
git commit --amend -m "a" &&
|
||||||
|
git rebase --continue &&
|
||||||
|
cat >expected <<-\EOF &&
|
||||||
|
# Not currently on any branch.
|
||||||
|
# You are currently editing a commit during a rebase.
|
||||||
|
# (use "git commit --amend" to amend the current commit)
|
||||||
|
# (use "git rebase --continue" once you are satisfied with your changes)
|
||||||
|
#
|
||||||
|
nothing to commit (use -u to show untracked files)
|
||||||
|
EOF
|
||||||
|
git status --untracked-files=no >actual &&
|
||||||
|
test_i18ncmp expected actual
|
||||||
|
'
|
||||||
|
|
||||||
|
|
||||||
|
test_expect_success 'status: (amend first edit) second edit and split' '
|
||||||
|
git reset --hard several_edits &&
|
||||||
|
FAKE_LINES="edit 1 edit 2 3" &&
|
||||||
|
export FAKE_LINES &&
|
||||||
|
test_when_finished "git rebase --abort" &&
|
||||||
|
git rebase -i HEAD~3 &&
|
||||||
|
git commit --amend -m "b" &&
|
||||||
|
git rebase --continue &&
|
||||||
|
git reset HEAD^ &&
|
||||||
|
cat >expected <<-\EOF &&
|
||||||
|
# Not currently on any branch.
|
||||||
|
# You are currently splitting a commit during a rebase.
|
||||||
|
# (Once your working directory is clean, run "git rebase --continue")
|
||||||
|
#
|
||||||
|
# Changes not staged for commit:
|
||||||
|
# (use "git add <file>..." to update what will be committed)
|
||||||
|
# (use "git checkout -- <file>..." to discard changes in working directory)
|
||||||
|
#
|
||||||
|
# modified: 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 'status: (amend first edit) second edit and amend' '
|
||||||
|
git reset --hard several_edits &&
|
||||||
|
FAKE_LINES="edit 1 edit 2 3" &&
|
||||||
|
export FAKE_LINES &&
|
||||||
|
test_when_finished "git rebase --abort" &&
|
||||||
|
git rebase -i HEAD~3 &&
|
||||||
|
git commit --amend -m "c" &&
|
||||||
|
git rebase --continue &&
|
||||||
|
git commit --amend -m "d" &&
|
||||||
|
cat >expected <<-\EOF &&
|
||||||
|
# Not currently on any branch.
|
||||||
|
# You are currently editing a commit during a rebase.
|
||||||
|
# (use "git commit --amend" to amend the current commit)
|
||||||
|
# (use "git rebase --continue" once you are satisfied with your changes)
|
||||||
|
#
|
||||||
|
nothing to commit (use -u to show untracked files)
|
||||||
|
EOF
|
||||||
|
git status --untracked-files=no >actual &&
|
||||||
|
test_i18ncmp expected actual
|
||||||
|
'
|
||||||
|
|
||||||
|
|
||||||
|
test_expect_success 'status: (split first edit) second edit' '
|
||||||
|
git reset --hard several_edits &&
|
||||||
|
FAKE_LINES="edit 1 edit 2 3" &&
|
||||||
|
export FAKE_LINES &&
|
||||||
|
test_when_finished "git rebase --abort" &&
|
||||||
|
git rebase -i HEAD~3 &&
|
||||||
|
git reset HEAD^ &&
|
||||||
|
git add main.txt &&
|
||||||
|
git commit -m "e" &&
|
||||||
|
git rebase --continue &&
|
||||||
|
cat >expected <<-\EOF &&
|
||||||
|
# Not currently on any branch.
|
||||||
|
# You are currently editing a commit during a rebase.
|
||||||
|
# (use "git commit --amend" to amend the current commit)
|
||||||
|
# (use "git rebase --continue" once you are satisfied with your changes)
|
||||||
|
#
|
||||||
|
nothing to commit (use -u to show untracked files)
|
||||||
|
EOF
|
||||||
|
git status --untracked-files=no >actual &&
|
||||||
|
test_i18ncmp expected actual
|
||||||
|
'
|
||||||
|
|
||||||
|
|
||||||
|
test_expect_success 'status: (split first edit) second edit and split' '
|
||||||
|
git reset --hard several_edits &&
|
||||||
|
FAKE_LINES="edit 1 edit 2 3" &&
|
||||||
|
export FAKE_LINES &&
|
||||||
|
test_when_finished "git rebase --abort" &&
|
||||||
|
git rebase -i HEAD~3 &&
|
||||||
|
git reset HEAD^ &&
|
||||||
|
git add main.txt &&
|
||||||
|
git commit --amend -m "f" &&
|
||||||
|
git rebase --continue &&
|
||||||
|
git reset HEAD^ &&
|
||||||
|
cat >expected <<-\EOF &&
|
||||||
|
# Not currently on any branch.
|
||||||
|
# You are currently splitting a commit during a rebase.
|
||||||
|
# (Once your working directory is clean, run "git rebase --continue")
|
||||||
|
#
|
||||||
|
# Changes not staged for commit:
|
||||||
|
# (use "git add <file>..." to update what will be committed)
|
||||||
|
# (use "git checkout -- <file>..." to discard changes in working directory)
|
||||||
|
#
|
||||||
|
# modified: 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 'status: (split first edit) second edit and amend' '
|
||||||
|
git reset --hard several_edits &&
|
||||||
|
FAKE_LINES="edit 1 edit 2 3" &&
|
||||||
|
export FAKE_LINES &&
|
||||||
|
test_when_finished "git rebase --abort" &&
|
||||||
|
git rebase -i HEAD~3 &&
|
||||||
|
git reset HEAD^ &&
|
||||||
|
git add main.txt &&
|
||||||
|
git commit --amend -m "g" &&
|
||||||
|
git rebase --continue &&
|
||||||
|
git commit --amend -m "h" &&
|
||||||
|
cat >expected <<-\EOF &&
|
||||||
|
# Not currently on any branch.
|
||||||
|
# You are currently editing a commit during a rebase.
|
||||||
|
# (use "git commit --amend" to amend the current commit)
|
||||||
|
# (use "git rebase --continue" once you are satisfied with your changes)
|
||||||
|
#
|
||||||
|
nothing to commit (use -u to show untracked files)
|
||||||
|
EOF
|
||||||
|
git status --untracked-files=no >actual &&
|
||||||
|
test_i18ncmp expected actual
|
||||||
|
'
|
||||||
|
|
||||||
|
|
||||||
|
test_expect_success 'prepare am_session' '
|
||||||
|
git reset --hard master &&
|
||||||
|
git checkout -b am_session &&
|
||||||
|
test_commit one_am one.txt "one" &&
|
||||||
|
test_commit two_am two.txt "two" &&
|
||||||
|
test_commit three_am three.txt "three"
|
||||||
|
'
|
||||||
|
|
||||||
|
|
||||||
|
test_expect_success 'status in an am session: file already exists' '
|
||||||
|
git checkout -b am_already_exists &&
|
||||||
|
test_when_finished "rm Maildir/* && git am --abort" &&
|
||||||
|
git format-patch -1 -oMaildir &&
|
||||||
|
test_must_fail git am Maildir/*.patch &&
|
||||||
|
cat >expected <<-\EOF &&
|
||||||
|
# On branch am_already_exists
|
||||||
|
# You are in the middle of an am session.
|
||||||
|
# (fix conflicts and then run "git am --resolved")
|
||||||
|
# (use "git am --skip" to skip this patch)
|
||||||
|
# (use "git am --abort" to restore the original branch)
|
||||||
|
#
|
||||||
|
nothing to commit (use -u to show untracked files)
|
||||||
|
EOF
|
||||||
|
git status --untracked-files=no >actual &&
|
||||||
|
test_i18ncmp expected actual
|
||||||
|
'
|
||||||
|
|
||||||
|
|
||||||
|
test_expect_success 'status in an am session: file does not exist' '
|
||||||
|
git reset --hard am_session &&
|
||||||
|
git checkout -b am_not_exists &&
|
||||||
|
git rm three.txt &&
|
||||||
|
git commit -m "delete three.txt" &&
|
||||||
|
test_when_finished "rm Maildir/* && git am --abort" &&
|
||||||
|
git format-patch -1 -oMaildir &&
|
||||||
|
test_must_fail git am Maildir/*.patch &&
|
||||||
|
cat >expected <<-\EOF &&
|
||||||
|
# On branch am_not_exists
|
||||||
|
# You are in the middle of an am session.
|
||||||
|
# (fix conflicts and then run "git am --resolved")
|
||||||
|
# (use "git am --skip" to skip this patch)
|
||||||
|
# (use "git am --abort" to restore the original branch)
|
||||||
|
#
|
||||||
|
nothing to commit (use -u to show untracked files)
|
||||||
|
EOF
|
||||||
|
git status --untracked-files=no >actual &&
|
||||||
|
test_i18ncmp expected actual
|
||||||
|
'
|
||||||
|
|
||||||
|
|
||||||
|
test_expect_success 'status in an am session: empty patch' '
|
||||||
|
git reset --hard am_session &&
|
||||||
|
git checkout -b am_empty &&
|
||||||
|
test_when_finished "rm Maildir/* && git am --abort" &&
|
||||||
|
git format-patch -3 -oMaildir &&
|
||||||
|
git rm one.txt two.txt three.txt &&
|
||||||
|
git commit -m "delete all am_empty" &&
|
||||||
|
echo error >Maildir/0002-two_am.patch &&
|
||||||
|
test_must_fail git am Maildir/*.patch &&
|
||||||
|
cat >expected <<-\EOF &&
|
||||||
|
# On branch am_empty
|
||||||
|
# You are in the middle of an am session.
|
||||||
|
# The current patch is empty.
|
||||||
|
# (use "git am --skip" to skip this patch)
|
||||||
|
# (use "git am --abort" to restore the original branch)
|
||||||
|
#
|
||||||
|
nothing to commit (use -u to show untracked files)
|
||||||
|
EOF
|
||||||
|
git status --untracked-files=no >actual &&
|
||||||
|
test_i18ncmp expected actual
|
||||||
|
'
|
||||||
|
|
||||||
|
|
||||||
|
test_expect_success 'status when bisecting' '
|
||||||
|
git reset --hard master &&
|
||||||
|
git checkout -b bisect &&
|
||||||
|
test_commit one_bisect main.txt one &&
|
||||||
|
test_commit two_bisect main.txt two &&
|
||||||
|
test_commit three_bisect main.txt three &&
|
||||||
|
test_when_finished "git bisect reset" &&
|
||||||
|
git bisect start &&
|
||||||
|
git bisect bad &&
|
||||||
|
git bisect good one_bisect &&
|
||||||
|
cat >expected <<-\EOF &&
|
||||||
|
# Not currently on any branch.
|
||||||
|
# You are currently bisecting.
|
||||||
|
# (use "git bisect reset" to get back to the original branch)
|
||||||
|
#
|
||||||
|
nothing to commit (use -u to show untracked files)
|
||||||
|
EOF
|
||||||
|
git status --untracked-files=no >actual &&
|
||||||
|
test_i18ncmp expected actual
|
||||||
|
'
|
||||||
|
|
||||||
|
|
||||||
|
test_expect_success 'status when rebase conflicts with statushints disabled' '
|
||||||
|
git reset --hard master &&
|
||||||
|
git checkout -b statushints_disabled &&
|
||||||
|
test_when_finished "git config --local advice.statushints true" &&
|
||||||
|
git config --local advice.statushints false &&
|
||||||
|
test_commit one_statushints main.txt one &&
|
||||||
|
test_commit two_statushints main.txt two &&
|
||||||
|
test_commit three_statushints main.txt three &&
|
||||||
|
test_when_finished "git rebase --abort" &&
|
||||||
|
test_must_fail git rebase HEAD^ --onto HEAD^^ &&
|
||||||
|
cat >expected <<-\EOF &&
|
||||||
|
# Not currently on any branch.
|
||||||
|
# You are currently rebasing.
|
||||||
|
#
|
||||||
|
# Unmerged paths:
|
||||||
|
# both modified: main.txt
|
||||||
|
#
|
||||||
|
no changes added to commit
|
||||||
|
EOF
|
||||||
|
git status --untracked-files=no >actual &&
|
||||||
|
test_i18ncmp expected actual
|
||||||
|
'
|
||||||
|
|
||||||
|
|
||||||
|
test_expect_success 'prepare for cherry-pick conflicts' '
|
||||||
|
git reset --hard master &&
|
||||||
|
git checkout -b cherry_branch &&
|
||||||
|
test_commit one_cherry main.txt one &&
|
||||||
|
test_commit two_cherries main.txt two &&
|
||||||
|
git checkout -b cherry_branch_second &&
|
||||||
|
test_commit second_cherry main.txt second &&
|
||||||
|
git checkout cherry_branch &&
|
||||||
|
test_commit three_cherries main.txt three
|
||||||
|
'
|
||||||
|
|
||||||
|
|
||||||
|
test_expect_success 'status when cherry-picking before resolving conflicts' '
|
||||||
|
test_when_finished "git cherry-pick --abort" &&
|
||||||
|
test_must_fail git cherry-pick cherry_branch_second &&
|
||||||
|
cat >expected <<-\EOF &&
|
||||||
|
# On branch cherry_branch
|
||||||
|
# You are currently cherry-picking.
|
||||||
|
# (fix conflicts and run "git commit")
|
||||||
|
#
|
||||||
|
# Unmerged paths:
|
||||||
|
# (use "git add <file>..." to mark resolution)
|
||||||
|
#
|
||||||
|
# both modified: 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 'status when cherry-picking after resolving conflicts' '
|
||||||
|
git reset --hard cherry_branch &&
|
||||||
|
test_when_finished "git cherry-pick --abort" &&
|
||||||
|
test_must_fail git cherry-pick cherry_branch_second &&
|
||||||
|
echo end >main.txt &&
|
||||||
|
git add main.txt &&
|
||||||
|
cat >expected <<-\EOF &&
|
||||||
|
# On branch cherry_branch
|
||||||
|
# You are currently cherry-picking.
|
||||||
|
# (all conflicts fixed: run "git commit")
|
||||||
|
#
|
||||||
|
# Changes to be committed:
|
||||||
|
#
|
||||||
|
# modified: main.txt
|
||||||
|
#
|
||||||
|
# Untracked files not listed (use -u option to show untracked files)
|
||||||
|
EOF
|
||||||
|
git status --untracked-files=no >actual &&
|
||||||
|
test_i18ncmp expected actual
|
||||||
|
'
|
||||||
|
|
||||||
|
|
||||||
|
test_done
|
245
wt-status.c
245
wt-status.c
@ -12,6 +12,7 @@
|
|||||||
#include "refs.h"
|
#include "refs.h"
|
||||||
#include "submodule.h"
|
#include "submodule.h"
|
||||||
#include "column.h"
|
#include "column.h"
|
||||||
|
#include "strbuf.h"
|
||||||
|
|
||||||
static char default_wt_status_colors[][COLOR_MAXLEN] = {
|
static char default_wt_status_colors[][COLOR_MAXLEN] = {
|
||||||
GIT_COLOR_NORMAL, /* WT_STATUS_HEADER */
|
GIT_COLOR_NORMAL, /* WT_STATUS_HEADER */
|
||||||
@ -23,6 +24,7 @@ static char default_wt_status_colors[][COLOR_MAXLEN] = {
|
|||||||
GIT_COLOR_GREEN, /* WT_STATUS_LOCAL_BRANCH */
|
GIT_COLOR_GREEN, /* WT_STATUS_LOCAL_BRANCH */
|
||||||
GIT_COLOR_RED, /* WT_STATUS_REMOTE_BRANCH */
|
GIT_COLOR_RED, /* WT_STATUS_REMOTE_BRANCH */
|
||||||
GIT_COLOR_NIL, /* WT_STATUS_ONBRANCH */
|
GIT_COLOR_NIL, /* WT_STATUS_ONBRANCH */
|
||||||
|
GIT_COLOR_NORMAL, /* WT_STATUS_IN_PROGRESS */
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *color(int slot, struct wt_status *s)
|
static const char *color(int slot, struct wt_status *s)
|
||||||
@ -130,9 +132,34 @@ void wt_status_prepare(struct wt_status *s)
|
|||||||
|
|
||||||
static void wt_status_print_unmerged_header(struct wt_status *s)
|
static void wt_status_print_unmerged_header(struct wt_status *s)
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
|
int del_mod_conflict = 0;
|
||||||
|
int both_deleted = 0;
|
||||||
|
int not_deleted = 0;
|
||||||
const char *c = color(WT_STATUS_HEADER, s);
|
const char *c = color(WT_STATUS_HEADER, s);
|
||||||
|
|
||||||
status_printf_ln(s, c, _("Unmerged paths:"));
|
status_printf_ln(s, c, _("Unmerged paths:"));
|
||||||
|
|
||||||
|
for (i = 0; i < s->change.nr; i++) {
|
||||||
|
struct string_list_item *it = &(s->change.items[i]);
|
||||||
|
struct wt_status_change_data *d = it->util;
|
||||||
|
|
||||||
|
switch (d->stagemask) {
|
||||||
|
case 0:
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
both_deleted = 1;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
case 5:
|
||||||
|
del_mod_conflict = 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
not_deleted = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!advice_status_hints)
|
if (!advice_status_hints)
|
||||||
return;
|
return;
|
||||||
if (s->whence != FROM_COMMIT)
|
if (s->whence != FROM_COMMIT)
|
||||||
@ -141,7 +168,17 @@ static void wt_status_print_unmerged_header(struct wt_status *s)
|
|||||||
status_printf_ln(s, c, _(" (use \"git reset %s <file>...\" to unstage)"), s->reference);
|
status_printf_ln(s, c, _(" (use \"git reset %s <file>...\" to unstage)"), s->reference);
|
||||||
else
|
else
|
||||||
status_printf_ln(s, c, _(" (use \"git rm --cached <file>...\" to unstage)"));
|
status_printf_ln(s, c, _(" (use \"git rm --cached <file>...\" to unstage)"));
|
||||||
status_printf_ln(s, c, _(" (use \"git add/rm <file>...\" as appropriate to mark resolution)"));
|
|
||||||
|
if (!both_deleted) {
|
||||||
|
if (!del_mod_conflict)
|
||||||
|
status_printf_ln(s, c, _(" (use \"git add <file>...\" to mark resolution)"));
|
||||||
|
else
|
||||||
|
status_printf_ln(s, c, _(" (use \"git add/rm <file>...\" as appropriate to mark resolution)"));
|
||||||
|
} else if (!del_mod_conflict && !not_deleted) {
|
||||||
|
status_printf_ln(s, c, _(" (use \"git rm <file>...\" to mark resolution)"));
|
||||||
|
} else {
|
||||||
|
status_printf_ln(s, c, _(" (use \"git add/rm <file>...\" as appropriate to mark resolution)"));
|
||||||
|
}
|
||||||
status_printf_ln(s, c, "");
|
status_printf_ln(s, c, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -728,6 +765,211 @@ static void wt_status_print_tracking(struct wt_status *s)
|
|||||||
color_fprintf_ln(s->fp, color(WT_STATUS_HEADER, s), "#");
|
color_fprintf_ln(s->fp, color(WT_STATUS_HEADER, s), "#");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int has_unmerged(struct wt_status *s)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < s->change.nr; i++) {
|
||||||
|
struct wt_status_change_data *d;
|
||||||
|
d = s->change.items[i].util;
|
||||||
|
if (d->stagemask)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void show_merge_in_progress(struct wt_status *s,
|
||||||
|
struct wt_status_state *state,
|
||||||
|
const char *color)
|
||||||
|
{
|
||||||
|
if (has_unmerged(s)) {
|
||||||
|
status_printf_ln(s, color, _("You have unmerged paths."));
|
||||||
|
if (advice_status_hints)
|
||||||
|
status_printf_ln(s, color,
|
||||||
|
_(" (fix conflicts and run \"git commit\")"));
|
||||||
|
} else {
|
||||||
|
status_printf_ln(s, color,
|
||||||
|
_("All conflicts fixed but you are still merging."));
|
||||||
|
if (advice_status_hints)
|
||||||
|
status_printf_ln(s, color,
|
||||||
|
_(" (use \"git commit\" to conclude merge)"));
|
||||||
|
}
|
||||||
|
wt_status_print_trailer(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void show_am_in_progress(struct wt_status *s,
|
||||||
|
struct wt_status_state *state,
|
||||||
|
const char *color)
|
||||||
|
{
|
||||||
|
status_printf_ln(s, color,
|
||||||
|
_("You are in the middle of an am session."));
|
||||||
|
if (state->am_empty_patch)
|
||||||
|
status_printf_ln(s, color,
|
||||||
|
_("The current patch is empty."));
|
||||||
|
if (advice_status_hints) {
|
||||||
|
if (!state->am_empty_patch)
|
||||||
|
status_printf_ln(s, color,
|
||||||
|
_(" (fix conflicts and then run \"git am --resolved\")"));
|
||||||
|
status_printf_ln(s, color,
|
||||||
|
_(" (use \"git am --skip\" to skip this patch)"));
|
||||||
|
status_printf_ln(s, color,
|
||||||
|
_(" (use \"git am --abort\" to restore the original branch)"));
|
||||||
|
}
|
||||||
|
wt_status_print_trailer(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *read_line_from_git_path(const char *filename)
|
||||||
|
{
|
||||||
|
struct strbuf buf = STRBUF_INIT;
|
||||||
|
FILE *fp = fopen(git_path("%s", filename), "r");
|
||||||
|
if (!fp) {
|
||||||
|
strbuf_release(&buf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
strbuf_getline(&buf, fp, '\n');
|
||||||
|
if (!fclose(fp)) {
|
||||||
|
return strbuf_detach(&buf, NULL);
|
||||||
|
} else {
|
||||||
|
strbuf_release(&buf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int split_commit_in_progress(struct wt_status *s)
|
||||||
|
{
|
||||||
|
int split_in_progress = 0;
|
||||||
|
char *head = read_line_from_git_path("HEAD");
|
||||||
|
char *orig_head = read_line_from_git_path("ORIG_HEAD");
|
||||||
|
char *rebase_amend = read_line_from_git_path("rebase-merge/amend");
|
||||||
|
char *rebase_orig_head = read_line_from_git_path("rebase-merge/orig-head");
|
||||||
|
|
||||||
|
if (!head || !orig_head || !rebase_amend || !rebase_orig_head ||
|
||||||
|
!s->branch || strcmp(s->branch, "HEAD"))
|
||||||
|
return split_in_progress;
|
||||||
|
|
||||||
|
if (!strcmp(rebase_amend, rebase_orig_head)) {
|
||||||
|
if (strcmp(head, rebase_amend))
|
||||||
|
split_in_progress = 1;
|
||||||
|
} else if (strcmp(orig_head, rebase_orig_head)) {
|
||||||
|
split_in_progress = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!s->amend && !s->nowarn && !s->workdir_dirty)
|
||||||
|
split_in_progress = 0;
|
||||||
|
|
||||||
|
free(head);
|
||||||
|
free(orig_head);
|
||||||
|
free(rebase_amend);
|
||||||
|
free(rebase_orig_head);
|
||||||
|
return split_in_progress;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void show_rebase_in_progress(struct wt_status *s,
|
||||||
|
struct wt_status_state *state,
|
||||||
|
const char *color)
|
||||||
|
{
|
||||||
|
struct stat st;
|
||||||
|
|
||||||
|
if (has_unmerged(s)) {
|
||||||
|
status_printf_ln(s, color, _("You are currently rebasing."));
|
||||||
|
if (advice_status_hints) {
|
||||||
|
status_printf_ln(s, color,
|
||||||
|
_(" (fix conflicts and then run \"git rebase --continue\")"));
|
||||||
|
status_printf_ln(s, color,
|
||||||
|
_(" (use \"git rebase --skip\" to skip this patch)"));
|
||||||
|
status_printf_ln(s, color,
|
||||||
|
_(" (use \"git rebase --abort\" to check out the original branch)"));
|
||||||
|
}
|
||||||
|
} else if (state->rebase_in_progress || !stat(git_path("MERGE_MSG"), &st)) {
|
||||||
|
status_printf_ln(s, color, _("You are currently rebasing."));
|
||||||
|
if (advice_status_hints)
|
||||||
|
status_printf_ln(s, color,
|
||||||
|
_(" (all conflicts fixed: run \"git rebase --continue\")"));
|
||||||
|
} else if (split_commit_in_progress(s)) {
|
||||||
|
status_printf_ln(s, color, _("You are currently splitting a commit during a rebase."));
|
||||||
|
if (advice_status_hints)
|
||||||
|
status_printf_ln(s, color,
|
||||||
|
_(" (Once your working directory is clean, run \"git rebase --continue\")"));
|
||||||
|
} else {
|
||||||
|
status_printf_ln(s, color, _("You are currently editing a commit during a rebase."));
|
||||||
|
if (advice_status_hints && !s->amend) {
|
||||||
|
status_printf_ln(s, color,
|
||||||
|
_(" (use \"git commit --amend\" to amend the current commit)"));
|
||||||
|
status_printf_ln(s, color,
|
||||||
|
_(" (use \"git rebase --continue\" once you are satisfied with your changes)"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wt_status_print_trailer(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void show_cherry_pick_in_progress(struct wt_status *s,
|
||||||
|
struct wt_status_state *state,
|
||||||
|
const char *color)
|
||||||
|
{
|
||||||
|
status_printf_ln(s, color, _("You are currently cherry-picking."));
|
||||||
|
if (advice_status_hints) {
|
||||||
|
if (has_unmerged(s))
|
||||||
|
status_printf_ln(s, color,
|
||||||
|
_(" (fix conflicts and run \"git commit\")"));
|
||||||
|
else
|
||||||
|
status_printf_ln(s, color,
|
||||||
|
_(" (all conflicts fixed: run \"git commit\")"));
|
||||||
|
}
|
||||||
|
wt_status_print_trailer(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void show_bisect_in_progress(struct wt_status *s,
|
||||||
|
struct wt_status_state *state,
|
||||||
|
const char *color)
|
||||||
|
{
|
||||||
|
status_printf_ln(s, color, _("You are currently bisecting."));
|
||||||
|
if (advice_status_hints)
|
||||||
|
status_printf_ln(s, color,
|
||||||
|
_(" (use \"git bisect reset\" to get back to the original branch)"));
|
||||||
|
wt_status_print_trailer(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void wt_status_print_state(struct wt_status *s)
|
||||||
|
{
|
||||||
|
const char *state_color = color(WT_STATUS_IN_PROGRESS, s);
|
||||||
|
struct wt_status_state state;
|
||||||
|
struct stat st;
|
||||||
|
|
||||||
|
memset(&state, 0, sizeof(state));
|
||||||
|
|
||||||
|
if (!stat(git_path("MERGE_HEAD"), &st)) {
|
||||||
|
state.merge_in_progress = 1;
|
||||||
|
} else if (!stat(git_path("rebase-apply"), &st)) {
|
||||||
|
if (!stat(git_path("rebase-apply/applying"), &st)) {
|
||||||
|
state.am_in_progress = 1;
|
||||||
|
if (!stat(git_path("rebase-apply/patch"), &st) && !st.st_size)
|
||||||
|
state.am_empty_patch = 1;
|
||||||
|
} else {
|
||||||
|
state.rebase_in_progress = 1;
|
||||||
|
}
|
||||||
|
} else if (!stat(git_path("rebase-merge"), &st)) {
|
||||||
|
if (!stat(git_path("rebase-merge/interactive"), &st))
|
||||||
|
state.rebase_interactive_in_progress = 1;
|
||||||
|
else
|
||||||
|
state.rebase_in_progress = 1;
|
||||||
|
} else if (!stat(git_path("CHERRY_PICK_HEAD"), &st)) {
|
||||||
|
state.cherry_pick_in_progress = 1;
|
||||||
|
}
|
||||||
|
if (!stat(git_path("BISECT_LOG"), &st))
|
||||||
|
state.bisect_in_progress = 1;
|
||||||
|
|
||||||
|
if (state.merge_in_progress)
|
||||||
|
show_merge_in_progress(s, &state, state_color);
|
||||||
|
else if (state.am_in_progress)
|
||||||
|
show_am_in_progress(s, &state, state_color);
|
||||||
|
else if (state.rebase_in_progress || state.rebase_interactive_in_progress)
|
||||||
|
show_rebase_in_progress(s, &state, state_color);
|
||||||
|
else if (state.cherry_pick_in_progress)
|
||||||
|
show_cherry_pick_in_progress(s, &state, state_color);
|
||||||
|
if (state.bisect_in_progress)
|
||||||
|
show_bisect_in_progress(s, &state, state_color);
|
||||||
|
}
|
||||||
|
|
||||||
void wt_status_print(struct wt_status *s)
|
void wt_status_print(struct wt_status *s)
|
||||||
{
|
{
|
||||||
const char *branch_color = color(WT_STATUS_ONBRANCH, s);
|
const char *branch_color = color(WT_STATUS_ONBRANCH, s);
|
||||||
@ -750,6 +992,7 @@ void wt_status_print(struct wt_status *s)
|
|||||||
wt_status_print_tracking(s);
|
wt_status_print_tracking(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wt_status_print_state(s);
|
||||||
if (s->is_initial) {
|
if (s->is_initial) {
|
||||||
status_printf_ln(s, color(WT_STATUS_HEADER, s), "");
|
status_printf_ln(s, color(WT_STATUS_HEADER, s), "");
|
||||||
status_printf_ln(s, color(WT_STATUS_HEADER, s), _("Initial commit"));
|
status_printf_ln(s, color(WT_STATUS_HEADER, s), _("Initial commit"));
|
||||||
|
11
wt-status.h
11
wt-status.h
@ -15,6 +15,7 @@ enum color_wt_status {
|
|||||||
WT_STATUS_LOCAL_BRANCH,
|
WT_STATUS_LOCAL_BRANCH,
|
||||||
WT_STATUS_REMOTE_BRANCH,
|
WT_STATUS_REMOTE_BRANCH,
|
||||||
WT_STATUS_ONBRANCH,
|
WT_STATUS_ONBRANCH,
|
||||||
|
WT_STATUS_IN_PROGRESS,
|
||||||
WT_STATUS_MAXSLOT
|
WT_STATUS_MAXSLOT
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -71,6 +72,16 @@ struct wt_status {
|
|||||||
struct string_list ignored;
|
struct string_list ignored;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct wt_status_state {
|
||||||
|
int merge_in_progress;
|
||||||
|
int am_in_progress;
|
||||||
|
int am_empty_patch;
|
||||||
|
int rebase_in_progress;
|
||||||
|
int rebase_interactive_in_progress;
|
||||||
|
int cherry_pick_in_progress;
|
||||||
|
int bisect_in_progress;
|
||||||
|
};
|
||||||
|
|
||||||
void wt_status_prepare(struct wt_status *s);
|
void wt_status_prepare(struct wt_status *s);
|
||||||
void wt_status_print(struct wt_status *s);
|
void wt_status_print(struct wt_status *s);
|
||||||
void wt_status_collect(struct wt_status *s);
|
void wt_status_collect(struct wt_status *s);
|
||||||
|
Reference in New Issue
Block a user