Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.kernel.org/pub/scm/git/git.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLucien Kong <Lucien.Kong@ensimag.imag.fr>2012-06-06 00:21:24 +0400
committerJunio C Hamano <gitster@pobox.com>2012-06-14 21:15:19 +0400
commit83c750acde6ac5847845f9c2eeb3261cf9cc54bc (patch)
tree7d942525b5580498d3d570f428bd70e3c33f1736
parent3fe4498197ced84886b4adaddf18f1109b477f8e (diff)
wt-status.*: better advices for git status added
This patch provides new informative help messages in the display of 'git status' (at the top) during conflicts, rebase, am, bisect or cherry-pick process. The new messages are not shown when using options such as -s or --porcelain. The messages about the current situation of the user are always displayed but the advices on what the user needs to do in order to resume a rebase/bisect/am/commit after resolving conflicts can be hidden by setting advice.statushints to 'false' in the config file. Thus, information about the updated advice.statushints key are added in Documentation/config.txt. Also, the test t7060-wt-status.sh is now working with the new help messages. Tests about suggestions of "git rm" are also added. Signed-off-by: Lucien Kong <Lucien.Kong@ensimag.imag.fr> Signed-off-by: Valentin Duperray <Valentin.Duperray@ensimag.imag.fr> Signed-off-by: Franck Jonas <Franck.Jonas@ensimag.imag.fr> Signed-off-by: Thomas Nguy <Thomas.Nguy@ensimag.imag.fr> Signed-off-by: Huynh Khoi Nguyen Nguyen <Huynh-Khoi-Nguyen.Nguyen@ensimag.imag.fr> Signed-off-by: Matthieu Moy <Matthieu.Moy@grenoble-inp.fr> Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rw-r--r--Documentation/config.txt7
-rwxr-xr-xt/t7060-wtstatus.sh64
-rw-r--r--wt-status.c156
-rw-r--r--wt-status.h11
4 files changed, 235 insertions, 3 deletions
diff --git a/Documentation/config.txt b/Documentation/config.txt
index 915cb5a547..ccce4f6697 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -159,9 +159,10 @@ advice.*::
specified a refspec that isn't your current branch) and
it resulted in a non-fast-forward error.
statusHints::
- Directions on how to stage/unstage/add shown in the
- output of linkgit:git-status[1] and the template shown
- when writing commit messages.
+ Show directions on how to proceed from the current
+ state in the output of linkgit:git-status[1] and in
+ the template shown when writing commit messages in
+ linkgit:git-commit[1].
commitBeforeMerge::
Advice shown when linkgit:git-merge[1] refuses to
merge to avoid overwriting local changes.
diff --git a/t/t7060-wtstatus.sh b/t/t7060-wtstatus.sh
index b8cb4906aa..e8c3690dac 100755
--- a/t/t7060-wtstatus.sh
+++ b/t/t7060-wtstatus.sh
@@ -30,6 +30,9 @@ test_expect_success 'Report new path with conflict' '
cat >expect <<EOF
# On branch side
+# You have unmerged paths.
+# (fix conflicts and run "git commit")
+#
# Unmerged paths:
# (use "git add/rm <file>..." as appropriate to mark resolution)
#
@@ -118,4 +121,65 @@ test_expect_success 'git diff-index --cached -C shows 2 copies + 1 unmerged' '
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 'status when conflicts with add and rm advice (both deleted)' '
+ 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_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_done
diff --git a/wt-status.c b/wt-status.c
index dd6d8c4106..e404f2d9ec 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -23,6 +23,7 @@ static char default_wt_status_colors[][COLOR_MAXLEN] = {
GIT_COLOR_GREEN, /* WT_STATUS_LOCAL_BRANCH */
GIT_COLOR_RED, /* WT_STATUS_REMOTE_BRANCH */
GIT_COLOR_NIL, /* WT_STATUS_ONBRANCH */
+ GIT_COLOR_NORMAL, /* WT_STATUS_IN_PROGRESS */
};
static const char *color(int slot, struct wt_status *s)
@@ -728,6 +729,160 @@ static void wt_status_print_tracking(struct wt_status *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 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 {
+ 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)
{
const char *branch_color = color(WT_STATUS_ONBRANCH, s);
@@ -750,6 +905,7 @@ void wt_status_print(struct wt_status *s)
wt_status_print_tracking(s);
}
+ wt_status_print_state(s);
if (s->is_initial) {
status_printf_ln(s, color(WT_STATUS_HEADER, s), "");
status_printf_ln(s, color(WT_STATUS_HEADER, s), _("Initial commit"));
diff --git a/wt-status.h b/wt-status.h
index 14aa9f7e13..c1066a0ec6 100644
--- a/wt-status.h
+++ b/wt-status.h
@@ -15,6 +15,7 @@ enum color_wt_status {
WT_STATUS_LOCAL_BRANCH,
WT_STATUS_REMOTE_BRANCH,
WT_STATUS_ONBRANCH,
+ WT_STATUS_IN_PROGRESS,
WT_STATUS_MAXSLOT
};
@@ -71,6 +72,16 @@ struct wt_status {
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_print(struct wt_status *s);
void wt_status_collect(struct wt_status *s);