From patchwork Mon Jan 11 08:36: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: 12010075 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 0267DC433E6 for ; Mon, 11 Jan 2021 08:38:03 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id BC16722AAA for ; Mon, 11 Jan 2021 08:38:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727987AbhAKIh5 (ORCPT ); Mon, 11 Jan 2021 03:37:57 -0500 Received: from wout4-smtp.messagingengine.com ([64.147.123.20]:33611 "EHLO wout4-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727739AbhAKIh5 (ORCPT ); Mon, 11 Jan 2021 03:37:57 -0500 Received: from compute1.internal (compute1.nyi.internal [10.202.2.41]) by mailout.west.internal (Postfix) with ESMTP id 5EF4F250A; Mon, 11 Jan 2021 03:36:48 -0500 (EST) Received: from mailfrontend1 ([10.202.2.162]) by compute1.internal (MEProxy); Mon, 11 Jan 2021 03:36: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=+bL+ktzYc2CG5dLgdv2SNOVUp4C h9gQxDS54I+fw9Dc=; b=ov3Oss+qdnGhjzKUWN9wZ3oybA+MhqdDXwJpXv84Mez AUt/ERDC8aPQQ+3DIQtA+Vxo/+/suRZ0qVw/37o7TC5sApjKa7aE/TLbi+eiBQjr 7+NetZ9TCCdck1+n8d8usjJ30k74rgI73Ev8z+/ujGzpjiRCSx7ANVAZZHEj18QD 3isrK0ctPvF7YHbzZYjZ38hcyICJF8vysgaw602BL5yIcL8kNqaVyvec6/14jItc GJeAGAz5Ec1uGplZ5vc9p+RKlWhlE17IZ8JNHj/eURTzqdlvtI+Ksl0zSVv6pLTB zIvLASxw4DoGxHQudG2nTCKUW2o5mfeVO0b8//XgloA== 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=+bL+kt zYc2CG5dLgdv2SNOVUp4Ch9gQxDS54I+fw9Dc=; b=rww7l/GlLKQbRHhi1xLVql ysnfEaau5Cn204hcw79YQxn2qWyMqPC0NRtnNqBuDunWz5SrAK3aFBmbBgwLvflg mdYH/DuyOtcZt0aAfCRlZmnAp4umnJFP197GWsKFcsMYZIlZ0W92zYfzjDXHdaZm 9T7tx0mNV93DIdFYma7UwQd2oxBgQgplsAXjXxwFnnGb6myTN95SAwR6h0smLy6I 2AAn/q+VVfEuYXF2k7m4D/MBNr6idzxWsaG84DhilRAZkkCGqSxKLM0a63CaCTfp AxFVUQ3nG3FkL8GOHrAR0wNfi8voCkI5pkeLe5/fz6Q0NG5kF3TKm9BbcZIsepgQ == X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedujedrvdehtddguddulecutefuodetggdotefrod ftvfcurfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfgh necuuegrihhlohhuthemuceftddtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmd enucfjughrpeffhffvuffkfhggtggujgesghdtreertddtvdenucfhrhhomheprfgrthhr ihgtkhcuufhtvghinhhhrghrughtuceophhssehpkhhsrdhimheqnecuggftrfgrthhtvg hrnhepheeghfdtfeeuffehkefgffduleffjedthfdvjeektdfhhedvlefgtefgvdettdfh necukfhppeekledrudegrdeghedrudejtdenucevlhhushhtvghrufhiiigvpedtnecurf grrhgrmhepmhgrihhlfhhrohhmpehpshesphhkshdrihhm X-ME-Proxy: Received: from vm-mail.pks.im (dynamic-089-014-045-170.89.14.pool.telefonica.de [89.14.45.170]) by mail.messagingengine.com (Postfix) with ESMTPA id F2E1024005C; Mon, 11 Jan 2021 03:36:46 -0500 (EST) Received: from localhost (ncase [10.192.0.11]) by vm-mail.pks.im (OpenSMTPD) with ESMTPSA id 7bb514ad (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Mon, 11 Jan 2021 08:36:46 +0000 (UTC) Date: Mon, 11 Jan 2021 09:36: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 v7 1/8] git: add `--super-prefix` to usage string Message-ID: <55fa4d0d11f92c5b3c86c47b91ca5f4ceab2f81a.1610353895.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 Mon Jan 11 08:36: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: 12010069 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 D98F7C433E6 for ; Mon, 11 Jan 2021 08:37:42 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 9059522527 for ; Mon, 11 Jan 2021 08:37:42 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727961AbhAKIhl (ORCPT ); Mon, 11 Jan 2021 03:37:41 -0500 Received: from wout4-smtp.messagingengine.com ([64.147.123.20]:39525 "EHLO wout4-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727739AbhAKIhl (ORCPT ); Mon, 11 Jan 2021 03:37:41 -0500 Received: from compute1.internal (compute1.nyi.internal [10.202.2.41]) by mailout.west.internal (Postfix) with ESMTP id 9743A2512; Mon, 11 Jan 2021 03:36:52 -0500 (EST) Received: from mailfrontend1 ([10.202.2.162]) by compute1.internal (MEProxy); Mon, 11 Jan 2021 03:36: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=Dux9L/dN7cYT8Cor70pLsw1PAQg NnDyKv8GSXazN964=; b=UwDHcKCMgNKoPF+3osN+02Vpfc2sW313/PzqXQygJiz IB/WwCdufLYOa7oE/yBuE4MljFiILhjP6tDox5vHR2SfG+tnDOjKos/MQ7JgCDh3 ALPURLZYg+xsRMs6hD9V4J7QjsGBDOIwxLSRp4l7KesGLXDeHGrfoYi4UFYl62/U AiNCDqdY8iCIzpNJbcFmWaT4TVWFNVEaMyf/lLBC8+/U0fp9+IL5Vs5D/oCLx4lS mf09B9hhw3en283iWm1nPvM8lokwXqleEtRqWnMS3qMvv9Xcjx1p7BAg+CjerRkF jQYsvfAZSPb2V28dox7xVWX6NSFPOxIfGx0rQRypAKQ== 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=Dux9L/ dN7cYT8Cor70pLsw1PAQgNnDyKv8GSXazN964=; b=PyDKrADmjGoFo2xRUufa4M bcqAmSLPwAu7v9ddN7ugpsLthzN5y8O3lGl1oU+Zruo+hPqE8M5kXx3u4v7XNSn0 kmT2NYan+L3EcCcmi2jUYzSLvIEDU3Uwv5BIx/ZVWtzHCOLMj/nNk4H6HSrvm4v9 0SvXU6iz4EPU6NGPHC/oZlHOT6A54O6MGZZ3Dc1amC3pAiwbNmBDJ8QOWAue2DGS YLmer5SLvZbHXrUKLjVWzBjIZgLQaE1Zy55XDlCSk/xGYRisxXofloXtD+Kl+Zyg 4zx8oBiMHcOnTwMmmDZzkzvLH/a0E5hqUoyBROiqZnzZtCYX8kn7aj35IiMqZssQ == X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedujedrvdehtddguddulecutefuodetggdotefrod ftvfcurfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfgh necuuegrihhlohhuthemuceftddtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmd enucfjughrpeffhffvuffkfhggtggujgesghdtreertddtvdenucfhrhhomheprfgrthhr ihgtkhcuufhtvghinhhhrghrughtuceophhssehpkhhsrdhimheqnecuggftrfgrthhtvg hrnhepheeghfdtfeeuffehkefgffduleffjedthfdvjeektdfhhedvlefgtefgvdettdfh necukfhppeekledrudegrdeghedrudejtdenucevlhhushhtvghrufhiiigvpedvnecurf grrhgrmhepmhgrihhlfhhrohhmpehpshesphhkshdrihhm X-ME-Proxy: Received: from vm-mail.pks.im (dynamic-089-014-045-170.89.14.pool.telefonica.de [89.14.45.170]) by mail.messagingengine.com (Postfix) with ESMTPA id 1B8AE24005D; Mon, 11 Jan 2021 03:36:51 -0500 (EST) Received: from localhost (ncase [10.192.0.11]) by vm-mail.pks.im (OpenSMTPD) with ESMTPSA id f6887057 (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Mon, 11 Jan 2021 08:36:50 +0000 (UTC) Date: Mon, 11 Jan 2021 09:36: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 v7 2/8] config: add new way to pass config via `--config-env` Message-ID: 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 | 24 ++++++++++++++++++++++ config.h | 1 + git.c | 4 +++- t/t1300-config.sh | 47 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 98 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..6484d13c46 100644 --- a/config.c +++ b/config.c @@ -345,6 +345,30 @@ 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 value for --config-env")); + + 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..1e23eb8213 100755 --- a/t/t1300-config.sh +++ b/t/t1300-config.sh @@ -1316,6 +1316,53 @@ 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 + { + env ENVVAR=value git --config-env=core.name=ENVVAR config core.name && + env ENVVAR=value git --config-env=foo.CamelCase=ENVVAR config foo.camelcase && + env 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" error && + test_must_fail git --config-env=foo.flag= config --bool foo.flag 2>error && + test_i18ngrep "missing value for --config-env" error && + 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 + env 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 + { + env ENVVAR=env git -c bar.bar=cmd --config-env=bar.bar=ENVVAR config bar.bar && + env 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 Mon Jan 11 08:36:53 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Steinhardt X-Patchwork-Id: 12010071 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 BBE7AC433DB for ; Mon, 11 Jan 2021 08:38:02 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 7F02D22527 for ; Mon, 11 Jan 2021 08:38:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727967AbhAKIhq (ORCPT ); Mon, 11 Jan 2021 03:37:46 -0500 Received: from wout4-smtp.messagingengine.com ([64.147.123.20]:38499 "EHLO wout4-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727739AbhAKIhq (ORCPT ); Mon, 11 Jan 2021 03:37:46 -0500 Received: from compute3.internal (compute3.nyi.internal [10.202.2.43]) by mailout.west.internal (Postfix) with ESMTP id 52C952522; Mon, 11 Jan 2021 03:36:58 -0500 (EST) Received: from mailfrontend1 ([10.202.2.162]) by compute3.internal (MEProxy); Mon, 11 Jan 2021 03:36: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=nC/e5601YAFxN7fZLeZyyQ4sGEB ZtWKhD7YYLzF8BL0=; b=OoZMCcDC4h5KziLgNzZKASCwyG18hAMvob95luQSZiQ piaQiGzf80hjtu5WtXhmnt0ajSuMk3+psq9TMd1hTQbhEs71ILBQvQcq61YlEopq lH1oL6ulz6m7QJug4smj+zZZnDy/zzPVntLXxJcOwxItbjawwqQdp+eRcOXx8BzI 0YluzmBfZWImemhKdxxotj0Damrx8DT9URdt4+3kjWE37jA8ReEFH5W9Vp26dfdt zxC740aj7hcE931NK+FRnAslsG6i4UdB3VF3g/rz2pwAVqLeEmCIjQ40yNrc7gaY 9Rb9IsmPj1eHZ1C97uxrjWA/7YCJGx56NyEqj7610SA== 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=nC/e56 01YAFxN7fZLeZyyQ4sGEBZtWKhD7YYLzF8BL0=; b=RR/Dk46JjJXNTRDkwfO0n9 ERsB/zMFBUf9d3Of1R8QqRlczQqyzPn5g57dGo7PXH6dSYO1zVgu4rYQoPNxumof 9AUvagEFeCsnj2iyPvW3vZxCU1Gusvy1zLV85laDa7dnhQ2lS1EkqpsnVOAtWUyG arpHNH7xLTa1UU0wm3OkHRRezITX63bh3Bdv4Lke6cF0OGY+GKKrrrUJrDGzCap7 jFojvtaExlAjYIP8dPD8e/3B4a+mEifDEppLkFuYGoJFqbbDRiCzBOCuZFseY3nd bpCnLeVZpzdU5i7noNmi4rn6QQRBZRdmTY7WUOjv/MyCfDUTHDT63vuhLvCACMaw == X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedujedrvdehtddguddulecutefuodetggdotefrod ftvfcurfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfgh necuuegrihhlohhuthemuceftddtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmd enucfjughrpeffhffvuffkfhggtggujgesghdtreertddtvdenucfhrhhomheprfgrthhr ihgtkhcuufhtvghinhhhrghrughtuceophhssehpkhhsrdhimheqnecuggftrfgrthhtvg hrnhepheeghfdtfeeuffehkefgffduleffjedthfdvjeektdfhhedvlefgtefgvdettdfh necukfhppeekledrudegrdeghedrudejtdenucevlhhushhtvghrufhiiigvpedtnecurf grrhgrmhepmhgrihhlfhhrohhmpehpshesphhkshdrihhm X-ME-Proxy: Received: from vm-mail.pks.im (dynamic-089-014-045-170.89.14.pool.telefonica.de [89.14.45.170]) by mail.messagingengine.com (Postfix) with ESMTPA id 52D0624005D; Mon, 11 Jan 2021 03:36:56 -0500 (EST) Received: from localhost (ncase [10.192.0.11]) by vm-mail.pks.im (OpenSMTPD) with ESMTPSA id 3735a225 (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Mon, 11 Jan 2021 08:36:55 +0000 (UTC) Date: Mon, 11 Jan 2021 09:36:53 +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 v7 3/8] quote: make sq_dequote_step() a public function Message-ID: <1b47f0db98a4453e4d30815753a57e654fd1aa52.1610353895.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 Mon Jan 11 08:36:58 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Steinhardt X-Patchwork-Id: 12010077 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 55ADAC433E0 for ; Mon, 11 Jan 2021 08:38:11 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 1F83E22581 for ; Mon, 11 Jan 2021 08:38:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728041AbhAKIiK (ORCPT ); Mon, 11 Jan 2021 03:38:10 -0500 Received: from wout4-smtp.messagingengine.com ([64.147.123.20]:44855 "EHLO wout4-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728037AbhAKIiJ (ORCPT ); Mon, 11 Jan 2021 03:38:09 -0500 Received: from compute1.internal (compute1.nyi.internal [10.202.2.41]) by mailout.west.internal (Postfix) with ESMTP id D96582509; Mon, 11 Jan 2021 03:37:01 -0500 (EST) Received: from mailfrontend1 ([10.202.2.162]) by compute1.internal (MEProxy); Mon, 11 Jan 2021 03:37:02 -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=nrHjIpOBEC8UV5yqviyUQmMsRRX ZVF3QTvWMJz4fWus=; b=lglaIugPmmf0mEVQMoJwAJfVBPeXojv0ELymsyI7vi/ oRrJrydSgcSO0Vlkqx+tb2RwEVbTkckJGJDBzaido1qkjreckj3YzTSGLNr6+9Mn F3IPjOq5DIeorBihcIq7rvL7+NfUW9AqFIMsps1Ix2tQPLLotVfppqKcCe6+Mgpn YYa+gDWjgb5z2HjuuZrYJsxFQmDgdpgg0ncZ9CW6c0WLFBFsVUVw6JOHCySHAvvR 7V3uerIe5CB5reYL5K99XKWpO9HxrIL9ARoTzdwmhfmUMDA2MGTwiX5OqpD4dj9w QpuvtIjv+pH9GT6txP9nW0jA24PKkk6yFunGQGPR8iQ== 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=nrHjIp OBEC8UV5yqviyUQmMsRRXZVF3QTvWMJz4fWus=; b=ij9VxxKR5aLLW51o5KQu4w F0NpY/Ch5x954ZhyW4aSAakiIx6RxH2X9Qbtl7d11pN3Cq/cAWpG3M/57tIPFJ9A VRprzFAy2ADcR0ESy8J7/mpg1rik8bmRZlprWLwHrzSFwiEz3UBZdiQ+dyZJzgfo lp37wIBFecLyt22Plo0TnEFsSbTBtcSwPH3iaKmW4T/aaxQHFw0u1k1wynm5F7pn y0zC5BEJN2Y+qek3iojI8OW4RqR9Imz8oQEpKSX8Q8pSCnJ5vz1UStOsPZkiajeg 8h9k3nHi29S/K+/OV9gFYrRAjhXAVknYzvLV0FvVmJY51MUtWZM5+H0csUkDb40g == X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedujedrvdehtddguddulecutefuodetggdotefrod ftvfcurfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfgh necuuegrihhlohhuthemuceftddtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmd enucfjughrpeffhffvuffkfhggtggujgesghdtreertddtvdenucfhrhhomheprfgrthhr ihgtkhcuufhtvghinhhhrghrughtuceophhssehpkhhsrdhimheqnecuggftrfgrthhtvg hrnhepheeghfdtfeeuffehkefgffduleffjedthfdvjeektdfhhedvlefgtefgvdettdfh necukfhppeekledrudegrdeghedrudejtdenucevlhhushhtvghrufhiiigvpeefnecurf grrhgrmhepmhgrihhlfhhrohhmpehpshesphhkshdrihhm X-ME-Proxy: Received: from vm-mail.pks.im (dynamic-089-014-045-170.89.14.pool.telefonica.de [89.14.45.170]) by mail.messagingengine.com (Postfix) with ESMTPA id 7158724005B; Mon, 11 Jan 2021 03:37:00 -0500 (EST) Received: from localhost (ncase [10.192.0.11]) by vm-mail.pks.im (OpenSMTPD) with ESMTPSA id 9973891c (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Mon, 11 Jan 2021 08:37:00 +0000 (UTC) Date: Mon, 11 Jan 2021 09:36:58 +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 v7 4/8] config: extract function to parse config pairs Message-ID: 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 6484d13c46..aeffe4f4bc 100644 --- a/config.c +++ b/config.c @@ -461,11 +461,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; @@ -486,12 +501,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 Mon Jan 11 08:37:03 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Steinhardt X-Patchwork-Id: 12010079 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 CBF87C433DB for ; Mon, 11 Jan 2021 08:38:28 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 8B1A322581 for ; Mon, 11 Jan 2021 08:38:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727887AbhAKIi1 (ORCPT ); Mon, 11 Jan 2021 03:38:27 -0500 Received: from wout4-smtp.messagingengine.com ([64.147.123.20]:55983 "EHLO wout4-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728045AbhAKIi1 (ORCPT ); Mon, 11 Jan 2021 03:38:27 -0500 Received: from compute5.internal (compute5.nyi.internal [10.202.2.45]) by mailout.west.internal (Postfix) with ESMTP id 3C1E42520; Mon, 11 Jan 2021 03:37:06 -0500 (EST) Received: from mailfrontend1 ([10.202.2.162]) by compute5.internal (MEProxy); Mon, 11 Jan 2021 03:37: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=2hk89cnWlfsZOdy+1kLd0vRcI+V BFsuBTK+aV5sXsrk=; b=oWXiaibjc5FX1eRl4cxj1PzJ/z0hIJB2pTkHdBmv+iM DsFjUqT8yZ9fH73VYdyQYaGPuj2vPGGj6nxfIIgxTXDuSIOShYcDXuRDYYO3FZ4D GJhsiQua/kY3vhkH+y//Y8uL7m6itl1OU5RrazbydcZOh77Q5sExRCkQykT2lj+a DL5ox9CHR8EpdZdWwiENTCXwwC0jvVG39gd4qhLoBVeO1j+8dQEE3cwZMNBNS17P TnH5SbS+8Kv6CAMS2TbaPn1H7yRJi7oCUAlVHBiOK8ClK/i680tU334hRX/1pEdd fKGy9KqIa8c7hwsyi192iS24sBYW+W324n7PFVD1O+A== 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=2hk89c nWlfsZOdy+1kLd0vRcI+VBFsuBTK+aV5sXsrk=; b=ApFlUyr+xxVrM5Fk8DeFfB da6YeBUIASG/ceFTBCY6cphCTJtl8efSNufF/tB8dB8HifL9Rxtgv2RBjnRNsuXP Y8b9g9cIvCeL2g4iUrhQK/Ty88Jp0JXw+CC/TOuQD45g+VVeuvPbqV5oVi2NWS8U jnasSMtnP8Q91x8X6rVlmf3ltvlprSyF0+E2uWy63PBdZ3+1CDLLtfeGj/X8Xe/x ApBDZXkGJ2JpwbehFb15qz9tGCuUwhw/sxFXMIVAGTsNGGhuHd6lSsjwwM2JTNOQ e4pS1FO3fS8geDN4NIs+Cw1vUvf1zxM7GWj6A3+6eA6SzafLMaGx2q01Ze6nFD9g == X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedujedrvdehtddguddulecutefuodetggdotefrod ftvfcurfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfgh necuuegrihhlohhuthemuceftddtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmd enucfjughrpeffhffvuffkfhggtggujgesghdtreertddtvdenucfhrhhomheprfgrthhr ihgtkhcuufhtvghinhhhrghrughtuceophhssehpkhhsrdhimheqnecuggftrfgrthhtvg hrnhepheeghfdtfeeuffehkefgffduleffjedthfdvjeektdfhhedvlefgtefgvdettdfh necukfhppeekledrudegrdeghedrudejtdenucevlhhushhtvghrufhiiigvpedtnecurf grrhgrmhepmhgrihhlfhhrohhmpehpshesphhkshdrihhm X-ME-Proxy: Received: from vm-mail.pks.im (dynamic-089-014-045-170.89.14.pool.telefonica.de [89.14.45.170]) by mail.messagingengine.com (Postfix) with ESMTPA id 98699240062; Mon, 11 Jan 2021 03:37:04 -0500 (EST) Received: from localhost (ncase [10.192.0.11]) by vm-mail.pks.im (OpenSMTPD) with ESMTPSA id 8dbd6612 (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Mon, 11 Jan 2021 08:37:04 +0000 (UTC) Date: Mon, 11 Jan 2021 09:37:03 +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 v7 5/8] config: store "git -c" variables using more robust format Message-ID: <8f998ac81a53a85b16029eed0fdf07f05d1e47f6.1610353895.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 aeffe4f4bc..b5475c28aa 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 value for --config-env")); @@ -363,10 +403,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 1e23eb8213..24919d5445 100755 --- a/t/t1300-config.sh +++ b/t/t1300-config.sh @@ -1363,6 +1363,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 Mon Jan 11 08:37:07 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Steinhardt X-Patchwork-Id: 12010083 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 8FD04C433DB for ; Mon, 11 Jan 2021 08:39:08 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 4871922B43 for ; Mon, 11 Jan 2021 08:39:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728003AbhAKIis (ORCPT ); Mon, 11 Jan 2021 03:38:48 -0500 Received: from wout4-smtp.messagingengine.com ([64.147.123.20]:56175 "EHLO wout4-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727899AbhAKIir (ORCPT ); Mon, 11 Jan 2021 03:38:47 -0500 Received: from compute1.internal (compute1.nyi.internal [10.202.2.41]) by mailout.west.internal (Postfix) with ESMTP id 2562424A6; Mon, 11 Jan 2021 03:37:11 -0500 (EST) Received: from mailfrontend1 ([10.202.2.162]) by compute1.internal (MEProxy); Mon, 11 Jan 2021 03:37:11 -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=x8W/58h/bdmlqtHesBth0huDZE6 f/2vIZz1wwTYc2DU=; b=nCnLKEhuzGgjHiH80WtgjZuHg1x6Nmk/FLkMSYYrtxz 22H2IZz2j1g70M7+TzsTyer4eHVHiBoehz9E4TIbq4tz0TwQcl0lg3GseQj+YuJP GGxSwAj8jL0RIIbKQYyCqCdkR/wenWFCCK9YKPeS+y3hoAuqerh2HKe441YIhyzV EFJeyj0pZyyIgtnLhBehBzwoZRtb+p16bidZ5nCshFfqrOv88Wh4RgGxlVo6oVOq xh+zljHSuz4VhO8k3ooXeCl+FFLJjdktnxiVjsbfvdPAvagPGIMB5obIfJv40Xhf TNNQzuD1UxB0/TV/znTFtKfN5n9IgFXaP0MJOllFTZQ== 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=x8W/58 h/bdmlqtHesBth0huDZE6f/2vIZz1wwTYc2DU=; b=c4h1Nz5rAeH9x60UtSaDtm 0LRDe1nBrIxdqzp4ElC5Jd0bkny9zhMsPRe9UwJLFz4eIeh5aJE2SIRbRJ9Z0ofK y6fmRMlSK3rlAdT6Rt3SqucEakehITq4AB+jvWciWcgDJAtdn0l+s8nlNCQ9vM3j XfLn1qIowt/mPrJuAjK9daxMvcjorfFhR2xRCUmXzu4OrJB7c/mwkuqaWNvDV7nw 7fEnPs/SSJnmC6f42+vC9h1tyROpOqzZ1cxiJL1FjqDLfPq9pKnbqB4wWuEx2HS7 ce+rhNe5vOrpaS9+in8+Baf3Allmd2eM3oH8xkGR7+VufIsUTBC3t5P5fwf1jxrg == X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedujedrvdehtddguddulecutefuodetggdotefrod ftvfcurfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfgh necuuegrihhlohhuthemuceftddtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmd enucfjughrpeffhffvuffkfhggtggujgesghdtreertddtvdenucfhrhhomheprfgrthhr ihgtkhcuufhtvghinhhhrghrughtuceophhssehpkhhsrdhimheqnecuggftrfgrthhtvg hrnhepheeghfdtfeeuffehkefgffduleffjedthfdvjeektdfhhedvlefgtefgvdettdfh necukfhppeekledrudegrdeghedrudejtdenucevlhhushhtvghrufhiiigvpeegnecurf grrhgrmhepmhgrihhlfhhrohhmpehpshesphhkshdrihhm X-ME-Proxy: Received: from vm-mail.pks.im (dynamic-089-014-045-170.89.14.pool.telefonica.de [89.14.45.170]) by mail.messagingengine.com (Postfix) with ESMTPA id B890D24005B; Mon, 11 Jan 2021 03:37:09 -0500 (EST) Received: from localhost (ncase [10.192.0.11]) by vm-mail.pks.im (OpenSMTPD) with ESMTPSA id 276ea490 (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Mon, 11 Jan 2021 08:37:08 +0000 (UTC) Date: Mon, 11 Jan 2021 09:37:07 +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 v7 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 b5475c28aa..33099a3b0d 100644 --- a/config.c +++ b/config.c @@ -544,14 +544,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) @@ -564,21 +612,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 24919d5445..0063e9f059 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 Mon Jan 11 08:37:11 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Steinhardt X-Patchwork-Id: 12010081 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 0B9DAC433E0 for ; Mon, 11 Jan 2021 08:38:33 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id D01BE22527 for ; Mon, 11 Jan 2021 08:38:32 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728037AbhAKIic (ORCPT ); Mon, 11 Jan 2021 03:38:32 -0500 Received: from wout4-smtp.messagingengine.com ([64.147.123.20]:47479 "EHLO wout4-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727785AbhAKIib (ORCPT ); Mon, 11 Jan 2021 03:38:31 -0500 Received: from compute1.internal (compute1.nyi.internal [10.202.2.41]) by mailout.west.internal (Postfix) with ESMTP id 3FA4C2524; Mon, 11 Jan 2021 03:37:15 -0500 (EST) Received: from mailfrontend1 ([10.202.2.162]) by compute1.internal (MEProxy); Mon, 11 Jan 2021 03:37:15 -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=/nuzo7NbhJ76GGnAlH7CcXehW74 KrjrjkhP+b0OrHCo=; b=QDxg2y7YXqmyPslWRq//7Ys0gSAVT1xKVag40AZiCvD 3dqFxELF2AYAF8cE+GOY8bOQ3YReyIQpTrLQGXhWCb7l98HZRJZqbiTq3CZQnju9 3gcNSSftiWWUSb1FoFB/c+KVD9Ilg4SuUNjUeouQ+bwMeUtqHMxKzdVOGVznuilr c5Jefegz0FCv95QkUjQQ9sXAn376FHKy5O52UXNJb3SAEhqSK/1TV8FN+EOxIIgc +qxS5UtMdYM/5TIC1ryp3RZ9Ta3PbFmCIgS5JzB2U0ePairqDFaa1Hb7AmarPx58 yvqpCMM7DIw8QhKg0LuvVqrvoIO+YqF5LhYnfSBuU9Q== 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=/nuzo7 NbhJ76GGnAlH7CcXehW74KrjrjkhP+b0OrHCo=; b=ZKna7SoG9zHi9wv0PWMZfU vGhvDRz9HUmMrdKTYpHOaPdutJfPjZSunOGV3sEMZaMCIvajzdqQe4Xq01k47vpi lDIW0XRF09um28zUrbifUAlW70rFyAj7aYHR6kVLhv4DZ8vGbIx/3tfHXVRI3y/G gVD0NpUforR4Jp5oG7AfMJTVlqfUAlPJAUKFWKb5oJkMERUu7KBzqZLD4Q5SYC5c q7t1pk2CGRB4B2vxKYNoPFWXdXRA++paOjcZ+viyML4g5jIsPyQgnW5LI9fCp4Qz RlM8GPoKo859RDqMZ1i4MVYQkeOc3NOFELf1AQy2xJZJBwsqbDk3fBIv7g6Aspdw == X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedujedrvdehtddguddulecutefuodetggdotefrod ftvfcurfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfgh necuuegrihhlohhuthemuceftddtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmd enucfjughrpeffhffvuffkfhggtggujgesghdtreertddtvdenucfhrhhomheprfgrthhr ihgtkhcuufhtvghinhhhrghrughtuceophhssehpkhhsrdhimheqnecuggftrfgrthhtvg hrnhepheeghfdtfeeuffehkefgffduleffjedthfdvjeektdfhhedvlefgtefgvdettdfh necukfhppeekledrudegrdeghedrudejtdenucevlhhushhtvghrufhiiigvpeehnecurf grrhgrmhepmhgrihhlfhhrohhmpehpshesphhkshdrihhm X-ME-Proxy: Received: from vm-mail.pks.im (dynamic-089-014-045-170.89.14.pool.telefonica.de [89.14.45.170]) by mail.messagingengine.com (Postfix) with ESMTPA id D701D24005D; Mon, 11 Jan 2021 03:37:13 -0500 (EST) Received: from localhost (ncase [10.192.0.11]) by vm-mail.pks.im (OpenSMTPD) with ESMTPSA id c8ad9ca4 (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Mon, 11 Jan 2021 08:37:13 +0000 (UTC) Date: Mon, 11 Jan 2021 09:37:11 +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 v7 7/8] environment: make `getenv_safe()` a public function Message-ID: <6c1800a18f3216541c79fd7809f8f6a6338ae317.1610353895.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 Mon Jan 11 08:37:16 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Steinhardt X-Patchwork-Id: 12010085 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 B16AAC433E6 for ; Mon, 11 Jan 2021 08:39:08 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 72A8622527 for ; Mon, 11 Jan 2021 08:39:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728014AbhAKIiw (ORCPT ); Mon, 11 Jan 2021 03:38:52 -0500 Received: from wout4-smtp.messagingengine.com ([64.147.123.20]:54049 "EHLO wout4-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727899AbhAKIiv (ORCPT ); Mon, 11 Jan 2021 03:38:51 -0500 Received: from compute2.internal (compute2.nyi.internal [10.202.2.42]) by mailout.west.internal (Postfix) with ESMTP id 0FE5024FD; Mon, 11 Jan 2021 03:37:20 -0500 (EST) Received: from mailfrontend1 ([10.202.2.162]) by compute2.internal (MEProxy); Mon, 11 Jan 2021 03:37:20 -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=E4haySKwgRYiuhiLpNBNZVuc2uF yomZjBxhpoNURHeg=; b=xdDsbRdLh+lMjh7dj4j7soV/Fhyp19chF4p1vfXOIBI oSfFS59yFom13YK4sDtMBYb53v6H2vzdLm4BFWiei9YbehzOGko0RmOgZ4VIQ7z0 aHe2UGlAw6GoNJH8EAtSCavC8NUDfUbdBkIyaCMeDAtRSyvQQs278xClVHZD0aUP CcDnUHt4ap/8/z7Qwv06g2DOzuaSdCVz1qtijWDw3zIuANx0AQwF/IowMHKeeGTY 9+2F9A/5xhmqS/APLucOSRSyiWBWy5PlmWk8h/KiP2cZ8bs50PMz15jRX+3cp19f 28d+JO9vWVls4K5IAk/HKtML8H/ahzVqGiPy7veehIw== 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=E4hayS KwgRYiuhiLpNBNZVuc2uFyomZjBxhpoNURHeg=; b=paxm1cHnpyo7RsmLuW3/Cf CY6ey+QoXvkaHFLzFXBMrj9ybwosRjx4uz51mFWCaD7P7eOqOqYmTLSJ1/kOhiFo Ns5HIZZwlUzDNuHasvXbtwd09/GsW7EIBhBnSMcZg9xobNFAvmIDwsHEjDZH0kVr mnj+VN07sfIaKouUnC6fVwJ2XOAvsm5SQ+Y+tZ4mkjkN1jWv2d92XjCGni76P6Kg u9rorjT0d6WWz8safGjhuhNIEQ9Ogj2YYfuzYFFXY85ca7ckhMpaUPU/hvFM7m8a ktXGSZ42svTxEMr1B7XXMFCFrYPnxf96WdYQfAu0ihH5uoDhSH9LnOkctxA+4/iA == X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedujedrvdehtddguddulecutefuodetggdotefrod ftvfcurfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfgh necuuegrihhlohhuthemuceftddtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmd enucfjughrpeffhffvuffkfhggtggujgesghdtreertddtvdenucfhrhhomheprfgrthhr ihgtkhcuufhtvghinhhhrghrughtuceophhssehpkhhsrdhimheqnecuggftrfgrthhtvg hrnhepheeghfdtfeeuffehkefgffduleffjedthfdvjeektdfhhedvlefgtefgvdettdfh necukfhppeekledrudegrdeghedrudejtdenucevlhhushhtvghrufhiiigvpedtnecurf grrhgrmhepmhgrihhlfhhrohhmpehpshesphhkshdrihhm X-ME-Proxy: Received: from vm-mail.pks.im (dynamic-089-014-045-170.89.14.pool.telefonica.de [89.14.45.170]) by mail.messagingengine.com (Postfix) with ESMTPA id 0062F240067; Mon, 11 Jan 2021 03:37:17 -0500 (EST) Received: from localhost (ncase [10.192.0.11]) by vm-mail.pks.im (OpenSMTPD) with ESMTPSA id fcdaf6ba (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Mon, 11 Jan 2021 08:37:17 +0000 (UTC) Date: Mon, 11 Jan 2021 09:37:16 +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 v7 8/8] config: allow specifying config entries via envvar pairs Message-ID: 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 33099a3b0d..2627a05e91 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" @@ -597,23 +598,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 0063e9f059..6ecf2c11a7 100755 --- a/t/t1300-config.sh +++ b/t/t1300-config.sh @@ -1423,6 +1423,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 && @@ -1768,9 +1879,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 '