From 1349484e341a3ec2ba02a86c8fbd97ea9dc8c756 Mon Sep 17 00:00:00 2001 From: Matthieu Moy Date: Wed, 30 Dec 2009 17:51:53 +0100 Subject: [PATCH] builtin-config: add --path option doing ~ and ~user expansion. 395de250 (Expand ~ and ~user in core.excludesfile, commit.template) introduced a C function git_config_pathname, doing ~/ and ~user/ expansion. This patch makes the feature available to scripts with 'git config --get --path'. Signed-off-by: Matthieu Moy Signed-off-by: Junio C Hamano --- Documentation/git-config.txt | 14 +++++++++++--- builtin-config.c | 20 +++++++++++++++++++- t/t1300-repo-config.sh | 28 ++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 4 deletions(-) diff --git a/Documentation/git-config.txt b/Documentation/git-config.txt index f68b198205..263292809d 100644 --- a/Documentation/git-config.txt +++ b/Documentation/git-config.txt @@ -37,11 +37,12 @@ existing values that match the regexp are updated or unset. If you want to handle the lines that do *not* match the regex, just prepend a single exclamation mark in front (see also <>). -The type specifier can be either '--int' or '--bool', which will make +The type specifier can be either '--int' or '--bool', to make 'git-config' ensure that the variable(s) are of the given type and convert the value to the canonical form (simple decimal number for int, -a "true" or "false" string for bool). If no type specifier is passed, -no checks or transformations are performed on the value. +a "true" or "false" string for bool), or '--path', which does some +path expansion (see '--path' below). If no type specifier is passed, no +checks or transformations are performed on the value. The file-option can be one of '--system', '--global' or '--file' which specify where the values will be read from or written to. @@ -136,6 +137,13 @@ See also <>. 'git-config' will ensure that the output matches the format of either --bool or --int, as described above. +--path:: + 'git-config' will expand leading '{tilde}' to the value of + '$HOME', and '{tilde}user' to the home directory for the + specified user. This option has no effect when setting the + value (but you can use 'git config bla {tilde}/' from the + command line to let your shell do the expansion). + -z:: --null:: For all options that output values and/or keys, always diff --git a/builtin-config.c b/builtin-config.c index a2d656edb3..2e3ef911d6 100644 --- a/builtin-config.c +++ b/builtin-config.c @@ -45,6 +45,7 @@ static int end_null; #define TYPE_BOOL (1<<0) #define TYPE_INT (1<<1) #define TYPE_BOOL_OR_INT (1<<2) +#define TYPE_PATH (1<<3) static struct option builtin_config_options[] = { OPT_GROUP("Config file location"), @@ -69,6 +70,7 @@ static struct option builtin_config_options[] = { OPT_BIT(0, "bool", &types, "value is \"true\" or \"false\"", TYPE_BOOL), OPT_BIT(0, "int", &types, "value is decimal number", TYPE_INT), OPT_BIT(0, "bool-or-int", &types, "value is --bool or --int", TYPE_BOOL_OR_INT), + OPT_BIT(0, "path", &types, "value is a path (file or directory name)", TYPE_PATH), OPT_GROUP("Other"), OPT_BOOLEAN('z', "null", &end_null, "terminate values with NUL byte"), OPT_END(), @@ -94,6 +96,7 @@ static int show_config(const char *key_, const char *value_, void *cb) { char value[256]; const char *vptr = value; + int must_free_vptr = 0; int dup_error = 0; if (!use_key_regexp && strcmp(key_, key)) @@ -123,6 +126,9 @@ static int show_config(const char *key_, const char *value_, void *cb) vptr = v ? "true" : "false"; else sprintf(value, "%d", v); + } else if (types == TYPE_PATH) { + git_config_pathname(&vptr, key_, value_); + must_free_vptr = 1; } else vptr = value_?value_:""; @@ -133,6 +139,12 @@ static int show_config(const char *key_, const char *value_, void *cb) } else printf("%s%c", vptr, term); + if (must_free_vptr) + /* If vptr must be freed, it's a pointer to a + * dynamically allocated buffer, it's safe to cast to + * const. + */ + free((char *)vptr); return 0; } @@ -215,7 +227,13 @@ static char *normalize_value(const char *key, const char *value) if (!value) return NULL; - if (types == 0) + if (types == 0 || types == TYPE_PATH) + /* + * We don't do normalization for TYPE_PATH here: If + * the path is like ~/foobar/, we prefer to store + * "~/foobar/" in the config file, and to expand the ~ + * when retrieving the value. + */ normalized = xstrdup(value); else { normalized = xmalloc(64); diff --git a/t/t1300-repo-config.sh b/t/t1300-repo-config.sh index 83b7294010..f89d7e9e49 100755 --- a/t/t1300-repo-config.sh +++ b/t/t1300-repo-config.sh @@ -683,6 +683,34 @@ test_expect_success 'set --bool-or-int' ' rm .git/config +cat >expect <<\EOF +[path] + home = ~/ + normal = /dev/null + trailingtilde = foo~ +EOF + +test_expect_success 'set --path' ' + git config --path path.home "~/" && + git config --path path.normal "/dev/null" && + git config --path path.trailingtilde "foo~" && + test_cmp expect .git/config' + +cat >expect < result && + git config --get --path path.normal >> result && + git config --get --path path.trailingtilde >> result && + test_cmp expect result +' + +rm .git/config + git config quote.leading " test" git config quote.ending "test " git config quote.semicolon "test;test"