From patchwork Tue Jan 12 12:26:40 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Steinhardt X-Patchwork-Id: 12013349 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8B85FC43381 for ; Tue, 12 Jan 2021 12:27:52 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 3FFBA22BE9 for ; Tue, 12 Jan 2021 12:27:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729253AbhALM1v (ORCPT ); Tue, 12 Jan 2021 07:27:51 -0500 Received: from wout4-smtp.messagingengine.com ([64.147.123.20]:47487 "EHLO wout4-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726275AbhALM1u (ORCPT ); Tue, 12 Jan 2021 07:27:50 -0500 Received: from compute1.internal (compute1.nyi.internal [10.202.2.41]) by mailout.west.internal (Postfix) with ESMTP id 137A216A2; Tue, 12 Jan 2021 07:26:44 -0500 (EST) Received: from mailfrontend2 ([10.202.2.163]) by compute1.internal (MEProxy); Tue, 12 Jan 2021 07:26:44 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=pks.im; h=date :from:to:cc:subject:message-id:references:mime-version :content-type:in-reply-to; s=fm3; bh=G0VEokrPqsU3t99Vk2jaPUISVxe JSwDYaDjLjW7bwuQ=; b=qYMFCoaIFTLg12wSPioPBRV0XgBY1AdlNL22mv7ZonL EL3TGC6Spfbo4Llu+15Y7/I/8MLTuwXzTnAww7OC/cLIcV7xoRsFqiiOa8yVgJ0I u7YcwF52P6vxQkt3tKdS+fVYIv/sVtMoP04rApx1vWRT2cz2BRelFJBCP8Rq7rlQ MiM7sHc56JRohmjVybEd8KIGJelulBiFm8RADE4ZYHWfb1pBmQmf/oss0k4Dq9Yr fSsNTphTrA6XRfxcYUNlIv3MnacxNXDru33QP0YG5e4y0sIMw36xNCkjVRcnv6fu 4VndG6gpX6ulDf5AWViivSbHxqbRJn3EH4ulNKIJ23g== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to:x-me-proxy :x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s=fm1; bh=G0VEok rPqsU3t99Vk2jaPUISVxeJSwDYaDjLjW7bwuQ=; b=qFK+En90p6VUarEa/F3NDk 88Ghbq0rzZllSdixtT02FKz2sLJN9ZnaN/1pMRQOIEky5RxEc0Zf1DVnAfgWQWkT HQuhMx/dUjKfzBvouCA09zXOlyk32avZw90z1SlR+j6vU14/3xpRAZHr3+3SAQzx kgBL9su9yTBTq1/thPKyVuNY3ZKx/vEEtcnC7WAISk05VA9/Nbcc70UkCU8VitME 8ZvF/z5iIVVbnvb4JRJOhFt3g+eOXs73FkMh8iG+Fx9TJDrU+Kpw6637k4sLE+Ei Bv4pSIKPkq+yNGASna1c1qyfgW9r1ZllmwrD+EgiF5qIM50d37qgzUc0xBZ/uLNw == X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedukedrtddtgddtkecutefuodetggdotefrodftvf curfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfghnecu uegrihhlohhuthemuceftddtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmdenuc fjughrpeffhffvuffkfhggtggujgesghdtreertddtvdenucfhrhhomheprfgrthhrihgt khcuufhtvghinhhhrghrughtuceophhssehpkhhsrdhimheqnecuggftrfgrthhtvghrnh epheeghfdtfeeuffehkefgffduleffjedthfdvjeektdfhhedvlefgtefgvdettdfhnecu kfhppeejjedrudefrdehvddrleefnecuvehluhhsthgvrhfuihiivgeptdenucfrrghrrg hmpehmrghilhhfrhhomhepphhssehpkhhsrdhimh X-ME-Proxy: Received: from vm-mail.pks.im (dynamic-077-013-052-093.77.13.pool.telefonica.de [77.13.52.93]) by mail.messagingengine.com (Postfix) with ESMTPA id BE665108005C; Tue, 12 Jan 2021 07:26:42 -0500 (EST) Received: from localhost (ncase [10.192.0.11]) by vm-mail.pks.im (OpenSMTPD) with ESMTPSA id 219c6616 (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Tue, 12 Jan 2021 12:26:41 +0000 (UTC) Date: Tue, 12 Jan 2021 13:26:40 +0100 From: Patrick Steinhardt To: git@vger.kernel.org Cc: Simon Ruderich , =?iso-8859-1?q?=C6var_Arnfj=F6r=F0?= Bjarmason , Junio C Hamano , Jeff King , "brian m. carlson" , Philip Oakley Subject: [PATCH v8 1/8] git: add `--super-prefix` to usage string Message-ID: <55fa4d0d11f92c5b3c86c47b91ca5f4ceab2f81a.1610453228.git.ps@pks.im> References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org When the `--super-prefix` option was implmented in 74866d7579 (git: make super-prefix option, 2016-10-07), its existence was only documented in the manpage but not in the command's own usage string. Given that the commit message didn't mention that this was done intentionally and given that it's documented in the manpage, this seems like an oversight. Add it to the usage string to fix the inconsistency. Signed-off-by: Patrick Steinhardt --- git.c | 1 + 1 file changed, 1 insertion(+) diff --git a/git.c b/git.c index a00a0a4d94..5a8ff12f87 100644 --- a/git.c +++ b/git.c @@ -29,6 +29,7 @@ const char git_usage_string[] = " [--exec-path[=]] [--html-path] [--man-path] [--info-path]\n" " [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--bare]\n" " [--git-dir=] [--work-tree=] [--namespace=]\n" + " [--super-prefix=]\n" " []"); const char git_more_info_string[] = From patchwork Tue Jan 12 12:26:45 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Steinhardt X-Patchwork-Id: 12013345 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1A532C433DB for ; Tue, 12 Jan 2021 12:27:52 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id A63DB22BE9 for ; Tue, 12 Jan 2021 12:27:51 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728467AbhALM1f (ORCPT ); Tue, 12 Jan 2021 07:27:35 -0500 Received: from wout4-smtp.messagingengine.com ([64.147.123.20]:41755 "EHLO wout4-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727855AbhALM1e (ORCPT ); Tue, 12 Jan 2021 07:27:34 -0500 Received: from compute1.internal (compute1.nyi.internal [10.202.2.41]) by mailout.west.internal (Postfix) with ESMTP id 3795C1AD9; Tue, 12 Jan 2021 07:26:48 -0500 (EST) Received: from mailfrontend2 ([10.202.2.163]) by compute1.internal (MEProxy); Tue, 12 Jan 2021 07:26:48 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=pks.im; h=date :from:to:cc:subject:message-id:references:mime-version :content-type:in-reply-to; s=fm3; bh=At9oS3BpmSJJZUD5TI3tBCfB8Dl OuHO+/1KiqIy69+4=; b=KoTOghGAUn8NnJ/hJy6YiHv96czxkEMPCRCiCtkEyTZ KTPPb6tJZWwWbXUHOQz1UTBOop8+rW2tk5Tv8DmRwdnU29VpQiWjt92xh7gE3hmW rmyfOYSfEE7tcE8hciPTt0NS1IeyzDao27JcgoXOQcEtAZX76riqu5vRsN3ovqr3 i31iiYoYUgmeTEvudwtybCRDfwC7ayigjWraJfEQ1fMFw3hzL1u/bM+Qb4uiQ7KS LxRxcaa7bXs+kImLtUl4fe5ozceLdHO315y21TPUzeAfkJlIrrZG2dXKe9jH8vuT VrNyKZHRcSRr7wLdFF5UCLr875WIdjxAHYPKpkWpmBw== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to:x-me-proxy :x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s=fm1; bh=At9oS3 BpmSJJZUD5TI3tBCfB8DlOuHO+/1KiqIy69+4=; b=a1jYk0ERq712cUVDGRWUKz I8o4HjLuHV4V9/iPEkeh+ABi5nPoERNnGDyc4qdbZdP75cAgkJiOK0/FeyoMnNN/ YoleW5mxdmf9G7Ns6etFo13TanuKhqx87R6bud1F5AIzLs4T3PC0+j9Dg5rC1S1x vmoJdHOcLE9bOWHLa65gu7n30u8Gg0ZpRTPYDMPpKcUlx5iQy3IcC5D0kgL7+8Sp q7UCViatebXd111TJPMaSBQWle9Q5QJr/+ad+GnvU1DUef/9H+G2ik6Bj2QtTSoT R1N1GDWen+vOVyB4XxCeKRFC58lBhKKffsgnP8+TuNX/0RzjzhYZgA988x84oNWg == X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedukedrtddtgddtkecutefuodetggdotefrodftvf curfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfghnecu uegrihhlohhuthemuceftddtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmdenuc fjughrpeffhffvuffkfhggtggujgesghdtreertddtvdenucfhrhhomheprfgrthhrihgt khcuufhtvghinhhhrghrughtuceophhssehpkhhsrdhimheqnecuggftrfgrthhtvghrnh epheeghfdtfeeuffehkefgffduleffjedthfdvjeektdfhhedvlefgtefgvdettdfhnecu kfhppeejjedrudefrdehvddrleefnecuvehluhhsthgvrhfuihiivgepvdenucfrrghrrg hmpehmrghilhhfrhhomhepphhssehpkhhsrdhimh X-ME-Proxy: Received: from vm-mail.pks.im (dynamic-077-013-052-093.77.13.pool.telefonica.de [77.13.52.93]) by mail.messagingengine.com (Postfix) with ESMTPA id C64E7108005C; Tue, 12 Jan 2021 07:26:46 -0500 (EST) Received: from localhost (ncase [10.192.0.11]) by vm-mail.pks.im (OpenSMTPD) with ESMTPSA id e20d97e7 (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Tue, 12 Jan 2021 12:26:46 +0000 (UTC) Date: Tue, 12 Jan 2021 13:26:45 +0100 From: Patrick Steinhardt To: git@vger.kernel.org Cc: Simon Ruderich , =?iso-8859-1?q?=C6var_Arnfj=F6r=F0?= Bjarmason , Junio C Hamano , Jeff King , "brian m. carlson" , Philip Oakley Subject: [PATCH v8 2/8] config: add new way to pass config via `--config-env` Message-ID: <470396d36f938f0070b8c849a85b1a30949056e3.1610453228.git.ps@pks.im> References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org While it's already possible to pass runtime configuration via `git -c =`, it may be undesirable to use when the value contains sensitive information. E.g. if one wants to set `http.extraHeader` to contain an authentication token, doing so via `-c` would trivially leak those credentials via e.g. ps(1), which typically also shows command arguments. To enable this usecase without leaking credentials, this commit introduces a new switch `--config-env==`. Instead of directly passing a value for the given key, it instead allows the user to specify the name of an environment variable. The value of that variable will then be used as value of the key. Co-authored-by: Jeff King Signed-off-by: Patrick Steinhardt --- Documentation/git.txt | 24 +++++++++++++++++++++- config.c | 25 ++++++++++++++++++++++ config.h | 1 + git.c | 4 +++- t/t1300-config.sh | 48 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 100 insertions(+), 2 deletions(-) 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[=]] [--html-path] [--man-path] [--info-path] [-p|--paginate|-P|--no-pager] [--no-replace-objects] [--bare] [--git-dir=] [--work-tree=] [--namespace=] - [--super-prefix=] + [--super-prefix=] [--config-env =] [] 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`. +--config-env==:: + Like `-c =`, give configuration variable + '' a value, where 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 `` does not exist + in the environment. `` may not contain an equals sign + to avoid ambiguity with ``s which contain one. ++ +This is useful for cases where you want to pass transitory +configuration options to git, but are doing so on OS's where +other processes might be able to read your cmdline +(e.g. `/proc/self/cmdline`), but not your environ +(e.g. `/proc/self/environ`). That behavior is the default on +Linux, but may not be on your system. ++ +Note that this might add security for variables such as +`http.extraHeader` where the sensitive information is part of +the value, but not e.g. `url..insteadOf` where the +sensitive information can be part of the key. + --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/config.c b/config.c index 1137bd73af..fd8c0c4dfc 100644 --- a/config.c +++ b/config.c @@ -345,6 +345,31 @@ void git_config_push_parameter(const char *text) strbuf_release(&env); } +void git_config_push_env(const char *spec) +{ + struct strbuf buf = STRBUF_INIT; + const char *env_name; + const char *env_value; + + env_name = strrchr(spec, '='); + if (!env_name) + die(_("invalid config format: %s"), spec); + env_name++; + if (!*env_name) + die(_("missing environment variable name for configuration '%.*s'"), + (int)(env_name - spec - 1), spec); + + env_value = getenv(env_name); + if (!env_value) + die(_("missing environment variable '%s' for configuration '%.*s'"), + env_name, (int)(env_name - spec - 1), spec); + + strbuf_add(&buf, spec, env_name - spec); + strbuf_addstr(&buf, env_value); + git_config_push_parameter(buf.buf); + strbuf_release(&buf); +} + static inline int iskeychar(int c) { return isalnum(c) || c == '-'; diff --git a/config.h b/config.h index c1449bb790..19a9adbaa9 100644 --- a/config.h +++ b/config.h @@ -138,6 +138,7 @@ int git_config_from_mem(config_fn_t fn, int git_config_from_blob_oid(config_fn_t fn, const char *name, const struct object_id *oid, void *data); void git_config_push_parameter(const char *text); +void git_config_push_env(const char *spec); int git_config_from_parameters(config_fn_t fn, void *data); void read_early_config(config_fn_t cb, void *data); void read_very_early_config(config_fn_t cb, void *data); diff --git a/git.c b/git.c index 5a8ff12f87..b5f63d346b 100644 --- a/git.c +++ b/git.c @@ -29,7 +29,7 @@ const char git_usage_string[] = " [--exec-path[=]] [--html-path] [--man-path] [--info-path]\n" " [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--bare]\n" " [--git-dir=] [--work-tree=] [--namespace=]\n" - " [--super-prefix=]\n" + " [--super-prefix=] [--config-env==]\n" " []"); const char git_more_info_string[] = @@ -255,6 +255,8 @@ static int handle_options(const char ***argv, int *argc, int *envchanged) git_config_push_parameter((*argv)[1]); (*argv)++; (*argc)--; + } else if (skip_prefix(cmd, "--config-env=", &cmd)) { + git_config_push_env(cmd); } else if (!strcmp(cmd, "--literal-pathspecs")) { setenv(GIT_LITERAL_PATHSPECS_ENVIRONMENT, "1", 1); if (envchanged) diff --git a/t/t1300-config.sh b/t/t1300-config.sh index 97a04c6cc2..853f2509c5 100755 --- a/t/t1300-config.sh +++ b/t/t1300-config.sh @@ -1316,6 +1316,54 @@ test_expect_success 'detect bogus GIT_CONFIG_PARAMETERS' ' git config --get-regexp "env.*" ' +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 && From patchwork Tue Jan 12 12:26:49 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Steinhardt X-Patchwork-Id: 12013351 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1C943C433E0 for ; Tue, 12 Jan 2021 12:28:01 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id CFE8122BE9 for ; Tue, 12 Jan 2021 12:28:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729301AbhALM2A (ORCPT ); Tue, 12 Jan 2021 07:28:00 -0500 Received: from wout4-smtp.messagingengine.com ([64.147.123.20]:51241 "EHLO wout4-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726275AbhALM17 (ORCPT ); Tue, 12 Jan 2021 07:27:59 -0500 Received: from compute1.internal (compute1.nyi.internal [10.202.2.41]) by mailout.west.internal (Postfix) with ESMTP id 576BA1B58; Tue, 12 Jan 2021 07:26:53 -0500 (EST) Received: from mailfrontend2 ([10.202.2.163]) by compute1.internal (MEProxy); Tue, 12 Jan 2021 07:26:53 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=pks.im; h=date :from:to:cc:subject:message-id:references:mime-version :content-type:in-reply-to; s=fm3; bh=xgbFHpLhJsUiGBhQ4u/GLhHevvf U+ADpnaT/fOqcdao=; b=Qpu6XdO/2KDulT8zUWvAsku6hM3RRkuYy2+hYwew2w7 amfgsIaQq2upv9Zb56kmoJjFIw+ifATnPVSJVVAA+33PSd38wwrDPcrhWYPUhYTe D7EYAUC+FBXEg57Dave+ojxMqICybDipKoEA4ueMU6ITI1G0wbrXAQcjnuSK7u39 jgrJV5Dk21HTWiFpZ7o20pBFu+CrmVn4PsEsJ0aO6i3U4O8A3FBMqEP5ZbVouiUe P4P4w7N+/6K2LVDTciY4RldKInBumvzPJA0rlShMde3aG3YKwe+S0xh5/Fo8W6/J 60v16Z+oOlQvzHte7BbvuSPerlRkYXZ62SHjII5lQ2A== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to:x-me-proxy :x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s=fm1; bh=xgbFHp LhJsUiGBhQ4u/GLhHevvfU+ADpnaT/fOqcdao=; b=ieIhcjvAMFc1XzREy8ufFB I2BgOJbjnzMTNQChKJ8kdGTw6SJypIWCycm9Uo/JITTyNTd6Y800xe+GDSBqhArl T1PQVhMVzt2vfKRIZd7koB6EzZCq8nL2TKaWYsJOcd9qgOdGUu78hVzlXoOcvv9v WhT7wkxT9wPzCt+iQO9PZr29z5aoaRIEXgBYWo9gkaxis91iXRgS10cT8AvDBWiV bHRdzbNk7VixPwyzJ10CnRP4BwQnLMK0rZ+38AXufI+Gs+WbE4A0orx5gllAH42B kulE/WnUPfVikAWZ9G/fBhqoyLrH2gywyKNpZtrtlquGwrUBe/Rvv5EBoQYZ5YsA == X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedukedrtddtgddtkecutefuodetggdotefrodftvf curfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfghnecu uegrihhlohhuthemuceftddtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmdenuc fjughrpeffhffvuffkfhggtggujgesghdtreertddtvdenucfhrhhomheprfgrthhrihgt khcuufhtvghinhhhrghrughtuceophhssehpkhhsrdhimheqnecuggftrfgrthhtvghrnh epheeghfdtfeeuffehkefgffduleffjedthfdvjeektdfhhedvlefgtefgvdettdfhnecu kfhppeejjedrudefrdehvddrleefnecuvehluhhsthgvrhfuihiivgepfeenucfrrghrrg hmpehmrghilhhfrhhomhepphhssehpkhhsrdhimh X-ME-Proxy: Received: from vm-mail.pks.im (dynamic-077-013-052-093.77.13.pool.telefonica.de [77.13.52.93]) by mail.messagingengine.com (Postfix) with ESMTPA id E8275108005C; Tue, 12 Jan 2021 07:26:51 -0500 (EST) Received: from localhost (ncase [10.192.0.11]) by vm-mail.pks.im (OpenSMTPD) with ESMTPSA id ade4ca2e (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Tue, 12 Jan 2021 12:26:50 +0000 (UTC) Date: Tue, 12 Jan 2021 13:26:49 +0100 From: Patrick Steinhardt To: git@vger.kernel.org Cc: Simon Ruderich , =?iso-8859-1?q?=C6var_Arnfj=F6r=F0?= Bjarmason , Junio C Hamano , Jeff King , "brian m. carlson" , Philip Oakley Subject: [PATCH v8 3/8] quote: make sq_dequote_step() a public function Message-ID: <7a7a4ae234d30c56e04c19a5e5b47afaa8680c72.1610453228.git.ps@pks.im> References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Jeff King We provide a function for dequoting an entire string, as well as one for handling a space-separated list of quoted strings. But there's no way for a caller to parse a string like 'foo'='bar', even though it is easy to generate one using sq_quote_buf() or similar. Let's make the single-step function available to callers outside of quote.c. Note that we do need to adjust its implementation slightly: it insists on seeing whitespace between items, and we'd like to be more flexible than that. Since it only has a single caller, we can move that check (and slurping up any extra whitespace) into that caller. Signed-off-by: Jeff King --- quote.c | 15 ++++++++++----- quote.h | 18 ++++++++++++++++-- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/quote.c b/quote.c index 69f4ca45da..8a3a5e39eb 100644 --- a/quote.c +++ b/quote.c @@ -116,7 +116,7 @@ void sq_append_quote_argv_pretty(struct strbuf *dst, const char **argv) } } -static char *sq_dequote_step(char *arg, char **next) +char *sq_dequote_step(char *arg, char **next) { char *dst = arg; char *src = arg; @@ -153,11 +153,8 @@ static char *sq_dequote_step(char *arg, char **next) } /* Fallthrough */ default: - if (!next || !isspace(*src)) + if (!next) return NULL; - do { - c = *++src; - } while (isspace(c)); *dst = 0; *next = src; return arg; @@ -182,6 +179,14 @@ static int sq_dequote_to_argv_internal(char *arg, char *dequoted = sq_dequote_step(next, &next); if (!dequoted) return -1; + if (next) { + char c; + if (!isspace(*next)) + return -1; + do { + c = *++next; + } while (isspace(c)); + } if (argv) { ALLOC_GROW(*argv, *nr + 1, *alloc); (*argv)[(*nr)++] = dequoted; diff --git a/quote.h b/quote.h index 4b72a583cf..768cc6338e 100644 --- a/quote.h +++ b/quote.h @@ -42,12 +42,26 @@ void sq_quote_buf_pretty(struct strbuf *, const char *src); void sq_quote_argv_pretty(struct strbuf *, const char **argv); void sq_append_quote_argv_pretty(struct strbuf *dst, const char **argv); -/* This unwraps what sq_quote() produces in place, but returns +/* + * This unwraps what sq_quote() produces in place, but returns * NULL if the input does not look like what sq_quote would have - * produced. + * produced (the full string must be a single quoted item). */ char *sq_dequote(char *); +/* + * Like sq_dequote(), but dequote a single item, and leave "next" pointing to + * the next character. E.g., in the string: + * + * 'one' 'two' 'three' + * + * after the first call, the return value would be the unquoted string "one", + * with "next" pointing to the space between "one" and "two"). The caller is + * responsible for advancing the pointer to the start of the next item before + * calling sq_dequote_step() again. + */ +char *sq_dequote_step(char *src, char **next); + /* * Same as the above, but can be used to unwrap many arguments in the * same string separated by space. Like sq_quote, it works in place, From patchwork Tue Jan 12 12:26:54 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Steinhardt X-Patchwork-Id: 12013347 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 66A43C433E6 for ; Tue, 12 Jan 2021 12:27:52 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 163512310D for ; Tue, 12 Jan 2021 12:27:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728882AbhALM1o (ORCPT ); Tue, 12 Jan 2021 07:27:44 -0500 Received: from wout4-smtp.messagingengine.com ([64.147.123.20]:58719 "EHLO wout4-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727855AbhALM1n (ORCPT ); Tue, 12 Jan 2021 07:27:43 -0500 Received: from compute1.internal (compute1.nyi.internal [10.202.2.41]) by mailout.west.internal (Postfix) with ESMTP id 899BD174E; Tue, 12 Jan 2021 07:26:57 -0500 (EST) Received: from mailfrontend2 ([10.202.2.163]) by compute1.internal (MEProxy); Tue, 12 Jan 2021 07:26:58 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=pks.im; h=date :from:to:cc:subject:message-id:references:mime-version :content-type:in-reply-to; s=fm3; bh=2+dg0QZPrPQRHWyaJFhjhjDVGMA 9rAliLC8XsYCL8O8=; b=sRc+68NPa3MepfFLQphzGI8F9xPk+zP3b2cCiaOYPtS pRdPKMO5SgCNNdULeFsVKJt7/W0CqPrYX9C9JJY5erdxVzY4QhGCr1D/scFRadsi 1FGjykn8yO30jZsjvWkwoHF8xJlfV8oz5Om2ho6sxDDMkcHcWzVPWK+tXZ/KpfPh aU/RIx055lbCV8cxieD5jyhJho0vThKh93zmtjnN/Al7J+0BWUtz8x0mw8+956W3 sGz2azIQ/JKlL3YYfLS/W5QrmCOG8GYwfOuFNK+SbstWFjByXlz2sOkpMK6CDbNK hncjjv8y9VSRWSi6fCcWnU48S91zlgJIRu5nFrnZ45w== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to:x-me-proxy :x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s=fm1; bh=2+dg0Q ZPrPQRHWyaJFhjhjDVGMA9rAliLC8XsYCL8O8=; b=fg9Wp9D94oY3HNblRkdEgC GKKimhPdC9zh1ZB2JRKZ5tQj64AU8RlhOgV5Ke4ysbBMjLPL7LSB9I9lX4G+4FOl TBwcS1XaA2TjXrwjwd7r4iMPW4/FasamT4EAvkt1Ftw7GNtUjF/mqRkCiK5phjzW iVdpWG2OdWLbdZdDoYSIj1AqLlmELRTTubNTwEicx4MJiv4EXCTPdSSYIPIV2m1G ++CJtBcB91JwvAgQVadCmu1PtkXOlHXrNVawG23qdh7tQQgOUTIcEZEUnkamAzYe jwUkB2L88Fs+4aU6333gyRB+nHoQtuUZmImE/Dxw6/RsPKKFO21gCTTW5Spt5tDg == X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedukedrtddtgddtkecutefuodetggdotefrodftvf curfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfghnecu uegrihhlohhuthemuceftddtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmdenuc fjughrpeffhffvuffkfhggtggujgesghdtreertddtvdenucfhrhhomheprfgrthhrihgt khcuufhtvghinhhhrghrughtuceophhssehpkhhsrdhimheqnecuggftrfgrthhtvghrnh epheeghfdtfeeuffehkefgffduleffjedthfdvjeektdfhhedvlefgtefgvdettdfhnecu kfhppeejjedrudefrdehvddrleefnecuvehluhhsthgvrhfuihiivgepfeenucfrrghrrg hmpehmrghilhhfrhhomhepphhssehpkhhsrdhimh X-ME-Proxy: Received: from vm-mail.pks.im (dynamic-077-013-052-093.77.13.pool.telefonica.de [77.13.52.93]) by mail.messagingengine.com (Postfix) with ESMTPA id 15C891080057; Tue, 12 Jan 2021 07:26:55 -0500 (EST) Received: from localhost (ncase [10.192.0.11]) by vm-mail.pks.im (OpenSMTPD) with ESMTPSA id 5db12c59 (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Tue, 12 Jan 2021 12:26:55 +0000 (UTC) Date: Tue, 12 Jan 2021 13:26:54 +0100 From: Patrick Steinhardt To: git@vger.kernel.org Cc: Simon Ruderich , =?iso-8859-1?q?=C6var_Arnfj=F6r=F0?= Bjarmason , Junio C Hamano , Jeff King , "brian m. carlson" , Philip Oakley Subject: [PATCH v8 4/8] config: extract function to parse config pairs Message-ID: <39552eb8b931442e656d0287447fce3b2cffa87a.1610453228.git.ps@pks.im> References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org The function `git_config_parse_parameter` is responsible for parsing a `foo.bar=baz`-formatted configuration key, sanitizing the key and then processing it via the given callback function. Given that we're about to add a second user which is going to process keys which already has keys and values separated, this commit extracts a function `config_parse_pair` which only does the sanitization and processing part as a preparatory step. Signed-off-by: Patrick Steinhardt --- config.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/config.c b/config.c index fd8c0c4dfc..b7a8129f6c 100644 --- a/config.c +++ b/config.c @@ -462,11 +462,26 @@ int git_config_key_is_valid(const char *key) return !git_config_parse_key_1(key, NULL, NULL, 1); } +static int config_parse_pair(const char *key, const char *value, + config_fn_t fn, void *data) +{ + char *canonical_name; + int ret; + + if (!strlen(key)) + return error(_("empty config key")); + if (git_config_parse_key(key, &canonical_name, NULL)) + return -1; + + ret = (fn(canonical_name, value, data) < 0) ? -1 : 0; + free(canonical_name); + return ret; +} + int git_config_parse_parameter(const char *text, config_fn_t fn, void *data) { const char *value; - char *canonical_name; struct strbuf **pair; int ret; @@ -487,12 +502,7 @@ int git_config_parse_parameter(const char *text, return error(_("bogus config parameter: %s"), text); } - if (git_config_parse_key(pair[0]->buf, &canonical_name, NULL)) { - ret = -1; - } else { - ret = (fn(canonical_name, value, data) < 0) ? -1 : 0; - free(canonical_name); - } + ret = config_parse_pair(pair[0]->buf, value, fn, data); strbuf_list_free(pair); return ret; } From patchwork Tue Jan 12 12:27:01 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Steinhardt X-Patchwork-Id: 12013363 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id C7228C433E0 for ; Tue, 12 Jan 2021 12:28:43 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 9C1F42310A for ; Tue, 12 Jan 2021 12:28:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731154AbhALM2m (ORCPT ); Tue, 12 Jan 2021 07:28:42 -0500 Received: from wout4-smtp.messagingengine.com ([64.147.123.20]:54727 "EHLO wout4-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729397AbhALM2l (ORCPT ); Tue, 12 Jan 2021 07:28:41 -0500 Received: from compute1.internal (compute1.nyi.internal [10.202.2.41]) by mailout.west.internal (Postfix) with ESMTP id AB9871B60; Tue, 12 Jan 2021 07:27:05 -0500 (EST) Received: from mailfrontend2 ([10.202.2.163]) by compute1.internal (MEProxy); Tue, 12 Jan 2021 07:27:06 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=pks.im; h=date :from:to:cc:subject:message-id:references:mime-version :content-type:in-reply-to; s=fm3; bh=YB4u0NXLw90lWxeelLCT8WpXruF WLhCxnbNPe5goKYc=; b=Q2edbXG0+KJZwsIKqZqZeEuTDG3HV/hDjex389AHdZC cnDMbD5ZR5woAlMXgAJYCbt6h8F6+rVY0MVfI35US7VBpaP27IjCbSQy+F0Rgesj p0wSTMzMmPRuEZivI8fRQg2+Grp/KsUbzHaVbt7QkdmcZ/4uLSn9td7PE1fWb875 aqkCGoAbmL2mxe+iV5EsgCU9h2V0Jj875OA8Poy3iwImPW+329oMRheBzRnadOeK p1vvclDcNnnmIolINzm3GXkQ1sDkXxWvieLBRxsKrmN8nJ3fNCmNJ0WBVOarrOQ+ sC9SO9aqy+kl6R2aF8eNVLOmbgzARsrU7quCI3YKfQQ== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to:x-me-proxy :x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s=fm1; bh=YB4u0N XLw90lWxeelLCT8WpXruFWLhCxnbNPe5goKYc=; b=TPVFer6iHRCya9fwVlMIiG YYLRwHSjCUj7puVxFyZ29haDCs3DrhWSldj1QT/MQJ/he0MkNSf2A88uS4OJ6rET jEd7mZtu8oANyUXhKL7jEU71LJHuPeApKmqm5Gv8tKyLG2YEadR07ZEx/L2xZJUk kCiimmExLAowsVCf6d3IEkPQqPf9yx+fuXmACb4n8TATU1iMgqTuRXQpnrVGmY3h ZfEuyKFHi1ueCOLZ7tCwtQo+7WBVXAqla9/MYoHNMXItfPaP/MmB06RO45Ra1v/M PiooWYlpTwmVBGuE4SmZJZvvKp1bEZle2WpkdGxezJ1jqvbjOeZBc8Yn8xlr810Q == X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedukedrtddtgddtkecutefuodetggdotefrodftvf curfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfghnecu uegrihhlohhuthemuceftddtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmdenuc fjughrpeffhffvuffkfhggtggujgesghdtreertddtvdenucfhrhhomheprfgrthhrihgt khcuufhtvghinhhhrghrughtuceophhssehpkhhsrdhimheqnecuggftrfgrthhtvghrnh epheeghfdtfeeuffehkefgffduleffjedthfdvjeektdfhhedvlefgtefgvdettdfhnecu kfhppeejjedrudefrdehvddrleefnecuvehluhhsthgvrhfuihiivgepheenucfrrghrrg hmpehmrghilhhfrhhomhepphhssehpkhhsrdhimh X-ME-Proxy: Received: from vm-mail.pks.im (dynamic-077-013-052-093.77.13.pool.telefonica.de [77.13.52.93]) by mail.messagingengine.com (Postfix) with ESMTPA id 46FAF1080063; Tue, 12 Jan 2021 07:27:04 -0500 (EST) Received: from localhost (ncase [10.192.0.11]) by vm-mail.pks.im (OpenSMTPD) with ESMTPSA id b717d6d8 (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Tue, 12 Jan 2021 12:27:03 +0000 (UTC) Date: Tue, 12 Jan 2021 13:27:01 +0100 From: Patrick Steinhardt To: git@vger.kernel.org Cc: Simon Ruderich , =?iso-8859-1?q?=C6var_Arnfj=F6r=F0?= Bjarmason , Junio C Hamano , Jeff King , "brian m. carlson" , Philip Oakley Subject: [PATCH v8 5/8] config: store "git -c" variables using more robust format Message-ID: <36c2a51b13e463a4aa8e5316447336927153d99d.1610453228.git.ps@pks.im> References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org The previous commit added a new format for $GIT_CONFIG_PARAMETERS which is able to robustly handle subsections with "=" in them. Let's start writing the new format. Unfortunately, this does much less than you'd hope, because "git -c" itself has the same ambiguity problem! But it's still worth doing: - we've now pushed the problem from the inter-process communication into the "-c" command-line parser. This would free us up to later add an unambiguous format there (e.g., separate arguments like "git --config key value", etc). - for --config-env, the parser already disallows "=" in the environment variable name. So: git --config-env section.with=equals.key=ENVVAR will robustly set section.with=equals.key to the contents of $ENVVAR. The new test shows the improvement for --config-env. Signed-off-by: Jeff King --- config.c | 52 ++++++++++++++++++++++++++++++++++++++++------- t/t1300-config.sh | 8 ++++++++ 2 files changed, 53 insertions(+), 7 deletions(-) diff --git a/config.c b/config.c index b7a8129f6c..7f7da60574 100644 --- a/config.c +++ b/config.c @@ -332,7 +332,7 @@ int git_config_include(const char *var, const char *value, void *data) return ret; } -void git_config_push_parameter(const char *text) +static void git_config_push_split_parameter(const char *key, const char *value) { struct strbuf env = STRBUF_INIT; const char *old = getenv(CONFIG_DATA_ENVIRONMENT); @@ -340,20 +340,60 @@ void git_config_push_parameter(const char *text) strbuf_addstr(&env, old); strbuf_addch(&env, ' '); } - sq_quote_buf(&env, text); + sq_quote_buf(&env, key); + strbuf_addch(&env, '='); + if (value) + sq_quote_buf(&env, value); setenv(CONFIG_DATA_ENVIRONMENT, env.buf, 1); strbuf_release(&env); } +void git_config_push_parameter(const char *text) +{ + const char *value; + + /* + * When we see: + * + * section.subsection=with=equals.key=value + * + * we cannot tell if it means: + * + * [section "subsection=with=equals"] + * key = value + * + * or: + * + * [section] + * subsection = with=equals.key=value + * + * We parse left-to-right for the first "=", meaning we'll prefer to + * keep the value intact over the subsection. This is historical, but + * also sensible since values are more likely to contain odd or + * untrusted input than a section name. + * + * A missing equals is explicitly allowed (as a bool-only entry). + */ + value = strchr(text, '='); + if (value) { + char *key = xmemdupz(text, value - text); + git_config_push_split_parameter(key, value + 1); + free(key); + } else { + git_config_push_split_parameter(text, NULL); + } +} + void git_config_push_env(const char *spec) { - struct strbuf buf = STRBUF_INIT; + char *key; const char *env_name; const char *env_value; env_name = strrchr(spec, '='); if (!env_name) die(_("invalid config format: %s"), spec); + key = xmemdupz(spec, env_name - spec); env_name++; if (!*env_name) die(_("missing environment variable name for configuration '%.*s'"), @@ -364,10 +404,8 @@ void git_config_push_env(const char *spec) die(_("missing environment variable '%s' for configuration '%.*s'"), env_name, (int)(env_name - spec - 1), spec); - strbuf_add(&buf, spec, env_name - spec); - strbuf_addstr(&buf, env_value); - git_config_push_parameter(buf.buf); - strbuf_release(&buf); + git_config_push_split_parameter(key, env_value); + free(key); } static inline int iskeychar(int c) diff --git a/t/t1300-config.sh b/t/t1300-config.sh index 853f2509c5..25437324c1 100755 --- a/t/t1300-config.sh +++ b/t/t1300-config.sh @@ -1364,6 +1364,14 @@ test_expect_success 'git -c and --config-env override each other' ' test_cmp expect actual ' +test_expect_success '--config-env handles keys with equals' ' + echo value=with=equals >expect && + ENVVAR=value=with=equals git \ + --config-env=section.subsection=with=equals.key=ENVVAR \ + config section.subsection=with=equals.key >actual && + test_cmp expect actual +' + test_expect_success 'git config --edit works' ' git config -f tmp test.value no && echo test.value=yes >expect && From patchwork Tue Jan 12 12:27:06 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Steinhardt X-Patchwork-Id: 12013353 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id ADD0DC433DB for ; Tue, 12 Jan 2021 12:28:24 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 68E5822BE9 for ; Tue, 12 Jan 2021 12:28:22 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727312AbhALM2V (ORCPT ); Tue, 12 Jan 2021 07:28:21 -0500 Received: from wout4-smtp.messagingengine.com ([64.147.123.20]:49507 "EHLO wout4-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726275AbhALM2V (ORCPT ); Tue, 12 Jan 2021 07:28:21 -0500 Received: from compute1.internal (compute1.nyi.internal [10.202.2.41]) by mailout.west.internal (Postfix) with ESMTP id BDE951525; Tue, 12 Jan 2021 07:27:09 -0500 (EST) Received: from mailfrontend2 ([10.202.2.163]) by compute1.internal (MEProxy); Tue, 12 Jan 2021 07:27:10 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=pks.im; h=date :from:to:cc:subject:message-id:references:mime-version :content-type:in-reply-to; s=fm3; bh=+82KNILWNeTZMZbbHiHV5Hhv/zl m2vuCVZPq6y0gkbA=; b=i2T4kPaq51kGxN6P3OLGQ5UO3+pVMzHemngEWoF39w0 eG8FRU6V1Kmp7ebHriEgGy9aQvRRhg9BqlbB3jHl2sDttK+Wu3NZ/3MgmR2gOrjj rdci4jxaDuSYAzhZIN+85+omyvgx3kHDf5t/hnL2si3nOZ+876ldizKUJ31bH2FC 32ypkJUnPkjH5faIJbNJzKOPGrkWE921o5Q1o7x0dfEWX5kF9+u/GulA8f0kamH8 pVCCv4FCaGx5JI4hY3lIZUj4xmpeuiF61oFwfQerfIekdD23HldJc7E36c3CiMGX RqMpkr0SwC3e+pyjF7Eizy+s/krxO+/jrWPU5i4v5Jw== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to:x-me-proxy :x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s=fm1; bh=+82KNI LWNeTZMZbbHiHV5Hhv/zlm2vuCVZPq6y0gkbA=; b=jFZQf7/uoKKzu4nm1Dlsw6 yeqfGa2EihPZ3gNc124ar5r2v+K9FHCmG91dunDT6RLJDRmEvs3MhcD7qB9vQarQ qVOvikP5VrqRZFpfQlwmotAIP7FQe86w0zr84NwnhrWikpY5geAFK5m39Cjaobew A9j7OlDv9ew3JEDwBL15uPUTsLZ3qpSyC6o4tZiIIW4jF0CLARTNSs4uAw29sgJT T84gzm1sF0+nnffsHodxw7Pm6H16r6naxKpZtEglURhrWZ7GfNN8Jl9vQ5u2hCoC H8/YOVPj+4dB+JuSthC75w4d7kqX+9yoFFD4/zLAcq7LkB+nwg2ufCWuxobu+EcQ == X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedukedrtddtgddtkecutefuodetggdotefrodftvf curfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfghnecu uegrihhlohhuthemuceftddtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmdenuc fjughrpeffhffvuffkfhggtggujgesghdtreertddtvdenucfhrhhomheprfgrthhrihgt khcuufhtvghinhhhrghrughtuceophhssehpkhhsrdhimheqnecuggftrfgrthhtvghrnh epheeghfdtfeeuffehkefgffduleffjedthfdvjeektdfhhedvlefgtefgvdettdfhnecu kfhppeejjedrudefrdehvddrleefnecuvehluhhsthgvrhfuihiivgepheenucfrrghrrg hmpehmrghilhhfrhhomhepphhssehpkhhsrdhimh X-ME-Proxy: Received: from vm-mail.pks.im (dynamic-077-013-052-093.77.13.pool.telefonica.de [77.13.52.93]) by mail.messagingengine.com (Postfix) with ESMTPA id 650541080063; Tue, 12 Jan 2021 07:27:08 -0500 (EST) Received: from localhost (ncase [10.192.0.11]) by vm-mail.pks.im (OpenSMTPD) with ESMTPSA id 510d6177 (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Tue, 12 Jan 2021 12:27:07 +0000 (UTC) Date: Tue, 12 Jan 2021 13:27:06 +0100 From: Patrick Steinhardt To: git@vger.kernel.org Cc: Simon Ruderich , =?iso-8859-1?q?=C6var_Arnfj=F6r=F0?= Bjarmason , Junio C Hamano , Jeff King , "brian m. carlson" , Philip Oakley Subject: [PATCH v8 6/8] config: parse more robust format in GIT_CONFIG_PARAMETERS Message-ID: References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Jeff King When we stuff config options into GIT_CONFIG_PARAMETERS, we shell-quote each one as a single unit, like: 'section.one=value1' 'section.two=value2' On the reading side, we de-quote to get the individual strings, and then parse them by splitting on the first "=" we find. This format is ambiguous, because an "=" may appear in a subsection. So the config represented in a file by both: [section "subsection=with=equals"] key = value and: [section] subsection = with=equals.key=value ends up in this flattened format like: 'section.subsection=with=equals.key=value' and we can't tell which was desired. We have traditionally resolved this by taking the first "=" we see starting from the left, meaning that we allowed arbitrary content in the value, but not in the subsection. Let's make our environment format a bit more robust by separately quoting the key and value. That turns those examples into: 'section.subsection=with=equals.key'='value' and: 'section.subsection'='with=equals.key=value' respectively, and we can tell the difference between them. We can detect which format is in use for any given element of the list based on the presence of the unquoted "=". That means we can continue to allow the old format to work to support any callers which manually used the old format, and we can even intermingle the two formats. The old format wasn't documented, and nobody was supposed to be using it. But it's likely that such callers exist in the wild, so it's nice if we can avoid breaking them. Likewise, it may be possible to trigger an older version of "git -c" that runs a script that calls into a newer version of "git -c"; that new version would see the intermingled format. This does create one complication, which is that the obvious format in the new scheme for [section] some-bool is: 'section.some-bool' with no equals. We'd mistake that for an old-style variable. And it even has the same meaning in the old style, but: [section "with=equals"] some-bool does not. It would be: 'section.with=equals=some-bool' which we'd take to mean: [section] with = equals=some-bool in the old, ambiguous style. Likewise, we can't use: 'section.some-bool'='' because that's ambiguous with an actual empty string. Instead, we'll again use the shell-quoting to give us a hint, and use: 'section.some-bool'= to show that we have no value. Note that this commit just expands the reading side. We'll start writing the new format via "git -c" in a future patch. In the meantime, the existing "git -c" tests will make sure we didn't break reading the old format. But we'll also add some explicit coverage of the two formats to make sure we continue to handle the old one after we move the writing side over. And one final note: since we're now using the shell-quoting as a semantically meaningful hint, this closes the door to us ever allowing arbitrary shell quoting, like: 'a'shell'would'be'ok'with'this'.key=value But we have never supported that (only what sq_quote() would produce), and we are probably better off keeping things simple, robust, and backwards-compatible, than trying to make it easier for humans. We'll continue not to advertise the format of the variable to users, and instead keep "git -c" as the recommended mechanism for setting config (even if we are trying to be kind not to break users who may be relying on the current undocumented format). Signed-off-by: Jeff King --- config.c | 69 +++++++++++++++++++++++++++++++++++------------ t/t1300-config.sh | 52 +++++++++++++++++++++++++++++++++++ 2 files changed, 104 insertions(+), 17 deletions(-) diff --git a/config.c b/config.c index 7f7da60574..99062915d7 100644 --- a/config.c +++ b/config.c @@ -545,14 +545,62 @@ int git_config_parse_parameter(const char *text, return ret; } +static int parse_config_env_list(char *env, config_fn_t fn, void *data) +{ + char *cur = env; + while (cur && *cur) { + const char *key = sq_dequote_step(cur, &cur); + if (!key) + return error(_("bogus format in %s"), + CONFIG_DATA_ENVIRONMENT); + + if (!cur || isspace(*cur)) { + /* old-style 'key=value' */ + if (git_config_parse_parameter(key, fn, data) < 0) + return -1; + } + else if (*cur == '=') { + /* new-style 'key'='value' */ + const char *value; + + cur++; + if (*cur == '\'') { + /* quoted value */ + value = sq_dequote_step(cur, &cur); + if (!value || (cur && !isspace(*cur))) { + return error(_("bogus format in %s"), + CONFIG_DATA_ENVIRONMENT); + } + } else if (!*cur || isspace(*cur)) { + /* implicit bool: 'key'= */ + value = NULL; + } else { + return error(_("bogus format in %s"), + CONFIG_DATA_ENVIRONMENT); + } + + if (config_parse_pair(key, value, fn, data) < 0) + return -1; + } + else { + /* unknown format */ + return error(_("bogus format in %s"), + CONFIG_DATA_ENVIRONMENT); + } + + if (cur) { + while (isspace(*cur)) + cur++; + } + } + return 0; +} + int git_config_from_parameters(config_fn_t fn, void *data) { const char *env = getenv(CONFIG_DATA_ENVIRONMENT); int ret = 0; char *envw; - const char **argv = NULL; - int nr = 0, alloc = 0; - int i; struct config_source source; if (!env) @@ -565,21 +613,8 @@ int git_config_from_parameters(config_fn_t fn, void *data) /* sq_dequote will write over it */ envw = xstrdup(env); + ret = parse_config_env_list(envw, fn, data); - if (sq_dequote_to_argv(envw, &argv, &nr, &alloc) < 0) { - ret = error(_("bogus format in %s"), CONFIG_DATA_ENVIRONMENT); - goto out; - } - - for (i = 0; i < nr; i++) { - if (git_config_parse_parameter(argv[i], fn, data) < 0) { - ret = -1; - goto out; - } - } - -out: - free(argv); free(envw); cf = source.prev; return ret; diff --git a/t/t1300-config.sh b/t/t1300-config.sh index 25437324c1..3f6778d474 100755 --- a/t/t1300-config.sh +++ b/t/t1300-config.sh @@ -1294,6 +1294,58 @@ test_expect_success 'git -c is not confused by empty environment' ' GIT_CONFIG_PARAMETERS="" git -c x.one=1 config --list ' +test_expect_success 'GIT_CONFIG_PARAMETERS handles old-style entries' ' + v="${SQ}key.one=foo${SQ}" && + v="$v ${SQ}key.two=bar${SQ}" && + v="$v ${SQ}key.ambiguous=section.whatever=value${SQ}" && + GIT_CONFIG_PARAMETERS=$v git config --get-regexp "key.*" >actual && + cat >expect <<-EOF && + key.one foo + key.two bar + key.ambiguous section.whatever=value + EOF + test_cmp expect actual +' + +test_expect_success 'GIT_CONFIG_PARAMETERS handles new-style entries' ' + v="${SQ}key.one${SQ}=${SQ}foo${SQ}" && + v="$v ${SQ}key.two${SQ}=${SQ}bar${SQ}" && + v="$v ${SQ}key.ambiguous=section.whatever${SQ}=${SQ}value${SQ}" && + GIT_CONFIG_PARAMETERS=$v git config --get-regexp "key.*" >actual && + cat >expect <<-EOF && + key.one foo + key.two bar + key.ambiguous=section.whatever value + EOF + test_cmp expect actual +' + +test_expect_success 'old and new-style entries can mix' ' + v="${SQ}key.oldone=oldfoo${SQ}" && + v="$v ${SQ}key.newone${SQ}=${SQ}newfoo${SQ}" && + v="$v ${SQ}key.oldtwo=oldbar${SQ}" && + v="$v ${SQ}key.newtwo${SQ}=${SQ}newbar${SQ}" && + GIT_CONFIG_PARAMETERS=$v git config --get-regexp "key.*" >actual && + cat >expect <<-EOF && + key.oldone oldfoo + key.newone newfoo + key.oldtwo oldbar + key.newtwo newbar + EOF + test_cmp expect actual +' + +test_expect_success 'old and new bools with ambiguous subsection' ' + v="${SQ}key.with=equals.oldbool${SQ}" && + v="$v ${SQ}key.with=equals.newbool${SQ}=" && + GIT_CONFIG_PARAMETERS=$v git config --get-regexp "key.*" >actual && + cat >expect <<-EOF && + key.with equals.oldbool + key.with=equals.newbool + EOF + test_cmp expect actual +' + test_expect_success 'detect bogus GIT_CONFIG_PARAMETERS' ' cat >expect <<-\EOF && env.one one From patchwork Tue Jan 12 12:27:10 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Steinhardt X-Patchwork-Id: 12013367 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id C6649C433E6 for ; Tue, 12 Jan 2021 12:29:39 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 95CD023110 for ; Tue, 12 Jan 2021 12:29:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387401AbhALM3A (ORCPT ); Tue, 12 Jan 2021 07:29:00 -0500 Received: from wout4-smtp.messagingengine.com ([64.147.123.20]:45487 "EHLO wout4-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1733015AbhALM2t (ORCPT ); Tue, 12 Jan 2021 07:28:49 -0500 Received: from compute1.internal (compute1.nyi.internal [10.202.2.41]) by mailout.west.internal (Postfix) with ESMTP id BE4511B61; Tue, 12 Jan 2021 07:27:13 -0500 (EST) Received: from mailfrontend2 ([10.202.2.163]) by compute1.internal (MEProxy); Tue, 12 Jan 2021 07:27:14 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=pks.im; h=date :from:to:cc:subject:message-id:references:mime-version :content-type:in-reply-to; s=fm3; bh=U1+40+UHQIsPAMpciXrArYnK6oH PN8/WXzdZUfgKp68=; b=ciBlEONcOl4nj6nJTyvtA/LpQ987Euguzd5p5tRBSW9 niVKIu+pSZHE/BC7R8G8ixWtCeIp28R5LMTrg6LQ3Bv2w8mXFA6NsLja433cP+8G WB0ecPSJ0dsDhYQ48UwdehSweLLKu8bh/O8ZNoSKHybRCBWRtB5lNiuXh19gxEcO x9GKbVWAY/79O8nazHRF7wP4f66rwdVVWBOuBL9Db3KRPYziRpQ9nDleCZeeAjp0 AqcwT0uwtIreDMRq9d7PPHuUvU9na/2AgfNJFO4owFevNWGzLauD0mi84yCn0Emq KAaP0HOH0Dhi+jQf7lWI6USupSa6HdSFtHC8Gocys4w== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to:x-me-proxy :x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s=fm1; bh=U1+40+ UHQIsPAMpciXrArYnK6oHPN8/WXzdZUfgKp68=; b=cavIvhQTrmLQKoSlGLsmtb 7keBtuBWfALQsczzbifeRM0lkey93ia+fR/Gv1dkSXWMO7cggm0AZDC/EyvCJCI4 SSdLO0A0YBWFRTzjwK32XZP/p5IRQuN2J/BQlNijK6iQuxwyg8+/2WSdoXfN+8HR 2lj1mjc7VnxmnLgfFcEZVDKZHGe+BA8u5FWFP5oa2beZzNthzojA25FlC5L7fvtA HRqo1EgtSZA+jiiDEPWdWYMnpXxJVpscxNmIhIUi1I10z38fy7MrbwUV8LSUpNeN 55VWto4HAtPg10kSKddoBtNDBOWSWb5Vc3ex5F79zs5LYC9sqx+j9F1Ez1CvjzCg == X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedukedrtddtgddtkecutefuodetggdotefrodftvf curfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfghnecu uegrihhlohhuthemuceftddtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmdenuc fjughrpeffhffvuffkfhggtggujgesghdtreertddtvdenucfhrhhomheprfgrthhrihgt khcuufhtvghinhhhrghrughtuceophhssehpkhhsrdhimheqnecuggftrfgrthhtvghrnh epheeghfdtfeeuffehkefgffduleffjedthfdvjeektdfhhedvlefgtefgvdettdfhnecu kfhppeejjedrudefrdehvddrleefnecuvehluhhsthgvrhfuihiivgepjeenucfrrghrrg hmpehmrghilhhfrhhomhepphhssehpkhhsrdhimh X-ME-Proxy: Received: from vm-mail.pks.im (dynamic-077-013-052-093.77.13.pool.telefonica.de [77.13.52.93]) by mail.messagingengine.com (Postfix) with ESMTPA id 8577E1080057; Tue, 12 Jan 2021 07:27:12 -0500 (EST) Received: from localhost (ncase [10.192.0.11]) by vm-mail.pks.im (OpenSMTPD) with ESMTPSA id 3d164d5e (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Tue, 12 Jan 2021 12:27:11 +0000 (UTC) Date: Tue, 12 Jan 2021 13:27:10 +0100 From: Patrick Steinhardt To: git@vger.kernel.org Cc: Simon Ruderich , =?iso-8859-1?q?=C6var_Arnfj=F6r=F0?= Bjarmason , Junio C Hamano , Jeff King , "brian m. carlson" , Philip Oakley Subject: [PATCH v8 7/8] environment: make `getenv_safe()` a public function Message-ID: <28cc229adeb4eaf8994821f0312ba7b84a6d618e.1610453228.git.ps@pks.im> References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org The `getenv_safe()` helper function helps to safely retrieve multiple environment values without the need to depend on platform-specific behaviour for the return value's lifetime. We'll make use of this function in a following patch, so let's make it available by making it non-static and adding a declaration. Signed-off-by: Patrick Steinhardt --- environment.c | 7 ++----- environment.h | 12 ++++++++++++ 2 files changed, 14 insertions(+), 5 deletions(-) create mode 100644 environment.h diff --git a/environment.c b/environment.c index bb518c61cd..2234af462c 100644 --- a/environment.c +++ b/environment.c @@ -9,6 +9,7 @@ */ #include "cache.h" #include "branch.h" +#include "environment.h" #include "repository.h" #include "config.h" #include "refs.h" @@ -152,11 +153,7 @@ static char *expand_namespace(const char *raw_namespace) return strbuf_detach(&buf, NULL); } -/* - * Wrapper of getenv() that returns a strdup value. This value is kept - * in argv to be freed later. - */ -static const char *getenv_safe(struct strvec *argv, const char *name) +const char *getenv_safe(struct strvec *argv, const char *name) { const char *value = getenv(name); diff --git a/environment.h b/environment.h new file mode 100644 index 0000000000..d438b5c8f3 --- /dev/null +++ b/environment.h @@ -0,0 +1,12 @@ +#ifndef ENVIRONMENT_H +#define ENVIRONMENT_H + +#include "strvec.h" + +/* + * Wrapper of getenv() that returns a strdup value. This value is kept + * in argv to be freed later. + */ +const char *getenv_safe(struct strvec *argv, const char *name); + +#endif From patchwork Tue Jan 12 12:27:14 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Steinhardt X-Patchwork-Id: 12013355 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id DA967C433E0 for ; Tue, 12 Jan 2021 12:28:30 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 92F6F22BE9 for ; Tue, 12 Jan 2021 12:28:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728542AbhALM23 (ORCPT ); Tue, 12 Jan 2021 07:28:29 -0500 Received: from wout4-smtp.messagingengine.com ([64.147.123.20]:36049 "EHLO wout4-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726275AbhALM23 (ORCPT ); Tue, 12 Jan 2021 07:28:29 -0500 Received: from compute1.internal (compute1.nyi.internal [10.202.2.41]) by mailout.west.internal (Postfix) with ESMTP id 03A0C1B62; Tue, 12 Jan 2021 07:27:17 -0500 (EST) Received: from mailfrontend2 ([10.202.2.163]) by compute1.internal (MEProxy); Tue, 12 Jan 2021 07:27:18 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=pks.im; h=date :from:to:cc:subject:message-id:references:mime-version :content-type:in-reply-to; s=fm3; bh=Z8V2pd0MfmHsfdRmYE95phtHm0D 82L12wUS+8PuZVq4=; b=vERlydDFIql0WKdsCwVfV3a2DRG4KIKegQ8RYBbWYlm DyTNmPLHQMc/orMNOl4eJ4gDZKSIHLJXbYYtVJ0xYXJF0rT1RZSU7ahnICBaZdlP wmL4gto22i6TBPa+bjAeDdDHrPiEEhBwC1MO1k3KB1Y03GtbJdbVbVhc9xL9sM77 oamh2sRyTxIw3HelgbXRE017yQeRP/lLNjkDINJT8PfGNijodhqe6SXiapisbuT9 kaXhiZA4/NorPEdtsmH/l3M/zDFfM//MV/K/ENC6pAdzOOpa0t3DWR6a+343QFtg 0D4ibIu5SPNMy59phGTtp9oJHkJMQcyWf4lp3JgpERA== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to:x-me-proxy :x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s=fm1; bh=Z8V2pd 0MfmHsfdRmYE95phtHm0D82L12wUS+8PuZVq4=; b=iwVCGZwHEtkxfFKCvdQjeo KZV1MCEAPRxtEFSu9UspeGxzhhHaoV+YWfq4DuTB9gP/8vIqr6KumE4rr7B9vsJK cii4QX77tIGsQetsXVmUr3qoePdzBDjkypCSI8B9/zZo/mUjjx4V+/buYeY4y+cq 3jogXGoqPxBljalNiRl4z4OzksptMQNJBOCCMpp9bI8ikCXLdmWQy7N+DuL9ufZd IZVD7dL3u8miQzWA0NehF4pLEQg/+Dj3w/JgngBpc8Rgk+RRlw2OHNXBXFMATwU2 4QSGuXRM7rskkIZd4U7/WRUChEtEkXdgdcS7vPpBbdl0CLN2A9sdiQzh7dH7FXeA == X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedukedrtddtgddtkecutefuodetggdotefrodftvf curfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfghnecu uegrihhlohhuthemuceftddtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmdenuc fjughrpeffhffvuffkfhggtggujgesghdtreertddtvdenucfhrhhomheprfgrthhrihgt khcuufhtvghinhhhrghrughtuceophhssehpkhhsrdhimheqnecuggftrfgrthhtvghrnh epheeghfdtfeeuffehkefgffduleffjedthfdvjeektdfhhedvlefgtefgvdettdfhnecu kfhppeejjedrudefrdehvddrleefnecuvehluhhsthgvrhfuihiivgepkeenucfrrghrrg hmpehmrghilhhfrhhomhepphhssehpkhhsrdhimh X-ME-Proxy: Received: from vm-mail.pks.im (dynamic-077-013-052-093.77.13.pool.telefonica.de [77.13.52.93]) by mail.messagingengine.com (Postfix) with ESMTPA id 8EDC11080057; Tue, 12 Jan 2021 07:27:16 -0500 (EST) Received: from localhost (ncase [10.192.0.11]) by vm-mail.pks.im (OpenSMTPD) with ESMTPSA id c7e4c098 (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Tue, 12 Jan 2021 12:27:16 +0000 (UTC) Date: Tue, 12 Jan 2021 13:27:14 +0100 From: Patrick Steinhardt To: git@vger.kernel.org Cc: Simon Ruderich , =?iso-8859-1?q?=C6var_Arnfj=F6r=F0?= Bjarmason , Junio C Hamano , Jeff King , "brian m. carlson" , Philip Oakley Subject: [PATCH v8 8/8] config: allow specifying config entries via envvar pairs Message-ID: <07697b0c21db06c9a88cc54cf671db48aa8a2f8f.1610453228.git.ps@pks.im> References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org While we currently have the `GIT_CONFIG_PARAMETERS` environment variable which can be used to pass runtime configuration data to git processes, it's an internal implementation detail and not supposed to be used by end users. Next to being for internal use only, this way of passing config entries has a major downside: the config keys need to be parsed as they contain both key and value in a single variable. As such, it is left to the user to escape any potentially harmful characters in the value, which is quite hard to do if values are controlled by a third party. This commit thus adds a new way of adding config entries via the environment which gets rid of this shortcoming. If the user passes the `GIT_CONFIG_COUNT=$n` environment variable, Git will parse environment variable pairs `GIT_CONFIG_KEY_$i` and `GIT_CONFIG_VALUE_$i` for each `i` in `[0,n)`. While the same can be achieved with `git -c =`, one may wish to not do so for potentially sensitive information. E.g. if one wants to set `http.extraHeader` to contain an authentication token, doing so via `-c` would trivially leak those credentials via e.g. ps(1), which typically also shows command arguments. Signed-off-by: Patrick Steinhardt --- Documentation/git-config.txt | 16 +++++ cache.h | 1 + config.c | 67 +++++++++++++++++--- environment.c | 1 + t/t1300-config.sh | 115 ++++++++++++++++++++++++++++++++++- 5 files changed, 191 insertions(+), 9 deletions(-) diff --git a/Documentation/git-config.txt b/Documentation/git-config.txt index 0e9351d3cb..4b4cc5c5e8 100644 --- a/Documentation/git-config.txt +++ b/Documentation/git-config.txt @@ -346,6 +346,22 @@ GIT_CONFIG_NOSYSTEM:: See also <>. +GIT_CONFIG_COUNT:: +GIT_CONFIG_KEY_:: +GIT_CONFIG_VALUE_:: + If GIT_CONFIG_COUNT is set to a positive number, all environment pairs + GIT_CONFIG_KEY_ and GIT_CONFIG_VALUE_ up to that number will be + added to the process's runtime configuration. The config pairs are + zero-indexed. Any missing key or value is treated as an error. An empty + GIT_CONFIG_COUNT is treated the same as GIT_CONFIG_COUNT=0, namely no + pairs are processed. These environment variables will override values + in configuration files, but will be overridden by any explicit options + passed via `git -c`. ++ +This is useful for cases where you want to spawn multiple git commands +with a common configuration but cannot depend on a configuration file, +for example when writing scripts. + [[EXAMPLES]] EXAMPLES diff --git a/cache.h b/cache.h index 7109765748..a2e318c62b 100644 --- a/cache.h +++ b/cache.h @@ -472,6 +472,7 @@ static inline enum object_type object_type(unsigned int mode) #define TEMPLATE_DIR_ENVIRONMENT "GIT_TEMPLATE_DIR" #define CONFIG_ENVIRONMENT "GIT_CONFIG" #define CONFIG_DATA_ENVIRONMENT "GIT_CONFIG_PARAMETERS" +#define CONFIG_COUNT_ENVIRONMENT "GIT_CONFIG_COUNT" #define EXEC_PATH_ENVIRONMENT "GIT_EXEC_PATH" #define CEILING_DIRECTORIES_ENVIRONMENT "GIT_CEILING_DIRECTORIES" #define NO_REPLACE_OBJECTS_ENVIRONMENT "GIT_NO_REPLACE_OBJECTS" diff --git a/config.c b/config.c index 99062915d7..a32569438a 100644 --- a/config.c +++ b/config.c @@ -8,6 +8,7 @@ #include "cache.h" #include "branch.h" #include "config.h" +#include "environment.h" #include "repository.h" #include "lockfile.h" #include "exec-cmd.h" @@ -598,23 +599,73 @@ static int parse_config_env_list(char *env, config_fn_t fn, void *data) int git_config_from_parameters(config_fn_t fn, void *data) { - const char *env = getenv(CONFIG_DATA_ENVIRONMENT); + const char *env; + struct strbuf envvar = STRBUF_INIT; + struct strvec to_free = STRVEC_INIT; int ret = 0; - char *envw; + char *envw = NULL; struct config_source source; - if (!env) - return 0; - memset(&source, 0, sizeof(source)); source.prev = cf; source.origin_type = CONFIG_ORIGIN_CMDLINE; cf = &source; - /* sq_dequote will write over it */ - envw = xstrdup(env); - ret = parse_config_env_list(envw, fn, data); + env = getenv(CONFIG_COUNT_ENVIRONMENT); + if (env) { + unsigned long count; + char *endp; + int i; + count = strtoul(env, &endp, 10); + if (*endp) { + ret = error(_("bogus count in %s"), CONFIG_COUNT_ENVIRONMENT); + goto out; + } + if (count > INT_MAX) { + ret = error(_("too many entries in %s"), CONFIG_COUNT_ENVIRONMENT); + goto out; + } + + for (i = 0; i < count; i++) { + const char *key, *value; + + strbuf_addf(&envvar, "GIT_CONFIG_KEY_%d", i); + key = getenv_safe(&to_free, envvar.buf); + if (!key) { + ret = error(_("missing config key %s"), envvar.buf); + goto out; + } + strbuf_reset(&envvar); + + strbuf_addf(&envvar, "GIT_CONFIG_VALUE_%d", i); + value = getenv_safe(&to_free, envvar.buf); + if (!value) { + ret = error(_("missing config value %s"), envvar.buf); + goto out; + } + strbuf_reset(&envvar); + + if (config_parse_pair(key, value, fn, data) < 0) { + ret = -1; + goto out; + } + } + } + + env = getenv(CONFIG_DATA_ENVIRONMENT); + if (env) { + /* sq_dequote will write over it */ + envw = xstrdup(env); + if (parse_config_env_list(envw, fn, data) < 0) { + ret = -1; + goto out; + } + } + +out: + strbuf_release(&envvar); + strvec_clear(&to_free); free(envw); cf = source.prev; return ret; diff --git a/environment.c b/environment.c index 2234af462c..2f27008424 100644 --- a/environment.c +++ b/environment.c @@ -117,6 +117,7 @@ const char * const local_repo_env[] = { ALTERNATE_DB_ENVIRONMENT, CONFIG_ENVIRONMENT, CONFIG_DATA_ENVIRONMENT, + CONFIG_COUNT_ENVIRONMENT, DB_ENVIRONMENT, GIT_DIR_ENVIRONMENT, GIT_WORK_TREE_ENVIRONMENT, diff --git a/t/t1300-config.sh b/t/t1300-config.sh index 3f6778d474..89b47bf5bd 100755 --- a/t/t1300-config.sh +++ b/t/t1300-config.sh @@ -1424,6 +1424,117 @@ test_expect_success '--config-env handles keys with equals' ' test_cmp expect actual ' +test_expect_success 'git config handles environment config pairs' ' + GIT_CONFIG_COUNT=2 \ + GIT_CONFIG_KEY_0="pair.one" GIT_CONFIG_VALUE_0="foo" \ + GIT_CONFIG_KEY_1="pair.two" GIT_CONFIG_VALUE_1="bar" \ + git config --get-regexp "pair.*" >actual && + cat >expect <<-EOF && + pair.one foo + pair.two bar + EOF + test_cmp expect actual +' + +test_expect_success 'git config ignores pairs without count' ' + test_must_fail env GIT_CONFIG_KEY_0="pair.one" GIT_CONFIG_VALUE_0="value" \ + git config pair.one 2>error && + test_must_be_empty error +' + +test_expect_success 'git config ignores pairs with zero count' ' + test_must_fail env \ + GIT_CONFIG_COUNT=0 \ + GIT_CONFIG_KEY_0="pair.one" GIT_CONFIG_VALUE_0="value" \ + git config pair.one +' + +test_expect_success 'git config ignores pairs exceeding count' ' + GIT_CONFIG_COUNT=1 \ + GIT_CONFIG_KEY_0="pair.one" GIT_CONFIG_VALUE_0="value" \ + GIT_CONFIG_KEY_1="pair.two" GIT_CONFIG_VALUE_1="value" \ + git config --get-regexp "pair.*" >actual && + cat >expect <<-EOF && + pair.one value + EOF + test_cmp expect actual +' + +test_expect_success 'git config ignores pairs with zero count' ' + test_must_fail env \ + GIT_CONFIG_COUNT=0 GIT_CONFIG_KEY_0="pair.one" GIT_CONFIG_VALUE_0="value" \ + git config pair.one >error && + test_must_be_empty error +' + +test_expect_success 'git config ignores pairs with empty count' ' + test_must_fail env \ + GIT_CONFIG_COUNT= GIT_CONFIG_KEY_0="pair.one" GIT_CONFIG_VALUE_0="value" \ + git config pair.one >error && + test_must_be_empty error +' + +test_expect_success 'git config fails with invalid count' ' + test_must_fail env GIT_CONFIG_COUNT=10a git config --list 2>error && + test_i18ngrep "bogus count" error && + test_must_fail env GIT_CONFIG_COUNT=9999999999999999 git config --list 2>error && + test_i18ngrep "too many entries" error +' + +test_expect_success 'git config fails with missing config key' ' + test_must_fail env GIT_CONFIG_COUNT=1 GIT_CONFIG_VALUE_0="value" \ + git config --list 2>error && + test_i18ngrep "missing config key" error +' + +test_expect_success 'git config fails with missing config value' ' + test_must_fail env GIT_CONFIG_COUNT=1 GIT_CONFIG_KEY_0="pair.one" \ + git config --list 2>error && + test_i18ngrep "missing config value" error +' + +test_expect_success 'git config fails with invalid config pair key' ' + test_must_fail env GIT_CONFIG_COUNT=1 \ + GIT_CONFIG_KEY_0= GIT_CONFIG_VALUE_0=value \ + git config --list && + test_must_fail env GIT_CONFIG_COUNT=1 \ + GIT_CONFIG_KEY_0=missing-section GIT_CONFIG_VALUE_0=value \ + git config --list +' + +test_expect_success 'environment overrides config file' ' + test_when_finished "rm -f .git/config" && + cat >.git/config <<-EOF && + [pair] + one = value + EOF + GIT_CONFIG_COUNT=1 GIT_CONFIG_KEY_0=pair.one GIT_CONFIG_VALUE_0=override \ + git config pair.one >actual && + cat >expect <<-EOF && + override + EOF + test_cmp expect actual +' + +test_expect_success 'GIT_CONFIG_PARAMETERS overrides environment config' ' + GIT_CONFIG_COUNT=1 GIT_CONFIG_KEY_0=pair.one GIT_CONFIG_VALUE_0=value \ + GIT_CONFIG_PARAMETERS="${SQ}pair.one=override${SQ}" \ + git config pair.one >actual && + cat >expect <<-EOF && + override + EOF + test_cmp expect actual +' + +test_expect_success 'command line overrides environment config' ' + GIT_CONFIG_COUNT=1 GIT_CONFIG_KEY_0=pair.one GIT_CONFIG_VALUE_0=value \ + git -c pair.one=override config pair.one >actual && + cat >expect <<-EOF && + override + EOF + test_cmp expect actual +' + test_expect_success 'git config --edit works' ' git config -f tmp test.value no && echo test.value=yes >expect && @@ -1769,9 +1880,11 @@ test_expect_success '--show-origin with --list' ' file:.git/config user.override=local file:.git/config include.path=../include/relative.include file:.git/../include/relative.include user.relative=include + command line: user.environ=true command line: user.cmdline=true EOF - git -c user.cmdline=true config --list --show-origin >output && + GIT_CONFIG_COUNT=1 GIT_CONFIG_KEY_0=user.environ GIT_CONFIG_VALUE_0=true\ + git -c user.cmdline=true config --list --show-origin >output && test_cmp expect output '