From patchwork Fri May 3 09:57:28 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Steinhardt X-Patchwork-Id: 13652606 Received: from wfhigh8-smtp.messagingengine.com (wfhigh8-smtp.messagingengine.com [64.147.123.159]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 05BB114F9E8 for ; Fri, 3 May 2024 09:57:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=64.147.123.159 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714730255; cv=none; b=VQND0xxenSvcCzxiQkZiMfDoT/tAL4Lca39AslO4zGCFr4jnQCbkCp3zZRtWveIdJT7lRbdCqf3KYrMpjROpFZl+oJqQxM8f2ufVout2kagTm035VH0D/z8AmeFk4u675rbN3RfKY8m02Q8pY2DRU4+AxQg/+N7Yqb33ma96HC0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714730255; c=relaxed/simple; bh=nLCkhMJbNoWei2FmQkfXCT88aarilPULTdtgRMNGqUk=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=eURTjZ8FBrBRHzWF3yAVWDROca89k/GjnZ2SWdYuIiuRDcYY9Mp7Np1OAX4gh7fvwN+KlHdmA+3l4ehfILLFUr4jyQbU0EdYotZx6Wymk3Pvd8BTEykZ0/ncIAPXUSDlAhOKiIRBGnd7RhR15QPhSKgyMQGJWV0Neep/GF5V2G4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=pks.im; spf=pass smtp.mailfrom=pks.im; dkim=pass (2048-bit key) header.d=pks.im header.i=@pks.im header.b=VbP9hlmL; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=Rw6Zg1jF; arc=none smtp.client-ip=64.147.123.159 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=pks.im Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=pks.im Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=pks.im header.i=@pks.im header.b="VbP9hlmL"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="Rw6Zg1jF" Received: from compute2.internal (compute2.nyi.internal [10.202.2.46]) by mailfhigh.west.internal (Postfix) with ESMTP id 2D3FC18000BE; Fri, 3 May 2024 05:57:33 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute2.internal (MEProxy); Fri, 03 May 2024 05:57:33 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=pks.im; h=cc:cc :content-type:content-type:date:date:from:from:in-reply-to :in-reply-to:message-id:mime-version:references:reply-to:subject :subject:to:to; s=fm3; t=1714730252; x=1714816652; bh=emLlLS5utG k2MJmk1Dizkq2AO9RDtQCFv2Bn8wiziM8=; b=VbP9hlmLQihypoo6TPEnddISL9 E4ApAF7qpCPs0CFUnsnpbCGwiIFk9xamKdZomjCFs9pcW1WB3AYootJ+dCVgEZZt 6p8r6OYVvqIliGD6PfwXQHzZBj/pAiGUAk2+zOU5LG0Qt4KaiHvDGidqPkH5FovQ oR8ORYtZYgbfVOydvrP9+LBHQqEvxgpVSgU8OJME7A8xySm75waslxh4QpaNKaY8 c5A5KjtEcImNyRcZB/QoY58cLYGVj65exB0YJ5xFbwBGrQdJiG8T+DSO7r8JafFt TNoN9yLjVsPuk4uvHgkhIaR+58Z+DX+D+9zdt9P8Zs+SOREYYYYsbyXjHAYA== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-type:content-type:date:date :feedback-id:feedback-id:from:from:in-reply-to:in-reply-to :message-id:mime-version:references:reply-to:subject:subject:to :to:x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm3; t=1714730252; x=1714816652; bh=emLlLS5utGk2MJmk1Dizkq2AO9RD tQCFv2Bn8wiziM8=; b=Rw6Zg1jFGGzuHN1T6ayXz8E7kVP6nYp6TqDHcOoP+/5c nHWr8ZkqprOU/m1OWdZj97KpY5jecztXVZ4NEByvuROPod8Y3tjlQgzlnSXXiL8f rQaGFnC26IK06G6Cqhto5eHRmiAJRRe+VoqrhIAXuX9lb4hrjevY3ZStFWVCWdFp O3Ty2WfiBv+vTNb3znewihwUaQr43YpIuaEupBYa38LHOnhaVsYOLAyFzXr4Bs1Y YKPk/aIByYR0I4I8B9oZaXxWQU2i7HpZ4NC4YZVos7/LzrNdarLSpWaofLs4gSLc w99k2CEDNWKxNCF6OfoiFGfTdvxO88Lnql8PESK8zQ== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvledrvddvtddgvddtucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhepfffhvfevuffkfhggtggujgesghdtreertddtvdenucfhrhhomheprfgrthhr ihgtkhcuufhtvghinhhhrghrughtuceophhssehpkhhsrdhimheqnecuggftrfgrthhtvg hrnhepieevkedtgffgleeugfdvledvfedthfegueegfeevjeelueefkeegfeffhefglefg necuffhomhgrihhnpehkvghrnhgvlhdrohhrghenucevlhhushhtvghrufhiiigvpedtne curfgrrhgrmhepmhgrihhlfhhrohhmpehpshesphhkshdrihhm X-ME-Proxy: Feedback-ID: i197146af:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Fri, 3 May 2024 05:57:31 -0400 (EDT) Received: by localhost (OpenSMTPD) with ESMTPSA id eabfe0d9 (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Fri, 3 May 2024 09:57:03 +0000 (UTC) Date: Fri, 3 May 2024 11:57:28 +0200 From: Patrick Steinhardt To: git@vger.kernel.org Cc: Kristoffer Haugsbakk , Taylor Blau , =?iso-8859-1?q?Jean-No=EBl?= AVILA , Eric Sunshine , Junio C Hamano Subject: [PATCH v4 10/14] builtin/config: introduce "unset" subcommand Message-ID: References: Precedence: bulk X-Mailing-List: git@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: Introduce a new "unset" subcommand to git-config(1). Please refer to preceding commits regarding the motivation behind this change. Signed-off-by: Patrick Steinhardt --- Documentation/git-config.txt | 27 +++++++++++++--------- builtin/config.c | 39 ++++++++++++++++++++++++++++++++ t/t1300-config.sh | 44 ++++++++++++++++++++++++------------ 3 files changed, 84 insertions(+), 26 deletions(-) diff --git a/Documentation/git-config.txt b/Documentation/git-config.txt index f57fa01085..5575fe55ea 100644 --- a/Documentation/git-config.txt +++ b/Documentation/git-config.txt @@ -11,9 +11,8 @@ SYNOPSIS [verse] 'git config list' [] [] [--includes] 'git config get' [] [] [--includes] [--all] [--regexp=] [--value=] [--fixed-value] [--default=] -'git config set' [] [--type=] [--comment=] [--all] [--value=] [--fixed-value] -'git config' [] [--fixed-value] --unset [] -'git config' [] [--fixed-value] --unset-all [] +'git config set' [] [--type=] [--all] [--value=] [--fixed-value] +'git config unset' [] [--all] [--value=] [--fixed-value] 'git config' [] --rename-section 'git config' [] --remove-section 'git config' [] --get-colorbool [] @@ -87,6 +86,12 @@ set:: `--value=` will replace all config options whose values match the given pattern. +unset:: + Unset value for one or more config options. By default, this command + refuses to unset multi-valued keys. Passing `--all` will unset all + multi-valued config options, whereas `--value` will unset all config + options whose values match the given pattern. + [[OPTIONS]] OPTIONS ------- @@ -190,12 +195,6 @@ See also <>. --rename-section:: Rename the given section to a new name. ---unset:: - Remove the line matching the key from config file. - ---unset-all:: - Remove all lines matching the key from config file. - --fixed-value:: When used with the `value-pattern` argument, treat `value-pattern` as an exact string instead of a regular expression. This will restrict @@ -325,6 +324,12 @@ recommended to migrate to the new syntax. --add :: Replaced by `git config set --append `. +--unset []:: + Replaced by `git config unset [--value=] `. + +--unset-all []:: + Replaced by `git config unset [--value=] --all `. + CONFIGURATION ------------- `pager.config` is only respected when listing configuration, i.e., when @@ -372,7 +377,7 @@ values of a key from all files will be used. By default, options are only written to the repository specific configuration file. Note that this also affects options like `set` -and `--unset`. *'git config' will only ever change one file at a time*. +and `unset`. *'git config' will only ever change one file at a time*. You can limit which configuration sources are read from or written to by specifying the path of a file with the `--file` option, or by specifying a @@ -523,7 +528,7 @@ This makes sure that only the key/value pair for kernel.org is replaced. To delete the entry for renames, do ------------ -% git config --unset diff.renames +% git config unset diff.renames ------------ If you want to delete an entry for a multivar (like core.gitproxy above), diff --git a/builtin/config.c b/builtin/config.c index 87fd12fda2..2578d4c930 100644 --- a/builtin/config.c +++ b/builtin/config.c @@ -19,6 +19,7 @@ static const char *const builtin_config_usage[] = { N_("git config list [] [] [--includes]"), N_("git config get [] [] [--includes] [--all] [--regexp=] [--value=] [--fixed-value] [--default=] "), N_("git config set [] [--type=] [--all] [--value=] [--fixed-value] "), + N_("git config unset [] [--all] [--value=] [--fixed-value] "), NULL }; @@ -37,6 +38,11 @@ static const char *const builtin_config_set_usage[] = { NULL }; +static const char *const builtin_config_unset_usage[] = { + N_("git config unset [] [--all] [--value=] [--fixed-value] "), + NULL +}; + static char *key; static regex_t *key_regexp; static const char *value_pattern; @@ -911,10 +917,43 @@ static int cmd_config_set(int argc, const char **argv, const char *prefix) return ret; } +static int cmd_config_unset(int argc, const char **argv, const char *prefix) +{ + const char *value_pattern = NULL; + int flags = 0; + struct option opts[] = { + CONFIG_LOCATION_OPTIONS, + OPT_GROUP(N_("Filter")), + OPT_BIT(0, "all", &flags, N_("replace multi-valued config option with new value"), CONFIG_FLAGS_MULTI_REPLACE), + OPT_STRING(0, "value", &value_pattern, N_("pattern"), N_("show config with values matching the pattern")), + OPT_BIT(0, "fixed-value", &flags, N_("use string equality when comparing values to value pattern"), CONFIG_FLAGS_FIXED_VALUE), + OPT_END(), + }; + + argc = parse_options(argc, argv, prefix, opts, builtin_config_unset_usage, + PARSE_OPT_STOP_AT_NON_OPTION); + check_write(); + check_argc(argc, 1, 1); + + if ((flags & CONFIG_FLAGS_FIXED_VALUE) && !value_pattern) + die(_("--fixed-value only applies with 'value-pattern'")); + + handle_config_location(prefix); + + if ((flags & CONFIG_FLAGS_MULTI_REPLACE) || value_pattern) + return git_config_set_multivar_in_file_gently(given_config_source.file, + argv[0], NULL, value_pattern, + NULL, flags); + else + return git_config_set_in_file_gently(given_config_source.file, argv[0], + NULL, NULL); +} + static struct option builtin_subcommand_options[] = { OPT_SUBCOMMAND("list", &subcommand, cmd_config_list), OPT_SUBCOMMAND("get", &subcommand, cmd_config_get), OPT_SUBCOMMAND("set", &subcommand, cmd_config_set), + OPT_SUBCOMMAND("unset", &subcommand, cmd_config_unset), OPT_END(), }; diff --git a/t/t1300-config.sh b/t/t1300-config.sh index aa3f179be5..2ab58bbd95 100755 --- a/t/t1300-config.sh +++ b/t/t1300-config.sh @@ -22,6 +22,8 @@ legacy) mode_get_regexp="--get-regexp" mode_set="" mode_replace_all="--replace-all" + mode_unset="--unset" + mode_unset_all="--unset-all" ;; subcommands) mode_prefix="" @@ -30,6 +32,8 @@ subcommands) mode_get_regexp="get --regexp --all --show-names" mode_set="set" mode_replace_all="set --all" + mode_unset="unset" + mode_unset_all="unset --all" ;; *) BUG "unknown mode $mode";; @@ -259,7 +263,7 @@ foo = bar EOF test_expect_success 'unset with cont. lines' ' - git config --unset beta.baz + git config ${mode_unset} beta.baz ' cat > expect <<\EOF @@ -286,7 +290,7 @@ EOF cp .git/config .git/config2 test_expect_success 'multiple unset' ' - git config --unset-all beta.haha + git config ${mode_unset_all} beta.haha ' cat > expect << EOF @@ -372,7 +376,7 @@ noIndent= sillyValue ; 'nother silly comment nonewline = wow EOF test_expect_success 'unset' ' - git config --unset beta.haha && + git config ${mode_unset} beta.haha && test_cmp expect .git/config ' @@ -428,11 +432,11 @@ test_expect_success 'multivar replace' ' ' test_expect_success 'ambiguous unset' ' - test_must_fail git config --unset nextsection.nonewline + test_must_fail git config ${mode_unset} nextsection.nonewline ' test_expect_success 'invalid unset' ' - test_must_fail git config --unset somesection.nonewline + test_must_fail git config ${mode_unset} somesection.nonewline ' cat > expect << EOF @@ -446,7 +450,12 @@ noIndent= sillyValue ; 'nother silly comment EOF test_expect_success 'multivar unset' ' - git config --unset nextsection.nonewline "wow3$" && + case "$mode" in + legacy) + git config --unset nextsection.nonewline "wow3$";; + subcommands) + git config unset --value="wow3$" nextsection.nonewline;; + esac && test_cmp expect .git/config ' @@ -2013,7 +2022,7 @@ test_expect_success '--unset last key removes section (except if commented)' ' # please be careful when you update the above variable EOF - git config --unset section.key && + git config ${mode_unset} section.key && test_cmp expect .git/config && cat >.git/config <<-\EOF && @@ -2026,7 +2035,7 @@ test_expect_success '--unset last key removes section (except if commented)' ' [next-section] EOF - git config --unset section.key && + git config ${mode_unset} section.key && test_cmp expect .git/config && q_to_tab >.git/config <<-\EOF && @@ -2036,7 +2045,7 @@ test_expect_success '--unset last key removes section (except if commented)' ' [two] key = true EOF - git config --unset two.key && + git config ${mode_unset} two.key && ! grep two .git/config && q_to_tab >.git/config <<-\EOF && @@ -2046,7 +2055,7 @@ test_expect_success '--unset last key removes section (except if commented)' ' [one] key = true EOF - git config --unset-all one.key && + git config ${mode_unset_all} one.key && test_line_count = 0 .git/config && q_to_tab >.git/config <<-\EOF && @@ -2056,7 +2065,7 @@ test_expect_success '--unset last key removes section (except if commented)' ' [two] Qkey = true EOF - git config --unset two.key && + git config ${mode_unset} two.key && grep two .git/config && q_to_tab >.git/config <<-\EOF && @@ -2068,7 +2077,7 @@ test_expect_success '--unset last key removes section (except if commented)' ' [TWO "subsection"] [one] EOF - git config --unset two.subsection.key && + git config ${mode_unset} two.subsection.key && test "not [two subsection]" = "$(git config ${mode_get} one.key)" && test_line_count = 3 .git/config ' @@ -2080,7 +2089,7 @@ test_expect_success '--unset-all removes section if empty & uncommented' ' key = value2 EOF - git config --unset-all section.key && + git config ${mode_unset_all} section.key && test_line_count = 0 .git/config ' @@ -2604,8 +2613,8 @@ test_expect_success 'refuse --fixed-value for incompatible actions' ' test_must_fail git config ${mode_prefix}get --file=config --fixed-value dev.null && test_must_fail git config ${mode_get_all} --file=config --fixed-value dev.null && test_must_fail git config ${mode_get_regexp} --file=config --fixed-value "dev.*" && - test_must_fail git config --file=config --fixed-value --unset dev.null && - test_must_fail git config --file=config --fixed-value --unset-all dev.null + test_must_fail git config ${mode_unset} --file=config --fixed-value dev.null && + test_must_fail git config ${mode_unset_all} --file=config --fixed-value dev.null ' test_expect_success '--fixed-value uses exact string matching' ' @@ -2635,6 +2644,11 @@ test_expect_success '--fixed-value uses exact string matching' ' git config --file=config --fixed-value --unset fixed.test "$META" && test_must_fail git config ${mode_get} --file=config fixed.test && + cp initial config && + test_must_fail git config unset --file=config --value="$META" fixed.test && + git config unset --file=config --fixed-value --value="$META" fixed.test && + test_must_fail git config ${mode_get} --file=config fixed.test && + cp initial config && test_must_fail git config --file=config --unset-all fixed.test "$META" && git config --file=config --fixed-value --unset-all fixed.test "$META" &&