[PATCH] Allow passing of configuration parameters in the command line
- From
Alex Riesen <raa.lkml@gmail.com>
- Date
- Mar 19, 2010, 14:42 UTC
- Message-ID
- <81b0412b1003190742v6e5577c9wb121d5e3cbc9fccd@mail.gmail.com>
The values passed this way will override whatever is defined in the config files.
Signed-off-by: Alex Riesen <raa.lkml@gmail.com> ---
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
From 99febf0858fde149009cff7d031f229eff8a92e1 Mon Sep 17 00:00:00 2001
From: Alex Riesen <raa.lkml@gmail.com>
Date: Fri, 19 Mar 2010 15:19:24 +0100
Subject: [PATCH] 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 <raa.lkml@gmail.com>
---
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