@@ -14,6 +14,7 @@ static const char *const builtin_config_usage[] = {
1414
1515static char * key ;
1616static regex_t * key_regexp ;
17+ static const char * value_pattern ;
1718static regex_t * regexp ;
1819static int show_keys ;
1920static int omit_values ;
@@ -34,6 +35,7 @@ static int respect_includes_opt = -1;
3435static struct config_options config_options ;
3536static int show_origin ;
3637static int show_scope ;
38+ static int fixed_value ;
3739
3840#define ACTION_GET (1<<0)
3941#define ACTION_GET_ALL (1<<1)
@@ -133,17 +135,18 @@ static struct option builtin_config_options[] = {
133135 OPT_STRING ('f' , "file" , & given_config_source .file , N_ ("file" ), N_ ("use given config file" )),
134136 OPT_STRING (0 , "blob" , & given_config_source .blob , N_ ("blob-id" ), N_ ("read config from given blob object" )),
135137 OPT_GROUP (N_ ("Action" )),
136- OPT_BIT (0 , "get" , & actions , N_ ("get value: name [value-regex ]" ), ACTION_GET ),
137- OPT_BIT (0 , "get-all" , & actions , N_ ("get all values: key [value-regex ]" ), ACTION_GET_ALL ),
138- OPT_BIT (0 , "get-regexp" , & actions , N_ ("get values for regexp: name-regex [value-regex ]" ), ACTION_GET_REGEXP ),
138+ OPT_BIT (0 , "get" , & actions , N_ ("get value: name [value-pattern ]" ), ACTION_GET ),
139+ OPT_BIT (0 , "get-all" , & actions , N_ ("get all values: key [value-pattern ]" ), ACTION_GET_ALL ),
140+ OPT_BIT (0 , "get-regexp" , & actions , N_ ("get values for regexp: name-regex [value-pattern ]" ), ACTION_GET_REGEXP ),
139141 OPT_BIT (0 , "get-urlmatch" , & actions , N_ ("get value specific for the URL: section[.var] URL" ), ACTION_GET_URLMATCH ),
140- OPT_BIT (0 , "replace-all" , & actions , N_ ("replace all matching variables: name value [value_regex ]" ), ACTION_REPLACE_ALL ),
142+ OPT_BIT (0 , "replace-all" , & actions , N_ ("replace all matching variables: name value [value-pattern ]" ), ACTION_REPLACE_ALL ),
141143 OPT_BIT (0 , "add" , & actions , N_ ("add a new variable: name value" ), ACTION_ADD ),
142- OPT_BIT (0 , "unset" , & actions , N_ ("remove a variable: name [value-regex ]" ), ACTION_UNSET ),
143- OPT_BIT (0 , "unset-all" , & actions , N_ ("remove all matches: name [value-regex ]" ), ACTION_UNSET_ALL ),
144+ OPT_BIT (0 , "unset" , & actions , N_ ("remove a variable: name [value-pattern ]" ), ACTION_UNSET ),
145+ OPT_BIT (0 , "unset-all" , & actions , N_ ("remove all matches: name [value-pattern ]" ), ACTION_UNSET_ALL ),
144146 OPT_BIT (0 , "rename-section" , & actions , N_ ("rename section: old-name new-name" ), ACTION_RENAME_SECTION ),
145147 OPT_BIT (0 , "remove-section" , & actions , N_ ("remove a section: name" ), ACTION_REMOVE_SECTION ),
146148 OPT_BIT ('l' , "list" , & actions , N_ ("list all" ), ACTION_LIST ),
149+ OPT_BOOL (0 , "fixed-value" , & fixed_value , N_ ("use string equality when comparing values to 'value-pattern'" )),
147150 OPT_BIT ('e' , "edit" , & actions , N_ ("open an editor" ), ACTION_EDIT ),
148151 OPT_BIT (0 , "get-color" , & actions , N_ ("find the color configured: slot [default]" ), ACTION_GET_COLOR ),
149152 OPT_BIT (0 , "get-colorbool" , & actions , N_ ("find the color setting: slot [stdout-is-tty]" ), ACTION_GET_COLORBOOL ),
@@ -296,6 +299,8 @@ static int collect_config(const char *key_, const char *value_, void *cb)
296299 return 0 ;
297300 if (use_key_regexp && regexec (key_regexp , key_ , 0 , NULL , 0 ))
298301 return 0 ;
302+ if (fixed_value && strcmp (value_pattern , (value_ ?value_ :"" )))
303+ return 0 ;
299304 if (regexp != NULL &&
300305 (do_not_match ^ !!regexec (regexp , (value_ ?value_ :"" ), 0 , NULL , 0 )))
301306 return 0 ;
@@ -306,7 +311,7 @@ static int collect_config(const char *key_, const char *value_, void *cb)
306311 return format_config (& values -> items [values -> nr ++ ], key_ , value_ );
307312}
308313
309- static int get_value (const char * key_ , const char * regex_ )
314+ static int get_value (const char * key_ , const char * regex_ , unsigned flags )
310315{
311316 int ret = CONFIG_GENERIC_ERROR ;
312317 struct strbuf_list values = {NULL };
@@ -343,7 +348,9 @@ static int get_value(const char *key_, const char *regex_)
343348 }
344349 }
345350
346- if (regex_ ) {
351+ if (regex_ && (flags & CONFIG_FLAGS_FIXED_VALUE ))
352+ value_pattern = regex_ ;
353+ else if (regex_ ) {
347354 if (regex_ [0 ] == '!' ) {
348355 do_not_match = 1 ;
349356 regex_ ++ ;
@@ -631,6 +638,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)
631638{
632639 int nongit = !startup_info -> have_repository ;
633640 char * value ;
641+ int flags = 0 ;
634642
635643 given_config_source .file = xstrdup_or_null (getenv (CONFIG_ENVIRONMENT ));
636644
@@ -766,6 +774,42 @@ int cmd_config(int argc, const char **argv, const char *prefix)
766774 usage_builtin_config ();
767775 }
768776
777+ /* check usage of --fixed-value */
778+ if (fixed_value ) {
779+ int allowed_usage = 0 ;
780+
781+ switch (actions ) {
782+ /* git config --get <name> <value-pattern> */
783+ case ACTION_GET :
784+ /* git config --get-all <name> <value-pattern> */
785+ case ACTION_GET_ALL :
786+ /* git config --get-regexp <name-pattern> <value-pattern> */
787+ case ACTION_GET_REGEXP :
788+ /* git config --unset <name> <value-pattern> */
789+ case ACTION_UNSET :
790+ /* git config --unset-all <name> <value-pattern> */
791+ case ACTION_UNSET_ALL :
792+ allowed_usage = argc > 1 && !!argv [1 ];
793+ break ;
794+
795+ /* git config <name> <value> <value-pattern> */
796+ case ACTION_SET_ALL :
797+ /* git config --replace-all <name> <value> <value-pattern> */
798+ case ACTION_REPLACE_ALL :
799+ allowed_usage = argc > 2 && !!argv [2 ];
800+ break ;
801+
802+ /* other options don't allow --fixed-value */
803+ }
804+
805+ if (!allowed_usage ) {
806+ error (_ ("--fixed-value only applies with 'value-pattern'" ));
807+ usage_builtin_config ();
808+ }
809+
810+ flags |= CONFIG_FLAGS_FIXED_VALUE ;
811+ }
812+
769813 if (actions & PAGING_ACTIONS )
770814 setup_auto_pager ("config" , 1 );
771815
@@ -827,7 +871,8 @@ int cmd_config(int argc, const char **argv, const char *prefix)
827871 value = normalize_value (argv [0 ], argv [1 ]);
828872 UNLEAK (value );
829873 return git_config_set_multivar_in_file_gently (given_config_source .file ,
830- argv [0 ], value , argv [2 ], 0 );
874+ argv [0 ], value , argv [2 ],
875+ flags );
831876 }
832877 else if (actions == ACTION_ADD ) {
833878 check_write ();
@@ -836,31 +881,33 @@ int cmd_config(int argc, const char **argv, const char *prefix)
836881 UNLEAK (value );
837882 return git_config_set_multivar_in_file_gently (given_config_source .file ,
838883 argv [0 ], value ,
839- CONFIG_REGEX_NONE , 0 );
884+ CONFIG_REGEX_NONE ,
885+ flags );
840886 }
841887 else if (actions == ACTION_REPLACE_ALL ) {
842888 check_write ();
843889 check_argc (argc , 2 , 3 );
844890 value = normalize_value (argv [0 ], argv [1 ]);
845891 UNLEAK (value );
846892 return git_config_set_multivar_in_file_gently (given_config_source .file ,
847- argv [0 ], value , argv [2 ], 1 );
893+ argv [0 ], value , argv [2 ],
894+ flags | CONFIG_FLAGS_MULTI_REPLACE );
848895 }
849896 else if (actions == ACTION_GET ) {
850897 check_argc (argc , 1 , 2 );
851- return get_value (argv [0 ], argv [1 ]);
898+ return get_value (argv [0 ], argv [1 ], flags );
852899 }
853900 else if (actions == ACTION_GET_ALL ) {
854901 do_all = 1 ;
855902 check_argc (argc , 1 , 2 );
856- return get_value (argv [0 ], argv [1 ]);
903+ return get_value (argv [0 ], argv [1 ], flags );
857904 }
858905 else if (actions == ACTION_GET_REGEXP ) {
859906 show_keys = 1 ;
860907 use_key_regexp = 1 ;
861908 do_all = 1 ;
862909 check_argc (argc , 1 , 2 );
863- return get_value (argv [0 ], argv [1 ]);
910+ return get_value (argv [0 ], argv [1 ], flags );
864911 }
865912 else if (actions == ACTION_GET_URLMATCH ) {
866913 check_argc (argc , 2 , 2 );
@@ -871,7 +918,8 @@ int cmd_config(int argc, const char **argv, const char *prefix)
871918 check_argc (argc , 1 , 2 );
872919 if (argc == 2 )
873920 return git_config_set_multivar_in_file_gently (given_config_source .file ,
874- argv [0 ], NULL , argv [1 ], 0 );
921+ argv [0 ], NULL , argv [1 ],
922+ flags );
875923 else
876924 return git_config_set_in_file_gently (given_config_source .file ,
877925 argv [0 ], NULL );
@@ -880,7 +928,8 @@ int cmd_config(int argc, const char **argv, const char *prefix)
880928 check_write ();
881929 check_argc (argc , 1 , 2 );
882930 return git_config_set_multivar_in_file_gently (given_config_source .file ,
883- argv [0 ], NULL , argv [1 ], 1 );
931+ argv [0 ], NULL , argv [1 ],
932+ flags | CONFIG_FLAGS_MULTI_REPLACE );
884933 }
885934 else if (actions == ACTION_RENAME_SECTION ) {
886935 int ret ;
0 commit comments