fmt-merge-msg: use branch.$name.description
This teaches "merge --log" and fmt-merge-msg to use branch description information when merging a local topic branch into the mainline. The description goes between the branch name label and the list of commit titles. The refactoring to share the common configuration parsing between merge and fmt-merge-msg needs to be made into a separate patch. Signed-off-by: Junio C Hamano <gitster@pobox.com>
Junio C Hamano committed
Oct 6, 2011 at 23:12 UTC
898eacd8ada2d012f977948350ed60845e238037
5 files changed
+78
-26
Makefile
+1
@@ -527,6 +527,7 @@ LIB_H += diffcore.h
527
LIB_H += diff.h
528
LIB_H += dir.h
529
LIB_H += exec_cmd.h
530
+LIB_H += fmt-merge-msg.h
531
LIB_H += fsck.h
532
LIB_H += gettext.h
533
LIB_H += git-compat-util.h
builtin/fmt-merge-msg.c
+59
-16
@@ -5,23 +5,27 @@
5
#include "revision.h"
6
#include "tag.h"
7
#include "string-list.h"
8
+#include "branch.h"
9
+#include "fmt-merge-msg.h"
10
11
static const char * const fmt_merge_msg_usage[] = {
12
"git fmt-merge-msg [-m <message>] [--log[=<n>]|--no-log] [--file <file>]",
13
NULL
14
};
15
14
-static int shortlog_len;
16
+static int use_branch_desc;
17
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)
19
{
20
if (!strcmp(key, "merge.log") || !strcmp(key, "merge.summary")) {
21
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)
24
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);
29
}
30
return 0;
31
}
@@ -31,6 +35,11 @@ struct src_data {
35
int head_status;
36
};
37
38
+struct origin_data {
39
+ unsigned char sha1[20];
40
+ int is_local_branch:1;
41
+};
42
+
43
static void init_src_data(struct src_data *data)
44
{
45
data->branch.strdup_strings = 1;
@@ -45,7 +54,7 @@ static struct string_list origins = STRING_LIST_INIT_DUP;
54
static int handle_line(char *line)
55
{
56
int i, len = strlen(line);
48
- unsigned char *sha1;
57
+ struct origin_data *origin_data;
58
char *src, *origin;
59
struct src_data *src_data;
60
struct string_list_item *item;
@@ -61,11 +70,13 @@ static int handle_line(char *line)
70
return 2;
71
72
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);
75
line[40] = '\t';
67
- if (i)
76
+ if (i) {
77
+ free(origin_data);
78
return 3;
79
+ }
80
81
if (line[len - 1] == '\n')
82
line[len - 1] = 0;
@@ -93,6 +104,7 @@ static int handle_line(char *line)
104
origin = src;
105
src_data->head_status |= 1;
106
} else if (!prefixcmp(line, "branch ")) {
107
+ origin_data->is_local_branch = 1;
108
origin = line + 7;
109
string_list_append(&src_data->branch, origin);
110
src_data->head_status |= 2;
@@ -119,7 +131,9 @@ static int handle_line(char *line)
131
sprintf(new_origin, "%s of %s", origin, src);
132
origin = new_origin;
133
}
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;
137
return 0;
138
}
139
@@ -140,9 +154,30 @@ static void print_joined(const char *singular, const char *plural,
154
}
155
}
156
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)
181
{
182
int i, count = 0;
183
struct commit *commit;
@@ -150,6 +185,7 @@ static void shortlog(const char *name, unsigned char *sha1,
185
struct string_list subjects = STRING_LIST_INIT_DUP;
186
int flags = UNINTERESTING | TREESAME | SEEN | SHOWN | ADDED;
187
struct strbuf sb = STRBUF_INIT;
188
+ const unsigned char *sha1 = origin_data->sha1;
189
190
branch = deref_tag(parse_object(sha1), sha1_to_hex(sha1), 40);
191
if (!branch || branch->type != OBJ_COMMIT)
@@ -188,6 +224,9 @@ static void shortlog(const char *name, unsigned char *sha1,
224
else
225
strbuf_addf(out, "\n* %s:\n", name);
226
227
+ if (origin_data->is_local_branch && use_branch_desc)
228
+ add_branch_desc(out, name);
229
+
230
for (i = 0; i < subjects.nr; i++)
231
if (i >= limit)
232
strbuf_addf(out, " ...\n");
@@ -303,8 +342,9 @@ static int do_fmt_merge_msg(int merge_title, struct strbuf *in,
342
strbuf_addch(out, '\n');
343
344
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);
348
}
349
return 0;
350
}
@@ -318,6 +358,7 @@ int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix)
358
{
359
const char *inpath = NULL;
360
const char *message = NULL;
361
+ int shortlog_len = -1;
362
struct option options[] = {
363
{ OPTION_INTEGER, 0, "log", &shortlog_len, "n",
364
"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)
382
0);
383
if (argc > 0)
384
usage_with_options(fmt_merge_msg_usage, options);
385
+ if (shortlog_len < 0)
386
+ shortlog_len = (merge_log_config > 0) ? merge_log_config : 0;
387
if (message && !shortlog_len) {
388
char nl = '\n';
389
write_in_full(STDOUT_FILENO, message, strlen(message));
builtin/merge.c
+10
-10
@@ -26,6 +26,7 @@
26
#include "merge-recursive.h"
27
#include "resolve-undo.h"
28
#include "remote.h"
29
+#include "fmt-merge-msg.h"
30
31
#define DEFAULT_TWOHEAD (1<<0)
32
#define DEFAULT_OCTOPUS (1<<1)
@@ -44,7 +45,7 @@ static const char * const builtin_merge_usage[] = {
45
NULL
46
};
47
47
-static int show_diffstat = 1, shortlog_len, squash;
48
+static int show_diffstat = 1, shortlog_len = -1, squash;
49
static int option_commit = 1, allow_fast_forward = 1;
50
static int fast_forward_only;
51
static int allow_trivial = 1, have_message;
@@ -525,6 +526,8 @@ static void parse_branch_merge_options(char *bmo)
526
527
static int git_merge_config(const char *k, const char *v, void *cb)
528
{
529
+ int status;
530
+
531
if (branch && !prefixcmp(k, "branch.") &&
532
!prefixcmp(k + 7, branch) &&
533
!strcmp(k + 7 + strlen(branch), ".mergeoptions")) {
@@ -541,15 +544,7 @@ static int git_merge_config(const char *k, const char *v, void *cb)
544
return git_config_string(&pull_octopus, k, v);
545
else if (!strcmp(k, "merge.renormalize"))
546
option_renormalize = git_config_bool(k, v);
544
- else if (!strcmp(k, "merge.log") || !strcmp(k, "merge.summary")) {
545
- int is_bool;
546
- shortlog_len = git_config_bool_or_int(k, v, &is_bool);
547
- if (!is_bool && shortlog_len < 0)
548
- return error(_("%s: negative length %s"), k, v);
549
- if (is_bool && shortlog_len)
550
- shortlog_len = DEFAULT_MERGE_LOG_LEN;
551
- return 0;
552
- } else if (!strcmp(k, "merge.ff")) {
547
+ else if (!strcmp(k, "merge.ff")) {
548
int boolval = git_config_maybe_bool(k, v);
549
if (0 <= boolval) {
550
allow_fast_forward = boolval;
@@ -562,6 +557,9 @@ static int git_merge_config(const char *k, const char *v, void *cb)
557
default_to_upstream = git_config_bool(k, v);
558
return 0;
559
}
560
+ status = fmt_merge_msg_config(k, v, cb);
561
+ if (status)
562
+ return status;
563
return git_diff_ui_config(k, v, cb);
564
}
565
@@ -1035,6 +1033,8 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
1033
parse_branch_merge_options(branch_mergeoptions);
1034
argc = parse_options(argc, argv, prefix, builtin_merge_options,
1035
builtin_merge_usage, 0);
1036
+ if (shortlog_len < 0)
1037
+ shortlog_len = (merge_log_config > 0) ? merge_log_config : 0;
1038
1039
if (verbosity < 0 && show_progress == -1)
1040
show_progress = 0;
environment.c
+1
@@ -58,6 +58,7 @@ enum object_creation_mode object_creation_mode = OBJECT_CREATION_MODE;
58
char *notes_ref_name;
59
int grafts_replace_parents = 1;
60
int core_apply_sparse_checkout;
61
+int merge_log_config = -1;
62
struct startup_info *startup_info;
63
64
/* Parallel index stat data preload? */
fmt-merge-msg.h
new
+7
@@ -0,0 +1,7 @@
1
+#ifndef FMT_MERGE_MSG_H
2
+#define FMT_MERGE_MSG_H
3
+
4
+extern int merge_log_config;
5
+extern int fmt_merge_msg_config(const char *key, const char *value, void *cb);
6
+
7
+#endif /* FMT_MERGE_MSG_H */