From patchwork Thu Jan 7 06:36:47 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Steinhardt X-Patchwork-Id: 12003043 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 359D9C43381 for ; Thu, 7 Jan 2021 06:38:07 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id E8AF122E00 for ; Thu, 7 Jan 2021 06:38:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726578AbhAGGh6 (ORCPT ); Thu, 7 Jan 2021 01:37:58 -0500 Received: from out4-smtp.messagingengine.com ([66.111.4.28]:40061 "EHLO out4-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725763AbhAGGh5 (ORCPT ); Thu, 7 Jan 2021 01:37:57 -0500 Received: from compute1.internal (compute1.nyi.internal [10.202.2.41]) by mailout.nyi.internal (Postfix) with ESMTP id A50815C00E2; Thu, 7 Jan 2021 01:36:51 -0500 (EST) Received: from mailfrontend1 ([10.202.2.162]) by compute1.internal (MEProxy); Thu, 07 Jan 2021 01:36:51 -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=NhcY0U38xKkTr7cUtve+a17n1ok jzjChAKiQALYXLhw=; b=wbGCnW7FM3tuszC6/YG95nycbDc94j7fIWNAfEXmuD2 4VaBqjwEeNouYfFy33Ke+e1PGAxjf+4c9gqzuWoO4qweHRV+eLlRhJ9dletyR7bl qlGFbQaIzJXB+OtdFfHNpshBJZDMMshGG71aZc1qNBEZ5gaj2AszBdyEvUEuiXQc BLJn+2SR/MiPaydjEfcOi/GWLxiiMkirohBxZ5auGRNPUhcKBQqEurxXYNmyeBDW UklaVB/qbr74oXVFVrGVSJ82L35OfUpx9KK990Lyd4cZj0Y3NurfChLcGVXT6OGO lRZ4GJ6QT6fm7MvXOaALgzcrXb2sBV+v+OE9KNip6EA== 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=NhcY0U 38xKkTr7cUtve+a17n1okjzjChAKiQALYXLhw=; b=r0DAlH8XUfxSvwZtg5aJvb 9NOXNV/TooeotB6MEQ0qKl3HvjPku1FYoFLBOiCOXNKKY/ffLrz9Pfgy+MdsR7Js NxXILhenuVdv4F+Yed6RPp4vcQKc1Wy228sCY7Ste0Em0HC5g4hUNqAh48lH2xG7 vFCK+bO54hAfPXj+rQSltBnVGz7Cw8hLPuzYblzeZaCA0qClneOdpQoT1ZgneMZ8 KwUUG78M4/A7Z3hvT8lD58W3n1BjLT9aCRH9HYL03Rr57cw8Nqs+ncoJrm5IS5Ys 8esncIEEH6mwlFn9hCzvBQGKNPgUTaJ+Mq8fZEhPHA6JLXNqzW4cpuHU1njTDJ7Q == X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedujedrvdeguddgudejucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhepfffhvffukfhfgggtuggjsehgtderredttddvnecuhfhrohhmpefrrghtrhhi tghkucfuthgvihhnhhgrrhguthcuoehpshesphhkshdrihhmqeenucggtffrrghtthgvrh hnpeehgefhtdefueffheekgfffudelffejtdfhvdejkedthfehvdelgfetgfdvtedthfen ucfkphepjeejrddufedrfeegrddvfedvnecuvehluhhsthgvrhfuihiivgeptdenucfrrg hrrghmpehmrghilhhfrhhomhepphhssehpkhhsrdhimh X-ME-Proxy: Received: from vm-mail.pks.im (dynamic-077-013-034-232.77.13.pool.telefonica.de [77.13.34.232]) by mail.messagingengine.com (Postfix) with ESMTPA id 26972240057; Thu, 7 Jan 2021 01:36:50 -0500 (EST) Received: from localhost (ncase [10.192.0.11]) by vm-mail.pks.im (OpenSMTPD) with ESMTPSA id 3ecd311f (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Thu, 7 Jan 2021 06:36:48 +0000 (UTC) Date: Thu, 7 Jan 2021 07:36:47 +0100 From: Patrick Steinhardt To: git@vger.kernel.org Cc: =?iso-8859-1?q?=C6var_Arnfj=F6r=F0?= Bjarmason , Junio C Hamano , Jeff King , "brian m. carlson" , Philip Oakley Subject: [PATCH v6 1/8] git: add `--super-prefix` to usage string Message-ID: 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 Thu Jan 7 06:36:52 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Steinhardt X-Patchwork-Id: 12003045 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 5236BC4332B for ; Thu, 7 Jan 2021 06:38:07 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 17DD1230FC for ; Thu, 7 Jan 2021 06:38:07 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726608AbhAGGiE (ORCPT ); Thu, 7 Jan 2021 01:38:04 -0500 Received: from out4-smtp.messagingengine.com ([66.111.4.28]:49707 "EHLO out4-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725763AbhAGGiE (ORCPT ); Thu, 7 Jan 2021 01:38:04 -0500 Received: from compute1.internal (compute1.nyi.internal [10.202.2.41]) by mailout.nyi.internal (Postfix) with ESMTP id 191735C00C3; Thu, 7 Jan 2021 01:36:57 -0500 (EST) Received: from mailfrontend1 ([10.202.2.162]) by compute1.internal (MEProxy); Thu, 07 Jan 2021 01:36:57 -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=k1ZdIyCHQOscgcPn2wPJB2WHGIn JiIE+ah/VWynsW9c=; b=EqNV5Bt2D5IRTRbeIfcjtp7VwKeuFSkgPo1htvJpWtt +19WwhWUxTIIAUXIck+sOW03/JS4+EK/oNZCHe3PlUVuvz13q8QBFAjSjStIjJei HhepWXE8pUSlbvOaSje8PvweQFXOlGWQYaFGdZdTwYAs9md5WvGGfdsIqEj7bv5B MvwhmvYv08/Fecbb6pQzpUuB1bK48uyq4zDxSCGNrMd+u5BEeC+AZWzpfvi81YLB jBD9F7OuNQ4ahLaDMtchhCGdvbdZhTIruJDyMDTDPklcaqvfjxEiHqCsrNuapP0K 8KOSyPegIsbkFoEdwp5XCwquXq3aA4g4BeYlXyij43A== 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=k1ZdIy CHQOscgcPn2wPJB2WHGInJiIE+ah/VWynsW9c=; b=SkGS21ttIsLuTT/39vUnCB XFCLMP8i31kfxPIV/Lf9457065XiN8pK8Ae5N5z1RyNCPBZD4B1UL2Y8aOLbFjuO T80Zna53LRNIR7ZYUiolesDCfBZj3k6sPnhZWRNAsuh6ZydNAwvOMHldu8l96vDG cCBUUyPVGk1pOI5DFba8Wy9gm/PAaMGa1wXOcOJcEhYER6AKdb/mYCUb7g5n1lJR dcTN9dNbNf5JqAspSH28HSXqR6WUifAeQazbUNtcigpzs1oUzxe5NMQfcpO98u/Y CmY3m0Y766HY08mdvHs4DRHt2jIrep/rWW44VQvgehu0ImMes6/JFj1p3055MGSg == X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedujedrvdeguddgudejucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhepfffhvffukfhfgggtuggjsehgtderredttddvnecuhfhrohhmpefrrghtrhhi tghkucfuthgvihhnhhgrrhguthcuoehpshesphhkshdrihhmqeenucggtffrrghtthgvrh hnpeehgefhtdefueffheekgfffudelffejtdfhvdejkedthfehvdelgfetgfdvtedthfen ucfkphepjeejrddufedrfeegrddvfedvnecuvehluhhsthgvrhfuihiivgepvdenucfrrg hrrghmpehmrghilhhfrhhomhepphhssehpkhhsrdhimh X-ME-Proxy: Received: from vm-mail.pks.im (dynamic-077-013-034-232.77.13.pool.telefonica.de [77.13.34.232]) by mail.messagingengine.com (Postfix) with ESMTPA id 0DC7A24005B; Thu, 7 Jan 2021 01:36:55 -0500 (EST) Received: from localhost (ncase [10.192.0.11]) by vm-mail.pks.im (OpenSMTPD) with ESMTPSA id 380129f3 (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Thu, 7 Jan 2021 06:36:53 +0000 (UTC) Date: Thu, 7 Jan 2021 07:36:52 +0100 From: Patrick Steinhardt To: git@vger.kernel.org Cc: =?iso-8859-1?q?=C6var_Arnfj=F6r=F0?= Bjarmason , Junio C Hamano , Jeff King , "brian m. carlson" , Philip Oakley Subject: [PATCH v6 2/8] config: add new way to pass config via `--config-env` Message-ID: <9b8461010e641369316d00e2fc58c16e0e191f42.1610001187.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 | 21 ++++++++++++++++++++ config.h | 1 + git.c | 4 +++- t/t1300-config.sh | 45 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 93 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..cde3511110 100644 --- a/config.c +++ b/config.c @@ -345,6 +345,27 @@ 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++; + + env_value = getenv(env_name); + if (!env_value) + die("config variable missing for '%s'", env_name); + + 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..46a94814d5 100755 --- a/t/t1300-config.sh +++ b/t/t1300-config.sh @@ -1316,6 +1316,51 @@ 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=NONEXISTENT config --bool foo.flag 2>error && + test_i18ngrep "config variable missing" 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 Thu Jan 7 06:36:56 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Steinhardt X-Patchwork-Id: 12003047 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 DAF97C433E0 for ; Thu, 7 Jan 2021 06:38:22 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id A844A208A9 for ; Thu, 7 Jan 2021 06:38:22 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726623AbhAGGiF (ORCPT ); Thu, 7 Jan 2021 01:38:05 -0500 Received: from out4-smtp.messagingengine.com ([66.111.4.28]:51153 "EHLO out4-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726581AbhAGGiF (ORCPT ); Thu, 7 Jan 2021 01:38:05 -0500 Received: from compute1.internal (compute1.nyi.internal [10.202.2.41]) by mailout.nyi.internal (Postfix) with ESMTP id 1C85A5C0160; Thu, 7 Jan 2021 01:36:59 -0500 (EST) Received: from mailfrontend1 ([10.202.2.162]) by compute1.internal (MEProxy); Thu, 07 Jan 2021 01:36:59 -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=acycrAqaDWKRJUGa4bI/EvvKSUo OGk7AnHY+BQHj2Cg=; b=OqYc9S1kZ6cHdAnaqF/HZYHrQnbT5FQcm8JPTH6ioxy MsZ0EPy9t2B63zQwzA9XQ3Moz5Nk+Z8Z5RkdYnR5LEmts2iri0d4rTcYjY9pYC1g MtRWDFHG/Rnml7tMASfeIJO2iVrpNkntJLv1N6zOCsaoGbsF8yuN4JcHh22eh+EH PK2gyPUNe2LBnrC/8obN6O7IUApM02Xnj6bHz/0sXvv0SGjoBuKNEQNLRARFZwDP okWKdYrbssKfI7KxVeuIbzhSujqKQ778VrX7I8UzOAxPZSFm0IZU9R9raQ2hLbyM fsvRYWMokQ0GjI31a9ZmmRwJDDXVUL1EXWtdkrxyM4w== 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=acycrA qaDWKRJUGa4bI/EvvKSUoOGk7AnHY+BQHj2Cg=; b=Z0kFgOMYpEapU/4oVuHBCw p4p7mLJYc2vckH26zJ4OKBn4cStp/eBOHuoioJYSKPescZjnE/LSI4t7ed1VL69s wW2/lLcTYw30n0aPu1DMtUj+wA2Fa9tc7DXAB2xeAFQyp/v7bn569ur/5pn2mgL2 wxLy6Wi1w7qr5mQJIM59XSacjuESdzKnTX98iDwXnAAzTbD9U//MM9tovj3BO0mm 4lFVMRLMrLT7yzm8kmuiD2W4w56xm/pRS7nqxPVEGALHhPtI4Dq+cK4vy25rDjzM 9tHKsQarcO/BKM8ynvgqC0uhQa2OsQ1qQUKXkSh/aBXNGYCbyYGQqLLtTsdClmmA == X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedujedrvdeguddgudejucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhepfffhvffukfhfgggtuggjsehgtderredttddvnecuhfhrohhmpefrrghtrhhi tghkucfuthgvihhnhhgrrhguthcuoehpshesphhkshdrihhmqeenucggtffrrghtthgvrh hnpeehgefhtdefueffheekgfffudelffejtdfhvdejkedthfehvdelgfetgfdvtedthfen ucfkphepjeejrddufedrfeegrddvfedvnecuvehluhhsthgvrhfuihiivgepfeenucfrrg hrrghmpehmrghilhhfrhhomhepphhssehpkhhsrdhimh X-ME-Proxy: Received: from vm-mail.pks.im (dynamic-077-013-034-232.77.13.pool.telefonica.de [77.13.34.232]) by mail.messagingengine.com (Postfix) with ESMTPA id 2965D24005B; Thu, 7 Jan 2021 01:36:58 -0500 (EST) Received: from localhost (ncase [10.192.0.11]) by vm-mail.pks.im (OpenSMTPD) with ESMTPSA id 5a3b1efd (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Thu, 7 Jan 2021 06:36:57 +0000 (UTC) Date: Thu, 7 Jan 2021 07:36:56 +0100 From: Patrick Steinhardt To: git@vger.kernel.org Cc: =?iso-8859-1?q?=C6var_Arnfj=F6r=F0?= Bjarmason , Junio C Hamano , Jeff King , "brian m. carlson" , Philip Oakley Subject: [PATCH v6 3/8] quote: make sq_dequote_step() a public function Message-ID: <9d4c8d7be9e8d358c7b342760034fa90676ed524.1610001187.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 Thu Jan 7 06:37:05 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Steinhardt X-Patchwork-Id: 12003049 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 BD0C9C433E0 for ; Thu, 7 Jan 2021 06:39:04 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 9540C22E00 for ; Thu, 7 Jan 2021 06:39:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726742AbhAGGif (ORCPT ); Thu, 7 Jan 2021 01:38:35 -0500 Received: from out4-smtp.messagingengine.com ([66.111.4.28]:59889 "EHLO out4-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726712AbhAGGif (ORCPT ); Thu, 7 Jan 2021 01:38:35 -0500 Received: from compute1.internal (compute1.nyi.internal [10.202.2.41]) by mailout.nyi.internal (Postfix) with ESMTP id 30BFE5C016D; Thu, 7 Jan 2021 01:37:08 -0500 (EST) Received: from mailfrontend1 ([10.202.2.162]) by compute1.internal (MEProxy); Thu, 07 Jan 2021 01:37:08 -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=+4Zzw0UC/dA6L9NOf7gcYXgDKls 7InH65dKhn3xqsKA=; b=t0POToXRKz4syf4GLx5D0EUKxt++Jb4I1URTFC02rTR x07E+O9mFenKhXbkNoLLpPokqSoF//7wDyMQDrVymRTt+2473+XeqhCdNUGQf7VZ BfopIbbC90qm6d4rEwLAWWdyqlbIs36aVrxqkt2lCScaDgEu6oTCwlIdzgfl0DBW oH6b8FZHRbofrIvdJnD8jetyrTKZ5ELCP4YkKGPmGS3yxvzv1A044zpMWGpAAJt/ m+4lVdDJ2B/BVj3hKTe/KXyYTj2jlOkupJQP1H8w7Y2mXTWWbAzxc0+cOAnzEphZ lrQMekZOYy+O3hu7oPa1IK/JBKua96eQh6SnawZnZnw== 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=+4Zzw0 UC/dA6L9NOf7gcYXgDKls7InH65dKhn3xqsKA=; b=L8zLn4YmkHn10N0BVGi6Gk kd1XDxB4IY/z9npTGoNdHrqQBfIdPUI7s4Q0xV/9woepNEIPtp3zc934WZhy3mHV dHRf4M1+B8xQCfKq0OeKwkI/POUncpDPdUiGIYhsHIIzEn/YCAO/6blgicI9q61+ tuFS6oZKHNxH30uJ3yNOsu16QOOmcEl9KMG4EqqFm2DwLmyyzHwr9B6qWu+jazgX nIsGRQzA6+gLcJiThkCcYily4U/gzvQDFvF8rdXTGCQkQcsmmRjMAztpFU6+iWlR fe74F1G+PqDNCNk0gzdtESqGqZRTP162pPTJa3MHz0f7dN45o7S9vtMravU0BcqA == X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedujedrvdeguddgudejucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhepfffhvffukfhfgggtuggjsehgtderredttddvnecuhfhrohhmpefrrghtrhhi tghkucfuthgvihhnhhgrrhguthcuoehpshesphhkshdrihhmqeenucggtffrrghtthgvrh hnpeehgefhtdefueffheekgfffudelffejtdfhvdejkedthfehvdelgfetgfdvtedthfen ucfkphepjeejrddufedrfeegrddvfedvnecuvehluhhsthgvrhfuihiivgepgeenucfrrg hrrghmpehmrghilhhfrhhomhepphhssehpkhhsrdhimh X-ME-Proxy: Received: from vm-mail.pks.im (dynamic-077-013-034-232.77.13.pool.telefonica.de [77.13.34.232]) by mail.messagingengine.com (Postfix) with ESMTPA id 3E8CE24005E; Thu, 7 Jan 2021 01:37:07 -0500 (EST) Received: from localhost (ncase [10.192.0.11]) by vm-mail.pks.im (OpenSMTPD) with ESMTPSA id a2280c3c (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Thu, 7 Jan 2021 06:37:06 +0000 (UTC) Date: Thu, 7 Jan 2021 07:37:05 +0100 From: Patrick Steinhardt To: git@vger.kernel.org Cc: =?iso-8859-1?q?=C6var_Arnfj=F6r=F0?= Bjarmason , Junio C Hamano , Jeff King , "brian m. carlson" , Philip Oakley Subject: [PATCH v6 5/8] config: store "git -c" variables using more robust format 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 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 151980e5c9..53ed048689 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,30 +340,68 @@ 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++; env_value = getenv(env_name); if (!env_value) die("config variable missing for '%s'", env_name); - 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 46a94814d5..36a60879f6 100755 --- a/t/t1300-config.sh +++ b/t/t1300-config.sh @@ -1361,6 +1361,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 Thu Jan 7 06:37: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: 12003051 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 A5931C433DB for ; Thu, 7 Jan 2021 06:39:04 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 74E4422D71 for ; Thu, 7 Jan 2021 06:39:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726731AbhAGGia (ORCPT ); Thu, 7 Jan 2021 01:38:30 -0500 Received: from out4-smtp.messagingengine.com ([66.111.4.28]:37085 "EHLO out4-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726712AbhAGGia (ORCPT ); Thu, 7 Jan 2021 01:38:30 -0500 Received: from compute1.internal (compute1.nyi.internal [10.202.2.41]) by mailout.nyi.internal (Postfix) with ESMTP id 395285C0163; Thu, 7 Jan 2021 01:37:13 -0500 (EST) Received: from mailfrontend1 ([10.202.2.162]) by compute1.internal (MEProxy); Thu, 07 Jan 2021 01:37:13 -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=y/+sWOf+wYwj+cOQ3h+b/kngs62 nC5tNfMvarA9Le+Y=; b=hxtdH8MvyJiYSlr3FGJZE2ehditdWpll7f2BM7y4wEX Dn2XDYUPgE2V4FN3BQJK/kIvttBEti1pMa8GSkOsIknfxywDUbRv2f1LnLZ8RswE feD4HQyzjmBZOCE4ghd2SJkjVUZ5kxpRRge4xdLy6PEZd5U6PO8DoHLYDADlRhdk aKmGm2kqbHG3Z0SJCBd3YYPjpa5UxWs4GLKpufO//HBH5AvZCwSEgy2bRdTHzH32 GuF9za92TyIyjyiyZEJH1Zew4DuVVcdv2so8vdsW/PcMKPteWoSGnjhwS1/Vmzkp h9SkN6qlwhHPPfKptWILmSCacZ84/p8VBrNWgb1J0+Q== 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=y/+sWO f+wYwj+cOQ3h+b/kngs62nC5tNfMvarA9Le+Y=; b=ICkLIA5mHl65yX8p1C+F8/ xeSgEkRNVbAX0c1YF0bPjNVna2bC2/2pxfJioXAgdBtjRUXwa/7e7fIYRB0aW6j+ XgsIwQhoUb8JCfQl6MiI563n2CUnYe9gWoXGoC2P31VBjAGAmZMV2vuXtfmaTPLZ 804ZxMnttvxET2DNoUdkkdAKGxlja5+JZu6yhVnjnokn6K7ND3XjS2al6fiHavWy qWCl6Z3YjeVD24tuS0nvy9VtoGGIL5HGo2m+En28RGVSamJ8c7CCa/Rv+HxZflz4 l2PJAew/11sK90hLP0wJ7BoLIHzARA82NKk56CK+E14Y9LLccn2uLkMYU1F+rHvw == X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedujedrvdeguddgudejucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhepfffhvffukfhfgggtuggjsehgtderredttddvnecuhfhrohhmpefrrghtrhhi tghkucfuthgvihhnhhgrrhguthcuoehpshesphhkshdrihhmqeenucggtffrrghtthgvrh hnpeehgefhtdefueffheekgfffudelffejtdfhvdejkedthfehvdelgfetgfdvtedthfen ucfkphepjeejrddufedrfeegrddvfedvnecuvehluhhsthgvrhfuihiivgepieenucfrrg hrrghmpehmrghilhhfrhhomhepphhssehpkhhsrdhimh X-ME-Proxy: Received: from vm-mail.pks.im (dynamic-077-013-034-232.77.13.pool.telefonica.de [77.13.34.232]) by mail.messagingengine.com (Postfix) with ESMTPA id 490E9240057; Thu, 7 Jan 2021 01:37:12 -0500 (EST) Received: from localhost (ncase [10.192.0.11]) by vm-mail.pks.im (OpenSMTPD) with ESMTPSA id 6f004ab2 (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Thu, 7 Jan 2021 06:37:11 +0000 (UTC) Date: Thu, 7 Jan 2021 07:37:10 +0100 From: Patrick Steinhardt To: git@vger.kernel.org Cc: =?iso-8859-1?q?=C6var_Arnfj=F6r=F0?= Bjarmason , Junio C Hamano , Jeff King , "brian m. carlson" , Philip Oakley Subject: [PATCH v6 6/8] config: parse more robust format in GIT_CONFIG_PARAMETERS Message-ID: <6597700ffbb338feb3d82e6baca2591c4e403a24.1610001187.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 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 53ed048689..60a7261807 100644 --- a/config.c +++ b/config.c @@ -541,14 +541,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) @@ -561,21 +609,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 36a60879f6..35a1a6e8b1 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 Thu Jan 7 06:37: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: 12003053 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 E62E0C433E9 for ; Thu, 7 Jan 2021 06:39:04 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id C468622E03 for ; Thu, 7 Jan 2021 06:39:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726769AbhAGGih (ORCPT ); Thu, 7 Jan 2021 01:38:37 -0500 Received: from out4-smtp.messagingengine.com ([66.111.4.28]:57561 "EHLO out4-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726712AbhAGGig (ORCPT ); Thu, 7 Jan 2021 01:38:36 -0500 Received: from compute1.internal (compute1.nyi.internal [10.202.2.41]) by mailout.nyi.internal (Postfix) with ESMTP id 4662C5C0174; Thu, 7 Jan 2021 01:37:17 -0500 (EST) Received: from mailfrontend1 ([10.202.2.162]) by compute1.internal (MEProxy); Thu, 07 Jan 2021 01:37:17 -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=RZTxXbhaK4gCsG7tzYUxxdlUHj4 CtFOBipNoLebr//c=; b=L3Uyd/p4OiqgaZmA4BUGiKeV9t20KLVN1rlCxcr7v/G rnaQyE4hu5dI4E2AcIKWJVDWmEigdkOWtlRx0+L6yprsMHkdRE6zbul3GcT1bdYY /0Lk2jrD2+ZhX650ZqOqAehH8N1adRQJlVIwm4+ozzbzgQWIdk2YmU/d4Vcx+Kig TZmhxgb8ZIqGJehMkyAKG3xL16SrNe3EIkQJVJtM4Z/ZaRbf+hVvbOgZluGpjBoV /5D/f2d4pomMBALoMVpsO/JSLMxPww565HXCtSuzHjPPEgRFCEup3npE1E+EN5qV RiKcyKh48p4oPal62u17x2m8ssr9NKWU46p+honkBmA== 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=RZTxXb haK4gCsG7tzYUxxdlUHj4CtFOBipNoLebr//c=; b=RobJ2m18CX4oCGw6jSKw4R pdn0z1iWopXKTJBPQmESFy7MdUPgcyjySYCQBSkWMMOtanWN2zUrypLKv4bjxWUw /c7WRa6gE+Bx7Xzjpf16tYGaFhWl/SiEHFF+f5SXDFNwDrqjNIK2ITJAjBpFzbS1 hwuySs9HwVk+rsAc1jzcvkPBUc/wUJBjNZvMECn8AA/zOYdA4uKY2thFSTP/bsMr Tf+2R+qDjkaFM6LgaLLRjlX681esm2Sdhz7Za4AD1i7apOS9GJQwYzNppZ8COkz4 f+7plq4RUgbYOlbb+dVChbGDxMrNPNEWDDeh11+iOz2KC45PzmAmpNj8JBVDW/vA == X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedujedrvdeguddgudejucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhepfffhvffukfhfgggtuggjsehgtderredttddvnecuhfhrohhmpefrrghtrhhi tghkucfuthgvihhnhhgrrhguthcuoehpshesphhkshdrihhmqeenucggtffrrghtthgvrh hnpeehgefhtdefueffheekgfffudelffejtdfhvdejkedthfehvdelgfetgfdvtedthfen ucfkphepjeejrddufedrfeegrddvfedvnecuvehluhhsthgvrhfuihiivgepjeenucfrrg hrrghmpehmrghilhhfrhhomhepphhssehpkhhsrdhimh X-ME-Proxy: Received: from vm-mail.pks.im (dynamic-077-013-034-232.77.13.pool.telefonica.de [77.13.34.232]) by mail.messagingengine.com (Postfix) with ESMTPA id 5332624005A; Thu, 7 Jan 2021 01:37:16 -0500 (EST) Received: from localhost (ncase [10.192.0.11]) by vm-mail.pks.im (OpenSMTPD) with ESMTPSA id 184fa0ab (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Thu, 7 Jan 2021 06:37:15 +0000 (UTC) Date: Thu, 7 Jan 2021 07:37:14 +0100 From: Patrick Steinhardt To: git@vger.kernel.org Cc: =?iso-8859-1?q?=C6var_Arnfj=F6r=F0?= Bjarmason , Junio C Hamano , Jeff King , "brian m. carlson" , Philip Oakley Subject: [PATCH v6 7/8] environment: make `getenv_safe()` a public function 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 `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 Thu Jan 7 06:37:19 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Steinhardt X-Patchwork-Id: 12003055 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 D1784C433E6 for ; Thu, 7 Jan 2021 06:39:04 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id AEE9722D71 for ; Thu, 7 Jan 2021 06:39:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726773AbhAGGih (ORCPT ); Thu, 7 Jan 2021 01:38:37 -0500 Received: from out4-smtp.messagingengine.com ([66.111.4.28]:36053 "EHLO out4-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726751AbhAGGig (ORCPT ); Thu, 7 Jan 2021 01:38:36 -0500 Received: from compute1.internal (compute1.nyi.internal [10.202.2.41]) by mailout.nyi.internal (Postfix) with ESMTP id 4E7B65C0178; Thu, 7 Jan 2021 01:37:22 -0500 (EST) Received: from mailfrontend1 ([10.202.2.162]) by compute1.internal (MEProxy); Thu, 07 Jan 2021 01:37:22 -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=yMfAJEY4BI+MuXS2tzJNgOCaS0W tIFbpXx9uTIv/M/4=; b=yMYEnT+jy7wg2FEnSOl4yiKJxQGd0dUFEd5Umg0CSnv QZ51KTJP/1Ft4feRTallHfbbF3i9jtkN0cnalGN626RxAiGG+ZLw+0mkozTBF9lj caYo2dXyxZ1sdTYmgxjL1eiNTBVl/0KvrRAK5vDVdyFW3IOSy5NF/rBvLA+RrYnz /m5VrqK0UTMFsKWFFo6zUX/IxDUT7jNypTJhjuYBm5YnOHJBo3fXWYrWcaC0Lxxu sykXksjoiPn/8PYKU8Nyfg3QiwBXdzKUBN4RMDAldaZZTVcLQvleMLmOat0ZP+Lg AfvhvJDKLpPh6OWWkXTTYowd5/zMRy5yIa71J2eZkyA== 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=yMfAJE Y4BI+MuXS2tzJNgOCaS0WtIFbpXx9uTIv/M/4=; b=mUUlRthwWyv3q7nrGOicOQ P5EdEBGJtFCMqLf5RHYf1KCD5VnDI1rBEdCsuUrsTsSujqEFN8DNgYJ2EDXQPyWq CfTQfMX2DUahWwbkO0/+tnYJjI+0HnkQ2kEt6MzB5rf2UOF5pdBG9+NtfCDStO8B ScF981aBefNF4ocuUhtLpdB5csV4RYuzVSbufhF02ITdiuWyZFfYoA+y7haxIw3w h/t6xJKtxI919NLmCcpnyy0CFNifJ9xQjEQcgYhg3O/TQQTCjbLeIOxwjWLLXB6S LUjh4aPFZ21mBAKkpAoDAXewyfOdOW84x7UYSA6SpRq7BoeROwnNM10Rfp8/0SwQ == X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedujedrvdeguddgudejucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhepfffhvffukfhfgggtuggjsehgtderredttddvnecuhfhrohhmpefrrghtrhhi tghkucfuthgvihhnhhgrrhguthcuoehpshesphhkshdrihhmqeenucggtffrrghtthgvrh hnpeehgefhtdefueffheekgfffudelffejtdfhvdejkedthfehvdelgfetgfdvtedthfen ucfkphepjeejrddufedrfeegrddvfedvnecuvehluhhsthgvrhfuihiivgepkeenucfrrg hrrghmpehmrghilhhfrhhomhepphhssehpkhhsrdhimh X-ME-Proxy: Received: from vm-mail.pks.im (dynamic-077-013-034-232.77.13.pool.telefonica.de [77.13.34.232]) by mail.messagingengine.com (Postfix) with ESMTPA id 5E1D624005C; Thu, 7 Jan 2021 01:37:21 -0500 (EST) Received: from localhost (ncase [10.192.0.11]) by vm-mail.pks.im (OpenSMTPD) with ESMTPSA id 71d45a58 (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Thu, 7 Jan 2021 06:37:20 +0000 (UTC) Date: Thu, 7 Jan 2021 07:37:19 +0100 From: Patrick Steinhardt To: git@vger.kernel.org Cc: =?iso-8859-1?q?=C6var_Arnfj=F6r=F0?= Bjarmason , Junio C Hamano , Jeff King , "brian m. carlson" , Philip Oakley Subject: [PATCH v6 8/8] config: allow specifying config entries via envvar pairs Message-ID: <4e3f208d1358193f253128dde747b235359edaa5.1610001187.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 60a7261807..1742aefa3e 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" @@ -594,23 +595,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 35a1a6e8b1..e06961767f 100755 --- a/t/t1300-config.sh +++ b/t/t1300-config.sh @@ -1421,6 +1421,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 && @@ -1766,9 +1877,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 '