Subject: [PATCH v2] branch: do not fail a no-op --edit-desc

From: Junio C Hamano <[email-masked]>
Date: Thu, 29 Sep 2022 18:27:58 -0700

Imagine running "git branch --edit-description" on a branch without
a branch description, and then exit the editor after emptying the
edit buffer, which is the way to tell the command that you changed
your mind and you do not want the description after all.

The command should just happily oblige, adding no branch description
for the current branch, and exit successfully.  But it fails to do
so:

    $ git init -b main
    $ git commit --allow-empty -m commit
    $ GIT_EDITOR=: git branch --edit-description
    fatal: could not unset 'branch.main.description'

The end result is OK in that the configuration variable does not
exist in the resulting repository, but we should do better, by using
git_config_set_gently() and ignoring only the specific error that is
returned when removing a missing configuration variable.

A nice side effect is that it allows us to give a pair of messages
that are tailored to the situation.  Instead of reporting a failure
to set or unset a configuration variable "branch.X.description", we
can report that we failed to set or unset the description for branch
X, allowing the user to be oblivious to the irrelevant detail that
the branch description is implemented as a configuration variable.

Signed-off-by: Junio C Hamano <[email-masked]>
---
 * So, this is the "other" implementation.  It is a bit more code
   than the simpler one, but may be OK.  I labeled this as v2 but I
   do not mean I consider this one is an improved version of the
   other one.  They are merely alternatives.

 builtin/branch.c  | 13 ++++++++++++-
 t/t3200-branch.sh |  3 +++
 2 files changed, 15 insertions(+), 1 deletion(-)

diff --git c/builtin/branch.c w/builtin/branch.c
index 5d00d0b8d3..033d8bd29b 100644
--- c/builtin/branch.c
+++ w/builtin/branch.c
@@ -606,6 +606,7 @@ static int edit_branch_description(const char *branch_name)
 {
 	struct strbuf buf = STRBUF_INIT;
 	struct strbuf name = STRBUF_INIT;
+	int status;
 
 	read_branch_desc(&buf, branch_name);
 	if (!buf.len || buf.buf[buf.len-1] != '\n')
@@ -624,7 +625,17 @@ static int edit_branch_description(const char *branch_name)
 	strbuf_stripspace(&buf, 1);
 
 	strbuf_addf(&name, "branch.%s.description", branch_name);
-	git_config_set(name.buf, buf.len ? buf.buf : NULL);
+
+	status = git_config_set_gently(name.buf, buf.len ? buf.buf : NULL);
+	if (status && !(status == CONFIG_NOTHING_SET && !buf.len)) {
+		if (buf.len)
+			die(_("failed to set description for branch '%s'"), 
+			    branch_name);
+		else
+			die(_("failed to unset description for branch '%s'"), 
+			    branch_name);
+	}
+
 	strbuf_release(&name);
 	strbuf_release(&buf);
 
diff --git c/t/t3200-branch.sh w/t/t3200-branch.sh
index 9723c2827c..5f72fd7453 100755
--- c/t/t3200-branch.sh
+++ w/t/t3200-branch.sh
@@ -1381,6 +1381,9 @@ test_expect_success 'branch --delete --force removes dangling branch' '
 '
 
 test_expect_success 'use --edit-description' '
+	EDITOR=: git branch --edit-description &&
+	test_must_fail git config branch.main.description &&
+
 	write_script editor <<-\EOF &&
 		echo "New contents" >"$1"
 	EOF