Subject: Re: [PATCH v8 2/8] config: add new way to pass config via `--config-env`

From: Ævar Arnfjörð Bjarmason <[email-masked]>
Date: Fri, 16 Apr 2021 17:40:36 +0200

On Tue, Jan 12 2021, Patrick Steinhardt wrote:

A minor doc bug that wasn't spotted before landing. Here we say
"--config-env foo=bar" will work:

> diff --git a/Documentation/git.txt b/Documentation/git.txt
> index a6d4ad0818..d36e6fd482 100644
> --- a/Documentation/git.txt
> +++ b/Documentation/git.txt
> @@ -13,7 +13,7 @@ SYNOPSIS
>      [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]
>      [-p|--paginate|-P|--no-pager] [--no-replace-objects] [--bare]
>      [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]
> -    [--super-prefix=<path>]
> +    [--super-prefix=<path>] [--config-env <name>=<envvar>]
>      <command> [<args>]
>  
>  DESCRIPTION
> @@ -80,6 +80,28 @@ config file). Including the equals but with an empty value (like `git -c
>  foo.bar= ...`) sets `foo.bar` to the empty string which `git config
>  --type=bool` will convert to `false`.

But not here, we ask for "--config-env=" (note the "="):

> +--config-env=<name>=<envvar>::
> +	Like `-c <name>=<value>`, give configuration variable
> +	'<name>' a value, where <envvar> is the name of an
> +	environment variable from which to retrieve the value. Unlike
> +	`-c` there is no shortcut for directly setting the value to an
> +	empty string, instead the environment variable itself must be
> +	set to the empty string.  It is an error if the `<envvar>` does not exist
> +	in the environment. `<envvar>` may not contain an equals sign
> +	to avoid ambiguity with `<name>`s which contain one.
> ++
> [...]
> +		} else if (skip_prefix(cmd, "--config-env=", &cmd)) {
> +			git_config_push_env(cmd);

But as this...

> +test_expect_success 'git --config-env=key=envvar support' '
> +	cat >expect <<-\EOF &&
> +	value
> +	value
> +	false
> +	EOF
> +	{
> +		ENVVAR=value git --config-env=core.name=ENVVAR config core.name &&
> +		ENVVAR=value git --config-env=foo.CamelCase=ENVVAR config foo.camelcase &&
> +		ENVVAR= git --config-env=foo.flag=ENVVAR config --bool foo.flag
> +	} >actual &&
> +	test_cmp expect actual
> +'
> +
> +test_expect_success 'git --config-env fails with invalid parameters' '
> +	test_must_fail git --config-env=foo.flag config --bool foo.flag 2>error &&
> +	test_i18ngrep "invalid config format: foo.flag" error &&
> +	test_must_fail git --config-env=foo.flag= config --bool foo.flag 2>error &&
> +	test_i18ngrep "missing environment variable name for configuration ${SQ}foo.flag${SQ}" error &&
> +	sane_unset NONEXISTENT &&
> +	test_must_fail git --config-env=foo.flag=NONEXISTENT config --bool foo.flag 2>error &&
> +	test_i18ngrep "missing environment variable ${SQ}NONEXISTENT${SQ} for configuration ${SQ}foo.flag${SQ}" error
> +'
> +
> +test_expect_success 'git -c and --config-env work together' '
> +	cat >expect <<-\EOF &&
> +	bar.cmd cmd-value
> +	bar.env env-value
> +	EOF
> +	ENVVAR=env-value git \
> +		-c bar.cmd=cmd-value \
> +		--config-env=bar.env=ENVVAR \
> +		config --get-regexp "^bar.*" >actual &&
> +	test_cmp expect actual
> +'
> +
> +test_expect_success 'git -c and --config-env override each other' '
> +	cat >expect <<-\EOF &&
> +	env
> +	cmd
> +	EOF
> +	{
> +		ENVVAR=env git -c bar.bar=cmd --config-env=bar.bar=ENVVAR config bar.bar &&
> +		ENVVAR=env git --config-env=bar.bar=ENVVAR -c bar.bar=cmd config bar.bar
> +	} >actual &&
> +	test_cmp expect actual
> +'
> +
>  test_expect_success 'git config --edit works' '
>  	git config -f tmp test.value no &&
>  	echo test.value=yes >expect &&

...and the tests show we just support the --opt=foo=bar form, not --opt
foo=bar.

Bonus points to anyone sorting out some of the existing inconsistencies
when fixing this, i.e. --exec-path supports either the "=" form, or not,
but various other skip_prefix() in the same function don't, seemingly
(but I have not tested) for no good reason.

It seems to me that having a skip_prefix_opt() or something would be a
good fix for this, i.e. a "maybe trim the last '='" version of
skip_prefix. Then we could just consistently use that.

Or maybe there's some reason we don't want to be as lax as --exec-path
with any other option...