Merge branch 'ak/add-i-empty-candidates'
[gitweb.git] / revision.c
index ebe3e93d1298c542ae655e3af3b5b2761f0061de..66520c671ee1141b1c0edb7ab776dd9d9df04726 100644 (file)
@@ -17,6 +17,7 @@
 #include "mailmap.h"
 #include "commit-slab.h"
 #include "dir.h"
+#include "cache-tree.h"
 
 volatile show_early_output_fn_t show_early_output;
 
@@ -86,16 +87,6 @@ void show_object_with_name(FILE *out, struct object *obj,
        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)
@@ -1303,6 +1294,53 @@ void add_reflogs_to_pending(struct rev_info *revs, unsigned 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];
@@ -1403,7 +1441,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);
@@ -1508,7 +1546,7 @@ int handle_revision_arg(const char *arg_, struct rev_info *revs, int flags, unsi
                                     : lookup_commit_reference(b_obj->sha1));
                                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);
@@ -1653,6 +1691,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="))
@@ -1814,6 +1853,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;
@@ -1972,6 +2017,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);
@@ -2082,6 +2129,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")) {
@@ -2868,7 +2917,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)
@@ -2921,6 +2970,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);
@@ -3220,54 +3324,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);
-}