Web lists-archives.com

[RFC PATCH v2] Allow aliases that include other aliases




Aliases can only contain non-alias git commands and their
arguments, not other user-defined aliases. Resolving further
(nested) aliases is prevented by breaking the loop after the
first alias was processed. Git then fails with a command-not-found
error.

Allow resolving nested aliases by not breaking the loop in
run_argv() after the first alias was processed. Instead, continue
incrementing `done_alias` until `handle_alias()` fails, which means that
there are no further aliases that can be processed. Prevent looping
aliases by storing substituted commands in `cmd_list` and checking if
a command has been substituted previously.
---

This is what I've come up with to prevent looping aliases. I'm not too
happy with the number of indentations needed, but this seemed to be the
easiest way to search an array for a value.

---
 git.c | 25 ++++++++++++++++++++++---
 1 file changed, 22 insertions(+), 3 deletions(-)

diff --git a/git.c b/git.c
index c27c38738..fd90a3341 100644
--- a/git.c
+++ b/git.c
@@ -674,6 +674,8 @@ static void execv_dashed_external(const char **argv)
 static int run_argv(int *argcp, const char ***argv)
 {
 	int done_alias = 0;
+	const char **cmd_list = NULL;
+	int cmd_list_alloc = 0;
 
 	while (1) {
 		/*
@@ -691,17 +693,34 @@ static int run_argv(int *argcp, const char ***argv)
 		/* .. then try the external ones */
 		execv_dashed_external(*argv);
 
+		/* Increase the array size and add the current
+		 * command to it.
+		 */
+		cmd_list_alloc += strlen(*argv[0]) + 1;
+		REALLOC_ARRAY(cmd_list, cmd_list_alloc);
+		cmd_list[done_alias] = *argv[0];
+
+		/* Search the array for occurrences of that command,
+		 * abort if something has been found.
+		 */
+		for (int i = 0; i < done_alias; i++) {
+			if (!strcmp(cmd_list[i], *argv[0])) {
+				die("loop alias: %s is called twice",
+				    cmd_list[done_alias]);
+			}
+		}
+
 		/* 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;
+		done_alias++;
 	}
 
+	free(cmd_list);
+
 	return done_alias;
 }
 
-- 
2.19.0.rc1.2.g8f4faccc1