summaryrefslogtreecommitdiff
path: root/revision.c
diff options
context:
space:
mode:
Diffstat (limited to 'revision.c')
-rw-r--r--revision.c124
1 files changed, 105 insertions, 19 deletions
diff --git a/revision.c b/revision.c
index 2646b78..0c6e26c 100644
--- a/revision.c
+++ b/revision.c
@@ -33,6 +33,7 @@
#include "bloom.h"
#include "json-writer.h"
#include "list-objects-filter-options.h"
+#include "resolve-undo.h"
volatile show_early_output_fn_t show_early_output;
@@ -606,6 +607,10 @@ static struct commit *one_relevant_parent(const struct rev_info *revs,
*
* 2. We saw anything except REV_TREE_NEW.
*/
+#define REV_TREE_SAME 0
+#define REV_TREE_NEW 1 /* Only new files */
+#define REV_TREE_OLD 2 /* Only files removed */
+#define REV_TREE_DIFFERENT 3 /* Mixed changes */
static int tree_difference = REV_TREE_SAME;
static void file_add_remove(struct diff_options *options,
@@ -1440,6 +1445,9 @@ static int limit_list(struct rev_info *revs)
if (revs->min_age != -1 && (commit->date > revs->min_age) &&
!revs->line_level_traverse)
continue;
+ if (revs->max_age_as_filter != -1 &&
+ (commit->date < revs->max_age_as_filter) && !revs->line_level_traverse)
+ continue;
date = commit->date;
p = &commit_list_insert(commit, p)->next;
@@ -1456,10 +1464,9 @@ static int limit_list(struct rev_info *revs)
if (revs->left_only || revs->right_only)
limit_left_right(newlist, revs);
- if (bottom) {
+ if (bottom)
limit_to_ancestry(bottom, newlist);
- free_commit_list(bottom);
- }
+ free_commit_list(bottom);
/*
* Check if any commits have become TREESAME by some of their parents
@@ -1690,6 +1697,39 @@ static void add_cache_tree(struct cache_tree *it, struct rev_info *revs,
}
+static void add_resolve_undo_to_pending(struct index_state *istate, struct rev_info *revs)
+{
+ struct string_list_item *item;
+ struct string_list *resolve_undo = istate->resolve_undo;
+
+ if (!resolve_undo)
+ return;
+
+ for_each_string_list_item(item, resolve_undo) {
+ const char *path = item->string;
+ struct resolve_undo_info *ru = item->util;
+ int i;
+
+ if (!ru)
+ continue;
+ for (i = 0; i < 3; i++) {
+ struct blob *blob;
+
+ if (!ru->mode[i] || !S_ISREG(ru->mode[i]))
+ continue;
+
+ blob = lookup_blob(revs->repo, &ru->oid[i]);
+ if (!blob) {
+ warning(_("resolve-undo records `%s` which is missing"),
+ oid_to_hex(&ru->oid[i]));
+ continue;
+ }
+ add_pending_object_with_path(revs, &blob->object, "",
+ ru->mode[i], path);
+ }
+ }
+}
+
static void do_add_index_objects_to_pending(struct rev_info *revs,
struct index_state *istate,
unsigned int flags)
@@ -1718,6 +1758,8 @@ static void do_add_index_objects_to_pending(struct rev_info *revs,
add_cache_tree(istate->cache_tree, revs, &path, flags);
strbuf_release(&path);
}
+
+ add_resolve_undo_to_pending(istate, revs);
}
void add_index_objects_to_pending(struct rev_info *revs, unsigned int flags)
@@ -1838,6 +1880,7 @@ void repo_init_revisions(struct repository *r,
revs->dense = 1;
revs->prefix = prefix;
revs->max_age = -1;
+ revs->max_age_as_filter = -1;
revs->min_age = -1;
revs->skip_count = -1;
revs->max_count = -1;
@@ -2218,6 +2261,9 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
} else if ((argcount = parse_long_opt("since", argv, &optarg))) {
revs->max_age = approxidate(optarg);
return argcount;
+ } else if ((argcount = parse_long_opt("since-as-filter", argv, &optarg))) {
+ revs->max_age_as_filter = approxidate(optarg);
+ return argcount;
} else if ((argcount = parse_long_opt("after", argv, &optarg))) {
revs->max_age = approxidate(optarg);
return argcount;
@@ -2691,9 +2737,9 @@ static int handle_revision_pseudo_opt(struct rev_info *revs,
revs->no_walk = 0;
} else if (!strcmp(arg, "--single-worktree")) {
revs->single_worktree = 1;
- } else if (skip_prefix(arg, ("--" CL_ARG__FILTER "="), &arg)) {
+ } else if (skip_prefix(arg, ("--filter="), &arg)) {
parse_list_objects_filter(&revs->filter, arg);
- } else if (!strcmp(arg, ("--no-" CL_ARG__FILTER))) {
+ } else if (!strcmp(arg, ("--no-filter"))) {
list_objects_filter_set_no_filter(&revs->filter);
} else {
return 0;
@@ -2833,7 +2879,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
}
strvec_clear(&prune_data);
- if (revs->def == NULL)
+ if (!revs->def)
revs->def = opt ? opt->def : NULL;
if (opt && opt->tweak)
opt->tweak(revs, opt);
@@ -2923,6 +2969,42 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
return left;
}
+static void release_revisions_cmdline(struct rev_cmdline_info *cmdline)
+{
+ unsigned int i;
+
+ for (i = 0; i < cmdline->nr; i++)
+ free((char *)cmdline->rev[i].name);
+ free(cmdline->rev);
+}
+
+static void release_revisions_mailmap(struct string_list *mailmap)
+{
+ if (!mailmap)
+ return;
+ clear_mailmap(mailmap);
+ free(mailmap);
+}
+
+static void release_revisions_topo_walk_info(struct topo_walk_info *info);
+
+void release_revisions(struct rev_info *revs)
+{
+ free_commit_list(revs->commits);
+ object_array_clear(&revs->pending);
+ object_array_clear(&revs->boundary_commits);
+ release_revisions_cmdline(&revs->cmdline);
+ list_objects_filter_release(&revs->filter);
+ clear_pathspec(&revs->prune_data);
+ date_mode_release(&revs->date_mode);
+ release_revisions_mailmap(revs->mailmap);
+ free_grep_patterns(&revs->grep_filter);
+ /* TODO (need to handle "no_free"): diff_free(&revs->diffopt) */
+ diff_free(&revs->pruning);
+ reflog_walk_info_release(revs->reflog_info);
+ release_revisions_topo_walk_info(revs->topo_walk_info);
+}
+
static void add_child(struct rev_info *revs, struct commit *parent, struct commit *child)
{
struct commit_list *l = xcalloc(1, sizeof(*l));
@@ -3433,17 +3515,22 @@ static void compute_indegrees_to_depth(struct rev_info *revs,
indegree_walk_step(revs);
}
-static void reset_topo_walk(struct rev_info *revs)
+static void release_revisions_topo_walk_info(struct topo_walk_info *info)
{
- struct topo_walk_info *info = revs->topo_walk_info;
-
+ if (!info)
+ return;
clear_prio_queue(&info->explore_queue);
clear_prio_queue(&info->indegree_queue);
clear_prio_queue(&info->topo_queue);
clear_indegree_slab(&info->indegree);
clear_author_date_slab(&info->author_date);
+ free(info);
+}
- FREE_AND_NULL(revs->topo_walk_info);
+static void reset_topo_walk(struct rev_info *revs)
+{
+ release_revisions_topo_walk_info(revs->topo_walk_info);
+ revs->topo_walk_info = NULL;
}
static void init_topo_walk(struct rev_info *revs)
@@ -3652,7 +3739,7 @@ static enum rewrite_result rewrite_one_1(struct rev_info *revs,
return rewrite_one_ok;
if (!p->parents)
return rewrite_one_noparents;
- if ((p = one_relevant_parent(revs, p->parents)) == NULL)
+ if (!(p = one_relevant_parent(revs, p->parents)))
return rewrite_one_ok;
*pp = p;
}
@@ -3862,6 +3949,9 @@ enum commit_action get_commit_action(struct rev_info *revs, struct commit *commi
if (revs->min_age != -1 &&
comparison_date(revs, commit) > revs->min_age)
return commit_ignore;
+ if (revs->max_age_as_filter != -1 &&
+ comparison_date(revs, commit) < revs->max_age_as_filter)
+ return commit_ignore;
if (revs->min_parents || (revs->max_parents >= 0)) {
int n = commit_list_count(commit->parents);
if ((n < revs->min_parents) ||
@@ -4080,10 +4170,8 @@ static void create_boundary_commit_list(struct rev_info *revs)
* boundary commits anyway. (This is what the code has always
* done.)
*/
- if (revs->commits) {
- free_commit_list(revs->commits);
- revs->commits = NULL;
- }
+ free_commit_list(revs->commits);
+ revs->commits = NULL;
/*
* Put all of the actual boundary commits from revs->boundary_commits
@@ -4220,10 +4308,8 @@ struct commit *get_revision(struct rev_info *revs)
graph_update(revs->graph, c);
if (!c) {
free_saved_parents(revs);
- if (revs->previous_parents) {
- free_commit_list(revs->previous_parents);
- revs->previous_parents = NULL;
- }
+ free_commit_list(revs->previous_parents);
+ revs->previous_parents = NULL;
}
return c;
}