commit: add short-circuit to paint_down_to_common()
[gitweb.git] / revision.c
index 05a7aac063bd4053a1478a0a4b51210af73ded58..d64d2a859e9750a1902994c091d02e9cd6743c2f 100644 (file)
@@ -397,8 +397,16 @@ static struct commit *one_relevant_parent(const struct rev_info *revs,
  * if the whole diff is removal of old data, and otherwise
  * REV_TREE_DIFFERENT (of course if the trees are the same we
  * want REV_TREE_SAME).
- * That means that once we get to REV_TREE_DIFFERENT, we do not
- * have to look any further.
+ *
+ * The only time we care about the distinction is when
+ * remove_empty_trees is in effect, in which case we care only about
+ * whether the whole change is REV_TREE_NEW, or if there's another type
+ * of change. Which means we can stop the diff early in either of these
+ * cases:
+ *
+ *   1. We're not using remove_empty_trees at all.
+ *
+ *   2. We saw anything except REV_TREE_NEW.
  */
 static int tree_difference = REV_TREE_SAME;
 
@@ -409,10 +417,11 @@ static void file_add_remove(struct diff_options *options,
                    const char *fullpath, unsigned dirty_submodule)
 {
        int diff = addremove == '+' ? REV_TREE_NEW : REV_TREE_OLD;
+       struct rev_info *revs = options->change_fn_data;
 
        tree_difference |= diff;
-       if (tree_difference == REV_TREE_DIFFERENT)
-               DIFF_OPT_SET(options, HAS_CHANGES);
+       if (!revs->remove_empty_trees || tree_difference != REV_TREE_NEW)
+               options->flags.has_changes = 1;
 }
 
 static void file_change(struct diff_options *options,
@@ -424,14 +433,14 @@ static void file_change(struct diff_options *options,
                 unsigned old_dirty_submodule, unsigned new_dirty_submodule)
 {
        tree_difference = REV_TREE_DIFFERENT;
-       DIFF_OPT_SET(options, HAS_CHANGES);
+       options->flags.has_changes = 1;
 }
 
 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;
+       struct tree *t1 = get_commit_tree(parent);
+       struct tree *t2 = get_commit_tree(commit);
 
        if (!t1)
                return REV_TREE_NEW;
@@ -457,7 +466,7 @@ static int rev_compare_tree(struct rev_info *revs,
        }
 
        tree_difference = REV_TREE_SAME;
-       DIFF_OPT_CLR(&revs->pruning, HAS_CHANGES);
+       revs->pruning.flags.has_changes = 0;
        if (diff_tree_oid(&t1->object.oid, &t2->object.oid, "",
                           &revs->pruning) < 0)
                return REV_TREE_DIFFERENT;
@@ -467,13 +476,13 @@ static int rev_compare_tree(struct rev_info *revs,
 static int rev_same_tree_as_empty(struct rev_info *revs, struct commit *commit)
 {
        int retval;
-       struct tree *t1 = commit->tree;
+       struct tree *t1 = get_commit_tree(commit);
 
        if (!t1)
                return 0;
 
        tree_difference = REV_TREE_SAME;
-       DIFF_OPT_CLR(&revs->pruning, HAS_CHANGES);
+       revs->pruning.flags.has_changes = 0;
        retval = diff_tree_oid(NULL, &t1->object.oid, "", &revs->pruning);
 
        return retval >= 0 && (tree_difference == REV_TREE_SAME);
@@ -605,7 +614,7 @@ static void try_to_simplify_commit(struct rev_info *revs, struct commit *commit)
        if (!revs->prune)
                return;
 
-       if (!commit->tree)
+       if (!get_commit_tree(commit))
                return;
 
        if (!commit->parents) {
@@ -1056,14 +1065,9 @@ static int limit_list(struct rev_info *revs)
                        return -1;
                if (obj->flags & UNINTERESTING) {
                        mark_parents_uninteresting(commit);
-                       if (revs->show_all)
-                               p = &commit_list_insert(commit, p)->next;
                        slop = still_interesting(list, date, slop, &interesting_cache);
                        if (slop)
                                continue;
-                       /* If showing all, add the whole pending list to the end */
-                       if (revs->show_all)
-                               *p = list;
                        break;
                }
                if (revs->min_age != -1 && (commit->date > revs->min_age))
@@ -1353,7 +1357,8 @@ void add_index_objects_to_pending(struct rev_info *revs, unsigned int flags)
                        continue; /* current index already taken care of */
 
                if (read_index_from(&istate,
-                                   worktree_git_path(wt, "index")) > 0)
+                                   worktree_git_path(wt, "index"),
+                                   get_worktree_git_dir(wt)) > 0)
                        do_add_index_objects_to_pending(revs, &istate);
                discard_index(&istate);
        }
@@ -1413,10 +1418,11 @@ void init_revisions(struct rev_info *revs, const char *prefix)
        revs->abbrev = DEFAULT_ABBREV;
        revs->ignore_merges = 1;
        revs->simplify_history = 1;
-       DIFF_OPT_SET(&revs->pruning, RECURSIVE);
-       DIFF_OPT_SET(&revs->pruning, QUICK);
+       revs->pruning.flags.recursive = 1;
+       revs->pruning.flags.quick = 1;
        revs->pruning.add_remove = file_add_remove;
        revs->pruning.change = file_change;
+       revs->pruning.change_fn_data = revs;
        revs->sort_order = REV_SORT_IN_GRAPH_ORDER;
        revs->dense = 1;
        revs->prefix = prefix;
@@ -1832,7 +1838,7 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
                revs->simplify_by_decoration = 1;
                revs->limited = 1;
                revs->prune = 1;
-               load_ref_decorations(DECORATE_SHORT_REFS);
+               load_ref_decorations(NULL, DECORATE_SHORT_REFS);
        } else if (!strcmp(arg, "--date-order")) {
                revs->sort_order = REV_SORT_BY_COMMIT_DATE;
                revs->topo_order = 1;
@@ -1853,8 +1859,8 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
                revs->dense = 1;
        } else if (!strcmp(arg, "--sparse")) {
                revs->dense = 0;
-       } else if (!strcmp(arg, "--show-all")) {
-               revs->show_all = 1;
+       } else if (!strcmp(arg, "--in-commit-order")) {
+               revs->tree_blobs_in_commit_order = 1;
        } else if (!strcmp(arg, "--remove-empty")) {
                revs->remove_empty_trees = 1;
        } else if (!strcmp(arg, "--merges")) {
@@ -1927,11 +1933,11 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
                die("--unpacked=<packfile> no longer supported.");
        } else if (!strcmp(arg, "-r")) {
                revs->diff = 1;
-               DIFF_OPT_SET(&revs->diffopt, RECURSIVE);
+               revs->diffopt.flags.recursive = 1;
        } else if (!strcmp(arg, "-t")) {
                revs->diff = 1;
-               DIFF_OPT_SET(&revs->diffopt, RECURSIVE);
-               DIFF_OPT_SET(&revs->diffopt, TREE_IN_RECURSIVE);
+               revs->diffopt.flags.recursive = 1;
+               revs->diffopt.flags.tree_in_recursive = 1;
        } else if (!strcmp(arg, "-m")) {
                revs->ignore_merges = 0;
        } else if (!strcmp(arg, "-c")) {
@@ -2076,7 +2082,7 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
                revs->grep_filter.pattern_type_option = GREP_PATTERN_TYPE_ERE;
        } else if (!strcmp(arg, "--regexp-ignore-case") || !strcmp(arg, "-i")) {
                revs->grep_filter.ignore_case = 1;
-               DIFF_OPT_SET(&revs->diffopt, PICKAXE_IGNORE_CASE);
+               revs->diffopt.pickaxe_opts |= DIFF_PICKAXE_IGNORE_CASE;
        } else if (!strcmp(arg, "--fixed-strings") || !strcmp(arg, "-F")) {
                revs->grep_filter.pattern_type_option = GREP_PATTERN_TYPE_FIXED;
        } else if (!strcmp(arg, "--perl-regexp") || !strcmp(arg, "-P")) {
@@ -2411,18 +2417,21 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
                revs->diff = 1;
 
        /* Pickaxe, diff-filter and rename following need diffs */
-       if (revs->diffopt.pickaxe ||
+       if ((revs->diffopt.pickaxe_opts & DIFF_PICKAXE_KINDS_MASK) ||
            revs->diffopt.filter ||
-           DIFF_OPT_TST(&revs->diffopt, FOLLOW_RENAMES))
+           revs->diffopt.flags.follow_renames)
                revs->diff = 1;
 
+       if (revs->diffopt.objfind)
+               revs->simplify_history = 0;
+
        if (revs->topo_order)
                revs->limited = 1;
 
        if (revs->prune_data.nr) {
                copy_pathspec(&revs->pruning.pathspec, &revs->prune_data);
                /* Can't prune commits with rename following: the paths change.. */
-               if (!DIFF_OPT_TST(&revs->diffopt, FOLLOW_RENAMES))
+               if (!revs->diffopt.flags.follow_renames)
                        revs->prune = 1;
                if (!revs->full_diff)
                        copy_pathspec(&revs->diffopt.pathspec,
@@ -2874,8 +2883,7 @@ int prepare_revision_walk(struct rev_info *revs)
                        }
                }
        }
-       if (!revs->leak_pending)
-               object_array_clear(&old_pending);
+       object_array_clear(&old_pending);
 
        /* Signal whether we need per-parent treesame decoration */
        if (revs->simplify_merges ||
@@ -3079,8 +3087,6 @@ enum commit_action get_commit_action(struct rev_info *revs, struct commit *commi
                return commit_ignore;
        if (revs->unpacked && has_sha1_pack(commit->object.oid.hash))
                return commit_ignore;
-       if (revs->show_all)
-               return commit_show;
        if (commit->object.flags & UNINTERESTING)
                return commit_ignore;
        if (revs->min_age != -1 &&
@@ -3179,7 +3185,6 @@ enum commit_action simplify_commit(struct rev_info *revs, struct commit *commit)
        enum commit_action action = get_commit_action(revs, commit);
 
        if (action == commit_show &&
-           !revs->show_all &&
            revs->prune && revs->dense && want_ancestry(revs)) {
                /*
                 * --full-diff on simplified parents is no good: it