@@ -362,18 +362,18 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
362362 return (* argv ) - orig_argv ;
363363}
364364
365- static int handle_alias (int * argcp , const char * * * argv )
365+ static int handle_alias (struct strvec * args )
366366{
367367 int envchanged = 0 , ret = 0 , saved_errno = errno ;
368368 int count , option_count ;
369369 const char * * new_argv ;
370370 const char * alias_command ;
371371 char * alias_string ;
372372
373- alias_command = ( * argv ) [0 ];
373+ alias_command = args -> v [0 ];
374374 alias_string = alias_lookup (alias_command );
375375 if (alias_string ) {
376- if (* argcp > 1 && !strcmp (( * argv ) [1 ], "-h" ))
376+ if (args -> nr > 1 && !strcmp (args -> v [1 ], "-h" ))
377377 fprintf_ln (stderr , _ ("'%s' is aliased to '%s'" ),
378378 alias_command , alias_string );
379379 if (alias_string [0 ] == '!' ) {
@@ -390,7 +390,7 @@ static int handle_alias(int *argcp, const char ***argv)
390390 child .wait_after_clean = 1 ;
391391 child .trace2_child_class = "shell_alias" ;
392392 strvec_push (& child .args , alias_string + 1 );
393- strvec_pushv (& child .args , ( * argv ) + 1 );
393+ strvec_pushv (& child .args , args -> v + 1 );
394394
395395 trace2_cmd_alias (alias_command , child .args .v );
396396 trace2_cmd_name ("_run_shell_alias_" );
@@ -423,15 +423,13 @@ static int handle_alias(int *argcp, const char ***argv)
423423 trace_argv_printf (new_argv ,
424424 "trace: alias expansion: %s =>" ,
425425 alias_command );
426-
427- REALLOC_ARRAY (new_argv , count + * argcp );
428- /* insert after command name */
429- COPY_ARRAY (new_argv + count , * argv + 1 , * argcp );
430-
431426 trace2_cmd_alias (alias_command , new_argv );
432427
433- * argv = new_argv ;
434- * argcp += count - 1 ;
428+ /* Replace the alias with the new arguments. */
429+ strvec_splice (args , 0 , 1 , new_argv , count );
430+
431+ free (alias_string );
432+ free (new_argv );
435433
436434 ret = 1 ;
437435 }
@@ -800,10 +798,10 @@ static void execv_dashed_external(const char **argv)
800798 exit (128 );
801799}
802800
803- static int run_argv (int * argcp , const char * * * argv )
801+ static int run_argv (struct strvec * args )
804802{
805803 int done_alias = 0 ;
806- struct string_list cmd_list = STRING_LIST_INIT_NODUP ;
804+ struct string_list cmd_list = STRING_LIST_INIT_DUP ;
807805 struct string_list_item * seen ;
808806
809807 while (1 ) {
@@ -817,8 +815,8 @@ static int run_argv(int *argcp, const char ***argv)
817815 * process.
818816 */
819817 if (!done_alias )
820- handle_builtin (* argcp , * argv );
821- else if (get_builtin (* * argv )) {
818+ handle_builtin (args -> nr , args -> v );
819+ else if (get_builtin (args -> v [ 0 ] )) {
822820 struct child_process cmd = CHILD_PROCESS_INIT ;
823821 int i ;
824822
@@ -834,8 +832,8 @@ static int run_argv(int *argcp, const char ***argv)
834832 commit_pager_choice ();
835833
836834 strvec_push (& cmd .args , "git" );
837- for (i = 0 ; i < * argcp ; i ++ )
838- strvec_push (& cmd .args , ( * argv ) [i ]);
835+ for (i = 0 ; i < args -> nr ; i ++ )
836+ strvec_push (& cmd .args , args -> v [i ]);
839837
840838 trace_argv_printf (cmd .args .v , "trace: exec:" );
841839
@@ -850,13 +848,13 @@ static int run_argv(int *argcp, const char ***argv)
850848 i = run_command (& cmd );
851849 if (i >= 0 || errno != ENOENT )
852850 exit (i );
853- die ("could not execute builtin %s" , * * argv );
851+ die ("could not execute builtin %s" , args -> v [ 0 ] );
854852 }
855853
856854 /* .. then try the external ones */
857- execv_dashed_external (* argv );
855+ execv_dashed_external (args -> v );
858856
859- seen = unsorted_string_list_lookup (& cmd_list , * argv [0 ]);
857+ seen = unsorted_string_list_lookup (& cmd_list , args -> v [0 ]);
860858 if (seen ) {
861859 int i ;
862860 struct strbuf sb = STRBUF_INIT ;
@@ -873,14 +871,14 @@ static int run_argv(int *argcp, const char ***argv)
873871 " not terminate:%s" ), cmd_list .items [0 ].string , sb .buf );
874872 }
875873
876- string_list_append (& cmd_list , * argv [0 ]);
874+ string_list_append (& cmd_list , args -> v [0 ]);
877875
878876 /*
879877 * It could be an alias -- this works around the insanity
880878 * of overriding "git log" with "git show" by having
881879 * alias.log = show
882880 */
883- if (!handle_alias (argcp , argv ))
881+ if (!handle_alias (args ))
884882 break ;
885883 done_alias = 1 ;
886884 }
@@ -892,6 +890,7 @@ static int run_argv(int *argcp, const char ***argv)
892890
893891int cmd_main (int argc , const char * * argv )
894892{
893+ struct strvec args = STRVEC_INIT ;
895894 const char * cmd ;
896895 int done_help = 0 ;
897896
@@ -951,25 +950,32 @@ int cmd_main(int argc, const char **argv)
951950 */
952951 setup_path ();
953952
953+ for (size_t i = 0 ; i < argc ; i ++ )
954+ strvec_push (& args , argv [i ]);
955+
954956 while (1 ) {
955- int was_alias = run_argv (& argc , & argv );
957+ int was_alias = run_argv (& args );
956958 if (errno != ENOENT )
957959 break ;
958960 if (was_alias ) {
959961 fprintf (stderr , _ ("expansion of alias '%s' failed; "
960962 "'%s' is not a git command\n" ),
961- cmd , argv [0 ]);
963+ cmd , args .v [0 ]);
964+ strvec_clear (& args );
962965 exit (1 );
963966 }
964967 if (!done_help ) {
965- cmd = argv [0 ] = help_unknown_cmd (cmd );
968+ strvec_replace (& args , 0 , help_unknown_cmd (cmd ));
969+ cmd = args .v [0 ];
966970 done_help = 1 ;
967- } else
971+ } else {
968972 break ;
973+ }
969974 }
970975
971976 fprintf (stderr , _ ("failed to run command '%s': %s\n" ),
972977 cmd , strerror (errno ));
978+ strvec_clear (& args );
973979
974980 return 1 ;
975981}
0 commit comments