Sync with 2.7.1
[gitweb.git] / builtin / shortlog.c
index a7708c3a333d2266fab5bdeec3b2b04baa3003af..bfc082e58467953c1e4c96fd27a884abea4f5127 100644 (file)
@@ -14,7 +14,26 @@ static char const * const shortlog_usage[] = {
        NULL
 };
 
-static int compare_by_number(const void *a1, const void *a2)
+/*
+ * The util field of our string_list_items will contain one of two things:
+ *
+ *   - if --summary is not in use, it will point to a string list of the
+ *     oneline subjects assigned to this author
+ *
+ *   - if --summary is in use, we don't need that list; we only need to know
+ *     its size. So we abuse the pointer slot to store our integer counter.
+ *
+ *  This macro accesses the latter.
+ */
+#define UTIL_TO_INT(x) ((intptr_t)(x)->util)
+
+static int compare_by_counter(const void *a1, const void *a2)
+{
+       const struct string_list_item *i1 = a1, *i2 = a2;
+       return UTIL_TO_INT(i2) - UTIL_TO_INT(i1);
+}
+
+static int compare_by_list(const void *a1, const void *a2)
 {
        const struct string_list_item *i1 = a1, *i2 = a2;
        const struct string_list *l1 = i1->util, *l2 = i2->util;
@@ -52,11 +71,9 @@ static void insert_one_record(struct shortlog *log,
                strbuf_addf(&namemailbuf, " <%.*s>", (int)maillen, mailbuf);
 
        item = string_list_insert(&log->list, namemailbuf.buf);
-       if (item->util == NULL)
-               item->util = xcalloc(1, sizeof(struct string_list));
 
        if (log->summary)
-               string_list_append(item->util, xstrdup(""));
+               item->util = (void *)(UTIL_TO_INT(item) + 1);
        else {
                const char *dot3 = log->common_repo_prefix;
                char *buffer, *p;
@@ -90,6 +107,8 @@ static void insert_one_record(struct shortlog *log,
                        }
                }
 
+               if (item->util == NULL)
+                       item->util = xcalloc(1, sizeof(struct string_list));
                string_list_append(item->util, buffer);
        }
 }
@@ -99,15 +118,15 @@ static void read_from_stdin(struct shortlog *log)
        struct strbuf author = STRBUF_INIT;
        struct strbuf oneline = STRBUF_INIT;
 
-       while (strbuf_getline(&author, stdin, '\n') != EOF) {
+       while (strbuf_getline_lf(&author, stdin) != EOF) {
                const char *v;
                if (!skip_prefix(author.buf, "Author: ", &v) &&
                    !skip_prefix(author.buf, "author ", &v))
                        continue;
-               while (strbuf_getline(&oneline, stdin, '\n') != EOF &&
+               while (strbuf_getline_lf(&oneline, stdin) != EOF &&
                       oneline.len)
                        ; /* discard headers */
-               while (strbuf_getline(&oneline, stdin, '\n') != EOF &&
+               while (strbuf_getline_lf(&oneline, stdin) != EOF &&
                       !oneline.len)
                        ; /* discard blanks */
                insert_one_record(log, v, oneline.buf);
@@ -130,13 +149,6 @@ void shortlog_add_commit(struct shortlog *log, struct commit *commit)
        ctx.output_encoding = get_log_output_encoding();
 
        format_commit_message(commit, "%an <%ae>", &author, &ctx);
-       /* we can detect a total failure only by seeing " <>" in the output */
-       if (author.len <= 3) {
-               warning(_("Missing author: %s"),
-                   oid_to_hex(&commit->object.oid));
-               goto out;
-       }
-
        if (!log->summary) {
                if (log->user_format)
                        pretty_print_commit(&ctx, commit, &oneline);
@@ -146,7 +158,6 @@ void shortlog_add_commit(struct shortlog *log, struct commit *commit)
 
        insert_one_record(log, author.buf, oneline.len ? oneline.buf : "<none>");
 
-out:
        strbuf_release(&author);
        strbuf_release(&oneline);
 }
@@ -295,14 +306,14 @@ void shortlog_output(struct shortlog *log)
 
        if (log->sort_by_number)
                qsort(log->list.items, log->list.nr, sizeof(struct string_list_item),
-                       compare_by_number);
+                     log->summary ? compare_by_counter : compare_by_list);
        for (i = 0; i < log->list.nr; i++) {
-               struct string_list *onelines = log->list.items[i].util;
-
+               const struct string_list_item *item = &log->list.items[i];
                if (log->summary) {
-                       printf("%6d\t%s\n", onelines->nr, log->list.items[i].string);
+                       printf("%6d\t%s\n", (int)UTIL_TO_INT(item), item->string);
                } else {
-                       printf("%s (%d):\n", log->list.items[i].string, onelines->nr);
+                       struct string_list *onelines = item->util;
+                       printf("%s (%d):\n", item->string, onelines->nr);
                        for (j = onelines->nr - 1; j >= 0; j--) {
                                const char *msg = onelines->items[j].string;
 
@@ -315,11 +326,11 @@ void shortlog_output(struct shortlog *log)
                                        printf("      %s\n", msg);
                        }
                        putchar('\n');
+                       onelines->strdup_strings = 1;
+                       string_list_clear(onelines, 0);
+                       free(onelines);
                }
 
-               onelines->strdup_strings = 1;
-               string_list_clear(onelines, 0);
-               free(onelines);
                log->list.items[i].util = NULL;
        }