find_first_merges(): remove unnecessary code
[gitweb.git] / revision.c
index 95d21e6472921ab993373ef1848357379440d46e..be73cb46c95e87dd67ac72eb72d575bcd5fc7437 100644 (file)
@@ -13,6 +13,7 @@
 #include "decorate.h"
 #include "log-tree.h"
 #include "string-list.h"
+#include "mailmap.h"
 
 volatile show_early_output_fn_t show_early_output;
 
@@ -69,7 +70,8 @@ static int show_path_truncated(FILE *out, const struct name_path *path)
        return ours || emitted;
 }
 
-void show_object_with_name(FILE *out, struct object *obj, const struct name_path *path, const char *component)
+void show_object_with_name(FILE *out, struct object *obj,
+                          const struct name_path *path, const char *component)
 {
        struct name_path leaf;
        leaf.up = (struct name_path *)path;
@@ -185,7 +187,9 @@ void mark_parents_uninteresting(struct commit *commit)
        }
 }
 
-static void add_pending_object_with_mode(struct rev_info *revs, struct object *obj, const char *name, unsigned mode)
+static void add_pending_object_with_mode(struct rev_info *revs,
+                                        struct object *obj,
+                                        const char *name, unsigned mode)
 {
        if (!obj)
                return;
@@ -208,7 +212,8 @@ static void add_pending_object_with_mode(struct rev_info *revs, struct object *o
        add_object_array_with_mode(obj, name, &revs->pending, mode);
 }
 
-void add_pending_object(struct rev_info *revs, struct object *obj, const char *name)
+void add_pending_object(struct rev_info *revs,
+                       struct object *obj, const char *name)
 {
        add_pending_object_with_mode(revs, obj, name, S_IFINVALID);
 }
@@ -225,7 +230,9 @@ void add_head_to_pending(struct rev_info *revs)
        add_pending_object(revs, obj, "HEAD");
 }
 
