From 8b1fa778676ae94f7a6d4113fa90947b548154dd Mon Sep 17 00:00:00 2001 From: Alex Riesen Date: Fri, 26 Mar 2010 23:53:57 +0100 Subject: [PATCH 1/3] Allow passing of configuration parameters in the command line The values passed this way will override whatever is defined in the config files. Signed-off-by: Alex Riesen Signed-off-by: Junio C Hamano --- Documentation/git.txt | 7 +++++ builtin/config.c | 6 +++- cache.h | 2 ++ config.c | 71 ++++++++++++++++++++++++++++++++++++++++++ git.c | 9 ++++++ t/t1300-repo-config.sh | 8 +++++ 6 files changed, 102 insertions(+), 1 deletion(-) diff --git a/Documentation/git.txt b/Documentation/git.txt index 35c0c7983d..755fa4d472 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 =:: + Pass a configuration parameter to the command. The value + given will override values from configuration files. + The 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 4bc46b15fd..f3d1660d02 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 89f6a40d1a..4a0c75da7e 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 6963fbea43..b6a4257627 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 /* NUL */]; +}; +static struct config_item *config_parameters; +static struct config_item **config_parameters_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 = xcalloc(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 = xstrndup(val, text - val); + } + *config_parameters_tail = ct; + config_parameters_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 6bae30545b..99f036302a 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 f11f98c3ce..64f05080b6 100755 --- a/t/t1300-repo-config.sh +++ b/t/t1300-repo-config.sh @@ -824,4 +824,12 @@ 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 CamelCase=value config camelcase)" = zvalue && + test "z$(git -c flag config --bool flag)" = ztrue && + test_must_fail git -c core.name=value config name +' + test_done From 572e4f6a0c14f650d4cd71876e4249be4c3ad019 Mon Sep 17 00:00:00 2001 From: Alex Riesen Date: Fri, 26 Mar 2010 23:56:01 +0100 Subject: [PATCH 2/3] Use strbufs instead of open-coded string manipulation Signed-off-by: Alex Riesen Signed-off-by: Junio C Hamano --- config.c | 51 +++++++++++++++++++-------------------------------- 1 file changed, 19 insertions(+), 32 deletions(-) diff --git a/config.c b/config.c index b6a4257627..7df9664903 100644 --- a/config.c +++ b/config.c @@ -7,6 +7,7 @@ */ #include "cache.h" #include "exec_cmd.h" +#include "strbuf.h" #define MAXNAME (256) @@ -21,8 +22,8 @@ const char *config_exclusive_filename = NULL; struct config_item { struct config_item *next; + char *name; char *value; - char name[1 /* NUL */]; }; static struct config_item *config_parameters; static struct config_item **config_parameters_tail = &config_parameters; @@ -32,43 +33,29 @@ 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) + struct strbuf tmp = STRBUF_INIT; + struct strbuf **pair; + strbuf_addstr(&tmp, text); + pair = strbuf_split(&tmp, '='); + if (pair[0]->len && pair[0]->buf[pair[0]->len - 1] == '=') + strbuf_setlen(pair[0], pair[0]->len - 1); + strbuf_trim(pair[0]); + if (!pair[0]->len) { + strbuf_list_free(pair); return -1; - ct = xcalloc(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 = xstrndup(val, text - val); } + ct = xcalloc(1, sizeof(struct config_item)); + ct->name = strbuf_detach(pair[0], NULL); + if (pair[1]) { + strbuf_trim(pair[1]); + ct->value = strbuf_detach(pair[1], NULL); + } + strbuf_list_free(pair); + lowercase(ct->name); *config_parameters_tail = ct; config_parameters_tail = &ct->next; return 0; From b3d83d9f2ef1b0f0f53bb7254e234c743aa42817 Mon Sep 17 00:00:00 2001 From: Thomas Rast Date: Fri, 21 May 2010 12:07:47 +0200 Subject: [PATCH 3/3] Complete prototype of git_config_from_parameters() Add the missing argument list. (Its lack triggered a compiler warning for me.) Signed-off-by: Thomas Rast Acked-by: Alex Riesen Signed-off-by: Junio C Hamano --- cache.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cache.h b/cache.h index 4a0c75da7e..73f0f7b098 100644 --- a/cache.h +++ b/cache.h @@ -933,7 +933,7 @@ 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_from_parameters(config_fn_t fn, void *data); 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 *);