28
28
#define NEED_WORK_TREE (1<<3)
29
29
#define DELAY_PAGER_CONFIG (1<<4)
30
30
#define NO_PARSEOPT (1<<5) /* parse-options is not used */
31
+ #define DEPRECATED (1<<6)
31
32
32
33
struct cmd_struct {
33
34
const char * cmd ;
@@ -51,7 +52,9 @@ const char git_more_info_string[] =
51
52
52
53
static int use_pager = -1 ;
53
54
54
- static void list_builtins (struct string_list * list , unsigned int exclude_option );
55
+ static void list_builtins (struct string_list * list ,
56
+ unsigned int include_option ,
57
+ unsigned int exclude_option );
55
58
56
59
static void exclude_helpers_from_list (struct string_list * list )
57
60
{
@@ -88,7 +91,7 @@ static int list_cmds(const char *spec)
88
91
int len = sep - spec ;
89
92
90
93
if (match_token (spec , len , "builtins" ))
91
- list_builtins (& list , 0 );
94
+ list_builtins (& list , 0 , 0 );
92
95
else if (match_token (spec , len , "main" ))
93
96
list_all_main_cmds (& list );
94
97
else if (match_token (spec , len , "others" ))
@@ -99,6 +102,8 @@ static int list_cmds(const char *spec)
99
102
list_aliases (& list );
100
103
else if (match_token (spec , len , "config" ))
101
104
list_cmds_by_config (& list );
105
+ else if (match_token (spec , len , "deprecated" ))
106
+ list_builtins (& list , DEPRECATED , 0 );
102
107
else if (len > 5 && !strncmp (spec , "list-" , 5 )) {
103
108
struct strbuf sb = STRBUF_INIT ;
104
109
@@ -322,7 +327,7 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
322
327
if (!strcmp (cmd , "parseopt" )) {
323
328
struct string_list list = STRING_LIST_INIT_DUP ;
324
329
325
- list_builtins (& list , NO_PARSEOPT );
330
+ list_builtins (& list , 0 , NO_PARSEOPT );
326
331
for (size_t i = 0 ; i < list .nr ; i ++ )
327
332
printf ("%s " , list .items [i ].string );
328
333
string_list_clear (& list , 0 );
@@ -360,7 +365,7 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
360
365
return (* argv ) - orig_argv ;
361
366
}
362
367
363
- static int handle_alias (struct strvec * args )
368
+ static int handle_alias (struct strvec * args , struct string_list * expanded_aliases )
364
369
{
365
370
int envchanged = 0 , ret = 0 , saved_errno = errno ;
366
371
int count , option_count ;
@@ -371,6 +376,8 @@ static int handle_alias(struct strvec *args)
371
376
alias_command = args -> v [0 ];
372
377
alias_string = alias_lookup (alias_command );
373
378
if (alias_string ) {
379
+ struct string_list_item * seen ;
380
+
374
381
if (args -> nr == 2 && !strcmp (args -> v [1 ], "-h" ))
375
382
fprintf_ln (stderr , _ ("'%s' is aliased to '%s'" ),
376
383
alias_command , alias_string );
@@ -418,6 +425,25 @@ static int handle_alias(struct strvec *args)
418
425
if (!strcmp (alias_command , new_argv [0 ]))
419
426
die (_ ("recursive alias: %s" ), alias_command );
420
427
428
+ string_list_append (expanded_aliases , alias_command );
429
+ seen = unsorted_string_list_lookup (expanded_aliases ,
430
+ new_argv [0 ]);
431
+
432
+ if (seen ) {
433
+ struct strbuf sb = STRBUF_INIT ;
434
+ for (size_t i = 0 ; i < expanded_aliases -> nr ; i ++ ) {
435
+ struct string_list_item * item = & expanded_aliases -> items [i ];
436
+
437
+ strbuf_addf (& sb , "\n %s" , item -> string );
438
+ if (item == seen )
439
+ strbuf_addstr (& sb , " <==" );
440
+ else if (i == expanded_aliases -> nr - 1 )
441
+ strbuf_addstr (& sb , " ==>" );
442
+ }
443
+ die (_ ("alias loop detected: expansion of '%s' does"
444
+ " not terminate:%s" ), expanded_aliases -> items [0 ].string , sb .buf );
445
+ }
446
+
421
447
trace_argv_printf (new_argv ,
422
448
"trace: alias expansion: %s =>" ,
423
449
alias_command );
@@ -591,7 +617,7 @@ static struct cmd_struct commands[] = {
591
617
{ "notes" , cmd_notes , RUN_SETUP },
592
618
{ "pack-objects" , cmd_pack_objects , RUN_SETUP },
593
619
#ifndef WITH_BREAKING_CHANGES
594
- { "pack-redundant" , cmd_pack_redundant , RUN_SETUP | NO_PARSEOPT },
620
+ { "pack-redundant" , cmd_pack_redundant , RUN_SETUP | NO_PARSEOPT | DEPRECATED },
595
621
#endif
596
622
{ "pack-refs" , cmd_pack_refs , RUN_SETUP },
597
623
{ "patch-id" , cmd_patch_id , RUN_SETUP_GENTLY | NO_PARSEOPT },
@@ -649,7 +675,7 @@ static struct cmd_struct commands[] = {
649
675
{ "verify-tag" , cmd_verify_tag , RUN_SETUP },
650
676
{ "version" , cmd_version },
651
677
#ifndef WITH_BREAKING_CHANGES
652
- { "whatchanged" , cmd_whatchanged , RUN_SETUP },
678
+ { "whatchanged" , cmd_whatchanged , RUN_SETUP | DEPRECATED },
653
679
#endif
654
680
{ "worktree" , cmd_worktree , RUN_SETUP },
655
681
{ "write-tree" , cmd_write_tree , RUN_SETUP },
@@ -670,11 +696,16 @@ int is_builtin(const char *s)
670
696
return !!get_builtin (s );
671
697
}
672
698
673
- static void list_builtins (struct string_list * out , unsigned int exclude_option )
699
+ static void list_builtins (struct string_list * out ,
700
+ unsigned int include_option ,
701
+ unsigned int exclude_option )
674
702
{
703
+ if (include_option && exclude_option )
704
+ BUG ("'include_option' and 'exclude_option' are mutually exclusive" );
675
705
for (size_t i = 0 ; i < ARRAY_SIZE (commands ); i ++ ) {
676
- if (exclude_option &&
677
- (commands [i ].option & exclude_option ))
706
+ if (include_option && !(commands [i ].option & include_option ))
707
+ continue ;
708
+ if (exclude_option && (commands [i ].option & exclude_option ))
678
709
continue ;
679
710
string_list_append (out , commands [i ].cmd );
680
711
}
@@ -795,13 +826,29 @@ static void execv_dashed_external(const char **argv)
795
826
exit (128 );
796
827
}
797
828
829
+ static int is_deprecated_command (const char * cmd )
830
+ {
831
+ struct cmd_struct * builtin = get_builtin (cmd );
832
+ return builtin && (builtin -> option & DEPRECATED );
833
+ }
834
+
798
835
static int run_argv (struct strvec * args )
799
836
{
800
837
int done_alias = 0 ;
801
- struct string_list cmd_list = STRING_LIST_INIT_DUP ;
802
- struct string_list_item * seen ;
838
+ struct string_list expanded_aliases = STRING_LIST_INIT_DUP ;
803
839
804
840
while (1 ) {
841
+ /*
842
+ * Allow deprecated commands to be overridden by aliases. This
843
+ * creates a seamless path forward for people who want to keep
844
+ * using the name after it is gone, but want to skip the
845
+ * deprecation complaint in the meantime.
846
+ */
847
+ if (is_deprecated_command (args -> v [0 ]) &&
848
+ handle_alias (args , & expanded_aliases )) {
849
+ done_alias = 1 ;
850
+ continue ;
851
+ }
805
852
/*
806
853
* If we tried alias and futzed with our environment,
807
854
* it no longer is safe to invoke builtins directly in
@@ -851,35 +898,17 @@ static int run_argv(struct strvec *args)
851
898
/* .. then try the external ones */
852
899
execv_dashed_external (args -> v );
853
900
854
- seen = unsorted_string_list_lookup (& cmd_list , args -> v [0 ]);
855
- if (seen ) {
856
- struct strbuf sb = STRBUF_INIT ;
857
- for (size_t i = 0 ; i < cmd_list .nr ; i ++ ) {
858
- struct string_list_item * item = & cmd_list .items [i ];
859
-
860
- strbuf_addf (& sb , "\n %s" , item -> string );
861
- if (item == seen )
862
- strbuf_addstr (& sb , " <==" );
863
- else if (i == cmd_list .nr - 1 )
864
- strbuf_addstr (& sb , " ==>" );
865
- }
866
- die (_ ("alias loop detected: expansion of '%s' does"
867
- " not terminate:%s" ), cmd_list .items [0 ].string , sb .buf );
868
- }
869
-
870
- string_list_append (& cmd_list , args -> v [0 ]);
871
-
872
901
/*
873
902
* It could be an alias -- this works around the insanity
874
903
* of overriding "git log" with "git show" by having
875
904
* alias.log = show
876
905
*/
877
- if (!handle_alias (args ))
906
+ if (!handle_alias (args , & expanded_aliases ))
878
907
break ;
879
908
done_alias = 1 ;
880
909
}
881
910
882
- string_list_clear (& cmd_list , 0 );
911
+ string_list_clear (& expanded_aliases , 0 );
883
912
884
913
return done_alias ;
885
914
}
0 commit comments