{"thread":{"id":"8418","subject":"[PATCH] Support environment variables in config file","startedAt":"2007-06-03T22:37:27Z","lastAt":"2007-06-04T17:59:40Z","messageCount":7,"participants":["Martin Waitz","Matthias Lederhofer","Johannes Schindelin"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"43919","messageId":"20070603223727.GA16637@admingilde.org","threadId":"8418","inReplyTo":null,"subject":"[PATCH] Support environment variables in config file","fromName":"Martin Waitz","fromEmail":"tali@admingilde.org","sentAt":"2007-06-03T22:37:27Z","receivedAt":"2007-06-03T22:37:27Z","isPatch":true,"sender":{"key":"tali@admingilde.org","avatar":"https://gravatar.com/avatar/3f89b03eee362187effabe257898735b475673a12265c398ea9161259ae91553?d=mp&s=160"},"body":"Environment variables (e.g. $HOME) can be helpful for the GIT configuration.\nWith this change you can use them with the normal shell \"$\" syntax.\nIf you want to insert a plain \"$\" in a variable, it can be escaped as \\$\nor put inside quotes (\").\n\nSigned-off-by: Martin Waitz <tali@admingilde.org>\n---\n\nI found this particularly useful to be able to specify my own global\ngitignore list via core.excludesfile.\n\n Documentation/config.txt |   23 +++++++++++++++--------\n config.c                 |   23 +++++++++++++++++++++--\n t/t1300-repo-config.sh   |   13 +++++++++++++\n 3 files changed, 49 insertions(+), 10 deletions(-)\n\ndiff --git a/Documentation/config.txt b/Documentation/config.txt\nindex 5868d58..042a354 100644\n--- a/Documentation/config.txt\n+++ b/Documentation/config.txt\n@@ -65,17 +65,24 @@ a string, an integer, or a boolean.  Boolean values may be given as yes/no,\n converting value to the canonical form using '--bool' type specifier;\n `git-config` will ensure that the output is \"true\" or \"false\".\n \n+You can use the $VARIABLE shell syntax to use environment variables\n+in the configuration file.  All alpha-numeric characters after the\n+leading '`$`' will be interpreted as name of an environment variable\n+and the value of this variable will be used instead.\n+If the variable does not exist it will be treated as an empty string.\n+\n String values may be entirely or partially enclosed in double quotes.\n You need to enclose variable value in double quotes if you want to\n preserve leading or trailing whitespace, or if variable value contains\n-beginning of comment characters (if it contains '#' or ';').\n-Double quote '`\"`' and backslash '`\\`' characters in variable value must\n-be escaped: use '`\\\"`' for '`\"`' and '`\\\\`' for '`\\`'.\n-\n-The following escape sequences (beside '`\\\"`' and '`\\\\`') are recognized:\n-'`\\n`' for newline character (NL), '`\\t`' for horizontal tabulation (HT, TAB)\n-and '`\\b`' for backspace (BS).  No other char escape sequence, nor octal\n-char sequences are valid.\n+beginning of comment characters (if it contains '#' or ';') or a dollar\n+sign which would be interpreted as a variable.\n+Double quote '`\"`', backslash '`\\`' and dollar '`$`' characters in variable\n+value must be escaped: use '`\\\"`' for '`\"`' and '`\\\\`' for '`\\`'.\n+\n+The following escape sequences (beside '`\\\"`', '`\\$\"`' and '`\\\\`') are\n+recognized: '`\\n`' for newline character (NL), '`\\t`' for horizontal tabulation\n+(HT, TAB) and '`\\b`' for backspace (BS).  No other char escape sequence, nor\n+octal char sequences are valid.\n \n Variable value ending in a '`\\`' is continued on the next line in the\n customary UNIX fashion.\ndiff --git a/config.c b/config.c\nindex 0614c2b..058c0df 100644\n--- a/config.c\n+++ b/config.c\n@@ -43,12 +43,27 @@ static int get_next_char(void)\n static char *parse_value(void)\n {\n \tstatic char value[1024];\n-\tint quote = 0, comment = 0, len = 0, space = 0;\n+\tint quote = 0, comment = 0, envvar = -1, len = 0, space = 0;\n \n \tfor (;;) {\n \t\tint c = get_next_char();\n \t\tif (len >= sizeof(value))\n \t\t\treturn NULL;\n+\t\tif ((envvar >= 0) && !isalnum(c)) {\n+\t\t\tconst char *var;\n+\t\t\tvalue[len] = 0;\n+\t\t\tvar = getenv(&value[envvar]);\n+\t\t\tif (var) {\n+\t\t\t\tstrncpy(&value[envvar], var,\n+\t\t\t\t        sizeof(value) - envvar);\n+\t\t\t\tif (value[sizeof(value)-1])\n+\t\t\t\t\treturn NULL;\n+\t\t\t\tlen = envvar + strlen(&value[envvar]);\n+\t\t\t} else {\n+\t\t\t\tlen = envvar;\n+\t\t\t}\n+\t\t\tenvvar = -1;\n+\t\t}\n \t\tif (c == '\\n') {\n \t\t\tif (quote)\n \t\t\t\treturn NULL;\n@@ -66,6 +81,10 @@ static char *parse_value(void)\n \t\t\t\tcomment = 1;\n \t\t\t\tcontinue;\n \t\t\t}\n+\t\t\tif (c == '$') {\n+\t\t\t\tenvvar = len;\n+\t\t\t\tcontinue;\n+\t\t\t}\n \t\t}\n \t\tif (space) {\n \t\t\tif (len)\n@@ -87,7 +106,7 @@ static char *parse_value(void)\n \t\t\t\tc = '\\n';\n \t\t\t\tbreak;\n \t\t\t/* Some characters escape as themselves */\n-\t\t\tcase '\\\\': case '\"':\n+\t\t\tcase '\\\\': case '\"': case '$':\n \t\t\t\tbreak;\n \t\t\t/* Reject unknown escape sequences */\n \t\t\tdefault:\ndiff --git a/t/t1300-repo-config.sh b/t/t1300-repo-config.sh\nindex 3f3fd2d..eb84437 100755\n--- a/t/t1300-repo-config.sh\n+++ b/t/t1300-repo-config.sh\n@@ -513,5 +513,18 @@ git config --list > result\n \n test_expect_success 'value continued on next line' 'cmp result expect'\n \n+cat > .git/config <<\\EOF\n+[quoted]\n+\twithvar = \"$HOME/foo\"\n+[unquoted]\n+\twithvar = $HOME/foo\n+EOF\n+\n+test_expect_success 'quoted $VAR' \\\n+\t'test x\"\\$HOME/foo\" = x$(git config quoted.withvar)'\n+\n+test_expect_success 'unquoted $VAR' \\\n+\t'test x\"$HOME/foo\" = x$(git config unquoted.withvar)'\n+\n test_done\n \n-- \n1.5.2.1.112.gdb0c\n\n\n-- \nMartin Waitz\n"},{"id":"43936","messageId":"20070604053443.GA15148@moooo.ath.cx","threadId":"8418","inReplyTo":"20070603223727.GA16637@admingilde.org","subject":"Re: [PATCH] Support environment variables in config file","fromName":"Matthias Lederhofer","fromEmail":"matled@gmx.net","sentAt":"2007-06-04T05:34:43Z","receivedAt":"2007-06-04T05:34:43Z","isPatch":true,"sender":{"key":"matled@gmx.net","avatar":null},"body":"Martin Waitz <tali@admingilde.org> wrote:\n> Environment variables (e.g. $HOME) can be helpful for the GIT configuration.\n> With this change you can use them with the normal shell \"$\" syntax.\n> If you want to insert a plain \"$\" in a variable, it can be escaped as \\$\n> or put inside quotes (\").\n\nPerhaps we should also allow variable interpolation in double quoted\nstrings as this is quite common in various languages.\n\n> diff --git a/Documentation/config.txt b/Documentation/config.txt\n> index 5868d58..042a354 100644\n> --- a/Documentation/config.txt\n> +++ b/Documentation/config.txt\n> @@ -65,17 +65,24 @@ a string, an integer, or a boolean.  Boolean values may be given as yes/no,\n>  converting value to the canonical form using '--bool' type specifier;\n>  `git-config` will ensure that the output is \"true\" or \"false\".\n>  \n> +You can use the $VARIABLE shell syntax to use environment variables\n> +in the configuration file.  All alpha-numeric characters after the\n> +leading '`$`' will be interpreted as name of an environment variable\n> +and the value of this variable will be used instead.\n> +If the variable does not exist it will be treated as an empty string.\n\nWe could have a short example here how to concatenate a variable and a\nstring without a space in between.  I came up with '$FOO\"\"bar' which\nis not that obvious imo.\n\n> diff --git a/config.c b/config.c\n> index 0614c2b..058c0df 100644\n> --- a/config.c\n> +++ b/config.c\n> @@ -43,12 +43,27 @@ static int get_next_char(void)\n>  static char *parse_value(void)\n>  {\n>  \tstatic char value[1024];\n> -\tint quote = 0, comment = 0, len = 0, space = 0;\n> +\tint quote = 0, comment = 0, envvar = -1, len = 0, space = 0;\n>  \n>  \tfor (;;) {\n>  \t\tint c = get_next_char();\n>  \t\tif (len >= sizeof(value))\n>  \t\t\treturn NULL;\n> +\t\tif ((envvar >= 0) && !isalnum(c)) {\n\nYou should allow at least underscores in environment variables too.\n\n> diff --git a/t/t1300-repo-config.sh b/t/t1300-repo-config.sh\n> index 3f3fd2d..eb84437 100755\n> --- a/t/t1300-repo-config.sh\n> +++ b/t/t1300-repo-config.sh\n> @@ -513,5 +513,18 @@ git config --list > result\n>  \n>  test_expect_success 'value continued on next line' 'cmp result expect'\n>  \n> +cat > .git/config <<\\EOF\n> +[quoted]\n> +\twithvar = \"$HOME/foo\"\n> +[unquoted]\n> +\twithvar = $HOME/foo\n> +EOF\n> +\n> +test_expect_success 'quoted $VAR' \\\n> +\t'test x\"\\$HOME/foo\" = x$(git config quoted.withvar)'\n> +\n> +test_expect_success 'unquoted $VAR' \\\n> +\t'test x\"$HOME/foo\" = x$(git config unquoted.withvar)'\n> +\n>  test_done\n\nIf you use the HOME environment variable without setting it yourself\nyou should place quotes around the $(..) in case there is a space in\n$HOME:\n    $ ./git-config test.var '$HOME'\n    $ export HOME='/tmp/foo bar'\n    $ ./git-config test.var\n    /tmp/foo bar\n    $ test x\"$HOME/foo\" = x$(./git-config test.var)\n    test: 4: bar: unexpected operator\n    $ test x\"$HOME/foo\" = x\"$(./git-config test.var)\"\n"},{"id":"43949","messageId":"20070604072707.GE16637@admingilde.org","threadId":"8418","inReplyTo":"20070604053443.GA15148@moooo.ath.cx","subject":"Re: [PATCH] Support environment variables in config file","fromName":"Martin Waitz","fromEmail":"tali@admingilde.org","sentAt":"2007-06-04T07:27:07Z","receivedAt":"2007-06-04T07:27:07Z","isPatch":true,"sender":{"key":"tali@admingilde.org","avatar":"https://gravatar.com/avatar/3f89b03eee362187effabe257898735b475673a12265c398ea9161259ae91553?d=mp&s=160"},"body":"hoi :)\n\nthanks for the review!\n\nDo you think the approach is ok?\nCan you see other examples where we may need $VAR support?\nOr would everybody be happy with support for ~/ in filenames?\n\nOn Mon, Jun 04, 2007 at 07:34:43AM +0200, Matthias Lederhofer wrote:\n> Martin Waitz <tali@admingilde.org> wrote:\n> > Environment variables (e.g. $HOME) can be helpful for the GIT configuration.\n> > With this change you can use them with the normal shell \"$\" syntax.\n> > If you want to insert a plain \"$\" in a variable, it can be escaped as \\$\n> > or put inside quotes (\").\n> \n> Perhaps we should also allow variable interpolation in double quoted\n> strings as this is quite common in various languages.\n\nI thought about that too.  I guess I first will have to do a patch\nwhich adds single quote (') support.\n\n> We could have a short example here how to concatenate a variable and a\n> string without a space in between.  I came up with '$FOO\"\"bar' which\n> is not that obvious imo.\n\nyes, shell-like ${FOO} would be nicer but I don't know if it is that\nimportant.  Perhaps your example $FOO\"bar\".\n\n> You should allow at least underscores in environment variables too.\n\nright\n\n> If you use the HOME environment variable without setting it yourself\n> you should place quotes around the $(..) in case there is a space in\n> $HOME:\n\nstupid error, yes.\n\n-- \nMartin Waitz\n"},{"id":"43960","messageId":"20070604084411.GA17622@moooo.ath.cx","threadId":"8418","inReplyTo":"20070604072707.GE16637@admingilde.org","subject":"Re: [PATCH] Support environment variables in config file","fromName":"Matthias Lederhofer","fromEmail":"matled@gmx.net","sentAt":"2007-06-04T08:44:11Z","receivedAt":"2007-06-04T08:44:11Z","isPatch":true,"sender":{"key":"matled@gmx.net","avatar":null},"body":"Martin Waitz <tali@admingilde.org> wrote:\n> Do you think the approach is ok?\n\nLooks fine from the reading part.  Up to now\n    $ git config \"$key\" \"$value\" &&\n      [ \"$value\" = \"$(git config \"$key\")\" ] &&\n      echo true\nwill echo true for all values (at least from the things I tried with\n\", \\ and \\n).  When interpreting $VAR this changes.  I dunno if there\nare any programs out there that rely on the fact that the value you\nget out of the config is exactly the same as you have put in.\n\n> Can you see other examples where we may need $VAR support?\n> Or would everybody be happy with support for ~/ in filenames?\n\nIn my config I don't even use the path to my home directory anywhere\nand spontaneously I can't think of any config option for which I'd use\nan environment variable as value.\n"},{"id":"43985","messageId":"Pine.LNX.4.64.0706041657210.4046@racer.site","threadId":"8418","inReplyTo":"20070604072707.GE16637@admingilde.org","subject":"Re: [PATCH] Support environment variables in config file","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-06-04T15:57:35Z","receivedAt":"2007-06-04T15:57:35Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Mon, 4 Jun 2007, Martin Waitz wrote:\n\n> Do you think the approach is ok?\n\nI actually would like it more if the calling program did the interpolation \nitself.\n\nSo, for example if you want a script to access whatever.my.url, and want \nto allow to interpolate any environment variable, why not\n\n\turl=$(eval $(git config whatever.my.url))\n\nI am just hesitant to change the existing behaviour, and possibly \nintroduce weird breakages. (There could even be some unwanted env leakages \nin programs like gitweb...)\n\nCiao,\nDscho\n"},{"id":"43993","messageId":"20070604174719.GH16637@admingilde.org","threadId":"8418","inReplyTo":"Pine.LNX.4.64.0706041657210.4046@racer.site","subject":"Re: [PATCH] Support environment variables in config file","fromName":"Martin Waitz","fromEmail":"tali@admingilde.org","sentAt":"2007-06-04T17:47:19Z","receivedAt":"2007-06-04T17:47:19Z","isPatch":true,"sender":{"key":"tali@admingilde.org","avatar":"https://gravatar.com/avatar/3f89b03eee362187effabe257898735b475673a12265c398ea9161259ae91553?d=mp&s=160"},"body":"hoi :)\n\nOn Mon, Jun 04, 2007 at 04:57:35PM +0100, Johannes Schindelin wrote:\n> I actually would like it more if the calling program did the interpolation \n> itself.\n\nThat's another possibility, perhaps along the line of git_config_int.\n\n> So, for example if you want a script to access whatever.my.url, and want \n> to allow to interpolate any environment variable, why not\n> \n> \turl=$(eval $(git config whatever.my.url))\n\nWell, complete shell syntax does too much: it also supports $() and\nfriends.\n\n> I am just hesitant to change the existing behaviour, and possibly \n> introduce weird breakages. (There could even be some unwanted env leakages \n> in programs like gitweb...)\n\nexactly.\n\nSo should we simply update semantics of config variables to not require\nany environment variables?\n\n-- \nMartin Waitz\n"},{"id":"43996","messageId":"Pine.LNX.4.64.0706041856270.4046@racer.site","threadId":"8418","inReplyTo":"20070604174719.GH16637@admingilde.org","subject":"Re: [PATCH] Support environment variables in config file","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-06-04T17:59:40Z","receivedAt":"2007-06-04T17:59:40Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Mon, 4 Jun 2007, Martin Waitz wrote:\n\n> On Mon, Jun 04, 2007 at 04:57:35PM +0100, Johannes Schindelin wrote:\n> > I actually would like it more if the calling program did the \n> > interpolation itself.\n> \n> That's another possibility, perhaps along the line of git_config_int.\n\nMaybe...\n\n> > So, for example if you want a script to access whatever.my.url, and \n> > want to allow to interpolate any environment variable, why not\n> > \n> > \turl=$(eval $(git config whatever.my.url))\n> \n> Well, complete shell syntax does too much: it also supports $() and \n> friends.\n\nGood point.\n\n> > I am just hesitant to change the existing behaviour, and possibly \n> > introduce weird breakages. (There could even be some unwanted env \n> > leakages in programs like gitweb...)\n> \n> exactly.\n> \n> So should we simply update semantics of config variables to not require \n> any environment variables?\n\nWell, actually there is a perfect example when you would want to do even \nmore than just expanding environment variables: aliases.\n\nI'm happy to understand the config as a relatively versatile key/value \nstore, without much in the way of pre- or post-processing from git-config \nor git_config().\n\nBut if there are a few callers of git_config() which want environment \nvariable interpolation, git_config_expand_envs() would be good.\n\nCiao,\nDscho\n"}]}