Merge branch 'ms/mailmap'
authorJunio C Hamano <gitster@pobox.com>
Sun, 15 Feb 2009 09:44:15 +0000 (01:44 -0800)
committerJunio C Hamano <gitster@pobox.com>
Sun, 15 Feb 2009 09:44:15 +0000 (01:44 -0800)
* ms/mailmap:
Move mailmap documentation into separate file
Change current mailmap usage to do matching on both name and email of author/committer.
Add map_user() and clear_mailmap() to mailmap
Add find_insert_index, insert_at_index and clear_func functions to string_list
Add mailmap.file as configurational option for mailmap location

1  2 
Documentation/config.txt
builtin-blame.c
cache.h
pretty.c
diff --combined Documentation/config.txt
index 1806a606100095fa1238076efed57ba7e79142aa,6dd57bd52c8d4735899a89a5136072e841f59f91..f5152c5038b49ab5ebe3804e8e9b314d4a752690
@@@ -556,8 -556,8 +556,8 @@@ color.interactive:
  
  color.interactive.<slot>::
        Use customized color for 'git-add --interactive'
 -      output. `<slot>` may be `prompt`, `header`, or `help`, for
 -      three distinct types of normal output from interactive
 +      output. `<slot>` may be `prompt`, `header`, `help` or `error`, for
 +      four distinct types of normal output from interactive
        programs.  The values of these variables may be specified as
        in color.branch.<slot>.
  
@@@ -1000,13 -1000,6 +1000,13 @@@ instaweb.port:
        The port number to bind the gitweb httpd to. See
        linkgit:git-instaweb[1].
  
 +interactive.singlekey::
 +      In interactive programs, allow the user to provide one-letter
 +      input with a single key (i.e., without hitting enter).
 +      Currently this is used only by the `\--patch` mode of
 +      linkgit:git-add[1].  Note that this setting is silently
 +      ignored if portable keystroke input is not available.
 +
  log.date::
        Set default date-time mode for the log command. Setting log.date
        value is similar to using 'git-log'\'s --date option. The value is one of the
@@@ -1019,6 -1012,14 +1019,14 @@@ log.showroot:
        Tools like linkgit:git-log[1] or linkgit:git-whatchanged[1], which
        normally hide the root commit will now show it. True by default.
  
+ mailmap.file::
+       The location of an augmenting mailmap file. The default
+       mailmap, located in the root of the repository, is loaded
+       first, then the mailmap file pointed to by this variable.
+       The location of the mailmap file may be in a repository
+       subdirectory, or somewhere outside of the repository itself.
+       See linkgit:git-shortlog[1] and linkgit:git-blame[1].
  man.viewer::
        Specify the programs that may be used to display help in the
        'man' format. See linkgit:git-help[1].
diff --combined builtin-blame.c
index 9b9f5442a277082c8ad04295107eb9ddd6c95b19,f3be9fa9a516b8cf03cd25c0af2d1d8f50670b51..114a214ed3fef40ae5cc13737d037f29d6f8acfd
@@@ -19,7 -19,6 +19,7 @@@
  #include "string-list.h"
  #include "mailmap.h"
  #include "parse-options.h"
 +#include "utf8.h"
  
  static char blame_usage[] = "git blame [options] [rev-opts] [rev] [--] file";
  
