branch: teach --edit-description option

Using branch.$name.description as the configuration key, give users a place to write about what the purpose of the branch is and things like that, so that various subsystems, e.g. "push -s", "request-pull", and "format-patch --cover-letter", can later be taught to use this information. The "-m" option similar to "commit/tag" is deliberately omitted, as the whole point of branch description is about giving descriptive information (the name of the branch itself is a better place for information that fits on a single-line). Signed-off-by: Junio C Hamano <gitster@pobox.com>

Junio C Hamano committed Sep 20, 2011 at 15:10 UTC b7200e839737491dfe8f0297fba54621fd7d7583
2 files changed +59 -2
Documentation/git-branch.txt
+5
@@ -14,6 +14,7 @@ SYNOPSIS
14 'git branch' [--set-upstream | --track | --no-track] [-l] [-f] <branchname> [<start-point>]
15 'git branch' (-m | -M) [<oldbranch>] <newbranch>
16 'git branch' (-d | -D) [-r] <branchname>...
17 +'git branch' --edit-description [<branchname>]
18
19 DESCRIPTION
20 -----------
@@ -144,6 +145,10 @@ start-point is either a local or remote-tracking branch.
145 like '--track' would when creating the branch, except that where
146 branch points to is not changed.
147
148 +--edit-description::
149 + Open an editor and edit the text to explain what the branch is
150 + for, to be used by various other commands (e.g. `request-pull`).
151 +
152 --contains <commit>::
153 Only list branches which contain the specified commit.
154
builtin/branch.c
+54 -2
@@ -606,11 +606,49 @@ static int opt_parse_merge_filter(const struct option *opt, const char *arg, int
606 return 0;
607 }
608
609 +static const char edit_description[] = "BRANCH_DESCRIPTION";
610 +
611 +static int edit_branch_description(const char *branch_name)
612 +{
613 + FILE *fp;
614 + int status;
615 + struct strbuf buf = STRBUF_INIT;
616 + struct strbuf name = STRBUF_INIT;
617 +
618 + read_branch_desc(&buf, branch_name);
619 + if (!buf.len || buf.buf[buf.len-1] != '\n')
620 + strbuf_addch(&buf, '\n');
621 + strbuf_addf(&buf,
622 + "# Please edit the description for the branch\n"
623 + "# %s\n"
624 + "# Lines starting with '#' will be stripped.\n",
625 + branch_name);
626 + fp = fopen(git_path(edit_description), "w");
627 + if ((fwrite(buf.buf, 1, buf.len, fp) < buf.len) || fclose(fp)) {
628 + strbuf_release(&buf);
629 + return error(_("could not write branch description template: %s\n"),
630 + strerror(errno));
631 + }
632 + strbuf_reset(&buf);
633 + if (launch_editor(git_path(edit_description), &buf, NULL)) {
634 + strbuf_release(&buf);
635 + return -1;
636 + }
637 + stripspace(&buf, 1);
638 +
639 + strbuf_addf(&name, "branch.%s.description", branch_name);
640 + status = git_config_set(name.buf, buf.buf);
641 + strbuf_release(&name);
642 + strbuf_release(&buf);
643 +
644 + return status;
645 +}
646 +
647 int cmd_branch(int argc, const char **argv, const char *prefix)
648 {
649 int delete = 0, rename = 0, force_create = 0;
650 int verbose = 0, abbrev = -1, detached = 0;
613 - int reflog = 0;
651 + int reflog = 0, edit_description = 0;
652 enum branch_track track;
653 int kinds = REF_LOCAL_BRANCH;
654 struct commit_list *with_commit = NULL;
@@ -648,6 +686,8 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
686 OPT_BIT('m', NULL, &rename, "move/rename a branch and its reflog", 1),
687 OPT_BIT('M', NULL, &rename, "move/rename a branch, even if target exists", 2),
688 OPT_BOOLEAN('l', NULL, &reflog, "create the branch's reflog"),
689 + OPT_BOOLEAN(0, "edit-description", &edit_description,
690 + "edit the description for the branch"),
691 OPT__FORCE(&force_create, "force creation (when already exists)"),
692 {
693 OPTION_CALLBACK, 0, "no-merged", &merge_filter_ref,
@@ -694,7 +734,19 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
734
735 if (delete)
736 return delete_branches(argc, argv, delete > 1, kinds);
697 - else if (argc == 0)
737 + else if (edit_description) {
738 + const char *branch_name;
739 + if (detached)
740 + die("Cannot give description to detached HEAD");
741 + if (!argc)
742 + branch_name = head;
743 + else if (argc == 1)
744 + branch_name = argv[0];
745 + else
746 + usage_with_options(builtin_branch_usage, options);
747 + if (edit_branch_description(branch_name))
748 + return 1;
749 + } else if (argc == 0)
750 return print_ref_list(kinds, detached, verbose, abbrev, with_commit);
751 else if (rename && (argc == 1))
752 rename_branch(head, argv[0], rename > 1);