Merge branch 'jk/pending-keep-tag-name'
[gitweb.git] / revision.c
index 0a0ef3ce5bb9a030b774dc68fc9c60533732a364..0a282f533b3e225a996221d614de8bdc960092a3 100644 (file)
 #include "mailmap.h"
 #include "commit-slab.h"
 #include "dir.h"
+#include "cache-tree.h"
+#include "bisect.h"
 
 volatile show_early_output_fn_t show_early_output;
 
+static const char *term_bad;
+static const char *term_good;
+
 char *path_name(const struct name_path *path, const char *name)
 {
        const struct name_path *p;
@@ -33,7 +38,7 @@ char *path_name(const struct name_path *path, const char *name)
        }
        n = xmalloc(len);
        m = n + len - (nlen + 1);
-       strcpy(m, name);
+       memcpy(m, name, nlen + 1);
        for (p = path; p; p = p->up) {
                if (p->elem_len) {
                        m -= p->elem_len + 1;
@@ -81,21 +86,11 @@ void show_object_with_name(FILE *out, struct object *obj,
        leaf.elem = component;
        leaf.elem_len = strlen(component);
 
-       fprintf(out, "%s ", sha1_to_hex(obj->sha1));
+       fprintf(out, "%s ", oid_to_hex(&obj->oid));
        show_path_truncated(out, &leaf);
        fputc('\n', out);
 }
 
-void add_object(struct object *obj,
-               struct object_array *p,
-               struct name_path *path,
-               const char *name)
-{
-       char *pn = path_name(path, name);
-       add_object_array(obj, pn, p);
-       free(pn);
-}
-
 static void mark_blob_uninteresting(struct blob *blob)
 {
        if (!blob)
@@ -111,10 +106,10 @@ static void mark_tree_contents_uninteresting(struct tree *tree)
        struct name_entry entry;
        struct object *obj = &tree->object;
 
-       if (!has_sha1_file(obj->sha1))
+       if (!has_object_file(&obj->oid))
                return;
        if (parse_tree(tree) < 0)
-               die("bad tree %s", sha1_to_hex(obj->sha1));
+               die("bad tree %s", oid_to_hex(&obj->oid));
 
        init_tree_desc(&desc, tree->buffer, tree->size);
        while (tree_entry(&desc, &entry)) {
@@ -140,10 +135,12 @@ static void mark_tree_contents_uninteresting(struct tree *tree)
 
 void mark_tree_uninteresting(struct tree *tree)
 {
-       struct object *obj = &tree->object;
+       struct object *obj;
 
        if (!tree)
                return;
+
+       obj = &tree->object;
        if (obj->flags & UNINTERESTING)
                return;
        obj->flags |= UNINTERESTING;
@@ -158,10 +155,7 @@ void mark_parents_uninteresting(struct commit *commit)
                commit_list_insert(l->item, &parents);
 
        while (parents) {
-               struct commit *commit = parents->item;
-               l = parents;
-               parents = parents->next;
-               free(l);
+               struct commit *commit = pop_commit(&parents);
 
                while (commit) {
                        /*
@@ -172,7 +166,7 @@ void mark_parents_uninteresting(struct commit *commit)
                         * it is popped next time around, we won't be trying
                         * to parse it and get an error.
                         */
-                       if (!has_sha1_file(commit->object.sha1))
+                       if (!has_object_file(&commit->object.oid))
                                commit->object.parsed = 1;
 
                        if (commit->object.flags & UNINTERESTING)
@@ -290,11 +284,11 @@ static struct commit *handle_commit(struct rev_info *revs,
                        add_pending_object(revs, object, tag->tag);
                if (!tag->tagged)
                        die("bad tag");
-               object = parse_object(tag->tagged->sha1);
+               object = parse_object(tag->tagged->oid.hash);
                if (!object) {
                        if (flags & UNINTERESTING)
                                return NULL;
-                       die("bad object %s", sha1_to_hex(tag->tagged->sha1));
+                       die("bad object %s", oid_to_hex(&tag->tagged->oid));
                }
                object->flags |= flags;
                /*
@@ -353,14 +347,24 @@ static struct commit *handle_commit(struct rev_info *revs,
        die("%s is unknown object", name);
 }
 
-static int everybody_uninteresting(struct commit_list *orig)
+static int everybody_uninteresting(struct commit_list *orig,
+                                  struct commit **interesting_cache)
 {
        struct commit_list *list = orig;
+
+       if (*interesting_cache) {
+               struct commit *commit = *interesting_cache;
+               if (!(commit->object.flags & UNINTERESTING))
+                       return 0;
+       }
+
        while (list) {
                struct commit *commit = list->item;
                list = list->next;
                if (commit->object.flags & UNINTERESTING)
                        continue;
+
+               *interesting_cache = commit;
                return 0;
        }
        return 1;
@@ -507,7 +511,7 @@ static int rev_compare_tree(struct rev_info *revs,
 
        tree_difference = REV_TREE_SAME;
        DIFF_OPT_CLR(&revs->pruning, HAS_CHANGES);
-       if (diff_tree_sha1(t1->object.sha1, t2->object.sha1, "",
+       if (diff_tree_sha1(t1->object.oid.hash, t2->object.oid.hash, "",
                           &revs->pruning) < 0)
                return REV_TREE_DIFFERENT;
        return tree_difference;
@@ -523,7 +527,7 @@ static int rev_same_tree_as_empty(struct rev_info *revs, struct commit *commit)
 
        tree_difference = REV_TREE_SAME;
        DIFF_OPT_CLR(&revs->pruning, HAS_CHANGES);
-       retval = diff_tree_sha1(NULL, t1->object.sha1, "", &revs->pruning);
+       retval = diff_tree_sha1(NULL, t1->object.oid.hash, "", &revs->pruning);
 
        return retval >= 0 && (tree_difference == REV_TREE_SAME);
 }
@@ -607,7 +611,7 @@ static unsigned update_treesame(struct rev_info *revs, struct commit *commit)
 
                st = lookup_decoration(&revs->treesame, &commit->object);
                if (!st)
-                       die("update_treesame %s", sha1_to_hex(commit->object.sha1));
+                       die("update_treesame %s", oid_to_hex(&commit->object.oid));
                relevant_parents = 0;
                relevant_change = irrelevant_change = 0;
                for (p = commit->parents, n = 0; p; n++, p = p->next) {
@@ -705,8 +709,8 @@ static void try_to_simplify_commit(struct rev_info *revs, struct commit *commit)
                }
                if (parse_commit(p) < 0)
                        die("cannot simplify commit %s (because of %s)",
-                           sha1_to_hex(commit->object.sha1),
-                           sha1_to_hex(p->object.sha1));
+                           oid_to_hex(&commit->object.oid),
+                           oid_to_hex(&p->object.oid));
                switch (rev_compare_tree(revs, p, commit)) {
                case REV_TREE_SAME:
                        if (!revs->simplify_history || !relevant_commit(p)) {
@@ -738,8 +742,8 @@ static void try_to_simplify_commit(struct rev_info *revs, struct commit *commit)
                                 */
                                if (parse_commit(p) < 0)
                                        die("cannot simplify commit %s (invalid %s)",
-                                           sha1_to_hex(commit->object.sha1),
-                                           sha1_to_hex(p->object.sha1));
+                                           oid_to_hex(&commit->object.oid),
+                                           oid_to_hex(&p->object.oid));
                                p->parents = NULL;
                        }
                /* fallthrough */
@@ -751,7 +755,7 @@ static void try_to_simplify_commit(struct rev_info *revs, struct commit *commit)
                                irrelevant_change = 1;
                        continue;
                }
-               die("bad tree compare for commit %s", sha1_to_hex(commit->object.sha1));
+               die("bad tree compare for commit %s", oid_to_hex(&commit->object.oid));
        }
 
        /*
@@ -815,7 +819,7 @@ static int add_parents_to_list(struct rev_info *revs, struct commit *commit,
                        parent = parent->next;
                        if (p)
                                p->object.flags |= UNINTERESTING;
-                       if (parse_commit(p) < 0)
+                       if (parse_commit_gently(p, 1) < 0)
                                continue;
                        if (p->parents)
                                mark_parents_uninteresting(p);
@@ -842,7 +846,7 @@ static int add_parents_to_list(struct rev_info *revs, struct commit *commit,
        for (parent = commit->parents; parent; parent = parent->next) {
                struct commit *p = parent->item;
 
-               if (parse_commit(p) < 0)
+               if (parse_commit_gently(p, revs->ignore_missing_links) < 0)
                        return -1;
                if (revs->show_source && !p->util)
                        p->util = commit->util;
@@ -948,7 +952,8 @@ static void cherry_pick_list(struct commit_list *list, struct rev_info *revs)
 /* How many extra uninteresting commits we want to see.. */
 #define SLOP 5
 
-static int still_interesting(struct commit_list *src, unsigned long date, int slop)
+static int still_interesting(struct commit_list *src, unsigned long date, int slop,
+                            struct commit **interesting_cache)
 {
        /*
         * No source list at all? We're definitely done..
@@ -967,7 +972,7 @@ static int still_interesting(struct commit_list *src, unsigned long date, int sl
         * Does the source list still have interesting commits in
         * it? Definitely not done..
         */
-       if (!everybody_uninteresting(src))
+       if (!everybody_uninteresting(src, interesting_cache))
                return SLOP;
 
        /* Ok, we're closing in.. */
@@ -1086,6 +1091,7 @@ static int limit_list(struct rev_info *revs)
        struct commit_list *newlist = NULL;
        struct commit_list **p = &newlist;
        struct commit_list *bottom = NULL;
+       struct commit *interesting_cache = NULL;
 
        if (revs->ancestry_path) {
                bottom = collect_bottom_commits(list);
@@ -1094,13 +1100,12 @@ static int limit_list(struct rev_info *revs)
        }
 
        while (list) {
-               struct commit_list *entry = list;
-               struct commit *commit = list->item;
+               struct commit *commit = pop_commit(&list);
                struct object *obj = &commit->object;
                show_early_output_fn_t show;
 
-               list = list->next;
-               free(entry);
+               if (commit == interesting_cache)
+                       interesting_cache = NULL;
 
                if (revs->max_age != -1 && (commit->date < revs->max_age))
                        obj->flags |= UNINTERESTING;
@@ -1110,7 +1115,7 @@ static int limit_list(struct rev_info *revs)
                        mark_parents_uninteresting(commit);
                        if (revs->show_all)
                                p = &commit_list_insert(commit, p)->next;
-                       slop = still_interesting(list, date, slop);
+                       slop = still_interesting(list, date, slop, &interesting_cache);
                        if (slop)
                                continue;
                        /* If showing all, add the whole pending list to the end */
@@ -1185,7 +1190,7 @@ static void add_rev_cmdline_list(struct rev_info *revs,
 {
        while (commit_list) {
                struct object *object = &commit_list->item->object;
-               add_rev_cmdline(revs, object, sha1_to_hex(object->sha1),
+               add_rev_cmdline(revs, object, oid_to_hex(&object->oid),
                                whence, flags);
                commit_list = commit_list->next;
        }
@@ -1211,7 +1216,8 @@ int ref_excluded(struct string_list *ref_excludes, const char *path)
        return 0;
 }
 
-static int handle_one_ref(const char *path, const unsigned char *sha1, int flag, void *cb_data)
+static int handle_one_ref(const char *path, const struct object_id *oid,
+                         int flag, void *cb_data)
 {
        struct all_refs_cb *cb = cb_data;
        struct object *object;
@@ -1219,9 +1225,9 @@ static int handle_one_ref(const char *path, const unsigned char *sha1, int flag,
        if (ref_excluded(cb->all_revs->ref_excludes, path))
            return 0;
 
-       object = get_reference(cb->all_revs, path, sha1, cb->all_flags);
+       object = get_reference(cb->all_revs, path, oid->hash, cb->all_flags);
        add_rev_cmdline(cb->all_revs, object, path, REV_CMD_REF, cb->all_flags);
-       add_pending_sha1(cb->all_revs, path, sha1, cb->all_flags);
+       add_pending_sha1(cb->all_revs, path, oid->hash, cb->all_flags);
        return 0;
 }
 
@@ -1285,7 +1291,8 @@ static int handle_one_reflog_ent(unsigned char *osha1, unsigned char *nsha1,
        return 0;
 }
 
-static int handle_one_reflog(const char *path, const unsigned char *sha1, int flag, void *cb_data)
+static int handle_one_reflog(const char *path, const struct object_id *oid,
+                            int flag, void *cb_data)
 {
        struct all_refs_cb *cb = cb_data;
        cb->warned_bad_reflog = 0;
@@ -1297,11 +1304,59 @@ static int handle_one_reflog(const char *path, const unsigned char *sha1, int fl
 void add_reflogs_to_pending(struct rev_info *revs, unsigned flags)
 {
        struct all_refs_cb cb;
+
        cb.all_revs = revs;
        cb.all_flags = flags;
        for_each_reflog(handle_one_reflog, &cb);
 }
 
+static void add_cache_tree(struct cache_tree *it, struct rev_info *revs,
+                          struct strbuf *path)
+{
+       size_t baselen = path->len;
+       int i;
+
+       if (it->entry_count >= 0) {
+               struct tree *tree = lookup_tree(it->sha1);
+               add_pending_object_with_path(revs, &tree->object, "",
+                                            040000, path->buf);
+       }
+
+       for (i = 0; i < it->subtree_nr; i++) {
+               struct cache_tree_sub *sub = it->down[i];
+               strbuf_addf(path, "%s%s", baselen ? "/" : "", sub->name);
+               add_cache_tree(sub->cache_tree, revs, path);
+               strbuf_setlen(path, baselen);
+       }
+
+}
+
+void add_index_objects_to_pending(struct rev_info *revs, unsigned flags)
+{
+       int i;
+
+       read_cache();
+       for (i = 0; i < active_nr; i++) {
+               struct cache_entry *ce = active_cache[i];
+               struct blob *blob;
+
+               if (S_ISGITLINK(ce->ce_mode))
+                       continue;
+
+               blob = lookup_blob(ce->sha1);
+               if (!blob)
+                       die("unable to add index blob to traversal");
+               add_pending_object_with_path(revs, &blob->object, "",
+                                            ce->ce_mode, ce->name);
+       }
+
+       if (active_cache_tree) {
+               struct strbuf path = STRBUF_INIT;
+               add_cache_tree(active_cache_tree, revs, &path);
+               strbuf_release(&path);
+       }
+}
+
 static int add_parents_only(struct rev_info *revs, const char *arg_, int flags)
 {
        unsigned char sha1[20];
@@ -1324,7 +1379,7 @@ static int add_parents_only(struct rev_info *revs, const char *arg_, int flags)
                        break;
                if (!((struct tag*)it)->tagged)
                        return 0;
-               hashcpy(sha1, ((struct tag*)it)->tagged->sha1);
+               hashcpy(sha1, ((struct tag*)it)->tagged->oid.hash);
        }
        if (it->type != OBJ_COMMIT)
                return 0;
@@ -1381,7 +1436,7 @@ static void add_pending_commit_list(struct rev_info *revs,
        while (commit_list) {
                struct object *object = &commit_list->item->object;
                object->flags |= flags;
-               add_pending_object(revs, object, sha1_to_hex(object->sha1));
+               add_pending_object(revs, object, oid_to_hex(&object->oid));
                commit_list = commit_list->next;
        }
 }
@@ -1402,7 +1457,7 @@ static void prepare_show_merge(struct rev_info *revs)
        other = lookup_commit_or_die(sha1, "MERGE_HEAD");
        add_pending_object(revs, &head->object, "HEAD");
        add_pending_object(revs, &other->object, "MERGE_HEAD");
-       bases = get_merge_bases(head, other, 1);
+       bases = get_merge_bases(head, other);
        add_rev_cmdline_list(revs, bases, REV_CMD_MERGE_BASE, UNINTERESTING | BOTTOM);
        add_pending_commit_list(revs, bases, UNINTERESTING | BOTTOM);
        free_commit_list(bases);
@@ -1501,13 +1556,13 @@ int handle_revision_arg(const char *arg_, struct rev_info *revs, int flags, unsi
 
                                a = (a_obj->type == OBJ_COMMIT
                                     ? (struct commit *)a_obj
-                                    : lookup_commit_reference(a_obj->sha1));
+                                    : lookup_commit_reference(a_obj->oid.hash));
                                b = (b_obj->type == OBJ_COMMIT
                                     ? (struct commit *)b_obj
-                                    : lookup_commit_reference(b_obj->sha1));
+                                    : lookup_commit_reference(b_obj->oid.hash));
                                if (!a || !b)
                                        goto missing;
-                               exclude = get_merge_bases(a, b, 1);
+                               exclude = get_merge_bases(a, b);
                                add_rev_cmdline_list(revs, exclude,
                                                     REV_CMD_MERGE_BASE,
                                                     flags_exclude);
@@ -1652,6 +1707,7 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
            !strcmp(arg, "--reflog") || !strcmp(arg, "--not") ||
            !strcmp(arg, "--no-walk") || !strcmp(arg, "--do-walk") ||
            !strcmp(arg, "--bisect") || starts_with(arg, "--glob=") ||
+           !strcmp(arg, "--indexed-objects") ||
            starts_with(arg, "--exclude=") ||
            starts_with(arg, "--branches=") || starts_with(arg, "--tags=") ||
            starts_with(arg, "--remotes=") || starts_with(arg, "--no-walk="))
@@ -1813,6 +1869,12 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
                revs->tree_objects = 1;
                revs->blob_objects = 1;
                revs->edge_hint = 1;
+       } else if (!strcmp(arg, "--objects-edge-aggressive")) {
+               revs->tag_objects = 1;
+               revs->tree_objects = 1;
+               revs->blob_objects = 1;
+               revs->edge_hint = 1;
+               revs->edge_hint_aggressive = 1;
        } else if (!strcmp(arg, "--verify-objects")) {
                revs->tag_objects = 1;
                revs->tree_objects = 1;
@@ -1932,10 +1994,10 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
        } else if (!strcmp(arg, "--full-history")) {
                revs->simplify_history = 0;
        } else if (!strcmp(arg, "--relative-date")) {
-               revs->date_mode = DATE_RELATIVE;
+               revs->date_mode.type = DATE_RELATIVE;
                revs->date_mode_explicit = 1;
        } else if ((argcount = parse_long_opt("date", argv, &optarg))) {
-               revs->date_mode = parse_date_format(optarg);
+               parse_date_format(optarg, &revs->date_mode);
                revs->date_mode_explicit = 1;
                return argcount;
        } else if (!strcmp(arg, "--log-size")) {
@@ -1971,6 +2033,8 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
                grep_set_pattern_type_option(GREP_PATTERN_TYPE_PCRE, &revs->grep_filter);
        } else if (!strcmp(arg, "--all-match")) {
                revs->grep_filter.all_match = 1;
+       } else if (!strcmp(arg, "--invert-grep")) {
+               revs->invert_grep = 1;
        } else if ((argcount = parse_long_opt("encoding", argv, &optarg))) {
                if (strcmp(optarg, "none"))
                        git_log_output_encoding = xstrdup(optarg);
@@ -2010,14 +2074,23 @@ void parse_revision_opt(struct rev_info *revs, struct parse_opt_ctx_t *ctx,
        ctx->argc -= n;
 }
 
+static int for_each_bisect_ref(const char *submodule, each_ref_fn fn, void *cb_data, const char *term) {
+       struct strbuf bisect_refs = STRBUF_INIT;
+       int status;
+       strbuf_addf(&bisect_refs, "refs/bisect/%s", term);
+       status = for_each_ref_in_submodule(submodule, bisect_refs.buf, fn, cb_data);
+       strbuf_release(&bisect_refs);
+       return status;
+}
+
 static int for_each_bad_bisect_ref(const char *submodule, each_ref_fn fn, void *cb_data)
 {
-       return for_each_ref_in_submodule(submodule, "refs/bisect/bad", fn, cb_data);
+       return for_each_bisect_ref(submodule, fn, cb_data, term_bad);
 }
 
 static int for_each_good_bisect_ref(const char *submodule, each_ref_fn fn, void *cb_data)
 {
-       return for_each_ref_in_submodule(submodule, "refs/bisect/good", fn, cb_data);
+       return for_each_bisect_ref(submodule, fn, cb_data, term_good);
 }
 
 static int handle_revision_pseudo_opt(const char *submodule,
@@ -2046,6 +2119,7 @@ static int handle_revision_pseudo_opt(const char *submodule,
                handle_refs(submodule, revs, *flags, for_each_branch_ref_submodule);
                clear_ref_exclusion(&revs->ref_excludes);
        } else if (!strcmp(arg, "--bisect")) {
+               read_bisect_terms(&term_bad, &term_good);
                handle_refs(submodule, revs, *flags, for_each_bad_bisect_ref);
                handle_refs(submodule, revs, *flags ^ (UNINTERESTING | BOTTOM), for_each_good_bisect_ref);
                revs->bisect = 1;
@@ -2081,6 +2155,8 @@ static int handle_revision_pseudo_opt(const char *submodule,
                clear_ref_exclusion(&revs->ref_excludes);
        } else if (!strcmp(arg, "--reflog")) {
                add_reflogs_to_pending(revs, *flags);
+       } else if (!strcmp(arg, "--indexed-objects")) {
+               add_index_objects_to_pending(revs, *flags);
        } else if (!strcmp(arg, "--not")) {
                *flags ^= UNINTERESTING | BOTTOM;
        } else if (!strcmp(arg, "--no-walk")) {
@@ -2105,6 +2181,21 @@ static int handle_revision_pseudo_opt(const char *submodule,
        return 1;
 }
 
+static void NORETURN diagnose_missing_default(const char *def)
+{
+       unsigned char sha1[20];
+       int flags;
+       const char *refname;
+
+       refname = resolve_ref_unsafe(def, 0, sha1, &flags);
+       if (!refname || !(flags & REF_ISSYMREF) || (flags & REF_ISBROKEN))
+               die(_("your current branch appears to be broken"));
+
+       skip_prefix(refname, "refs/heads/", &refname);
+       die(_("your current branch '%s' does not have any commits yet"),
+           refname);
+}
+
 /*
  * Parse revision information, filling in the "rev_info" structure,
  * and removing the used arguments from the argument list.
@@ -2234,7 +2325,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
                struct object *object;
                struct object_context oc;
                if (get_sha1_with_context(revs->def, 0, sha1, &oc))
-                       die("bad default revision '%s'", revs->def);
+                       diagnose_missing_default(revs->def);
                object = get_reference(revs, revs->def, sha1, 0);
                add_pending_object_with_mode(revs, object, revs->def, oc.mode);
        }
@@ -2289,9 +2380,14 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
 
        if (revs->reflog_info && revs->graph)
                die("cannot combine --walk-reflogs with --graph");
+       if (revs->no_walk && revs->graph)
+               die("cannot combine --no-walk with --graph");
        if (!revs->reflog_info && revs->grep_filter.use_reflog_filter)
                die("cannot use --grep-reflog without --walk-reflogs");
 
+       if (revs->first_parent_only && revs->bisect)
+               die(_("--first-parent is incompatible with --bisect"));
+
        return left;
 }
 
@@ -2631,10 +2727,7 @@ static void simplify_merges(struct rev_info *revs)
                yet_to_do = NULL;
                tail = &yet_to_do;
                while (list) {
-                       commit = list->item;
-                       next = list->next;
-                       free(list);
-                       list = next;
+                       commit = pop_commit(&list);
                        tail = simplify_one(revs, commit, tail);
                }
        }
@@ -2646,10 +2739,7 @@ static void simplify_merges(struct rev_info *revs)
        while (list) {
                struct merge_simplify_state *st;
 
-               commit = list->item;
-               next = list->next;
-               free(list);
-               list = next;
+               commit = pop_commit(&list);
                st = locate_simplify_state(revs, commit);
                if (st->simplified == commit)
                        tail = &commit_list_insert(commit, tail)->next;
@@ -2849,7 +2939,7 @@ static int commit_match(struct commit *commit, struct rev_info *opt)
        if (opt->show_notes) {
                if (!buf.len)
                        strbuf_addstr(&buf, message);
-               format_display_notes(commit->object.sha1, &buf, encoding, 1);
+               format_display_notes(commit->object.oid.hash, &buf, encoding, 1);
        }
 
        /*
@@ -2867,7 +2957,7 @@ static int commit_match(struct commit *commit, struct rev_info *opt)
                                     (char *)message, strlen(message));
        strbuf_release(&buf);
        unuse_commit_buffer(commit, message);
-       return retval;
+       return opt->invert_grep ? !retval : retval;
 }
 
 static inline int want_ancestry(const struct rev_info *revs)
@@ -2879,7 +2969,7 @@ enum commit_action get_commit_action(struct rev_info *revs, struct commit *commi
 {
        if (commit->object.flags & SHOWN)
                return commit_ignore;
-       if (revs->unpacked && has_sha1_pack(commit->object.sha1))
+       if (revs->unpacked && has_sha1_pack(commit->object.oid.hash))
                return commit_ignore;
        if (revs->show_all)
                return commit_show;
@@ -2920,6 +3010,61 @@ enum commit_action get_commit_action(struct rev_info *revs, struct commit *commi
        return commit_show;
 }
 
+define_commit_slab(saved_parents, struct commit_list *);
+
+#define EMPTY_PARENT_LIST ((struct commit_list *)-1)
+
+/*
+ * You may only call save_parents() once per commit (this is checked
+ * for non-root commits).
+ */
+static void save_parents(struct rev_info *revs, struct commit *commit)
+{
+       struct commit_list **pp;
+
+       if (!revs->saved_parents_slab) {
+               revs->saved_parents_slab = xmalloc(sizeof(struct saved_parents));
+               init_saved_parents(revs->saved_parents_slab);
+       }
+
+       pp = saved_parents_at(revs->saved_parents_slab, commit);
+
+       /*
+        * When walking with reflogs, we may visit the same commit
+        * several times: once for each appearance in the reflog.
+        *
+        * In this case, save_parents() will be called multiple times.
+        * We want to keep only the first set of parents.  We need to
+        * store a sentinel value for an empty (i.e., NULL) parent
+        * list to distinguish it from a not-yet-saved list, however.
+        */
+       if (*pp)
+               return;
+       if (commit->parents)
+               *pp = copy_commit_list(commit->parents);
+       else
+               *pp = EMPTY_PARENT_LIST;
+}
+
+static void free_saved_parents(struct rev_info *revs)
+{
+       if (revs->saved_parents_slab)
+               clear_saved_parents(revs->saved_parents_slab);
+}
+
+struct commit_list *get_saved_parents(struct rev_info *revs, const struct commit *commit)
+{
+       struct commit_list *parents;
+
+       if (!revs->saved_parents_slab)
+               return commit->parents;
+
+       parents = *saved_parents_at(revs->saved_parents_slab, commit);
+       if (parents == EMPTY_PARENT_LIST)
+               return NULL;
+       return parents;
+}
+
 enum commit_action simplify_commit(struct rev_info *revs, struct commit *commit)
 {
        enum commit_action action = get_commit_action(revs, commit);
@@ -2950,7 +3095,7 @@ static void track_linear(struct rev_info *revs, struct commit *commit)
                struct commit_list *p;
                for (p = revs->previous_parents; p; p = p->next)
                        if (p->item == NULL || /* first commit */
-                           !hashcmp(p->item->object.sha1, commit->object.sha1))
+                           !oidcmp(&p->item->object.oid, &commit->object.oid))
                                break;
                revs->linear = p != NULL;
        }
@@ -2968,11 +3113,7 @@ static struct commit *get_revision_1(struct rev_info *revs)
                return NULL;
 
        do {
-               struct commit_list *entry = revs->commits;
-               struct commit *commit = entry->item;
-
-               revs->commits = entry->next;
-               free(entry);
+               struct commit *commit = pop_commit(&revs->commits);
 
                if (revs->reflog_info) {
                        save_parents(revs, commit);
@@ -2992,7 +3133,7 @@ static struct commit *get_revision_1(struct rev_info *revs)
                        if (add_parents_to_list(revs, commit, &revs->commits, NULL) < 0) {
                                if (!revs->ignore_missing_links)
                                        die("Failed to traverse parents of commit %s",
-                                               sha1_to_hex(commit->object.sha1));
+                                               oid_to_hex(&commit->object.oid));
                        }
                }
 
@@ -3001,7 +3142,7 @@ static struct commit *get_revision_1(struct rev_info *revs)
                        continue;
                case commit_error:
                        die("Failed to simplify parents of commit %s",
-                           sha1_to_hex(commit->object.sha1));
+                           oid_to_hex(&commit->object.oid));
                default:
                        if (revs->track_linear)
                                track_linear(revs, commit);
@@ -3219,54 +3360,3 @@ void put_revision_mark(const struct rev_info *revs, const struct commit *commit)
        fputs(mark, stdout);
        putchar(' ');
 }
-
-define_commit_slab(saved_parents, struct commit_list *);
-
-#define EMPTY_PARENT_LIST ((struct commit_list *)-1)
-
-void save_parents(struct rev_info *revs, struct commit *commit)
-{
-       struct commit_list **pp;
-
-       if (!revs->saved_parents_slab) {
-               revs->saved_parents_slab = xmalloc(sizeof(struct saved_parents));
-               init_saved_parents(revs->saved_parents_slab);
-       }
-
-       pp = saved_parents_at(revs->saved_parents_slab, commit);
-
-       /*
-        * When walking with reflogs, we may visit the same commit
-        * several times: once for each appearance in the reflog.
-        *
-        * In this case, save_parents() will be called multiple times.
-        * We want to keep only the first set of parents.  We need to
-        * store a sentinel value for an empty (i.e., NULL) parent
-        * list to distinguish it from a not-yet-saved list, however.
-        */
-       if (*pp)
-               return;
-       if (commit->parents)
-               *pp = copy_commit_list(commit->parents);
-       else
-               *pp = EMPTY_PARENT_LIST;
-}
-
-struct commit_list *get_saved_parents(struct rev_info *revs, const struct commit *commit)
-{
-       struct commit_list *parents;
-
-       if (!revs->saved_parents_slab)
-               return commit->parents;
-
-       parents = *saved_parents_at(revs->saved_parents_slab, commit);
-       if (parents == EMPTY_PARENT_LIST)
-               return NULL;
-       return parents;
-}
-
-void free_saved_parents(struct rev_info *revs)
-{
-       if (revs->saved_parents_slab)
-               clear_saved_parents(revs->saved_parents_slab);
-}