Skip to content

Commit 503c15a

Browse files
committed
Merge branch 'jc/fmt-merge-msg-people'
The "fmt-merge-msg" command learns to list the primary contributors involved in the side topic you are merging. * jc/fmt-merge-msg-people: fmt-merge-msg: show those involved in a merged series
2 parents 0bb2ee1 + 418a143 commit 503c15a

File tree

2 files changed

+134
-7
lines changed

2 files changed

+134
-7
lines changed

builtin/fmt-merge-msg.c

Lines changed: 110 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ int fmt_merge_msg_config(const char *key, const char *value, void *cb)
2727
merge_log_config = DEFAULT_MERGE_LOG_LEN;
2828
} else if (!strcmp(key, "merge.branchdesc")) {
2929
use_branch_desc = git_config_bool(key, value);
30+
} else {
31+
return git_default_config(key, value, cb);
3032
}
3133
return 0;
3234
}
@@ -180,6 +182,101 @@ static void add_branch_desc(struct strbuf *out, const char *name)
180182
strbuf_release(&desc);
181183
}
182184

185+
#define util_as_integral(elem) ((intptr_t)((elem)->util))
186+
187+
static void record_person(int which, struct string_list *people,
188+
struct commit *commit)
189+
{
190+
char name_buf[MAX_GITNAME], *name, *name_end;
191+
struct string_list_item *elem;
192+
const char *field = (which == 'a') ? "\nauthor " : "\ncommitter ";
193+
194+
name = strstr(commit->buffer, field);
195+
if (!name)
196+
return;
197+
name += strlen(field);
198+
name_end = strchrnul(name, '<');
199+
if (*name_end)
200+
name_end--;
201+
while (isspace(*name_end) && name <= name_end)
202+
name_end--;
203+
if (name_end < name || name + MAX_GITNAME <= name_end)
204+
return;
205+
memcpy(name_buf, name, name_end - name + 1);
206+
name_buf[name_end - name + 1] = '\0';
207+
208+
elem = string_list_lookup(people, name_buf);
209+
if (!elem) {
210+
elem = string_list_insert(people, name_buf);
211+
elem->util = (void *)0;
212+
}
213+
elem->util = (void*)(util_as_integral(elem) + 1);
214+
}
215+
216+
static int cmp_string_list_util_as_integral(const void *a_, const void *b_)
217+
{
218+
const struct string_list_item *a = a_, *b = b_;
219+
return util_as_integral(b) - util_as_integral(a);
220+
}
221+
222+
static void add_people_count(struct strbuf *out, struct string_list *people)
223+
{
224+
if (people->nr == 1)
225+
strbuf_addf(out, "%s", people->items[0].string);
226+
else if (people->nr == 2)
227+
strbuf_addf(out, "%s (%d) and %s (%d)",
228+
people->items[0].string,
229+
(int)util_as_integral(&people->items[0]),
230+
people->items[1].string,
231+
(int)util_as_integral(&people->items[1]));
232+
else if (people->nr)
233+
strbuf_addf(out, "%s (%d) and others",
234+
people->items[0].string,
235+
(int)util_as_integral(&people->items[0]));
236+
}
237+
238+
static void credit_people(struct strbuf *out,
239+
struct string_list *them,
240+
int kind)
241+
{
242+
const char *label;
243+
const char *me;
244+
245+
if (kind == 'a') {
246+
label = "\nBy ";
247+
me = git_author_info(IDENT_NO_DATE);
248+
} else {
249+
label = "\nvia ";
250+
me = git_committer_info(IDENT_NO_DATE);
251+
}
252+
253+
if (!them->nr ||
254+
(them->nr == 1 &&
255+
me &&
256+
(me = skip_prefix(me, them->items->string)) != NULL &&
257+
skip_prefix(me, " <")))
258+
return;
259+
strbuf_addstr(out, label);
260+
add_people_count(out, them);
261+
}
262+
263+
static void add_people_info(struct strbuf *out,
264+
struct string_list *authors,
265+
struct string_list *committers)
266+
{
267+
if (authors->nr)
268+
qsort(authors->items,
269+
authors->nr, sizeof(authors->items[0]),
270+
cmp_string_list_util_as_integral);
271+
if (committers->nr)
272+
qsort(committers->items,
273+
committers->nr, sizeof(committers->items[0]),
274+
cmp_string_list_util_as_integral);
275+
276+
credit_people(out, authors, 'a');
277+
credit_people(out, committers, 'c');
278+
}
279+
183280
static void shortlog(const char *name,
184281
struct origin_data *origin_data,
185282
struct commit *head,
@@ -190,6 +287,8 @@ static void shortlog(const char *name,
190287
struct commit *commit;
191288
struct object *branch;
192289
struct string_list subjects = STRING_LIST_INIT_DUP;
290+
struct string_list authors = STRING_LIST_INIT_DUP;
291+
struct string_list committers = STRING_LIST_INIT_DUP;
193292
int flags = UNINTERESTING | TREESAME | SEEN | SHOWN | ADDED;
194293
struct strbuf sb = STRBUF_INIT;
195294
const unsigned char *sha1 = origin_data->sha1;
@@ -199,7 +298,6 @@ static void shortlog(const char *name,
199298
return;
200299

201300
setup_revisions(0, NULL, rev, NULL);
202-
rev->ignore_merges = 1;
203301
add_pending_object(rev, branch, name);
204302
add_pending_object(rev, &head->object, "^HEAD");
205303
head->object.flags |= UNINTERESTING;
@@ -208,10 +306,15 @@ static void shortlog(const char *name,
208306
while ((commit = get_revision(rev)) != NULL) {
209307
struct pretty_print_context ctx = {0};
210308

211-
/* ignore merges */
212-
if (commit->parents && commit->parents->next)
309+
if (commit->parents && commit->parents->next) {
310+
/* do not list a merge but count committer */
311+
record_person('c', &committers, commit);
213312
continue;
214-
313+
}
314+
if (!count)
315+
/* the 'tip' committer */
316+
record_person('c', &committers, commit);
317+
record_person('a', &authors, commit);
215318
count++;
216319
if (subjects.nr > limit)
217320
continue;
@@ -226,6 +329,7 @@ static void shortlog(const char *name,
226329
string_list_append(&subjects, strbuf_detach(&sb, NULL));
227330
}
228331

332+
add_people_info(out, &authors, &committers);
229333
if (count > limit)
230334
strbuf_addf(out, "\n* %s: (%d commits)\n", name, count);
231335
else
@@ -246,6 +350,8 @@ static void shortlog(const char *name,
246350
rev->commits = NULL;
247351
rev->pending.nr = 0;
248352

353+
string_list_clear(&authors, 0);
354+
string_list_clear(&committers, 0);
249355
string_list_clear(&subjects, 0);
250356
}
251357

t/t6200-fmt-merge-msg.sh

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,15 +35,18 @@ test_expect_success setup '
3535
3636
echo "l3" >two &&
3737
test_tick &&
38-
git commit -a -m "Left #3" &&
38+
GIT_COMMITTER_NAME="Another Committer" \
39+
GIT_AUTHOR_NAME="Another Author" git commit -a -m "Left #3" &&
3940
4041
echo "l4" >two &&
4142
test_tick &&
42-
git commit -a -m "Left #4" &&
43+
GIT_COMMITTER_NAME="Another Committer" \
44+
GIT_AUTHOR_NAME="Another Author" git commit -a -m "Left #4" &&
4345
4446
echo "l5" >two &&
4547
test_tick &&
46-
git commit -a -m "Left #5" &&
48+
GIT_COMMITTER_NAME="Another Committer" \
49+
GIT_AUTHOR_NAME="Another Author" git commit -a -m "Left #5" &&
4750
git tag tag-l5 &&
4851
4952
git checkout right &&
@@ -99,6 +102,8 @@ test_expect_success '[merge] summary/log configuration' '
99102
cat >expected <<-EOF &&
100103
Merge branch ${apos}left${apos}
101104
105+
By Another Author (3) and A U Thor (2)
106+
via Another Committer
102107
* left:
103108
Left #5
104109
Left #4
@@ -144,6 +149,8 @@ test_expect_success 'merge.log=3 limits shortlog length' '
144149
cat >expected <<-EOF &&
145150
Merge branch ${apos}left${apos}
146151
152+
By Another Author (3) and A U Thor (2)
153+
via Another Committer
147154
* left: (5 commits)
148155
Left #5
149156
Left #4
@@ -159,6 +166,8 @@ test_expect_success 'merge.log=5 shows all 5 commits' '
159166
cat >expected <<-EOF &&
160167
Merge branch ${apos}left${apos}
161168
169+
By Another Author (3) and A U Thor (2)
170+
via Another Committer
162171
* left:
163172
Left #5
164173
Left #4
@@ -181,6 +190,8 @@ test_expect_success '--log=3 limits shortlog length' '
181190
cat >expected <<-EOF &&
182191
Merge branch ${apos}left${apos}
183192
193+
By Another Author (3) and A U Thor (2)
194+
via Another Committer
184195
* left: (5 commits)
185196
Left #5
186197
Left #4
@@ -196,6 +207,8 @@ test_expect_success '--log=5 shows all 5 commits' '
196207
cat >expected <<-EOF &&
197208
Merge branch ${apos}left${apos}
198209
210+
By Another Author (3) and A U Thor (2)
211+
via Another Committer
199212
* left:
200213
Left #5
201214
Left #4
@@ -225,6 +238,8 @@ test_expect_success 'fmt-merge-msg -m' '
225238
cat >expected.log <<-EOF &&
226239
Sync with left
227240
241+
By Another Author (3) and A U Thor (2)
242+
via Another Committer
228243
* ${apos}left${apos} of $(pwd):
229244
Left #5
230245
Left #4
@@ -256,6 +271,8 @@ test_expect_success 'setup: expected shortlog for two branches' '
256271
cat >expected <<-EOF
257272
Merge branches ${apos}left${apos} and ${apos}right${apos}
258273
274+
By Another Author (3) and A U Thor (2)
275+
via Another Committer
259276
* left:
260277
Left #5
261278
Left #4
@@ -379,6 +396,8 @@ test_expect_success 'merge-msg two tags' '
379396
Common #2
380397
Common #1
381398
399+
By Another Author (3) and A U Thor (2)
400+
via Another Committer
382401
* tag ${apos}tag-l5${apos}:
383402
Left #5
384403
Left #4
@@ -407,6 +426,8 @@ test_expect_success 'merge-msg tag and branch' '
407426
Common #2
408427
Common #1
409428
429+
By Another Author (3) and A U Thor (2)
430+
via Another Committer
410431
* left:
411432
Left #5
412433
Left #4

0 commit comments

Comments
 (0)