Merge branch 'jk/help-unknown-ref-fix'
authorJunio C Hamano <gitster@pobox.com>
Thu, 13 Jun 2019 20:19:42 +0000 (13:19 -0700)
committerJunio C Hamano <gitster@pobox.com>
Thu, 13 Jun 2019 20:19:42 +0000 (13:19 -0700)
Improve the code to show args with potential typo that cannot be
interpreted as a commit-ish.

* jk/help-unknown-ref-fix:
help_unknown_ref(): check for refname ambiguity
help_unknown_ref(): duplicate collected refnames

1  2 
help.c
t/t7600-merge.sh
diff --combined help.c
index a9e451f2ee7a165eecb17746db9cc1a2f7e2cfbb,602d9fa20153ca7265314edf69e8416a90085c82..5261d83ecf15042d8babccf9779f0b96fac94e92
--- 1/help.c
--- 2/help.c
+++ b/help.c
@@@ -375,6 -375,13 +375,6 @@@ void list_cmds_by_config(struct string_
  {
        const char *cmd_list;
  
 -      /*
 -       * There's no actual repository setup at this point (and even
 -       * if there is, we don't really care; only global config
 -       * matters). If we accidentally set up a repository, it's ok
 -       * too since the caller (git --list-cmds=) should exit shortly
 -       * anyway.
 -       */
        if (git_config_get_string_const("completion.commands", &cmd_list))
                return;
  
                const char *p = strchrnul(cmd_list, ' ');
  
                strbuf_add(&sb, cmd_list, p - cmd_list);
 -              if (*cmd_list == '-')
 -                      string_list_remove(list, cmd_list + 1, 0);
 +              if (sb.buf[0] == '-')
 +                      string_list_remove(list, sb.buf + 1, 0);
                else
                        string_list_insert(list, sb.buf);
                strbuf_release(&sb);
@@@ -754,19 -761,19 +754,19 @@@ static int append_similar_ref(const cha
  {
        struct similar_ref_cb *cb = (struct similar_ref_cb *)(cb_data);
        char *branch = strrchr(refname, '/') + 1;
-       const char *remote;
  
        /* A remote branch of the same name is deemed similar */
-       if (skip_prefix(refname, "refs/remotes/", &remote) &&
+       if (starts_with(refname, "refs/remotes/") &&
            !strcmp(branch, cb->base_ref))
-               string_list_append(cb->similar_refs, remote);
+               string_list_append_nodup(cb->similar_refs,
+                                        shorten_unambiguous_ref(refname, 1));
        return 0;
  }
  
  static struct string_list guess_refs(const char *ref)
  {
        struct similar_ref_cb ref_cb;
-       struct string_list similar_refs = STRING_LIST_INIT_NODUP;
+       struct string_list similar_refs = STRING_LIST_INIT_DUP;
  
        ref_cb.base_ref = ref;
        ref_cb.similar_refs = &similar_refs;
diff --combined t/t7600-merge.sh
index 3e16aaed3b775b6e02f7cd6708f07746841271eb,36b2c8c91ffdf57d192281857a075e12b5eb801f..612ebe7d8289d10fe35a72945b5991dca169c1c2
@@@ -233,65 -233,20 +233,65 @@@ test_expect_success 'merge --squash c3 
        cat result.9z >file &&
        git commit --no-edit -a &&
  
 -      {
 -              cat <<-EOF
 -              Squashed commit of the following:
 +      cat >expect <<-EOF &&
 +      Squashed commit of the following:
  
 -              $(git show -s c7)
 +      $(git show -s c7)
  
 -              # Conflicts:
 -              #       file
 -              EOF
 -      } >expect &&
 -      git cat-file commit HEAD | sed -e '1,/^$/d' >actual &&
 +      # Conflicts:
 +      #       file
 +      EOF
 +      git cat-file commit HEAD >raw &&
 +      sed -e '1,/^$/d' raw >actual &&
        test_cmp expect actual
  '
  
 +test_expect_success 'merge c3 with c7 with commit.cleanup = scissors' '
 +      git config commit.cleanup scissors &&
 +      git reset --hard c3 &&
 +      test_must_fail git merge c7 &&
 +      cat result.9z >file &&
 +      git commit --no-edit -a &&
 +
 +      cat >expect <<-\EOF &&
 +      Merge tag '"'"'c7'"'"'
 +
 +      # ------------------------ >8 ------------------------
 +      # Do not modify or remove the line above.
 +      # Everything below it will be ignored.
 +      #
 +      # Conflicts:
 +      #       file
 +      EOF
 +      git cat-file commit HEAD >raw &&
 +      sed -e '1,/^$/d' raw >actual &&
 +      test_i18ncmp expect actual
 +'
 +
 +test_expect_success 'merge c3 with c7 with --squash commit.cleanup = scissors' '
 +      git config commit.cleanup scissors &&
 +      git reset --hard c3 &&
 +      test_must_fail git merge --squash c7 &&
 +      cat result.9z >file &&
 +      git commit --no-edit -a &&
 +
 +      cat >expect <<-EOF &&
 +      Squashed commit of the following:
 +
 +      $(git show -s c7)
 +
 +      # ------------------------ >8 ------------------------
 +      # Do not modify or remove the line above.
 +      # Everything below it will be ignored.
 +      #
 +      # Conflicts:
 +      #       file
 +      EOF
 +      git cat-file commit HEAD >raw &&
 +      sed -e '1,/^$/d' raw >actual &&
 +      test_i18ncmp expect actual
 +'
 +
  test_debug 'git log --graph --decorate --oneline --all'
  
  test_expect_success 'merge c1 with c2 and c3' '
@@@ -725,10 -680,10 +725,10 @@@ cat >editor <<\EO
  (
        echo "Merge work done on the side branch c1"
        echo
 -      cat <"$1"
 +      cat "$1"
  ) >"$1.tmp" && mv "$1.tmp" "$1"
  # strip comments and blank lines from end of message
 -sed -e '/^#/d' < "$1" | sed -e :a -e '/^\n*$/{$d;N;ba' -e '}' > expected
 +sed -e '/^#/d' "$1" | sed -e :a -e '/^\n*$/{$d;N;ba' -e '}' >expected
  EOF
  chmod 755 editor
  
@@@ -813,14 -768,14 +813,14 @@@ test_expect_success 'set up mod-256 con
        git commit -m base &&
  
        # one side changes the first line of each to "master"
 -      sed s/-1/-master/ <file >tmp &&
 +      sed s/-1/-master/ file >tmp &&
        mv tmp file &&
        git commit -am master &&
  
        # and the other to "side"; merging the two will
        # yield 256 separate conflicts
        git checkout -b side HEAD^ &&
 -      sed s/-1/-side/ <file >tmp &&
 +      sed s/-1/-side/ file >tmp &&
        mv tmp file &&
        git commit -am side
  '
@@@ -859,7 -814,7 +859,7 @@@ EO
  test_expect_success EXECKEEPSPID 'killed merge can be completed with --continue' '
        git reset --hard c0 &&
        ! "$SHELL_PATH" -c '\''
 -        echo kill -TERM $$ >> .git/FAKE_EDITOR
 +        echo kill -TERM $$ >>.git/FAKE_EDITOR
          GIT_EDITOR=.git/FAKE_EDITOR
          export GIT_EDITOR
          exec git merge --no-ff --edit c1'\'' &&
        verify_parents $c0 $c1
  '
  
 +test_expect_success 'merge --quit' '
 +      git init merge-quit &&
 +      (
 +              cd merge-quit &&
 +              test_commit base &&
 +              echo one >>base.t &&
 +              git commit -am one &&
 +              git branch one &&
 +              git checkout base &&
 +              echo two >>base.t &&
 +              git commit -am two &&
 +              test_must_fail git -c rerere.enabled=true merge one &&
 +              test_path_is_file .git/MERGE_HEAD &&
 +              test_path_is_file .git/MERGE_MODE &&
 +              test_path_is_file .git/MERGE_MSG &&
 +              git rerere status >rerere.before &&
 +              git merge --quit &&
 +              test_path_is_missing .git/MERGE_HEAD &&
 +              test_path_is_missing .git/MERGE_MODE &&
 +              test_path_is_missing .git/MERGE_MSG &&
 +              git rerere status >rerere.after &&
 +              test_must_be_empty rerere.after &&
 +              ! test_cmp rerere.after rerere.before
 +      )
 +'
 +
+ test_expect_success 'merge suggests matching remote refname' '
+       git commit --allow-empty -m not-local &&
+       git update-ref refs/remotes/origin/not-local HEAD &&
+       git reset --hard HEAD^ &&
+       # This is white-box testing hackery; we happen to know
+       # that reading packed refs is more picky about the memory
+       # ownership of strings we pass to for_each_ref() callbacks.
+       git pack-refs --all --prune &&
+       test_must_fail git merge not-local 2>stderr &&
+       grep origin/not-local stderr
+ '
+ test_expect_success 'suggested names are not ambiguous' '
+       git update-ref refs/heads/origin/not-local HEAD &&
+       test_must_fail git merge not-local 2>stderr &&
+       grep remotes/origin/not-local stderr
+ '
  test_done