From: René Scharfe Date: Wed, 07 Mar 2012 21:22:19 GMT Subject: Re: [PATCH] fmt-merge-msg: show those involved in a merged series Message-ID: <4F57D18B.5090506@lsrfire.ath.cx> In-Reply-To: <7vmx7uzq8h.fsf_-_@alter.siamese.dyndns.org> Am 05.03.2012 22:34, schrieb Junio C Hamano: > diff --git a/builtin/fmt-merge-msg.c b/builtin/fmt-merge-msg.c > index c81a7fe..b2465b4 100644 > --- a/builtin/fmt-merge-msg.c > +++ b/builtin/fmt-merge-msg.c > @@ -27,6 +27,8 @@ int fmt_merge_msg_config(const char *key, const char *value, void *cb) > merge_log_config = DEFAULT_MERGE_LOG_LEN; > } else if (!strcmp(key, "merge.branchdesc")) { > use_branch_desc = git_config_bool(key, value); > + } else { > + return git_default_config(key, value, cb); > } > return 0; > } > @@ -180,6 +182,89 @@ static void add_branch_desc(struct strbuf *out, const char *name) > strbuf_release(&desc); > } > > +static void record_person(int which, struct string_list *people, > + struct commit *commit) > +{ > + char name_buf[MAX_GITNAME], *name, *name_end; > + struct string_list_item *elem; > + const char *field = (which == 'a') ? "\nauthor " : "\ncommitter "; > + > + name = strstr(commit->buffer, field); > + if (!name) > + return; > + name += strlen(field); > + name_end = strchrnul(name, '<'); > + if (*name_end) > + name_end--; > + while (isspace(*name_end) && name <= name_end) > + name_end--; > + if (name_end < name || name + MAX_GITNAME <= name_end) > + return; > + memcpy(name_buf, name, name_end - name + 1); > + name_buf[name_end - name + 1] = '\0'; > + > + elem = string_list_lookup(people, name_buf); > + if (!elem) { > + elem = string_list_insert(people, name_buf); > + elem->util = (void *) 0; > + } > + elem->util = (void*)(((intptr_t)elem->util) + 1); > +} > + > +#define util_as_int(elem) ((intptr_t)((elem)->util)) Something that actually returns an int would fit the name better. ;) > + > +static int cmp_string_list_util_as_int(const void *a_, const void *b_) > +{ > + const struct string_list_item *a = a_, *b = b_; > + return util_as_int(b) - util_as_int(a); > +} > + > +static void add_people_count(struct strbuf *out, struct string_list *people) > +{ > + if (people->nr == 1) > + strbuf_addf(out, "%s", people->items[0].string); > + else if (people->nr == 2) > + strbuf_addf(out, "%s (%d) and %s (%d)", > + people->items[0].string, > + (int)util_as_int(&people->items[0]), > + people->items[1].string, > + (int)util_as_int(&people->items[1])); > + else if (people->nr) > + strbuf_addf(out, "%s (%d) and others", > + people->items[0].string, > + (int)util_as_int(&people->items[0])); > +} > + > +static int committer_is_me(const char *name) > +{ > + int namelen = strlen(name); > + const char *me = git_committer_info(IDENT_NO_DATE); > + return (me && !memcmp(me, name, namelen) && > + !memcmp(me + namelen, " <", 2)); > +} This looks scary due to the missing length check of me before the memcmp() call, but is actually safe because git_committer_info() returns a pointer to a static buffer that is just as long as name can possibly be. Still, perhaps this is nicer instead: const char *me = git_committer_info(IDENT_NO_DATE); const char *rest = skip_prefix(me, name); return rest && skip_prefix(rest, " <"); René