@@@ -1264,11 -1263,12 +1264,12 @@@ struct commit_inf
   * Parse author/committer line in the commit object buffer
   */
  static void get_ac_line(const char *inbuf, const char *what,
-                       int bufsz, char *person, const char **mail,
+                       int person_len, char *person,
+                       int mail_len, char *mail,
                        unsigned long *time, const char **tz)
  {
        int len, tzlen, maillen;
-       char *tmp, *endp, *timepos;
+       char *tmp, *endp, *timepos, *mailpos;
  
        tmp = strstr(inbuf, what);
        if (!tmp)
                len = strlen(tmp);
        else
                len = endp - tmp;
-       if (bufsz <= len) {
+       if (person_len <= len) {
        error_out:
                /* Ugh */
-               *mail = *tz = "(unknown)";
+               *tz = "(unknown)";
+               strcpy(mail, *tz);
                *time = 0;
                return;
        }
        *tmp = 0;
        while (*tmp != ' ')
                tmp--;
-       *mail = tmp + 1;
+       mailpos = tmp + 1;
        *tmp = 0;
        maillen = timepos - tmp;
+       memcpy(mail, mailpos, maillen);
  
        if (!mailmap.nr)
                return;
         * mailmap expansion may make the name longer.
         * make room by pushing stuff down.
         */
-       tmp = person + bufsz - (tzlen + 1);
+       tmp = person + person_len - (tzlen + 1);
        memmove(tmp, *tz, tzlen);
        tmp[tzlen] = 0;
        *tz = tmp;
  
-       tmp = tmp - (maillen + 1);
-       memmove(tmp, *mail, maillen);
-       tmp[maillen] = 0;
-       *mail = tmp;
        /*
-        * Now, convert e-mail using mailmap
+        * Now, convert both name and e-mail using mailmap
         */
-       map_email(&mailmap, tmp + 1, person, tmp-person-1);
+       if(map_user(&mailmap, mail+1, mail_len-1, person, tmp-person-1)) {
+               /* Add a trailing '>' to email, since map_user returns plain emails
+                  Note: It already has '<', since we replace from mail+1 */
+               mailpos = memchr(mail, '\0', mail_len);
+               if (mailpos && mailpos-mail < mail_len - 1) {
+                       *mailpos = '>';
+                       *(mailpos+1) = '\0';
+               }
+       }
  }
  
  static void get_commit_info(struct commit *commit,
  {
        int len;
        char *tmp, *endp, *reencoded, *message;
-       static char author_buf[1024];
-       static char committer_buf[1024];
+       static char author_name[1024];
+       static char author_mail[1024];
+       static char committer_name[1024];
+       static char committer_mail[1024];
        static char summary_buf[1024];
  
        /*
        }
        reencoded = reencode_commit_message(commit, NULL);
        message   = reencoded ? reencoded : commit->buffer;
-       ret->author = author_buf;
+       ret->author = author_name;
+       ret->author_mail = author_mail;
        get_ac_line(message, "\nauthor ",
-                   sizeof(author_buf), author_buf, &ret->author_mail,
+                   sizeof(author_name), author_name,
+                   sizeof(author_mail), author_mail,
                    &ret->author_time, &ret->author_tz);
  
        if (!detailed) {
                return;
        }
  
-       ret->committer = committer_buf;
+       ret->committer = committer_name;
+       ret->committer_mail = committer_mail;
        get_ac_line(message, "\ncommitter ",
-                   sizeof(committer_buf), committer_buf, &ret->committer_mail,
+                   sizeof(committer_name), committer_name,
+                   sizeof(committer_mail), committer_mail,
                    &ret->committer_time, &ret->committer_tz);
  
        ret->summary = summary_buf;
@@@ -1619,14 -1630,13 +1631,14 @@@ static void emit_other(struct scoreboar
                                printf(" %*d", max_orig_digits,
                                       ent->s_lno + 1 + cnt);
  
 -                      if (!(opt & OUTPUT_NO_AUTHOR))
 -                              printf(" (%-*.*s %10s",
 -                                     longest_author, longest_author,
 -                                     ci.author,
 +                      if (!(opt & OUTPUT_NO_AUTHOR)) {
 +                              int pad = longest_author - utf8_strwidth(ci.author);
 +                              printf(" (%s%*s %10s",
 +                                     ci.author, pad, "",
                                       format_time(ci.author_time,
                                                   ci.author_tz,
                                                   show_raw_time));
 +                      }
                        printf(" %*d) ",
                               max_digits, ent->lno + 1 + cnt);
                }
@@@ -1757,7 -1767,7 +1769,7 @@@ static void find_alignment(struct score
                if (!(suspect->commit->object.flags & METAINFO_SHOWN)) {
                        suspect->commit->object.flags |= METAINFO_SHOWN;
                        get_commit_info(suspect->commit, &ci, 1);
 -                      num = strlen(ci.author);
 +                      num = utf8_strwidth(ci.author);
                        if (longest_author < num)
                                longest_author = num;
                }
@@@ -2396,7 -2406,7 +2408,7 @@@ parse_done
                die("reading graft file %s failed: %s",
                    revs_file, strerror(errno));
  
-       read_mailmap(&mailmap, ".mailmap", NULL);
+       read_mailmap(&mailmap, NULL);
  
        if (!incremental)
                setup_pager();
diff --combined cache.h
index a7f435ddefe3ce780c684804af20d25a51bfded2,e88bcca96da5074aff86138493633c8d4ce3d9ad..37dfb1c18f5b19082ae82349cf4e89dd110dfdc9
+++ b/cache.h
@@@ -624,7 -624,7 +624,7 @@@ int is_directory(const char *)
  const char *make_absolute_path(const char *path);
  const char *make_nonrelative_path(const char *path);
  const char *make_relative_path(const char *abs, const char *base);
 -int normalize_absolute_path(char *buf, const char *path);
 +int normalize_path_copy(char *dst, const char *src);
  int longest_ancestor_length(const char *path, const char *prefix_list);
  
  /* Read and unpack a sha1 file into memory, write memory to a sha1 file */
@@@ -827,7 -827,6 +827,7 @@@ extern unsigned char* use_pack(struct p
  extern void close_pack_windows(struct packed_git *);
  extern void unuse_pack(struct pack_window **);
  extern void free_pack_by_name(const char *);
 +extern void clear_delta_base_cache(void);
  extern struct packed_git *add_packed_git(const char *, int, int);
  extern const unsigned char *nth_packed_object_sha1(struct packed_git *, uint32_t);
  extern off_t nth_packed_object_offset(const struct packed_git *, uint32_t);
@@@ -868,6 -867,7 +868,7 @@@ extern int user_ident_explicitly_given
  
  extern const char *git_commit_encoding;
  extern const char *git_log_output_encoding;
+ extern const char *git_mailmap_file;
  
  /* IO helper functions */
  extern void maybe_flush_or_die(FILE *, const char *);
diff --combined pretty.c
index 428fbb61a331c667b52b1ad6f26c3765f951b6b9,29f81c3f44f7cc9185b23b75ac3e119d04b2c6c7..6cd91491d348b9aabea902c0ea60465074e9c06e
+++ b/pretty.c
@@@ -210,13 -210,15 +210,13 @@@ static void add_merge_info(enum cmit_fm
        while (parent) {
                struct commit *p = parent->item;
                const char *hex = NULL;
 -              const char *dots;
                if (abbrev)
                        hex = find_unique_abbrev(p->object.sha1, abbrev);
                if (!hex)
                        hex = sha1_to_hex(p->object.sha1);
 -              dots = (abbrev && strlen(hex) != 40) ?  "..." : "";
                parent = parent->next;
  
 -              strbuf_addf(sb, " %s%s", hex, dots);
 +              strbuf_addf(sb, " %s", hex);
        }
        strbuf_addch(sb, '\n');
  }
@@@ -303,23 -305,14 +303,14 @@@ static char *logmsg_reencode(const stru
        return out;
  }
  
- static int mailmap_name(struct strbuf *sb, const char *email)
+ static int mailmap_name(char *email, int email_len, char *name, int name_len)
  {
        static struct string_list *mail_map;
-       char buffer[1024];
        if (!mail_map) {
                mail_map = xcalloc(1, sizeof(*mail_map));
-               read_mailmap(mail_map, ".mailmap", NULL);
+               read_mailmap(mail_map, NULL);
        }
-       if (!mail_map->nr)
-               return -1;
-       if (!map_email(mail_map, email, buffer, sizeof(buffer)))
-               return -1;
-       strbuf_addstr(sb, buffer);
-       return 0;
+       return mail_map->nr && map_user(mail_map, email, email_len, name, name_len);
  }
  
  static size_t format_person_part(struct strbuf *sb, char part,
        int start, end, tz = 0;
        unsigned long date = 0;
        char *ep;
+       const char *name_start, *name_end, *mail_start, *mail_end, *msg_end = msg+len;
+       char person_name[1024];
+       char person_mail[1024];
  
        /* advance 'end' to point to email start delimiter */
        for (end = 0; end < len && msg[end] != '<'; end++)
        if (end >= len - 2)
                goto skip;
  
+       /* Seek for both name and email part */
+       name_start = msg;
+       name_end = msg+end;
+       while (name_end > name_start && isspace(*(name_end-1)))
+               name_end--;
+       mail_start = msg+end+1;
+       mail_end = mail_start;
+       while (mail_end < msg_end && *mail_end != '>')
+               mail_end++;
+       if (mail_end == msg_end)
+               goto skip;
+       end = mail_end-msg;
+       if (part == 'N' || part == 'E') { /* mailmap lookup */
+               strlcpy(person_name, name_start, name_end-name_start+1);
+               strlcpy(person_mail, mail_start, mail_end-mail_start+1);
+               mailmap_name(person_mail, sizeof(person_mail), person_name, sizeof(person_name));
+               name_start = person_name;
+               name_end = name_start + strlen(person_name);
+               mail_start = person_mail;
+               mail_end = mail_start +  strlen(person_mail);
+       }
        if (part == 'n' || part == 'N') {       /* name */
-               while (end > 0 && isspace(msg[end - 1]))
-                       end--;
-               if (part != 'N' || !msg[end] || !msg[end + 1] ||
-                   mailmap_name(sb, msg + end + 2) < 0)
-                       strbuf_add(sb, msg, end);
+               strbuf_add(sb, name_start, name_end-name_start);
                return placeholder_len;
        }
-       start = ++end; /* save email start position */
-       /* advance 'end' to point to email end delimiter */
-       for ( ; end < len && msg[end] != '>'; end++)
-               ; /* do nothing */
-       if (end >= len)
-               goto skip;
-       if (part == 'e') {      /* email */
-               strbuf_add(sb, msg + start, end - start);
+       if (part == 'e' || part == 'E') {       /* email */
+               strbuf_add(sb, mail_start, mail_end-mail_start);
                return placeholder_len;
        }