Merge branch 'mm/detach-at-HEAD-reflog'
authorJunio C Hamano <gitster@pobox.com>
Thu, 15 Oct 2015 22:43:42 +0000 (15:43 -0700)
committerJunio C Hamano <gitster@pobox.com>
Thu, 15 Oct 2015 22:43:42 +0000 (15:43 -0700)
After "git checkout --detach", "git status" reported a fairly
useless "HEAD detached at HEAD", instead of saying at which exact
commit.

* mm/detach-at-HEAD-reflog:
status: don't say 'HEAD detached at HEAD'
t3203: test 'detached at' after checkout --detach

1  2 
t/t3203-branch-output.sh
wt-status.c
diff --combined t/t3203-branch-output.sh
index f1ae5ff662efa3941748f29a7958f23d9519dda1,16efe7af03d210cb349337e978c6105cb22d80e8..9454423ca02af98ad50a089e0c0dc2bc1e952bd0
@@@ -106,6 -106,19 +106,19 @@@ EO
        test_i18ncmp expect actual
  '
  
+ test_expect_success 'git branch shows detached HEAD properly after checkout --detach' '
+       git checkout master &&
+       cat >expect <<EOF &&
+ * (HEAD detached at $(git rev-parse --short HEAD^0))
+   branch-one
+   branch-two
+   master
+ EOF
+       git checkout --detach &&
+       git branch >actual &&
+       test_i18ncmp expect actual
+ '
  test_expect_success 'git branch shows detached HEAD properly after moving' '
        cat >expect <<EOF &&
  * (HEAD detached from $(git rev-parse --short HEAD))
@@@ -143,24 -156,4 +156,24 @@@ EO
        test_i18ncmp expect actual
  '
  
 +test_expect_success 'git branch `--sort` option' '
 +      cat >expect <<-\EOF &&
 +        branch-two
 +      * (HEAD detached from fromtag)
 +        branch-one
 +        master
 +      EOF
 +      git branch --sort=objectsize >actual &&
 +      test_i18ncmp expect actual
 +'
 +
 +test_expect_success 'git branch --points-at option' '
 +      cat >expect <<-\EOF &&
 +        branch-one
 +        master
 +      EOF
 +      git branch --points-at=branch-one >actual &&
 +      test_cmp expect actual
 +'
 +
  test_done
diff --combined wt-status.c
index c327fe8128fdb2e380db15f526056a22862ac33f,fd9d98b39966a372ab56b2aee8e72fe99d9f0f4e..3e3b8c098924d655bccb395e95cee832abb1d39f
@@@ -1,4 -1,5 +1,4 @@@
  #include "cache.h"
 -#include "pathspec.h"
  #include "wt-status.h"
  #include "object.h"
  #include "dir.h"
@@@ -584,8 -585,6 +584,8 @@@ static void wt_status_collect_untracked
                        DIR_SHOW_OTHER_DIRECTORIES | DIR_HIDE_EMPTY_DIRECTORIES;
        if (s->show_ignored_files)
                dir.flags |= DIR_SHOW_IGNORED_TOO;
 +      else
 +              dir.untracked = the_index.untracked;
        setup_standard_excludes(&dir);
  
        fill_directory(&dir, &s->pathspec);
