]> git.ipfire.org Git - thirdparty/git.git/blobdiff - revision.c
add -p: fix memory leak
[thirdparty/git.git] / revision.c
index 60cca8c0b9660e5c3e9927da99dee1fcda1c0069..6aa7f4f56755bdc2b79455c61a9882085980f90a 100644 (file)
@@ -39,6 +39,8 @@ static const char *term_good;
 
 implement_shared_commit_slab(revision_sources, char *);
 
+static inline int want_ancestry(const struct rev_info *revs);
+
 void show_object_with_name(FILE *out, struct object *obj, const char *name)
 {
        const char *p;
@@ -687,6 +689,9 @@ static void prepare_to_use_bloom_filter(struct rev_info *revs)
        if (!revs->bloom_filter_settings)
                return;
 
+       if (!revs->pruning.pathspec.nr)
+               return;
+
        pi = &revs->pruning.pathspec.items[0];
        last_index = pi->len - 1;
 
@@ -720,7 +725,7 @@ static int check_maybe_different_in_bloom_filter(struct rev_info *revs,
        if (!revs->repo->objects->commit_graph)
                return -1;
 
-       if (commit->generation == GENERATION_NUMBER_INFINITY)
+       if (commit_graph_generation(commit) == GENERATION_NUMBER_INFINITY)
                return -1;
 
        filter = get_bloom_filter(revs->repo, commit, 0);
@@ -1405,7 +1410,8 @@ static int limit_list(struct rev_info *revs)
                                continue;
                        break;
                }
-               if (revs->min_age != -1 && (commit->date > revs->min_age))
+               if (revs->min_age != -1 && (commit->date > revs->min_age) &&
+                   !revs->line_level_traverse)
                        continue;
                date = commit->date;
                p = &commit_list_insert(commit, p)->next;
@@ -1604,7 +1610,7 @@ static void add_other_reflogs_to_pending(struct all_refs_cb *cb)
 {
        struct worktree **worktrees, **p;
 
-       worktrees = get_worktrees(0);
+       worktrees = get_worktrees();
        for (p = worktrees; *p; p++) {
                struct worktree *wt = *p;
 
@@ -1692,7 +1698,7 @@ void add_index_objects_to_pending(struct rev_info *revs, unsigned int flags)
        if (revs->single_worktree)
                return;
 
-       worktrees = get_worktrees(0);
+       worktrees = get_worktrees();
        for (p = worktrees; *p; p++) {
                struct worktree *wt = *p;
                struct index_state istate = { NULL };
@@ -2810,6 +2816,12 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
        if (revs->diffopt.objfind)
                revs->simplify_history = 0;
 
+       if (revs->line_level_traverse) {
+               if (want_ancestry(revs))
+                       revs->limited = 1;
+               revs->topo_order = 1;
+       }
+
        if (revs->topo_order && !generation_numbers_enabled(the_repository))
                revs->limited = 1;
 
@@ -2829,11 +2841,6 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
 
        revs->diffopt.abbrev = revs->abbrev;
 
-       if (revs->line_level_traverse) {
-               revs->limited = 1;
-               revs->topo_order = 1;
-       }
-
        diff_setup_done(&revs->diffopt);
 
        grep_commit_pattern_type(GREP_PATTERN_TYPE_UNSPECIFIED,
@@ -3314,7 +3321,7 @@ static void explore_to_depth(struct rev_info *revs,
        struct topo_walk_info *info = revs->topo_walk_info;
        struct commit *c;
        while ((c = prio_queue_peek(&info->explore_queue)) &&
-              c->generation >= gen_cutoff)
+              commit_graph_generation(c) >= gen_cutoff)
                explore_walk_step(revs);
 }
 
@@ -3330,7 +3337,7 @@ static void indegree_walk_step(struct rev_info *revs)
        if (parse_commit_gently(c, 1) < 0)
                return;
 
-       explore_to_depth(revs, c->generation);
+       explore_to_depth(revs, commit_graph_generation(c));
 
        for (p = c->parents; p; p = p->next) {
                struct commit *parent = p->item;
@@ -3354,7 +3361,7 @@ static void compute_indegrees_to_depth(struct rev_info *revs,
        struct topo_walk_info *info = revs->topo_walk_info;
        struct commit *c;
        while ((c = prio_queue_peek(&info->indegree_queue)) &&
-              c->generation >= gen_cutoff)
+              commit_graph_generation(c) >= gen_cutoff)
                indegree_walk_step(revs);
 }
 
@@ -3407,6 +3414,7 @@ static void init_topo_walk(struct rev_info *revs)
        info->min_generation = GENERATION_NUMBER_INFINITY;
        for (list = revs->commits; list; list = list->next) {
                struct commit *c = list->item;
+               uint32_t generation;
 
                if (parse_commit_gently(c, 1))
                        continue;
@@ -3414,8 +3422,9 @@ static void init_topo_walk(struct rev_info *revs)
                test_flag_and_insert(&info->explore_queue, c, TOPO_WALK_EXPLORED);
                test_flag_and_insert(&info->indegree_queue, c, TOPO_WALK_INDEGREE);
 
-               if (c->generation < info->min_generation)
-                       info->min_generation = c->generation;
+               generation = commit_graph_generation(c);
+               if (generation < info->min_generation)
+                       info->min_generation = generation;
 
                *(indegree_slab_at(&info->indegree, c)) = 1;
 
@@ -3466,6 +3475,7 @@ static void expand_topo_walk(struct rev_info *revs, struct commit *commit)
        for (p = commit->parents; p; p = p->next) {
                struct commit *parent = p->item;
                int *pi;
+               uint32_t generation;
 
                if (parent->object.flags & UNINTERESTING)
                        continue;
@@ -3473,8 +3483,9 @@ static void expand_topo_walk(struct rev_info *revs, struct commit *commit)
                if (parse_commit_gently(parent, 1) < 0)
                        continue;
 
-               if (parent->generation < info->min_generation) {
-                       info->min_generation = parent->generation;
+               generation = commit_graph_generation(parent);
+               if (generation < info->min_generation) {
+                       info->min_generation = generation;
                        compute_indegrees_to_depth(revs, info->min_generation);
                }
 
@@ -3521,7 +3532,7 @@ int prepare_revision_walk(struct rev_info *revs)
                                       FOR_EACH_OBJECT_PROMISOR_ONLY);
        }
 
-       if (revs->pruning.pathspec.nr == 1 && !revs->reflog_info)
+       if (!revs->reflog_info)
                prepare_to_use_bloom_filter(revs);
        if (revs->no_walk != REVISION_WALK_NO_WALK_UNSORTED)
                commit_list_sort_by_date(&revs->commits);
@@ -3534,7 +3545,14 @@ int prepare_revision_walk(struct rev_info *revs)
                        sort_in_topological_order(&revs->commits, revs->sort_order);
        } else if (revs->topo_order)
                init_topo_walk(revs);
-       if (revs->line_level_traverse)
+       if (revs->line_level_traverse && want_ancestry(revs))
+               /*
+                * At the moment we can only do line-level log with parent
+                * rewriting by performing this expensive pre-filtering step.
+                * If parent rewriting is not requested, then we rather
+                * perform the line-level log filtering during the regular
+                * history traversal.
+                */
                line_log_filter(revs);
        if (revs->simplify_merges)
                simplify_merges(revs);
@@ -3745,6 +3763,22 @@ enum commit_action get_commit_action(struct rev_info *revs, struct commit *commi
                return commit_ignore;
        if (commit->object.flags & UNINTERESTING)
                return commit_ignore;
+       if (revs->line_level_traverse && !want_ancestry(revs)) {
+               /*
+                * In case of line-level log with parent rewriting
+                * prepare_revision_walk() already took care of all line-level
+                * log filtering, and there is nothing left to do here.
+                *
+                * If parent rewriting was not requested, then this is the
+                * place to perform the line-level log filtering.  Notably,
+                * this check, though expensive, must come before the other,
+                * cheaper filtering conditions, because the tracked line
+                * ranges must be adjusted even when the commit will end up
+                * being ignored based on other conditions.
+                */
+               if (!line_log_process_ranges_arbitrary_commit(revs, commit))
+                       return commit_ignore;
+       }
        if (revs->min_age != -1 &&
            comparison_date(revs, commit) > revs->min_age)
                        return commit_ignore;