wt-status: split wt_status_state parsing function out
[gitweb.git] / wt-status.c
index c110cbc1250b08fe491d60244e1c8f27c0201532..96b3701b8a5f18086ad1438930d8147d5b13d96f 100644 (file)
@@ -100,8 +100,8 @@ void status_printf(struct wt_status *s, const char *color,
        va_end(ap);
 }
 
-void status_printf_more(struct wt_status *s, const char *color,
-                       const char *fmt, ...)
+static void status_printf_more(struct wt_status *s, const char *color,
+                              const char *fmt, ...)
 {
        va_list ap;
 
@@ -221,7 +221,7 @@ static void wt_status_print_other_header(struct wt_status *s,
                                         const char *how)
 {
        const char *c = color(WT_STATUS_HEADER, s);
-       status_printf_ln(s, c, _("%s files:"), what);
+       status_printf_ln(s, c, "%s:", what);
        if (!advice_status_hints)
                return;
        status_printf_ln(s, c, _("  (use \"git %s <file>...\" to include in what will be committed)"), how);
@@ -516,7 +516,9 @@ static void wt_status_collect_untracked(struct wt_status *s)
 
        if (s->show_ignored_files) {
                dir.nr = 0;
-               dir.flags = DIR_SHOW_IGNORED | DIR_SHOW_OTHER_DIRECTORIES;
+               dir.flags = DIR_SHOW_IGNORED;
+               if (s->show_untracked_files != SHOW_ALL_UNTRACKED_FILES)
+                       dir.flags |= DIR_SHOW_OTHER_DIRECTORIES;
                fill_directory(&dir, s->pathspec);
                for (i = 0; i < dir.nr; i++) {
                        struct dir_entry *ent = dir.entries[i];
@@ -870,7 +872,14 @@ static void show_rebase_in_progress(struct wt_status *s,
        struct stat st;
 
        if (has_unmerged(s)) {
-               status_printf_ln(s, color, _("You are currently rebasing."));
+               if (state->branch)
+                       status_printf_ln(s, color,
+                                        _("You are currently rebasing branch '%s' on '%s'."),
+                                        state->branch,
+                                        state->onto);
+               else
+                       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\")"));
@@ -880,17 +889,38 @@ static void show_rebase_in_progress(struct wt_status *s,
                                _("  (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 (state->branch)
+                       status_printf_ln(s, color,
+                                        _("You are currently rebasing branch '%s' on '%s'."),
+                                        state->branch,
+                                        state->onto);
+               else
+                       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 (state->branch)
+                       status_printf_ln(s, color,
+                                        _("You are currently splitting a commit while rebasing branch '%s' on '%s'."),
+                                        state->branch,
+                                        state->onto);
+               else
+                       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 (state->branch)
+                       status_printf_ln(s, color,
+                                        _("You are currently editing a commit while rebasing branch '%s' on '%s'."),
+                                        state->branch,
+                                        state->onto);
+               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)"));
@@ -921,41 +951,93 @@ 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 (state->branch)
+               status_printf_ln(s, color,
+                                _("You are currently bisecting branch '%s'."),
+                                state->branch);
+       else
+               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)
+/*
+ * Extract branch information from rebase/bisect
+ */
+static char *read_and_strip_branch(const char *path)
 {
-       const char *state_color = color(WT_STATUS_HEADER, s);
-       struct wt_status_state state;
-       struct stat st;
+       struct strbuf sb = STRBUF_INIT;
+       unsigned char sha1[20];
 
-       memset(&state, 0, sizeof(state));
+       if (strbuf_read_file(&sb, git_path("%s", path), 0) <= 0)
+               goto got_nothing;
+
+       while (&sb.len && sb.buf[sb.len - 1] == '\n')
+               strbuf_setlen(&sb, sb.len - 1);
+       if (!sb.len)
+               goto got_nothing;
+       if (!prefixcmp(sb.buf, "refs/heads/"))
+               strbuf_remove(&sb,0, strlen("refs/heads/"));
+       else if (!prefixcmp(sb.buf, "refs/"))
+               ;
+       else if (!get_sha1_hex(sb.buf, sha1)) {
+               const char *abbrev;
+               abbrev = find_unique_abbrev(sha1, DEFAULT_ABBREV);
+               strbuf_reset(&sb);
+               strbuf_addstr(&sb, abbrev);
+       } else if (!strcmp(sb.buf, "detached HEAD")) /* rebase */
+               goto got_nothing;
+       else                    /* bisect */
+               ;
+       return strbuf_detach(&sb, NULL);
+
+got_nothing:
+       strbuf_release(&sb);
+       return NULL;
+}
+
+void wt_status_get_state(struct wt_status_state *state)
+{
+       struct stat st;
 
        if (!stat(git_path("MERGE_HEAD"), &st)) {
-               state.merge_in_progress = 1;
+               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;
+                       state->am_in_progress = 1;
                        if (!stat(git_path("rebase-apply/patch"), &st) && !st.st_size)
-                               state.am_empty_patch = 1;
+                               state->am_empty_patch = 1;
                } else {
-                       state.rebase_in_progress = 1;
+                       state->rebase_in_progress = 1;
+                       state->branch = read_and_strip_branch("rebase-apply/head-name");
+                       state->onto = read_and_strip_branch("rebase-apply/onto");
                }
        } else if (!stat(git_path("rebase-merge"), &st)) {
                if (!stat(git_path("rebase-merge/interactive"), &st))
-                       state.rebase_interactive_in_progress = 1;
+                       state->rebase_interactive_in_progress = 1;
                else
-                       state.rebase_in_progress = 1;
+                       state->rebase_in_progress = 1;
+               state->branch = read_and_strip_branch("rebase-merge/head-name");
+               state->onto = read_and_strip_branch("rebase-merge/onto");
        } else if (!stat(git_path("CHERRY_PICK_HEAD"), &st)) {
-               state.cherry_pick_in_progress = 1;
+               state->cherry_pick_in_progress = 1;
+       }
+       if (!stat(git_path("BISECT_LOG"), &st)) {
+               state->bisect_in_progress = 1;
+               state->branch = read_and_strip_branch("BISECT_START");
        }
-       if (!stat(git_path("BISECT_LOG"), &st))
-               state.bisect_in_progress = 1;
+}
+
+static void wt_status_print_state(struct wt_status *s)
+{
+       const char *state_color = color(WT_STATUS_HEADER, s);
+       struct wt_status_state state;
+
+       memset(&state, 0, sizeof(state));
+       wt_status_get_state(&state);
 
        if (state.merge_in_progress)
                show_merge_in_progress(s, &state, state_color);
@@ -967,6 +1049,8 @@ static void wt_status_print_state(struct wt_status *s)
                show_cherry_pick_in_progress(s, &state, state_color);
        if (state.bisect_in_progress)
                show_bisect_in_progress(s, &state, state_color);
+       free(state.branch);
+       free(state.onto);
 }
 
 void wt_status_print(struct wt_status *s)
@@ -1008,9 +1092,9 @@ void wt_status_print(struct wt_status *s)
                wt_status_print_submodule_summary(s, 1);  /* unstaged */
        }
        if (s->show_untracked_files) {
-               wt_status_print_other(s, &s->untracked, _("Untracked"), "add");
+               wt_status_print_other(s, &s->untracked, _("Untracked files"), "add");
                if (s->show_ignored_files)
-                       wt_status_print_other(s, &s->ignored, _("Ignored"), "add -f");
+                       wt_status_print_other(s, &s->ignored, _("Ignored files"), "add -f");
        } else if (s->commitable)
                status_printf_ln(s, GIT_COLOR_NORMAL, _("Untracked files not listed%s"),
                        advice_status_hints
@@ -1023,23 +1107,31 @@ void wt_status_print(struct wt_status *s)
                        status_printf_ln(s, GIT_COLOR_NORMAL, _("No changes"));
                else if (s->nowarn)
                        ; /* nothing */
-               else if (s->workdir_dirty)
-                       printf(_("no changes added to commit%s\n"),
-                               advice_status_hints
-                               ? _(" (use \"git add\" and/or \"git commit -a\")") : "");
-               else if (s->untracked.nr)
-                       printf(_("nothing added to commit but untracked files present%s\n"),
-                               advice_status_hints
-                               ? _(" (use \"git add\" to track)") : "");
-               else if (s->is_initial)
-                       printf(_("nothing to commit%s\n"), advice_status_hints
-                               ? _(" (create/copy files and use \"git add\" to track)") : "");
-               else if (!s->show_untracked_files)
-                       printf(_("nothing to commit%s\n"), advice_status_hints
-                               ? _(" (use -u to show untracked files)") : "");
-               else
-                       printf(_("nothing to commit%s\n"), advice_status_hints
-                               ? _(" (working directory clean)") : "");
+               else if (s->workdir_dirty) {
+                       if (advice_status_hints)
+                               printf(_("no changes added to commit "
+                                        "(use \"git add\" and/or \"git commit -a\")\n"));
+                       else
+                               printf(_("no changes added to commit\n"));
+               } else if (s->untracked.nr) {
+                       if (advice_status_hints)
+                               printf(_("nothing added to commit but untracked files "
+                                        "present (use \"git add\" to track)\n"));
+                       else
+                               printf(_("nothing added to commit but untracked files present\n"));
+               } else if (s->is_initial) {
+                       if (advice_status_hints)
+                               printf(_("nothing to commit (create/copy files "
+                                        "and use \"git add\" to track)\n"));
+                       else
+                               printf(_("nothing to commit\n"));
+               } else if (!s->show_untracked_files) {
+                       if (advice_status_hints)
+                               printf(_("nothing to commit (use -u to show untracked files)\n"));
+                       else
+                               printf(_("nothing to commit\n"));
+               } else
+                       printf(_("nothing to commit, working directory clean\n"));
        }
 }