Allow passing of configuration parameters in the command line
authorAlex Riesen <raa.lkml@gmail.com>
Fri, 26 Mar 2010 22:53:57 +0000 (23:53 +0100)
committerJunio C Hamano <gitster@pobox.com>
Sun, 28 Mar 2010 16:48:25 +0000 (09:48 -0700)
The values passed this way will override whatever is defined
in the config files.

Signed-off-by: Alex Riesen <raa.lkml@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Documentation/git.txt
builtin/config.c
cache.h
config.c
git.c
t/t1300-repo-config.sh

index 35c0c7983d2c18bc0701bc5d6ec22bebc53f792f..755fa4d472f79fbc1c07e76ee73bbf013cb2cb4a 100644 (file)
@@ -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
index 4bc46b15fde00d913577a2980778746f8315bb70..f3d1660d023f7893373436617a9f729ce1d60f4d 100644 (file)
@@ -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 89f6a40d1a1011bca4d546c5979d66d44b408ece..4a0c75da7e0e53c008816bf5b26ae21a1bb32ce1 100644 (file)
--- 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 *);
index 6963fbea43e6420f5f8dafc5b94fb5c27de6ffd2..b6a4257627373b2ce83321a7f21b0c86e50b9641 100644 (file)
--- 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 6bae30545b85f19eb51c4b055f303f70909f0cf2..99f036302a7e6d884369d1d3f4ce428e437cbccd 100644 (file)
--- 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);
index f11f98c3ce7e35f61d06542ce707d61b98079fda..64f05080b65c2b9506d1e34748b47ee721026aef 100755 (executable)
@@ -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