diff options
Diffstat (limited to 'builtin-shortlog.c')
-rw-r--r-- | builtin-shortlog.c | 158 |
1 files changed, 74 insertions, 84 deletions
diff --git a/builtin-shortlog.c b/builtin-shortlog.c index 29343aefc8..8d3f742d43 100644 --- a/builtin-shortlog.c +++ b/builtin-shortlog.c @@ -4,6 +4,8 @@ #include "diff.h" #include "path-list.h" #include "revision.h" +#include "utf8.h" +#include "mailmap.h" static const char shortlog_usage[] = "git-shortlog [-n] [-s] [<commit-id>... ]"; @@ -25,83 +27,6 @@ static int compare_by_number(const void *a1, const void *a2) static struct path_list mailmap = {NULL, 0, 0, 0}; -static int read_mailmap(const char *filename) -{ - char buffer[1024]; - FILE *f = fopen(filename, "r"); - - if (f == NULL) - return 1; - while (fgets(buffer, sizeof(buffer), f) != NULL) { - char *end_of_name, *left_bracket, *right_bracket; - char *name, *email; - int i; - if (buffer[0] == '#') { - static const char abbrev[] = "# repo-abbrev:"; - int abblen = sizeof(abbrev) - 1; - int len = strlen(buffer); - - if (len && buffer[len - 1] == '\n') - buffer[--len] = 0; - if (!strncmp(buffer, abbrev, abblen)) { - char *cp; - - if (common_repo_prefix) - free(common_repo_prefix); - common_repo_prefix = xmalloc(len); - - for (cp = buffer + abblen; isspace(*cp); cp++) - ; /* nothing */ - strcpy(common_repo_prefix, cp); - } - continue; - } - if ((left_bracket = strchr(buffer, '<')) == NULL) - continue; - if ((right_bracket = strchr(left_bracket + 1, '>')) == NULL) - continue; - if (right_bracket == left_bracket + 1) - continue; - for (end_of_name = left_bracket; end_of_name != buffer - && isspace(end_of_name[-1]); end_of_name--) - /* keep on looking */ - if (end_of_name == buffer) - continue; - name = xmalloc(end_of_name - buffer + 1); - strlcpy(name, buffer, end_of_name - buffer + 1); - email = xmalloc(right_bracket - left_bracket); - for (i = 0; i < right_bracket - left_bracket - 1; i++) - email[i] = tolower(left_bracket[i + 1]); - email[right_bracket - left_bracket - 1] = '\0'; - path_list_insert(email, &mailmap)->util = name; - } - fclose(f); - return 0; -} - -static int map_email(char *email, char *name, int maxlen) -{ - char *p; - struct path_list_item *item; - - /* autocomplete common developers */ - p = strchr(email, '>'); - if (!p) - return 0; - - *p = '\0'; - /* downcase the email address */ - for (p = email; *p; p++) - *p = tolower(*p); - item = path_list_lookup(email, &mailmap); - if (item != NULL) { - const char *realname = (const char *)item->util; - strncpy(name, realname, maxlen); - return 1; - } - return 0; -} - static void insert_author_oneline(struct path_list *list, const char *author, int authorlen, const char *oneline, int onelinelen) @@ -183,7 +108,7 @@ static void read_from_stdin(struct path_list *list) (bob = strchr(buffer + 7, '<')) != NULL) { char buffer2[1024], offset = 0; - if (map_email(bob + 1, buffer, sizeof(buffer))) + if (map_email(&mailmap, bob + 1, buffer, sizeof(buffer))) bob = buffer + strlen(buffer); else { offset = 8; @@ -237,7 +162,7 @@ static void get_from_rev(struct rev_info *rev, struct path_list *list) die("Invalid commit buffer: %s", sha1_to_hex(commit->object.sha1)); - if (map_email(bracket + 1, scratch, + if (map_email(&mailmap, bracket + 1, scratch, sizeof(scratch))) { author = scratch; authorlen = strlen(scratch); @@ -276,11 +201,64 @@ static void get_from_rev(struct rev_info *rev, struct path_list *list) } +static int parse_uint(char const **arg, int comma) +{ + unsigned long ul; + int ret; + char *endp; + + ul = strtoul(*arg, &endp, 10); + if (endp != *arg && *endp && *endp != comma) + return -1; + ret = (int) ul; + if (ret != ul) + return -1; + *arg = endp; + if (**arg) + (*arg)++; + return ret; +} + +static const char wrap_arg_usage[] = "-w[<width>[,<indent1>[,<indent2>]]]"; +#define DEFAULT_WRAPLEN 76 +#define DEFAULT_INDENT1 6 +#define DEFAULT_INDENT2 9 + +static void parse_wrap_args(const char *arg, int *in1, int *in2, int *wrap) +{ + arg += 2; /* skip -w */ + + *wrap = parse_uint(&arg, ','); + if (*wrap < 0) + die(wrap_arg_usage); + *in1 = parse_uint(&arg, ','); + if (*in1 < 0) + die(wrap_arg_usage); + *in2 = parse_uint(&arg, '\0'); + if (*in2 < 0) + die(wrap_arg_usage); + + if (!*wrap) + *wrap = DEFAULT_WRAPLEN; + if (!*in1) + *in1 = DEFAULT_INDENT1; + if (!*in2) + *in2 = DEFAULT_INDENT2; + if (*wrap && + ((*in1 && *wrap <= *in1) || + (*in2 && *wrap <= *in2))) + die(wrap_arg_usage); +} + int cmd_shortlog(int argc, const char **argv, const char *prefix) { struct rev_info rev; struct path_list list = { NULL, 0, 0, 1 }; int i, j, sort_by_number = 0, summary = 0; + int wrap_lines = 0; + int wrap = DEFAULT_WRAPLEN; + int in1 = DEFAULT_INDENT1; + int in2 = DEFAULT_INDENT2; /* since -n is a shadowed rev argument, parse our args first */ while (argc > 1) { @@ -289,6 +267,10 @@ int cmd_shortlog(int argc, const char **argv, const char *prefix) else if (!strcmp(argv[1], "-s") || !strcmp(argv[1], "--summary")) summary = 1; + else if (!prefixcmp(argv[1], "-w")) { + wrap_lines = 1; + parse_wrap_args(argv[1], &in1, &in2, &wrap); + } else if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) usage(shortlog_usage); else @@ -301,8 +283,7 @@ int cmd_shortlog(int argc, const char **argv, const char *prefix) if (argc > 1) die ("unrecognized argument: %s", argv[1]); - if (!access(".mailmap", R_OK)) - read_mailmap(".mailmap"); + read_mailmap(&mailmap, ".mailmap", &common_repo_prefix); if (rev.pending.nr == 0) { if (isatty(0)) @@ -323,9 +304,18 @@ int cmd_shortlog(int argc, const char **argv, const char *prefix) printf("%s: %d\n", list.items[i].path, onelines->nr); } else { printf("%s (%d):\n", list.items[i].path, onelines->nr); - for (j = onelines->nr - 1; j >= 0; j--) - printf(" %s\n", onelines->items[j].path); - printf("\n"); + for (j = onelines->nr - 1; j >= 0; j--) { + const char *msg = onelines->items[j].path; + + if (wrap_lines) { + int col = print_wrapped_text(msg, in1, in2, wrap); + if (col != wrap) + putchar('\n'); + } + else + printf(" %s\n", msg); + } + putchar('\n'); } onelines->strdup_paths = 1; |