Merge branch 'ts/alias-of-alias'
[gitweb.git] / git.c
diff --git a/git.c b/git.c
index a6f4b44af520627bd1d7caaaf38ba6356ef807b3..5920f8019bb3b26db0c7c50f9ea02f8ff96230e8 100644 (file)
--- a/git.c
+++ b/git.c
@@ -675,6 +675,8 @@ static void execv_dashed_external(const char **argv)
 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) {
                /*
@@ -692,17 +694,37 @@ static int run_argv(int *argcp, const char ***argv)
                /* .. 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;
 }