Skip to content

Commit a4043ae

Browse files
committed
Merge branch 'jc/request-pull-show-head-4'
* jc/request-pull-show-head-4: request-pull: use the annotated tag contents fmt-merge-msg.c: Fix an "dubious one-bit signed bitfield" sparse error environment.c: Fix an sparse "symbol not declared" warning builtin/log.c: Fix an "Using plain integer as NULL pointer" warning fmt-merge-msg: use branch.$name.description request-pull: use the branch description request-pull: state what commit to expect request-pull: modernize style branch: teach --edit-description option format-patch: use branch description in cover letter branch: add read_branch_desc() helper function Conflicts: builtin/branch.c
2 parents 1ee740e + d050464 commit a4043ae

File tree

12 files changed

+313
-59
lines changed

12 files changed

+313
-59
lines changed

Documentation/git-branch.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ SYNOPSIS
1414
'git branch' [--set-upstream | --track | --no-track] [-l] [-f] <branchname> [<start-point>]
1515
'git branch' (-m | -M) [<oldbranch>] <newbranch>
1616
'git branch' (-d | -D) [-r] <branchname>...
17+
'git branch' --edit-description [<branchname>]
1718

1819
DESCRIPTION
1920
-----------
@@ -158,6 +159,10 @@ start-point is either a local or remote-tracking branch.
158159
like '--track' would when creating the branch, except that where
159160
branch points to is not changed.
160161

162+
--edit-description::
163+
Open an editor and edit the text to explain what the branch is
164+
for, to be used by various other commands (e.g. `request-pull`).
165+
161166
--contains <commit>::
162167
Only list branches which contain the specified commit.
163168

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -532,6 +532,7 @@ LIB_H += diffcore.h
532532
LIB_H += diff.h
533533
LIB_H += dir.h
534534
LIB_H += exec_cmd.h
535+
LIB_H += fmt-merge-msg.h
535536
LIB_H += fsck.h
536537
LIB_H += gettext.h
537538
LIB_H += git-compat-util.h

branch.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,37 @@ static int setup_tracking(const char *new_ref, const char *orig_ref,
136136
return 0;
137137
}
138138