-static struct object *get_reference(struct rev_info *revs, const char *name, const unsigned char *sha1, unsigned int flags)
+static struct object *get_reference(struct rev_info *revs, const char *name,
+                                   const unsigned char *sha1,
+                                   unsigned int flags)
 {
        struct object *object;
 
@@ -246,7 +253,8 @@ void add_pending_sha1(struct rev_info *revs, const char *name,
        add_pending_object(revs, object, name);
 }
 
-static struct commit *handle_commit(struct rev_info *revs, struct object *object, const char *name)
+static struct commit *handle_commit(struct rev_info *revs,
+                                   struct object *object, const char *name)
 {
        unsigned long flags = object->flags;
 
@@ -367,7 +375,8 @@ static void file_change(struct diff_options *options,
        DIFF_OPT_SET(options, HAS_CHANGES);
 }
 
-static int rev_compare_tree(struct rev_info *revs, struct commit *parent, struct commit *commit)
+static int rev_compare_tree(struct rev_info *revs,
+                           struct commit *parent, struct commit *commit)
 {
        struct tree *t1 = parent->tree;
        struct tree *t2 = commit->tree;
@@ -708,7 +717,7 @@ static int still_interesting(struct commit_list *src, unsigned long date, int sl
         * Does the destination list contain entries with a date
         * before the source list? Definitely _not_ done.
         */
-       if (date < src->item->date)
+       if (date <= src->item->date)
                return SLOP;
 
        /*
@@ -897,6 +906,10 @@ static int limit_list(struct rev_info *revs)
        return 0;
 }
 
+/*
+ * Add an entry to refs->cmdline with the specified information.
+ * *name is copied.
+ */
 static void add_rev_cmdline(struct rev_info *revs,
                            struct object *item,
                            const char *name,
@@ -908,7 +921,7 @@ static void add_rev_cmdline(struct rev_info *revs,
 
        ALLOC_GROW(info->rev, nr + 1, info->alloc);
        info->rev[nr].item = item;
-       info->rev[nr].name = name;
+       info->rev[nr].name = xstrdup(name);
        info->rev[nr].whence = whence;
        info->rev[nr].flags = flags;
        info->nr++;
@@ -1275,7 +1288,8 @@ static void read_revisions_from_stdin(struct rev_info *revs,
                        }
                        die("options not supported in --stdin mode");
                }
-               if (handle_revision_arg(sb.buf, revs, 0, REVARG_CANNOT_BE_FILENAME))
+               if (handle_revision_arg(xstrdup(sb.buf), revs, 0,
+                                       REVARG_CANNOT_BE_FILENAME))
                        die("bad revision '%s'", sb.buf);
        }
        if (seen_dashdash)
@@ -2021,10 +2035,11 @@ static struct commit_list **simplify_one(struct rev_info *revs, struct commit *c
                if (revs->first_parent_only)
                        break;
        }
-       if (!revs->first_parent_only)
-               cnt = remove_duplicate_parents(commit);
-       else
+
+       if (revs->first_parent_only)
                cnt = 1;
+       else
+               cnt = remove_duplicate_parents(commit);
 
        /*
         * It is possible that we are a merge and one side branch
@@ -2219,10 +2234,58 @@ static int rewrite_parents(struct rev_info *revs, struct commit *commit)
        return 0;
 }
 
+static int commit_rewrite_person(struct strbuf *buf, const char *what, struct string_list *mailmap)
+{
+       char *person, *endp;
+       size_t len, namelen, maillen;
+       const char *name;
+       const char *mail;
+       struct ident_split ident;
+
+       person = strstr(buf->buf, what);
+       if (!person)
+               return 0;
+
+       person += strlen(what);
+       endp = strchr(person, '\n');
+       if (!endp)
+               return 0;
+
+       len = endp - person;
+
+       if (split_ident_line(&ident, person, len))
+               return 0;
+
+       mail = ident.mail_begin;
+       maillen = ident.mail_end - ident.mail_begin;
+       name = ident.name_begin;
+       namelen = ident.name_end - ident.name_begin;
+
+       if (map_user(mailmap, &mail, &maillen, &name, &namelen)) {
+               struct strbuf namemail = STRBUF_INIT;
+
+               strbuf_addf(&namemail, "%.*s <%.*s>",
+                           (int)namelen, name, (int)maillen, mail);
+
+               strbuf_splice(buf, ident.name_begin - buf->buf,
+                             ident.mail_end - ident.name_begin + 1,
+                             namemail.buf, namemail.len);
+
+               strbuf_release(&namemail);
+
+               return 1;
+       }
+
+       return 0;
+}
+
 static int commit_match(struct commit *commit, struct rev_info *opt)
 {
        int retval;
+       const char *encoding;
+       char *message;
        struct strbuf buf = STRBUF_INIT;
+
        if (!opt->grep_filter.pattern_list && !opt->grep_filter.header_list)
                return 1;
 
@@ -2233,25 +2296,43 @@ static int commit_match(struct commit *commit, struct rev_info *opt)
                strbuf_addch(&buf, '\n');
        }
 
+       /*
+        * We grep in the user's output encoding, under the assumption that it
+        * is the encoding they are most likely to write their grep pattern
+        * for. In addition, it means we will match the "notes" encoding below,
+        * so we will not end up with a buffer that has two different encodings
+        * in it.
+        */
+       encoding = get_log_output_encoding();
+       message = logmsg_reencode(commit, NULL, encoding);
+
        /* Copy the commit to temporary if we are using "fake" headers */
        if (buf.len)
-               strbuf_addstr(&buf, commit->buffer);
+               strbuf_addstr(&buf, message);
+
+       if (opt->grep_filter.header_list && opt->mailmap) {
+               if (!buf.len)
+                       strbuf_addstr(&buf, message);
+
+               commit_rewrite_person(&buf, "\nauthor ", opt->mailmap);
+               commit_rewrite_person(&buf, "\ncommitter ", opt->mailmap);
+       }
 
        /* Append "fake" message parts as needed */
        if (opt->show_notes) {
                if (!buf.len)
-                       strbuf_addstr(&buf, commit->buffer);
-               format_display_notes(commit->object.sha1, &buf,
-                                    get_log_output_encoding(), 1);
+                       strbuf_addstr(&buf, message);
+               format_display_notes(commit->object.sha1, &buf, encoding, 1);
        }
 
-       /* Find either in the commit object, or in the temporary */
+       /* Find either in the original commit message, or in the temporary */
        if (buf.len)
                retval = grep_buffer(&opt->grep_filter, buf.buf, buf.len);
        else
                retval = grep_buffer(&opt->grep_filter,
-                                    commit->buffer, strlen(commit->buffer));
+                                    message, strlen(message));
        strbuf_release(&buf);
+       logmsg_free(message, commit);
        return retval;
 }
 
@@ -2354,25 +2435,23 @@ static struct commit *get_revision_1(struct rev_info *revs)
        return NULL;
 }
 
-static void gc_boundary(struct object_array *array)
+/*
+ * Return true for entries that have not yet been shown.  (This is an
+ * object_array_each_func_t.)
+ */
+static int entry_unshown(struct object_array_entry *entry, void *cb_data_unused)
 {
-       unsigned nr = array->nr;
-       unsigned alloc = array->alloc;
-       struct object_array_entry *objects = array->objects;
+       return !(entry->item->flags & SHOWN);
+}
 
-       if (alloc <= nr) {
-               unsigned i, j;
-               for (i = j = 0; i < nr; i++) {
-                       if (objects[i].item->flags & SHOWN)
-                               continue;
-                       if (i != j)
-                               objects[j] = objects[i];
-                       j++;
-               }
-               for (i = j; i < nr; i++)
-                       objects[i].item = NULL;
-               array->nr = j;
-       }
+/*
+ * If array is on the verge of a realloc, garbage-collect any entries
+ * that have already been shown to try to free up some space.
+ */
+static void gc_boundary(struct object_array *array)
+{
+       if (array->nr == array->alloc)
+               object_array_filter(array, entry_unshown, NULL);
 }
 
 static void create_boundary_commit_list(struct rev_info *revs)