Merge branch 'ts/alias-of-alias'
authorJunio C Hamano <gitster@pobox.com>
Tue, 16 Oct 2018 07:15:59 +0000 (16:15 +0900)
committerJunio C Hamano <gitster@pobox.com>
Tue, 16 Oct 2018 07:15:59 +0000 (16:15 +0900)
An alias that expands to another alias has so far been forbidden,
but now it is allowed to create such an alias.

* ts/alias-of-alias:
t0014: introduce an alias testing suite
alias: show the call history when an alias is looping
alias: add support for aliases of an alias

1  2 
git.c
diff --combined git.c
index a6f4b44af520627bd1d7caaaf38ba6356ef807b3,a20eb4fa1536c0d81a12cc09340d8dff3a373e82..5920f8019bb3b26db0c7c50f9ea02f8ff96230e8
--- 1/git.c
--- 2/git.c
+++ b/git.c
@@@ -508,7 -508,6 +508,7 @@@ static struct cmd_struct commands[] = 
        { "merge-tree", cmd_merge_tree, RUN_SETUP | NO_PARSEOPT },
        { "mktag", cmd_mktag, RUN_SETUP | NO_PARSEOPT },
        { "mktree", cmd_mktree, RUN_SETUP },
 +      { "multi-pack-index", cmd_multi_pack_index, RUN_SETUP_GENTLY },
        { "mv", cmd_mv, RUN_SETUP | NEED_WORK_TREE },
        { "name-rev", cmd_name_rev, RUN_SETUP },
        { "notes", cmd_notes, RUN_SETUP },
@@@ -675,6 -674,8 +675,8 @@@ static void execv_dashed_external(cons
  static int run_argv(int *argcp, const char ***argv)
  {
        int done_alias = 0;
+       struct string_list cmd_list = STRING_LIST_INIT_NODUP;
+       struct string_list_item *seen;
  
        while (1) {
                /*
                /* .. then try the external ones */
                execv_dashed_external(*argv);
  
-               /* It could be an alias -- this works around the insanity
+               seen = unsorted_string_list_lookup(&cmd_list, *argv[0]);
+               if (seen) {
+                       int i;
+                       struct strbuf sb = STRBUF_INIT;
+                       for (i = 0; i < cmd_list.nr; i++) {
+                               struct string_list_item *item = &cmd_list.items[i];
+                               strbuf_addf(&sb, "\n  %s", item->string);
+                               if (item == seen)
+                                       strbuf_addstr(&sb, " <==");
+                               else if (i == cmd_list.nr - 1)
+                                       strbuf_addstr(&sb, " ==>");
+                       }
+                       die(_("alias loop detected: expansion of '%s' does"
+                             " not terminate:%s"), cmd_list.items[0].string, sb.buf);
+               }
+               string_list_append(&cmd_list, *argv[0]);
+               /*
+                * It could be an alias -- this works around the insanity
                 * of overriding "git log" with "git show" by having
                 * alias.log = show
                 */
-               if (done_alias)
-                       break;
                if (!handle_alias(argcp, argv))
                        break;
                done_alias = 1;
        }
  
+       string_list_clear(&cmd_list, 0);
        return done_alias;
  }