139+
struct branch_desc_cb {
140+
const char *config_name;
141+
const char *value;
142+
};
143+
144+
static int read_branch_desc_cb(const char *var, const char *value, void *cb)
145+
{
146+
struct branch_desc_cb *desc = cb;
147+
if (strcmp(desc->config_name, var))
148+
return 0;
149+
free((char *)desc->value);
150+
return git_config_string(&desc->value, var, value);
151+
}
152+
153+
int read_branch_desc(struct strbuf *buf, const char *branch_name)
154+
{
155+
struct branch_desc_cb cb;
156+
struct strbuf name = STRBUF_INIT;
157+
strbuf_addf(&name, "branch.%s.description", branch_name);
158+
cb.config_name = name.buf;
159+
cb.value = NULL;
160+
if (git_config(read_branch_desc_cb, &cb) < 0) {
161+
strbuf_release(&name);
162+
return -1;
163+
}
164+
if (cb.value)
165+
strbuf_addstr(buf, cb.value);
166+
strbuf_release(&name);
167+
return 0;
168+
}
169+
139170
int validate_new_branchname(const char *name, struct strbuf *ref,
140171
int force, int attr_only)
141172
{

branch.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,4 +46,9 @@ void remove_branch_state(void);
4646
#define BRANCH_CONFIG_VERBOSE 01
4747
extern void install_branch_config(int flag, const char *local, const char *origin, const char *remote);
4848

49+
/*
50+
* Read branch description
51+
*/
52+
extern int read_branch_desc(struct strbuf *, const char *branch_name);
53+
4954
#endif

builtin/branch.c

Lines changed: 55 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -623,11 +623,49 @@ static int opt_parse_merge_filter(const struct option *opt, const char *arg, int
623623
return 0;
624624
}
625625

626+
static const char edit_description[] = "BRANCH_DESCRIPTION";
627+
628+
static int edit_branch_description(const char *branch_name)
629+
{
630+
FILE *fp;
631+
int status;
632+
struct strbuf buf = STRBUF_INIT;
633+
struct strbuf name = STRBUF_INIT;
634+
635+
read_branch_desc(&buf, branch_name);
636+
if (!buf.len || buf.buf[buf.len-1] != '\n')
637+
strbuf_addch(&buf, '\n');
638+
strbuf_addf(&buf,
639+
"# Please edit the description for the branch\n"
640+
"# %s\n"
641+
"# Lines starting with '#' will be stripped.\n",
642+
branch_name);
643+
fp = fopen(git_path(edit_description), "w");
644+
if ((fwrite(buf.buf, 1, buf.len, fp) < buf.len) || fclose(fp)) {
645+
strbuf_release(&buf);
646+
return error(_("could not write branch description template: %s\n"),
647+
strerror(errno));
648+
}
649+
strbuf_reset(&buf);
650+
if (launch_editor(git_path(edit_description), &buf, NULL)) {
651+
strbuf_release(&buf);
652+
return -1;
653+
}
654+
stripspace(&buf, 1);
655+
656+
strbuf_addf(&name, "branch.%s.description", branch_name);
657+
status = git_config_set(name.buf, buf.buf);
658+
strbuf_release(&name);
659+
strbuf_release(&buf);
660+
661+
return status;
662+
}
663+
626664
int cmd_branch(int argc, const char **argv, const char *prefix)
627665
{
628666
int delete = 0, rename = 0, force_create = 0, list = 0;
629667
int verbose = 0, abbrev = -1, detached = 0;
630-
int reflog = 0;
668+
int reflog = 0, edit_description = 0;
631669
enum branch_track track;
632670
int kinds = REF_LOCAL_BRANCH;
633671
struct commit_list *with_commit = NULL;
@@ -666,6 +704,8 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
666704
OPT_BIT('M', NULL, &rename, "move/rename a branch, even if target exists", 2),
667705
OPT_BOOLEAN(0, "list", &list, "list branch names"),
668706
OPT_BOOLEAN('l', "create-reflog", &reflog, "create the branch's reflog"),
707+
OPT_BOOLEAN(0, "edit-description", &edit_description,
708+
"edit the description for the branch"),
669709
OPT__FORCE(&force_create, "force creation (when already exists)"),
670710
{
671711
OPTION_CALLBACK, 0, "no-merged", &merge_filter_ref,
@@ -705,7 +745,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
705745
argc = parse_options(argc, argv, prefix, options, builtin_branch_usage,
706746
0);
707747

708-
if (!delete && !rename && argc == 0)
748+
if (!delete && !rename && !edit_description && argc == 0)
709749
list = 1;
710750

711751
if (!!delete + !!rename + !!force_create + !!list > 1)
@@ -719,7 +759,19 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
719759
else if (list)
720760
return print_ref_list(kinds, detached, verbose, abbrev,
721761
with_commit, argv);
722-
else if (rename) {
762+
else if (edit_description) {
763+
const char *branch_name;
764+
if (detached)
765+
die("Cannot give description to detached HEAD");
766+
if (!argc)
767+
branch_name = head;
768+
else if (argc == 1)
769+
branch_name = argv[0];
770+
else
771+
usage_with_options(builtin_branch_usage, options);
772+
if (edit_branch_description(branch_name))
773+
return 1;
774+
} else if (rename) {
723775
if (argc == 1)
724776
rename_branch(head, argv[0], rename > 1);
725777
else if (argc == 2)

builtin/fmt-merge-msg.c

Lines changed: 59 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,27 @@
55
#include "revision.h"
66
#include "tag.h"
77
#include "string-list.h"
8+
#include "branch.h"
9+
#include "fmt-merge-msg.h"
810

911
static const char * const fmt_merge_msg_usage[] = {
1012
"git fmt-merge-msg [-m <message>] [--log[=<n>]|--no-log] [--file <file>]",
1113
NULL
1214
};
1315

14-
static int shortlog_len;
16+
static int use_branch_desc;
1517

16-
static int fmt_merge_msg_config(const char *key, const char *value, void *cb)
18+
int fmt_merge_msg_config(const char *key, const char *value, void *cb)
1719
{
1820
if (!strcmp(key, "merge.log") || !strcmp(key, "merge.summary")) {
1921
int is_bool;
20-
shortlog_len = git_config_bool_or_int(key, value, &is_bool);
21-
if (!is_bool && shortlog_len < 0)
22+
merge_log_config = git_config_bool_or_int(key, value, &is_bool);
23+
if (!is_bool && merge_log_config < 0)
2224
return error("%s: negative length %s", key, value);
23-
if (is_bool && shortlog_len)
24-
shortlog_len = DEFAULT_MERGE_LOG_LEN;
25+
if (is_bool && merge_log_config)
26+
merge_log_config = DEFAULT_MERGE_LOG_LEN;
27+
} else if (!strcmp(key, "merge.branchdesc")) {
28+
use_branch_desc = git_config_bool(key, value);
2529
}
2630
return 0;
2731
}
@@ -31,6 +35,11 @@ struct src_data {
3135
int head_status;
3236
};
3337

38+
struct origin_data {
39+
unsigned char sha1[20];
40+
unsigned is_local_branch:1;
41+
};
42+
3443
static void init_src_data(struct src_data *data)
3544
{
3645
data->branch.strdup_strings = 1;
@@ -45,7 +54,7 @@ static struct string_list origins = STRING_LIST_INIT_DUP;
4554
static int handle_line(char *line)
4655
{
4756
int i, len = strlen(line);
48-
unsigned char *sha1;
57+
struct origin_data *origin_data;
4958
char *src, *origin;
5059
struct src_data *src_data;
5160
struct string_list_item *item;
@@ -61,11 +70,13 @@ static int handle_line(char *line)
6170
return 2;
6271

6372
line[40] = 0;
64-
sha1 = xmalloc(20);
65-
i = get_sha1(line, sha1);
73+
origin_data = xcalloc(1, sizeof(struct origin_data));
74+
i = get_sha1(line, origin_data->sha1);
6675
line[40] = '\t';
67-
if (i)
76+
if (i) {
77+
free(origin_data);
6878
return 3;
79+
}
6980

7081
if (line[len - 1] == '\n')
7182
line[len - 1] = 0;
@@ -93,6 +104,7 @@ static int handle_line(char *line)
93104
origin = src;
94105
src_data->head_status |= 1;
95106
} else if (!prefixcmp(line, "branch ")) {
107+
origin_data->is_local_branch = 1;
96108
origin = line + 7;
97109
string_list_append(&src_data->branch, origin);
98110
src_data->head_status |= 2;
@@ -119,7 +131,9 @@ static int handle_line(char *line)
119131
sprintf(new_origin, "%s of %s", origin, src);
120132
origin = new_origin;
121133
}
122-
string_list_append(&origins, origin)->util = sha1;
134+
if (strcmp(".", src))
135+
origin_data->is_local_branch = 0;
136+
string_list_append(&origins, origin)->util = origin_data;
123137
return 0;
124138
}
125139

@@ -140,16 +154,38 @@ static void print_joined(const char *singular, const char *plural,
140154
}
141155
}
142156

143-
static void shortlog(const char *name, unsigned char *sha1,
144-
struct commit *head, struct rev_info *rev, int limit,
145-
struct strbuf *out)
157+
static void add_branch_desc(struct strbuf *out, const char *name)
158+
{
159+
struct strbuf desc = STRBUF_INIT;
160+
161+
if (!read_branch_desc(&desc, name)) {
162+
const char *bp = desc.buf;
163+
while (*bp) {
164+
const char *ep = strchrnul(bp, '\n');
165+
if (*ep)
166+
ep++;
167+
strbuf_addf(out, " : %.*s", (int)(ep - bp), bp);
168+
bp = ep;
169+
}
170+
if (out->buf[out->len - 1] != '\n')
171+
strbuf_addch(out, '\n');
172+
}
173+
strbuf_release(&desc);
174+
}
175+
176+
static void shortlog(const char *name,
177+
struct origin_data *origin_data,
178+
struct commit *head,
179+
struct rev_info *rev, int limit,
180+
struct strbuf *out)
146181
{
147182
int i, count = 0;
148183
struct commit *commit;
149184
struct object *branch;
150185
struct string_list subjects = STRING_LIST_INIT_DUP;
151186
int flags = UNINTERESTING | TREESAME | SEEN | SHOWN | ADDED;
152187
struct strbuf sb = STRBUF_INIT;
188+
const unsigned char *sha1 = origin_data->sha1;
153189

154190
branch = deref_tag(parse_object(sha1), sha1_to_hex(sha1), 40);
155191
if (!branch || branch->type != OBJ_COMMIT)
@@ -188,6 +224,9 @@ static void shortlog(const char *name, unsigned char *sha1,
188224
else
189225
strbuf_addf(out, "\n* %s:\n", name);
190226

227+
if (origin_data->is_local_branch && use_branch_desc)
228+
add_branch_desc(out, name);
229+
191230
for (i = 0; i < subjects.nr; i++)
192231
if (i >= limit)
193232
strbuf_addf(out, " ...\n");
@@ -303,8 +342,9 @@ static int do_fmt_merge_msg(int merge_title, struct strbuf *in,
303342
strbuf_addch(out, '\n');
304343

305344
for (i = 0; i < origins.nr; i++)
306-
shortlog(origins.items[i].string, origins.items[i].util,
307-
head, &rev, shortlog_len, out);
345+
shortlog(origins.items[i].string,
346+
origins.items[i].util,
347+
head, &rev, shortlog_len, out);
308348
}
309349
return 0;
310350
}
@@ -318,6 +358,7 @@ int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix)
318358
{
319359
const char *inpath = NULL;
320360
const char *message = NULL;
361+
int shortlog_len = -1;
321362
struct option options[] = {
322363
{ OPTION_INTEGER, 0, "log", &shortlog_len, "n",
323364
"populate log with at most <n> entries from shortlog",
@@ -341,6 +382,8 @@ int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix)
341382
0);
342383
if (argc > 0)
343384
usage_with_options(fmt_merge_msg_usage, options);
385+
if (shortlog_len < 0)
386+
shortlog_len = (merge_log_config > 0) ? merge_log_config : 0;
344387
if (message && !shortlog_len) {
345388
char nl = '\n';
346389
write_in_full(STDOUT_FILENO, message, strlen(message));

0 commit comments

Comments
 (0)