{"thread":{"id":"37865","subject":"Branch Title","startedAt":"2014-11-01T14:32:55Z","lastAt":"2014-11-01T14:32:55Z","messageCount":1,"participants":["Peter Kuemmel"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"251286","messageId":"trinity-e17125ce-b18f-4d48-bd98-afcb4224b80e-1414852375225@3capp-gmx-bs67","threadId":"37865","inReplyTo":null,"subject":"Branch Title","fromName":"Peter Kuemmel","fromEmail":"syntheticpp@gmx.net","sentAt":"2014-11-01T14:32:55Z","receivedAt":"2014-11-01T14:32:55Z","isPatch":false,"sender":{"key":"syntheticpp@gmx.net","avatar":null},"body":"I would like to give a branch a \"title\" which is similar to the branch description\nbut should be pushable.\n\nThere was a discussion several years ago with the hint to extend\npush to make it shareable:\nhttp://git.661346.n2.nabble.com/push-branch-descriptions-tt7571217.html\n\nI've patched buildin/branch.c for the local part, but how could the title be pushed,\nand where should it be stored on the remote side?\n\nPeter\n\n\n\nSubject: [PATCH] branch.c: add option to edit/show the title of a branch\n\n---\n branch.c         | 15 ++++++++++\n branch.h         |  5 ++++\n builtin/branch.c | 89 +++++++++++++++++++++++++++++++++++++++++++-------------\n 3 files changed, 88 insertions(+), 21 deletions(-)\n\ndiff --git a/branch.c b/branch.c\nindex 4bab55a..47380d8 100644\n--- a/branch.c\n+++ b/branch.c\n@@ -155,6 +155,21 @@ int read_branch_desc(struct strbuf *buf, const char *branch_name)\n \treturn 0;\n }\n \n+int read_branch_title(struct strbuf *buf, const char *branch_name)\n+{\n+\tchar *v = NULL;\n+\tstruct strbuf name = STRBUF_INIT;\n+\tstrbuf_addf(&name, \"branch.%s.title\", branch_name);\n+\tif (git_config_get_string(name.buf, &v)) {\n+\t\tstrbuf_release(&name);\n+\t\treturn -1;\n+\t}\n+\tstrbuf_addstr(buf, v);\n+\tfree(v);\n+\tstrbuf_release(&name);\n+\treturn 0;\n+}\n+\n int validate_new_branchname(const char *name, struct strbuf *ref,\n \t\t\t    int force, int attr_only)\n {\ndiff --git a/branch.h b/branch.h\nindex 64173ab..f1050ab 100644\n--- a/branch.h\n+++ b/branch.h\n@@ -52,4 +52,9 @@ extern void install_branch_config(int flag, const char *local, const char *origi\n  */\n extern int read_branch_desc(struct strbuf *, const char *branch_name);\n \n+/*\n+ * Read branch title\n+ */\n+extern int read_branch_title(struct strbuf *, const char *branch_name);\n+\n #endif\ndiff --git a/builtin/branch.c b/builtin/branch.c\nindex 3b79c50..0680464 100644\n--- a/builtin/branch.c\n+++ b/builtin/branch.c\n@@ -290,7 +290,7 @@ struct ref_item {\n \n struct ref_list {\n \tstruct rev_info revs;\n-\tint index, alloc, maxwidth, verbose, abbrev;\n+\tint index, alloc, maxwidth, verbose, showtitle, abbrev;\n \tstruct ref_item *list;\n \tstruct commit_list *with_commit;\n \tint kinds;\n@@ -511,7 +511,7 @@ static void add_verbose_info(struct strbuf *out, struct ref_item *item,\n \tstrbuf_release(&subject);\n }\n \n-static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,\n+static void print_ref_item(struct ref_item *item, int maxwidth, int verbose, int showtitle,\n \t\t\t   int abbrev, int current, char *prefix)\n {\n \tchar c;\n@@ -554,6 +554,15 @@ static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,\n \telse if (verbose)\n \t\t/* \" f7c0c00 [ahead 58, behind 197] vcs-svn: drop obj_pool.h\" */\n \t\tadd_verbose_info(&out, item, verbose, abbrev);\n+\tif (showtitle) {\n+\t\tstruct strbuf title = STRBUF_INIT;\n+\t\tread_branch_title(&title, name.buf);\n+\t\tif (title.len > 0) {\n+\t\t\tstrbuf_trim(&title);\n+\t\t\tstrbuf_addf(&out, \" \\\"%s\\\"\", title.buf);\n+\t\t}\n+\t\tstrbuf_release(&title);\n+\t}\n \tif (column_active(colopts)) {\n \t\tassert(!verbose && \"--column and --verbose are incompatible\");\n \t\tstring_list_append(&output, out.buf);\n@@ -614,12 +623,12 @@ static void show_detached(struct ref_list *ref_list)\n \t\titem.ignore = 0;\n \t\tif (item.width > ref_list->maxwidth)\n \t\t\tref_list->maxwidth = item.width;\n-\t\tprint_ref_item(&item, ref_list->maxwidth, ref_list->verbose, ref_list->abbrev, 1, \"\");\n+\t\tprint_ref_item(&item, ref_list->maxwidth, ref_list->verbose, ref_list->showtitle, ref_list->abbrev, 1, \"\");\n \t\tfree(item.name);\n \t}\n }\n \n-static int print_ref_list(int kinds, int detached, int verbose, int abbrev, struct commit_list *with_commit, const char **pattern)\n+static int print_ref_list(int kinds, int detached, int verbose, int showtitle, int abbrev, struct commit_list *with_commit, const char **pattern)\n {\n \tint i;\n \tstruct append_ref_cb cb;\n@@ -628,6 +637,7 @@ static int print_ref_list(int kinds, int detached, int verbose, int abbrev, stru\n \tmemset(&ref_list, 0, sizeof(ref_list));\n \tref_list.kinds = kinds;\n \tref_list.verbose = verbose;\n+\tref_list.showtitle = showtitle;\n \tref_list.abbrev = abbrev;\n \tref_list.with_commit = with_commit;\n \tif (merge_filter != NO_FILTER)\n@@ -664,7 +674,7 @@ static int print_ref_list(int kinds, int detached, int verbose, int abbrev, stru\n \t\t}\n \t\tclear_commit_marks(filter, ALL_REV_FLAGS);\n \n-\t\tif (verbose)\n+\t\tif (verbose || showtitle)\n \t\t\tref_list.maxwidth = calc_maxwidth(&ref_list);\n \t}\n \n@@ -681,7 +691,7 @@ static int print_ref_list(int kinds, int detached, int verbose, int abbrev, stru\n \t\tchar *prefix = (kinds != REF_REMOTE_BRANCH &&\n \t\t\t\tref_list.list[i].kind == REF_REMOTE_BRANCH)\n \t\t\t\t? \"remotes/\" : \"\";\n-\t\tprint_ref_item(&ref_list.list[i], ref_list.maxwidth, verbose,\n+\t\tprint_ref_item(&ref_list.list[i], ref_list.maxwidth, verbose, showtitle,\n \t\t\t       abbrev, current, prefix);\n \t}\n \n@@ -761,36 +771,40 @@ static int opt_parse_merge_filter(const struct option *opt, const char *arg, int\n }\n \n static const char edit_description[] = \"BRANCH_DESCRIPTION\";\n+static const char edit_title[] = \"BRANCH_TITLE\";\n \n-static int edit_branch_description(const char *branch_name)\n+static int edit_branch_description(const char *branch_name, int desc)\n {\n \tFILE *fp;\n \tint status;\n \tstruct strbuf buf = STRBUF_INIT;\n \tstruct strbuf name = STRBUF_INIT;\n \n-\tread_branch_desc(&buf, branch_name);\n+\tif (desc)\n+\t\tread_branch_desc(&buf, branch_name);\n+\telse\n+\t\tread_branch_title(&buf, branch_name);\n \tif (!buf.len || buf.buf[buf.len-1] != '\\n')\n \t\tstrbuf_addch(&buf, '\\n');\n \tstrbuf_commented_addf(&buf,\n-\t\t    \"Please edit the description for the branch\\n\"\n+\t\t    \"Please edit the %s for the branch\\n\"\n \t\t    \"  %s\\n\"\n \t\t    \"Lines starting with '%c' will be stripped.\\n\",\n-\t\t    branch_name, comment_line_char);\n-\tfp = fopen(git_path(edit_description), \"w\");\n+\t\t    (desc?\"description\":\"title\"), branch_name, comment_line_char);\n+\tfp = fopen(git_path(desc?edit_description:edit_title), \"w\");\n \tif ((fwrite(buf.buf, 1, buf.len, fp) < buf.len) || fclose(fp)) {\n \t\tstrbuf_release(&buf);\n-\t\treturn error(_(\"could not write branch description template: %s\"),\n-\t\t\t     strerror(errno));\n+\t\treturn error(_(\"could not write branch %s template: %s\"),\n+\t\t\t     (desc?\"description\":\"title\"), strerror(errno));\n \t}\n \tstrbuf_reset(&buf);\n-\tif (launch_editor(git_path(edit_description), &buf, NULL)) {\n+\tif (launch_editor(git_path(desc?edit_description:edit_title), &buf, NULL)) {\n \t\tstrbuf_release(&buf);\n \t\treturn -1;\n \t}\n \tstripspace(&buf, 1);\n \n-\tstrbuf_addf(&name, \"branch.%s.description\", branch_name);\n+\tstrbuf_addf(&name, \"branch.%s.%s\", branch_name, (desc?\"description\":\"title\"));\n \tstatus = git_config_set(name.buf, buf.len ? buf.buf : NULL);\n \tstrbuf_release(&name);\n \tstrbuf_release(&buf);\n@@ -801,8 +815,8 @@ static int edit_branch_description(const char *branch_name)\n int cmd_branch(int argc, const char **argv, const char *prefix)\n {\n \tint delete = 0, rename = 0, force_create = 0, list = 0;\n-\tint verbose = 0, abbrev = -1, detached = 0;\n-\tint reflog = 0, edit_description = 0;\n+\tint verbose = 0, showtitle = 0, abbrev = -1, detached = 0;\n+\tint reflog = 0, edit_description = 0, edit_title = 0;\n \tint quiet = 0, unset_upstream = 0;\n \tconst char *new_upstream = NULL;\n \tenum branch_track track;\n@@ -813,6 +827,8 @@ int cmd_branch(int argc, const char **argv, const char *prefix)\n \t\tOPT_GROUP(N_(\"Generic options\")),\n \t\tOPT__VERBOSE(&verbose,\n \t\t\tN_(\"show hash and subject, give twice for upstream branch\")),\n+\t\tOPT_BOOL('s', \"title\", &showtitle,\n+\t\t\t N_(\"show title of branches if available\")),\n \t\tOPT__QUIET(&quiet, N_(\"suppress informational messages\")),\n \t\tOPT_SET_INT('t', \"track\",  &track, N_(\"set up tracking mode (see git-pull(1))\"),\n \t\t\tBRANCH_TRACK_EXPLICIT),\n@@ -848,6 +864,8 @@ int cmd_branch(int argc, const char **argv, const char *prefix)\n \t\tOPT_BOOL('l', \"create-reflog\", &reflog, N_(\"create the branch's reflog\")),\n \t\tOPT_BOOL(0, \"edit-description\", &edit_description,\n \t\t\t N_(\"edit the description for the branch\")),\n+\t\tOPT_BOOL('e', \"edit-title\", &edit_title,\n+\t\t\t N_(\"edit the title for the branch\")),\n \t\tOPT__FORCE(&force_create, N_(\"force creation (when already exists)\")),\n \t\t{\n \t\t\tOPTION_CALLBACK, 0, \"no-merged\", &merge_filter_ref,\n@@ -885,7 +903,8 @@ int cmd_branch(int argc, const char **argv, const char *prefix)\n \targc = parse_options(argc, argv, prefix, options, builtin_branch_usage,\n \t\t\t     0);\n \n-\tif (!delete && !rename && !edit_description && !new_upstream && !unset_upstream && argc == 0)\n+\tif (!delete && !rename && !edit_description && !edit_title && \n+\t\t\t\t!new_upstream && !unset_upstream && argc == 0)\n \t\tlist = 1;\n \n \tif (with_commit || merge_filter != NO_FILTER)\n@@ -898,7 +917,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)\n \tif (abbrev == -1)\n \t\tabbrev = DEFAULT_ABBREV;\n \tfinalize_colopts(&colopts, -1);\n-\tif (verbose) {\n+\tif (verbose || showtitle) {\n \t\tif (explicitly_enable_column(colopts))\n \t\t\tdie(_(\"--column and --verbose are incompatible\"));\n \t\tcolopts = 0;\n@@ -909,7 +928,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)\n \t\t\tdie(_(\"branch name required\"));\n \t\treturn delete_branches(argc, argv, delete > 1, kinds, quiet);\n \t} else if (list) {\n-\t\tint ret = print_ref_list(kinds, detached, verbose, abbrev,\n+\t\tint ret = print_ref_list(kinds, detached, verbose, showtitle, abbrev,\n \t\t\t\t\t with_commit, argv);\n \t\tprint_columns(&output, colopts, NULL);\n \t\tstring_list_clear(&output, 0);\n@@ -941,7 +960,35 @@ int cmd_branch(int argc, const char **argv, const char *prefix)\n \t\t}\n \t\tstrbuf_release(&branch_ref);\n \n-\t\tif (edit_branch_description(branch_name))\n+\t\tif (edit_branch_description(branch_name, 1))\n+\t\t\treturn 1;\n+\t} else if (edit_title) {\n+\t\tconst char *branch_name;\n+\t\tstruct strbuf branch_ref = STRBUF_INIT;\n+\n+\t\tif (!argc) {\n+\t\t\tif (detached)\n+\t\t\t\tdie(_(\"Cannot give title to detached HEAD\"));\n+\t\t\tbranch_name = head;\n+\t\t} else if (argc == 1)\n+\t\t\tbranch_name = argv[0];\n+\t\telse\n+\t\t\tdie(_(\"cannot edit title of more than one branch\"));\n+\n+\t\tstrbuf_addf(&branch_ref, \"refs/heads/%s\", branch_name);\n+\t\tif (!ref_exists(branch_ref.buf)) {\n+\t\t\tstrbuf_release(&branch_ref);\n+\n+\t\t\tif (!argc)\n+\t\t\t\treturn error(_(\"No commit on branch '%s' yet.\"),\n+\t\t\t\t\t     branch_name);\n+\t\t\telse\n+\t\t\t\treturn error(_(\"No branch named '%s'.\"),\n+\t\t\t\t\t     branch_name);\n+\t\t}\n+\t\tstrbuf_release(&branch_ref);\n+\n+\t\tif (edit_branch_description(branch_name, 0))\n \t\t\treturn 1;\n \t} else if (rename) {\n \t\tif (!argc)\n-- \n1.9.1\n"}]}