Subject: Re: [PATCH 4/4] branch: add '--show-description' option

From: SZEDER Gábor <[email-masked]>
Date: Tue, 2 Jan 2018 20:25:49 +0100

On Tue, Jan 2, 2018 at 10:32 AM, Johannes Sixt <[email-masked]> wrote:
> > Which makes me wonder: Why would --show-description have to error out
> > silently? This is not 'git config' after all.

> I don't have a strong opinion about this, and certainly wouldn't mind
> adding an error message instead.

And it would look like this:

  -- >8 --

Subject: [PATCH 4/4] branch: add '--show-description' option

'git branch' has an option to edit a branch's description, but lacks
the option to show that description.

Therefore, add a new '--show-description' option to do just that, as a
more user-friendly alternative to 'git config --get
branch.$branchname.description':

  - it's shorter to type (both in the number of characters and the
    number of TABs if using completion),
  - works on the current branch without explicitly naming it,
  - hides the implementation detail that branch descriptions are
    stored in the config file, and
  - errors out with a proper error message when the given branch
    doesn't exist or has no description.

Signed-off-by: SZEDER Gábor <[email-masked]>
---
 Documentation/git-branch.txt           |  6 +++++-
 builtin/branch.c                       | 39 +++++++++++++++++++++++++++++++---
 contrib/completion/git-completion.bash |  4 ++--
 t/t3200-branch.sh                      | 21 ++++++++++++++++++
 4 files changed, 64 insertions(+), 6 deletions(-)

diff --git a/Documentation/git-branch.txt b/Documentation/git-branch.txt
index b3084c99c..e05c9e193 100644
--- a/Documentation/git-branch.txt
+++ b/Documentation/git-branch.txt
@@ -20,7 +20,7 @@ SYNOPSIS
 'git branch' (-m | -M) [<oldbranch>] <newbranch>
 'git branch' (-c | -C) [<oldbranch>] <newbranch>
 'git branch' (-d | -D) [-r] <branchname>...
-'git branch' --edit-description [<branchname>]
+'git branch' (--edit-description | --show-description) [<branchname>]
 
 DESCRIPTION
 -----------
@@ -226,6 +226,10 @@ start-point is either a local or remote-tracking branch.
 	`request-pull`, and `merge` (if enabled)). Multi-line explanations
 	may be used.
 
+--show-description::
+	Show the description of the branch previously set using
+	`--edit-description`.
+
 --contains [<commit>]::
 	Only list branches which contain the specified commit (HEAD
 	if not specified). Implies `--list`.
diff --git a/builtin/branch.c b/builtin/branch.c
index 32531aa44..748a1a575 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -573,7 +573,7 @@ static int edit_branch_description(const char *branch_name)
 int cmd_branch(int argc, const char **argv, const char *prefix)
 {
 	int delete = 0, rename = 0, copy = 0, force = 0, list = 0;
-	int reflog = 0, edit_description = 0;
+	int reflog = 0, edit_description = 0, show_description = 0;
 	int quiet = 0, unset_upstream = 0;
 	const char *new_upstream = NULL;
 	enum branch_track track;
@@ -615,6 +615,8 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
 		OPT_BOOL('l', "create-reflog", &reflog, N_("create the branch's reflog")),
 		OPT_BOOL(0, "edit-description", &edit_description,
 			 N_("edit the description for the branch")),
+		OPT_BOOL(0, "show-description", &show_description,
+			 N_("show the description for the branch")),
 		OPT__FORCE(&force, N_("force creation, move/rename, deletion")),
 		OPT_MERGED(&filter, N_("print only branches that are merged")),
 		OPT_NO_MERGED(&filter, N_("print only branches that are not merged")),
@@ -654,7 +656,9 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
 	argc = parse_options(argc, argv, prefix, options, builtin_branch_usage,
 			     0);
 
-	if (!delete && !rename && !copy && !edit_description && !new_upstream && !unset_upstream && argc == 0)
+	if (!delete && !rename && !copy &&
+	    !edit_description && !show_description &&
+	    !new_upstream && !unset_upstream && argc == 0)
 		list = 1;
 
 	if (filter.with_commit || filter.merge != REF_FILTER_MERGED_NONE || filter.points_at.nr ||
@@ -662,7 +666,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
 		list = 1;
 
 	if (!!delete + !!rename + !!copy + !!new_upstream +
-	    list + unset_upstream + edit_description > 1)
+	    list + unset_upstream + edit_description + show_description > 1)
 		usage_with_options(builtin_branch_usage, options);
 
 	if (filter.abbrev == -1)
@@ -737,6 +741,35 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
 
 		if (edit_branch_description(branch_name))
 			return 1;
+	} else if (show_description) {
+		const char *branch_name;
+		struct strbuf buf = STRBUF_INIT;
+		char *description = NULL;
+
+		if (!argc) {
+			if (filter.detached)
+				die(_("cannot show description on detached HEAD"));
+			branch_name = head;
+		} else if (argc == 1)
+			branch_name = argv[0];
+		else
+			die(_("cannot show description of more than one branch"));
+
+		strbuf_addf(&buf, "refs/heads/%s", branch_name);
+		if (!ref_exists(buf.buf)) {
+			strbuf_release(&buf);
+			return error(_("no branch named '%s'"), branch_name);
+		}
+		strbuf_reset(&buf);
+
+		strbuf_addf(&buf, "branch.%s.description", branch_name);
+		if (git_config_get_string(buf.buf, &description)) {
+			strbuf_release(&buf);
+			return error(_("no description for branch '%s'"), branch_name);
+		}
+		printf("%s", description);
+		strbuf_release(&buf);
+		free(description);
 	} else if (copy) {
 		if (!argc)
 			die(_("branch name required"));
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 3683c772c..0fcc13ea0 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -1203,8 +1203,8 @@ _git_branch ()
 		__gitcomp "
 			--color --no-color --verbose --abbrev= --no-abbrev
 			--track --no-track --contains --no-contains --merged --no-merged
-			--set-upstream-to= --edit-description --list
-			--unset-upstream --delete --move --copy --remotes
+			--set-upstream-to= --edit-description --show-description
+			--list --unset-upstream --delete --move --copy --remotes
 			--column --no-column --sort= --points-at
 			"
 		;;
diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh
index 427ad490d..54e8dcbe2 100755
--- a/t/t3200-branch.sh
+++ b/t/t3200-branch.sh
@@ -1239,6 +1239,27 @@ test_expect_success 'refuse --edit-description on unborn branch for now' '
 	test_must_fail env EDITOR=./editor git branch --edit-description
 '
 
+test_expect_success '--show-description' '
+	echo "New contents" >expect &&
+	git branch --show-description >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success '--show-description on detached HEAD' '
+	git checkout --detach &&
+	test_when_finished git checkout master &&
+	test_must_fail git branch --show-description
+'
+
+test_expect_success '--show-description with no description' '
+	git config --unset branch.master.description &&
+	test_must_fail git branch --show-description master
+'
+
+test_expect_success '--show-description on non-existing branch' '
+	test_must_fail git branch --show-description no-such-branch
+'
+
 test_expect_success '--merged catches invalid object names' '
 	test_must_fail git branch --merged 0000000000000000000000000000000000000000
 '
-- 
2.16.0.rc0.67.g3a46dbca7