@@@ -1026,142 -1025,21 +1026,142 @@@ static int split_commit_in_progress(str
        return split_in_progress;
  }
  
 +/*
 + * Turn
 + * "pick d6a2f0303e897ec257dd0e0a39a5ccb709bc2047 some message"
 + * into
 + * "pick d6a2f03 some message"
 + *
 + * The function assumes that the line does not contain useless spaces
 + * before or after the command.
 + */
 +static void abbrev_sha1_in_line(struct strbuf *line)
 +{
 +      struct strbuf **split;
 +      int i;
 +
 +      if (starts_with(line->buf, "exec ") ||
 +          starts_with(line->buf, "x "))
 +              return;
 +
 +      split = strbuf_split_max(line, ' ', 3);
 +      if (split[0] && split[1]) {
 +              unsigned char sha1[20];
 +              const char *abbrev;
 +
 +              /*
 +               * strbuf_split_max left a space. Trim it and re-add
 +               * it after abbreviation.
 +               */
 +              strbuf_trim(split[1]);
 +              if (!get_sha1(split[1]->buf, sha1)) {
 +                      abbrev = find_unique_abbrev(sha1, DEFAULT_ABBREV);
 +                      strbuf_reset(split[1]);
 +                      strbuf_addf(split[1], "%s ", abbrev);
 +                      strbuf_reset(line);
 +                      for (i = 0; split[i]; i++)
 +                              strbuf_addf(line, "%s", split[i]->buf);
 +              }
 +      }
 +      for (i = 0; split[i]; i++)
 +              strbuf_release(split[i]);
 +
 +}
 +
 +static void read_rebase_todolist(const char *fname, struct string_list *lines)
 +{
 +      struct strbuf line = STRBUF_INIT;
 +      FILE *f = fopen(git_path("%s", fname), "r");
 +
 +      if (!f)
 +              die_errno("Could not open file %s for reading",
 +                        git_path("%s", fname));
 +      while (!strbuf_getline(&line, f, '\n')) {
 +              if (line.len && line.buf[0] == comment_line_char)
 +                      continue;
 +              strbuf_trim(&line);
 +              if (!line.len)
 +                      continue;
 +              abbrev_sha1_in_line(&line);
 +              string_list_append(lines, line.buf);
 +      }
 +}
 +
 +static void show_rebase_information(struct wt_status *s,
 +                                      struct wt_status_state *state,
 +                                      const char *color)
 +{
 +      if (state->rebase_interactive_in_progress) {
 +              int i;
 +              int nr_lines_to_show = 2;
 +
 +              struct string_list have_done = STRING_LIST_INIT_DUP;
 +              struct string_list yet_to_do = STRING_LIST_INIT_DUP;
 +
 +              read_rebase_todolist("rebase-merge/done", &have_done);
 +              read_rebase_todolist("rebase-merge/git-rebase-todo", &yet_to_do);
 +
 +              if (have_done.nr == 0)
 +                      status_printf_ln(s, color, _("No commands done."));
 +              else {
 +                      status_printf_ln(s, color,
 +                              Q_("Last command done (%d command done):",
 +                                      "Last commands done (%d commands done):",
 +                                      have_done.nr),
 +                              have_done.nr);
 +                      for (i = (have_done.nr > nr_lines_to_show)
 +                              ? have_done.nr - nr_lines_to_show : 0;
 +                              i < have_done.nr;
 +                              i++)
 +                              status_printf_ln(s, color, "   %s", have_done.items[i].string);
 +                      if (have_done.nr > nr_lines_to_show && s->hints)
 +                              status_printf_ln(s, color,
 +                                      _("  (see more in file %s)"), git_path("rebase-merge/done"));
 +              }
 +
 +              if (yet_to_do.nr == 0)
 +                      status_printf_ln(s, color,
 +                                       _("No commands remaining."));
 +              else {
 +                      status_printf_ln(s, color,
 +                              Q_("Next command to do (%d remaining command):",
 +                                      "Next commands to do (%d remaining commands):",
 +                                      yet_to_do.nr),
 +                              yet_to_do.nr);
 +                      for (i = 0; i < nr_lines_to_show && i < yet_to_do.nr; i++)
 +                              status_printf_ln(s, color, "   %s", yet_to_do.items[i].string);
 +                      if (s->hints)
 +                              status_printf_ln(s, color,
 +                                      _("  (use \"git rebase --edit-todo\" to view and edit)"));
 +              }
 +              string_list_clear(&yet_to_do, 0);
 +              string_list_clear(&have_done, 0);
 +      }
 +}
 +
 +static void print_rebase_state(struct wt_status *s,
 +                              struct wt_status_state *state,
 +                              const char *color)
 +{
 +      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."));
 +}
 +
  static void show_rebase_in_progress(struct wt_status *s,
                                struct wt_status_state *state,
                                const char *color)
  {
        struct stat st;
  
 +      show_rebase_information(s, state, color);
        if (has_unmerged(s)) {
 -              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."));
 +              print_rebase_state(s, state, color);
                if (s->hints) {
                        status_printf_ln(s, color,
                                _("  (fix conflicts and then run \"git rebase --continue\")"));
                        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)) {
 -              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."));
 +      } else if (state->rebase_in_progress || !stat(git_path_merge_msg(), &st)) {
 +              print_rebase_state(s, state, color);
                if (s->hints)
                        status_printf_ln(s, color,
                                _("  (all conflicts fixed: run \"git rebase --continue\")"));
@@@ -1319,6 -1204,12 +1319,12 @@@ static int grab_1st_switch(unsigned cha
        hashcpy(cb->nsha1, nsha1);
        for (end = target; *end && *end != '\n'; end++)
                ;
+       if (!memcmp(target, "HEAD", end - target)) {
+               /* HEAD is relative. Resolve it to the right reflog entry. */
+               strbuf_addstr(&cb->buf,
+                             find_unique_abbrev(nsha1, DEFAULT_ABBREV));
+               return 1;
+       }
        strbuf_add(&cb->buf, target, end - target);
        return 1;
  }
@@@ -1367,7 -1258,7 +1373,7 @@@ void wt_status_get_state(struct wt_stat
        struct stat st;
        unsigned char sha1[20];
  
 -      if (!stat(git_path("MERGE_HEAD"), &st)) {
 +      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->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) &&
 +      } else if (!stat(git_path_cherry_pick_head(), &st) &&
                        !get_sha1("CHERRY_PICK_HEAD", sha1)) {
                state->cherry_pick_in_progress = 1;
                hashcpy(state->cherry_pick_head_sha1, sha1);
                state->bisect_in_progress = 1;
                state->branch = read_and_strip_branch("BISECT_START");
        }
 -      if (!stat(git_path("REVERT_HEAD"), &st) &&
 +      if (!stat(git_path_revert_head(), &st) &&
            !get_sha1("REVERT_HEAD", sha1)) {
                state->revert_in_progress = 1;
                hashcpy(state->revert_head_sha1, sha1);
@@@ -1441,10 -1332,7 +1447,10 @@@ void wt_status_print(struct wt_status *
                else if (!strcmp(branch_name, "HEAD")) {
                        branch_status_color = color(WT_STATUS_NOBRANCH, s);
                        if (state.rebase_in_progress || state.rebase_interactive_in_progress) {
 -                              on_what = _("rebase in progress; onto ");
 +                              if (state.rebase_interactive_in_progress)
 +                                      on_what = _("interactive rebase in progress; onto ");
 +                              else
 +                                      on_what = _("rebase in progress; onto ");
                                branch_name = state.onto;
                        } else if (state.detached_from) {
                                branch_name = state.detached_from;
@@@ -1651,15 -1539,21 +1657,15 @@@ static void wt_shortstatus_print_tracki
  
        color_fprintf(s->fp, branch_color_local, "%s", branch_name);
  
 -      switch (stat_tracking_info(branch, &num_ours, &num_theirs)) {
 -      case 0:
 -              /* no base */
 -              fputc(s->null_termination ? '\0' : '\n', s->fp);
 -              return;
 -      case -1:
 -              /* with "gone" base */
 +      if (stat_tracking_info(branch, &num_ours, &num_theirs, &base) < 0) {
 +              if (!base) {
 +                      fputc(s->null_termination ? '\0' : '\n', s->fp);
 +                      return;
 +              }
 +
                upstream_is_gone = 1;
 -              break;
 -      default:
 -              /* with base */
 -              break;
        }
  
 -      base = branch->merge[0]->dst;
        base = shorten_unambiguous_ref(base, 0);
        color_fprintf(s->fp, header_color, "...");
        color_fprintf(s->fp, branch_color_remote, "%s", base);