The values passed this way will override whatever is defined in the config files. Signed-off-by: Alex Riesen <raa.lkml@xxxxxxxxx> --- Someone wanted to have this once. I accidentally remembered that when I wanted to temporarily set some config parameter (format.suffix?). From looking at code it seemed simple enough, so I did it. I have to say that the feature is not very friendly: there are some values in .git/config which may not like to be changed (like core.fileMode, ...ignoreCase or ...repositoryFormatVersion). Documentation/git.txt | 7 +++++ builtin/config.c | 6 +++- cache.h | 2 + config.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++ git.c | 9 ++++++ t/t1300-repo-config.sh | 7 +++++ 6 files changed, 101 insertions(+), 1 deletions(-) diff --git a/Documentation/git.txt b/Documentation/git.txt index 35c0c79..755fa4d 100644 --- a/Documentation/git.txt +++ b/Documentation/git.txt @@ -12,6 +12,7 @@ SYNOPSIS 'git' [--version] [--exec-path[=GIT_EXEC_PATH]] [--html-path] [-p|--paginate|--no-pager] [--no-replace-objects] [--bare] [--git-dir=GIT_DIR] [--work-tree=GIT_WORK_TREE] + [-c name=value] [--help] COMMAND [ARGS] DESCRIPTION @@ -219,6 +220,12 @@ displayed. See linkgit:git-help[1] for more information, because `git --help ...` is converted internally into `git help ...`. +-c <name>=<value>:: + Pass a configuration parameter to the command. The value + given will override values from configuration files. + The <name> is expected in the same format as listed by + 'git config' (subkeys separated by dots). + --exec-path:: Path to wherever your core git programs are installed. This can also be controlled by setting the GIT_EXEC_PATH diff --git a/builtin/config.c b/builtin/config.c index 4bc46b1..f3d1660 100644 --- a/builtin/config.c +++ b/builtin/config.c @@ -197,7 +197,11 @@ static int get_value(const char *key_, const char *regex_) git_config_from_file(show_config, system_wide, NULL); if (do_all && global) git_config_from_file(show_config, global, NULL); - git_config_from_file(show_config, local, NULL); + if (do_all) + git_config_from_file(show_config, local, NULL); + git_config_from_parameters(show_config, NULL); + if (!do_all && !seen) + git_config_from_file(show_config, local, NULL); if (!do_all && !seen && global) git_config_from_file(show_config, global, NULL); if (!do_all && !seen && system_wide) diff --git a/cache.h b/cache.h index 89f6a40..4a0c75d 100644 --- a/cache.h +++ b/cache.h @@ -932,6 +932,8 @@ extern int update_server_info(int); typedef int (*config_fn_t)(const char *, const char *, void *); extern int git_default_config(const char *, const char *, void *); extern int git_config_from_file(config_fn_t fn, const char *, void *); +extern int git_config_parse_parameter(const char *text); +extern int git_config_from_parameters(); extern int git_config(config_fn_t fn, void *); extern int git_parse_ulong(const char *, unsigned long *); extern int git_config_int(const char *, const char *); diff --git a/config.c b/config.c index 6963fbe..2376ae9 100644 --- a/config.c +++ b/config.c @@ -18,6 +18,62 @@ static int zlib_compression_seen; const char *config_exclusive_filename = NULL; +struct config_item +{ + struct config_item *next; + char *value; + char name[1]; +}; +static struct config_item *config_parameters; +static struct config_item **config_parametes_tail = &config_parameters; + +static void lowercase(char *p) +{ + for (; *p; ++p) + *p = tolower(*p); +} +static char *skip_space(const char *p) +{ + for (; *p; ++p) + if (!isspace(*p)) + break; + return (char *)p; +} +static char *trailing_space(const char *begin, const char *p) +{ + while (p-- > begin) + if (!isspace(*p)) + break; + return (char *)p + 1; +} + +int git_config_parse_parameter(const char *text) +{ + struct config_item *ct; + const char *name; + const char *val; + name = skip_space(text); + text = val = strchr(name, '='); + if (!text) + text = name + strlen(name); + text = trailing_space(name, text); + if (text <= name) + return -1; + ct = calloc(1, sizeof(struct config_item) + (text - name)); + memcpy(ct->name, name, text - name); + lowercase(ct->name); + if (!val) + ct->value = NULL; + else { + val = skip_space(++val /* skip "=" */); + text = trailing_space(val, val + strlen(val)); + ct->value = strndup(val, text - val); + } + *config_parametes_tail = ct; + config_parametes_tail = &ct->next; + return 0; +} + static int get_next_char(void) { int c; @@ -699,6 +755,15 @@ int git_config_global(void) return !git_env_bool("GIT_CONFIG_NOGLOBAL", 0); } +int git_config_from_parameters(config_fn_t fn, void *data) +{ + const struct config_item *ct; + for (ct = config_parameters; ct; ct = ct->next) + if (fn(ct->name, ct->value, data) < 0) + return -1; + return 0; +} + int git_config(config_fn_t fn, void *data) { int ret = 0, found = 0; @@ -730,6 +795,12 @@ int git_config(config_fn_t fn, void *data) found += 1; } free(repo_config); + + if (config_parameters) { + ret += git_config_from_parameters(fn, data); + found += 1; + } + if (found == 0) return -1; return ret; diff --git a/git.c b/git.c index 6bae305..99f0363 100644 --- a/git.c +++ b/git.c @@ -8,6 +8,7 @@ const char git_usage_string[] = "git [--version] [--exec-path[=GIT_EXEC_PATH]] [--html-path]\n" " [-p|--paginate|--no-pager] [--no-replace-objects]\n" " [--bare] [--git-dir=GIT_DIR] [--work-tree=GIT_WORK_TREE]\n" + " [-c name=value\n" " [--help] COMMAND [ARGS]"; const char git_more_info_string[] = @@ -130,6 +131,14 @@ static int handle_options(const char ***argv, int *argc, int *envchanged) setenv(GIT_DIR_ENVIRONMENT, getcwd(git_dir, sizeof(git_dir)), 0); if (envchanged) *envchanged = 1; + } else if (!strcmp(cmd, "-c")) { + if (*argc < 2) { + fprintf(stderr, "-c expects a configuration string\n" ); + usage(git_usage_string); + } + git_config_parse_parameter((*argv)[1]); + (*argv)++; + (*argc)--; } else { fprintf(stderr, "Unknown option: %s\n", cmd); usage(git_usage_string); diff --git a/t/t1300-repo-config.sh b/t/t1300-repo-config.sh index f11f98c..d7c5501 100755 --- a/t/t1300-repo-config.sh +++ b/t/t1300-repo-config.sh @@ -824,4 +824,11 @@ test_expect_success 'check split_cmdline return' " test_must_fail git merge master " +test_expect_success 'git -c "key=value" support' ' + test "z$(git -c name=value config name)" = zvalue && + test "z$(git -c core.name=value config core.name)" = zvalue && + test "z$(git -c flag config --bool flag)" = ztrue && + test_must_fail git -c core.name=value config name +' + test_done -- 1.7.0.2.318.g49250
Attachment:
0001-Allow-passing-of-configuration-parameters-in-the-comm.diff
Description: Binary data