aboutsummaryrefslogtreecommitdiff
path: root/revision.c
diff options
context:
space:
mode:
Diffstat (limited to 'revision.c')
-rw-r--r--revision.c225
1 files changed, 113 insertions, 112 deletions
diff --git a/revision.c b/revision.c
index cf5e6c1ec9..599b3a66c3 100644
--- a/revision.c
+++ b/revision.c
@@ -72,7 +72,7 @@ static void mark_tree_contents_uninteresting(struct repository *r,
struct tree_desc desc;
struct name_entry entry;
- if (parse_tree_gently(tree, 1) < 0)
+ if (repo_parse_tree_gently(the_repository, tree, 1) < 0)
return;
init_tree_desc(&desc, &tree->object.oid, tree->buffer, tree->size);
@@ -179,7 +179,7 @@ static void add_children_by_path(struct repository *r,
if (!tree)
return;
- if (parse_tree_gently(tree, 1) < 0)
+ if (repo_parse_tree_gently(the_repository, tree, 1) < 0)
return;
init_tree_desc(&desc, &tree->object.oid, tree->buffer, tree->size);
@@ -250,29 +250,6 @@ void mark_trees_uninteresting_sparse(struct repository *r,
paths_and_oids_clear(&map);
}
-struct commit_stack {
- struct commit **items;
- size_t nr, alloc;
-};
-#define COMMIT_STACK_INIT { 0 }
-
-static void commit_stack_push(struct commit_stack *stack, struct commit *commit)
-{
- ALLOC_GROW(stack->items, stack->nr + 1, stack->alloc);
- stack->items[stack->nr++] = commit;
-}
-
-static struct commit *commit_stack_pop(struct commit_stack *stack)
-{
- return stack->nr ? stack->items[--stack->nr] : NULL;
-}
-
-static void commit_stack_clear(struct commit_stack *stack)
-{
- FREE_AND_NULL(stack->items);
- stack->nr = stack->alloc = 0;
-}
-
static void mark_one_parent_uninteresting(struct rev_info *revs, struct commit *commit,
struct commit_stack *pending)
{
@@ -1071,7 +1048,7 @@ static void try_to_simplify_commit(struct rev_info *revs, struct commit *commit)
continue;
}
- free_commit_list(parent->next);
+ commit_list_free(parent->next);
parent->next = NULL;
while (commit->parents != parent)
pop_commit(&commit->parents);
@@ -1106,7 +1083,7 @@ static void try_to_simplify_commit(struct rev_info *revs, struct commit *commit)
die("cannot simplify commit %s (invalid %s)",
oid_to_hex(&commit->object.oid),
oid_to_hex(&p->object.oid));
- free_commit_list(p->parents);
+ commit_list_free(p->parents);
p->parents = NULL;
}
/* fallthrough */
@@ -1173,7 +1150,8 @@ static int process_parents(struct rev_info *revs, struct commit *commit,
struct commit *p = parent->item;
parent = parent->next;
if (p)
- p->object.flags |= UNINTERESTING;
+ p->object.flags |= UNINTERESTING |
+ CHILD_VISITED;
if (repo_parse_commit_gently(revs->repo, p, 1) < 0)
continue;
if (p->parents)
@@ -1227,7 +1205,7 @@ static int process_parents(struct rev_info *revs, struct commit *commit,
if (!*slot)
*slot = *revision_sources_at(revs->sources, commit);
}
- p->object.flags |= pass_flags;
+ p->object.flags |= pass_flags | CHILD_VISITED;
if (!(p->object.flags & SEEN)) {
p->object.flags |= (SEEN | NOT_USER_GIVEN);
if (list)
@@ -1428,7 +1406,7 @@ static void limit_to_ancestry(struct commit_list *bottoms, struct commit_list *l
p->item->object.flags &= ~(TMP_MARK | ANCESTRY_PATH);
for (p = bottoms; p; p = p->next)
p->item->object.flags &= ~(TMP_MARK | ANCESTRY_PATH);
- free_commit_list(rlist);
+ commit_list_free(rlist);
}
/*
@@ -1531,7 +1509,7 @@ static int limit_list(struct rev_info *revs)
}
}
- free_commit_list(original_list);
+ commit_list_free(original_list);
revs->commits = newlist;
return 0;
}
@@ -1644,19 +1622,17 @@ struct all_refs_cb {
struct worktree *wt;
};
-static int handle_one_ref(const char *path, const char *referent UNUSED, const struct object_id *oid,
- int flag UNUSED,
- void *cb_data)
+static int handle_one_ref(const struct reference *ref, void *cb_data)
{
struct all_refs_cb *cb = cb_data;
struct object *object;
- if (ref_excluded(&cb->all_revs->ref_excludes, path))
+ if (ref_excluded(&cb->all_revs->ref_excludes, ref->name))
return 0;
- object = get_reference(cb->all_revs, path, oid, cb->all_flags);
- add_rev_cmdline(cb->all_revs, object, path, REV_CMD_REF, cb->all_flags);
- add_pending_object(cb->all_revs, object, path);
+ object = get_reference(cb->all_revs, ref->name, ref->oid, cb->all_flags);
+ add_rev_cmdline(cb->all_revs, object, ref->name, REV_CMD_REF, cb->all_flags);
+ add_pending_object(cb->all_revs, object, ref->name);
return 0;
}
@@ -1671,7 +1647,7 @@ static void init_all_refs_cb(struct all_refs_cb *cb, struct rev_info *revs,
static void handle_refs(struct ref_store *refs,
struct rev_info *revs, unsigned flags,
- int (*for_each)(struct ref_store *, each_ref_fn, void *))
+ int (*for_each)(struct ref_store *, refs_for_each_cb, void *))
{
struct all_refs_cb cb;
@@ -1872,7 +1848,7 @@ void add_index_objects_to_pending(struct rev_info *revs, unsigned int flags)
wt_gitdir = get_worktree_git_dir(wt);
if (read_index_from(&istate,
- worktree_git_path(the_repository, wt, "index"),
+ worktree_git_path(wt, "index"),
wt_gitdir) > 0)
do_add_index_objects_to_pending(revs, &istate, flags);
@@ -2036,7 +2012,7 @@ static void prepare_show_merge(struct rev_info *revs)
exit(128);
add_rev_cmdline_list(revs, bases, REV_CMD_MERGE_BASE, UNINTERESTING | BOTTOM);
add_pending_commit_list(revs, bases, UNINTERESTING | BOTTOM);
- free_commit_list(bases);
+ commit_list_free(bases);
head->object.flags |= SYMMETRIC_LEFT;
if (!istate->cache_nr)
@@ -2062,41 +2038,32 @@ static void prepare_show_merge(struct rev_info *revs)
free(prune);
}
-static int dotdot_missing(const char *arg, char *dotdot,
+static int dotdot_missing(const char *full_name,
struct rev_info *revs, int symmetric)
{
if (revs->ignore_missing)
return 0;
- /* de-munge so we report the full argument */
- *dotdot = '.';
die(symmetric
? "Invalid symmetric difference expression %s"
- : "Invalid revision range %s", arg);
+ : "Invalid revision range %s", full_name);
}
-static int handle_dotdot_1(const char *arg, char *dotdot,
+static int handle_dotdot_1(const char *a_name, const char *b_name,
+ const char *full_name, int symmetric,
struct rev_info *revs, int flags,
int cant_be_filename,
struct object_context *a_oc,
struct object_context *b_oc)
{
- const char *a_name, *b_name;
struct object_id a_oid, b_oid;
struct object *a_obj, *b_obj;
unsigned int a_flags, b_flags;
- int symmetric = 0;
unsigned int flags_exclude = flags ^ (UNINTERESTING | BOTTOM);
unsigned int oc_flags = GET_OID_COMMITTISH | GET_OID_RECORD_PATH;
- a_name = arg;
if (!*a_name)
a_name = "HEAD";
- b_name = dotdot + 2;
- if (*b_name == '.') {
- symmetric = 1;
- b_name++;
- }
if (!*b_name)
b_name = "HEAD";
@@ -2105,15 +2072,13 @@ static int handle_dotdot_1(const char *arg, char *dotdot,
return -1;
if (!cant_be_filename) {
- *dotdot = '.';
- verify_non_filename(revs->prefix, arg);
- *dotdot = '\0';
+ verify_non_filename(revs->prefix, full_name);
}
a_obj = parse_object(revs->repo, &a_oid);
b_obj = parse_object(revs->repo, &b_oid);
if (!a_obj || !b_obj)
- return dotdot_missing(arg, dotdot, revs, symmetric);
+ return dotdot_missing(full_name, revs, symmetric);
if (!symmetric) {
/* just A..B */
@@ -2127,16 +2092,16 @@ static int handle_dotdot_1(const char *arg, char *dotdot,
a = lookup_commit_reference(revs->repo, &a_obj->oid);
b = lookup_commit_reference(revs->repo, &b_obj->oid);
if (!a || !b)
- return dotdot_missing(arg, dotdot, revs, symmetric);
+ return dotdot_missing(full_name, revs, symmetric);
if (repo_get_merge_bases(the_repository, a, b, &exclude) < 0) {
- free_commit_list(exclude);
+ commit_list_free(exclude);
return -1;
}
add_rev_cmdline_list(revs, exclude, REV_CMD_MERGE_BASE,
flags_exclude);
add_pending_commit_list(revs, exclude, flags_exclude);
- free_commit_list(exclude);
+ commit_list_free(exclude);
b_flags = flags;
a_flags = flags | SYMMETRIC_LEFT;
@@ -2156,16 +2121,23 @@ static int handle_dotdot(const char *arg,
int cant_be_filename)
{
struct object_context a_oc = {0}, b_oc = {0};
- char *dotdot = strstr(arg, "..");
+ const char *dotdot = strstr(arg, "..");
+ char *tmp;
+ int symmetric = 0;
int ret;
if (!dotdot)
return -1;
- *dotdot = '\0';
- ret = handle_dotdot_1(arg, dotdot, revs, flags, cant_be_filename,
- &a_oc, &b_oc);
- *dotdot = '.';
+ tmp = xmemdupz(arg, dotdot - arg);
+ dotdot += 2;
+ if (*dotdot == '.') {
+ symmetric = 1;
+ dotdot++;
+ }
+ ret = handle_dotdot_1(tmp, dotdot, arg, symmetric, revs, flags,
+ cant_be_filename, &a_oc, &b_oc);
+ free(tmp);
object_context_release(&a_oc);
object_context_release(&b_oc);
@@ -2175,7 +2147,10 @@ static int handle_dotdot(const char *arg,
static int handle_revision_arg_1(const char *arg_, struct rev_info *revs, int flags, unsigned revarg_opt)
{
struct object_context oc = {0};
- char *mark;
+ const char *mark;
+ char *arg_minus_at = NULL;
+ char *arg_minus_excl = NULL;
+ char *arg_minus_dash = NULL;
struct object *object;
struct object_id oid;
int local_flags;
@@ -2202,18 +2177,17 @@ static int handle_revision_arg_1(const char *arg_, struct rev_info *revs, int fl
mark = strstr(arg, "^@");
if (mark && !mark[2]) {
- *mark = 0;
- if (add_parents_only(revs, arg, flags, 0)) {
+ arg_minus_at = xmemdupz(arg, mark - arg);
+ if (add_parents_only(revs, arg_minus_at, flags, 0)) {
ret = 0;
goto out;
}
- *mark = '^';
}
mark = strstr(arg, "^!");
if (mark && !mark[2]) {
- *mark = 0;
- if (!add_parents_only(revs, arg, flags ^ (UNINTERESTING | BOTTOM), 0))
- *mark = '^';
+ arg_minus_excl = xmemdupz(arg, mark - arg);
+ if (add_parents_only(revs, arg_minus_excl, flags ^ (UNINTERESTING | BOTTOM), 0))
+ arg = arg_minus_excl;
}
mark = strstr(arg, "^-");
if (mark) {
@@ -2227,9 +2201,9 @@ static int handle_revision_arg_1(const char *arg_, struct rev_info *revs, int fl
}
}
- *mark = 0;
- if (!add_parents_only(revs, arg, flags ^ (UNINTERESTING | BOTTOM), exclude_parent))
- *mark = '^';
+ arg_minus_dash = xmemdupz(arg, mark - arg);
+ if (add_parents_only(revs, arg_minus_dash, flags ^ (UNINTERESTING | BOTTOM), exclude_parent))
+ arg = arg_minus_dash;
}
local_flags = 0;
@@ -2264,6 +2238,9 @@ static int handle_revision_arg_1(const char *arg_, struct rev_info *revs, int fl
out:
object_context_release(&oc);
+ free(arg_minus_at);
+ free(arg_minus_excl);
+ free(arg_minus_dash);
return ret;
}
@@ -2402,6 +2379,8 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
} else if ((argcount = parse_long_opt("until", argv, &optarg))) {
revs->min_age = approxidate(optarg);
return argcount;
+ } else if (!strcmp(arg, "--maximal-only")) {
+ revs->maximal_only = 1;
} else if (!strcmp(arg, "--first-parent")) {
revs->first_parent_only = 1;
} else if (!strcmp(arg, "--exclude-first-parent-only")) {
@@ -2543,14 +2522,14 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
die(_("--unpacked=<packfile> no longer supported"));
} else if (!strcmp(arg, "--no-kept-objects")) {
revs->no_kept_objects = 1;
- revs->keep_pack_cache_flags |= IN_CORE_KEEP_PACKS;
- revs->keep_pack_cache_flags |= ON_DISK_KEEP_PACKS;
+ revs->keep_pack_cache_flags |= KEPT_PACK_IN_CORE;
+ revs->keep_pack_cache_flags |= KEPT_PACK_ON_DISK;
} else if (skip_prefix(arg, "--no-kept-objects=", &optarg)) {
revs->no_kept_objects = 1;
if (!strcmp(optarg, "in-core"))
- revs->keep_pack_cache_flags |= IN_CORE_KEEP_PACKS;
+ revs->keep_pack_cache_flags |= KEPT_PACK_IN_CORE;
if (!strcmp(optarg, "on-disk"))
- revs->keep_pack_cache_flags |= ON_DISK_KEEP_PACKS;
+ revs->keep_pack_cache_flags |= KEPT_PACK_ON_DISK;
} else if (!strcmp(arg, "-r")) {
revs->diff = 1;
revs->diffopt.flags.recursive = 1;
@@ -2753,23 +2732,25 @@ void revision_opts_finish(struct rev_info *revs)
}
}
-static int for_each_bisect_ref(struct ref_store *refs, each_ref_fn fn,
+static int for_each_bisect_ref(struct ref_store *refs, refs_for_each_cb fn,
void *cb_data, const char *term)
{
+ struct refs_for_each_ref_options opts = { 0 };
struct strbuf bisect_refs = STRBUF_INIT;
int status;
strbuf_addf(&bisect_refs, "refs/bisect/%s", term);
- status = refs_for_each_fullref_in(refs, bisect_refs.buf, NULL, fn, cb_data);
+ opts.prefix = bisect_refs.buf;
+ status = refs_for_each_ref_ext(refs, fn, cb_data, &opts);
strbuf_release(&bisect_refs);
return status;
}
-static int for_each_bad_bisect_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
+static int for_each_bad_bisect_ref(struct ref_store *refs, refs_for_each_cb fn, void *cb_data)
{
return for_each_bisect_ref(refs, fn, cb_data, term_bad);
}
-static int for_each_good_bisect_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
+static int for_each_good_bisect_ref(struct ref_store *refs, refs_for_each_cb fn, void *cb_data)
{
return for_each_bisect_ref(refs, fn, cb_data, term_good);
}
@@ -2839,10 +2820,13 @@ static int handle_revision_pseudo_opt(struct rev_info *revs,
handle_refs(refs, revs, *flags, refs_for_each_remote_ref);
clear_ref_exclusions(&revs->ref_excludes);
} else if ((argcount = parse_long_opt("glob", argv, &optarg))) {
+ struct refs_for_each_ref_options opts = {
+ .pattern = optarg,
+ };
struct all_refs_cb cb;
init_all_refs_cb(&cb, revs, *flags);
- refs_for_each_glob_ref(get_main_ref_store(the_repository),
- handle_one_ref, optarg, &cb);
+ refs_for_each_ref_ext(get_main_ref_store(the_repository),
+ handle_one_ref, &cb, &opts);
clear_ref_exclusions(&revs->ref_excludes);
return argcount;
} else if ((argcount = parse_long_opt("exclude", argv, &optarg))) {
@@ -2852,34 +2836,46 @@ static int handle_revision_pseudo_opt(struct rev_info *revs,
exclude_hidden_refs(&revs->ref_excludes, optarg);
return argcount;
} else if (skip_prefix(arg, "--branches=", &optarg)) {
+ struct refs_for_each_ref_options opts = {
+ .prefix = "refs/heads/",
+ .trim_prefix = strlen("refs/heads/"),
+ .pattern = optarg,
+ };
struct all_refs_cb cb;
if (revs->ref_excludes.hidden_refs_configured)
return error(_("options '%s' and '%s' cannot be used together"),
"--exclude-hidden", "--branches");
init_all_refs_cb(&cb, revs, *flags);
- refs_for_each_glob_ref_in(get_main_ref_store(the_repository),
- handle_one_ref, optarg,
- "refs/heads/", &cb);
+ refs_for_each_ref_ext(get_main_ref_store(the_repository),
+ handle_one_ref, &cb, &opts);
clear_ref_exclusions(&revs->ref_excludes);
} else if (skip_prefix(arg, "--tags=", &optarg)) {
+ struct refs_for_each_ref_options opts = {
+ .prefix = "refs/tags/",
+ .trim_prefix = strlen("refs/tags/"),
+ .pattern = optarg,
+ };
struct all_refs_cb cb;
if (revs->ref_excludes.hidden_refs_configured)
return error(_("options '%s' and '%s' cannot be used together"),
"--exclude-hidden", "--tags");
init_all_refs_cb(&cb, revs, *flags);
- refs_for_each_glob_ref_in(get_main_ref_store(the_repository),
- handle_one_ref, optarg,
- "refs/tags/", &cb);
+ refs_for_each_ref_ext(get_main_ref_store(the_repository),
+ handle_one_ref, &cb, &opts);
clear_ref_exclusions(&revs->ref_excludes);
} else if (skip_prefix(arg, "--remotes=", &optarg)) {
+ struct refs_for_each_ref_options opts = {
+ .prefix = "refs/remotes/",
+ .trim_prefix = strlen("refs/remotes/"),
+ .pattern = optarg,
+ };
struct all_refs_cb cb;
if (revs->ref_excludes.hidden_refs_configured)
return error(_("options '%s' and '%s' cannot be used together"),
"--exclude-hidden", "--remotes");
init_all_refs_cb(&cb, revs, *flags);
- refs_for_each_glob_ref_in(get_main_ref_store(the_repository),
- handle_one_ref, optarg,
- "refs/remotes/", &cb);
+ refs_for_each_ref_ext(get_main_ref_store(the_repository),
+ handle_one_ref, &cb, &opts);
clear_ref_exclusions(&revs->ref_excludes);
} else if (!strcmp(arg, "--reflog")) {
add_reflogs_to_pending(revs, *flags);
@@ -3133,6 +3129,8 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
if (want_ancestry(revs))
revs->limited = 1;
revs->topo_order = 1;
+ if (!revs->diffopt.output_format)
+ revs->diffopt.output_format = DIFF_FORMAT_PATCH;
}
if (revs->topo_order && !generation_numbers_enabled(the_repository))
@@ -3172,6 +3170,9 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
!!revs->reverse, "--reverse",
!!revs->reflog_info, "--walk-reflogs");
+ die_for_incompatible_opt2(!!revs->boundary, "--boundary",
+ !!revs->maximal_only, "--maximal-only");
+
if (revs->no_walk && revs->graph)
die(_("options '%s' and '%s' cannot be used together"), "--no-walk", "--graph");
if (!revs->reflog_info && revs->grep_filter.use_reflog_filter)
@@ -3246,13 +3247,13 @@ static void release_revisions_bloom_keyvecs(struct rev_info *revs)
static void free_void_commit_list(void *list)
{
- free_commit_list(list);
+ commit_list_free(list);
}
void release_revisions(struct rev_info *revs)
{
- free_commit_list(revs->commits);
- free_commit_list(revs->ancestry_path_bottoms);
+ commit_list_free(revs->commits);
+ commit_list_free(revs->ancestry_path_bottoms);
release_display_notes(&revs->notes_opt);
object_array_clear(&revs->pending);
object_array_clear(&revs->boundary_commits);
@@ -3360,7 +3361,7 @@ static int mark_redundant_parents(struct commit *commit)
if (i != cnt || cnt+marked != orig_cnt)
die("mark_redundant_parents %d %d %d %d", orig_cnt, cnt, i, marked);
- free_commit_list(h);
+ commit_list_free(h);
return marked;
}
@@ -3651,8 +3652,7 @@ void reset_revision_walk(void)
}
static int mark_uninteresting(const struct object_id *oid,
- struct packed_git *pack UNUSED,
- uint32_t pos UNUSED,
+ struct object_info *oi UNUSED,
void *cb)
{
struct rev_info *revs = cb;
@@ -3961,10 +3961,9 @@ int prepare_revision_walk(struct rev_info *revs)
(revs->limited && limiting_can_increase_treesame(revs)))
revs->treesame.name = "treesame";
- if (revs->exclude_promisor_objects) {
- for_each_packed_object(revs->repo, mark_uninteresting, revs,
- FOR_EACH_OBJECT_PROMISOR_ONLY);
- }
+ if (revs->exclude_promisor_objects)
+ odb_for_each_object(revs->repo->objects, NULL, mark_uninteresting,
+ revs, ODB_FOR_EACH_OBJECT_PROMISOR_ONLY);
if (!revs->reflog_info)
prepare_to_use_bloom_filter(revs);
@@ -4150,6 +4149,8 @@ enum commit_action get_commit_action(struct rev_info *revs, struct commit *commi
{
if (commit->object.flags & SHOWN)
return commit_ignore;
+ if (revs->maximal_only && (commit->object.flags & CHILD_VISITED))
+ return commit_ignore;
if (revs->unpacked && has_object_pack(revs->repo, &commit->object.oid))
return commit_ignore;
if (revs->no_kept_objects) {
@@ -4249,7 +4250,7 @@ static void save_parents(struct rev_info *revs, struct commit *commit)
if (*pp)
return;
if (commit->parents)
- *pp = copy_commit_list(commit->parents);
+ *pp = commit_list_copy(commit->parents);
else
*pp = EMPTY_PARENT_LIST;
}
@@ -4257,7 +4258,7 @@ static void save_parents(struct rev_info *revs, struct commit *commit)
static void free_saved_parent(struct commit_list **parents)
{
if (*parents != EMPTY_PARENT_LIST)
- free_commit_list(*parents);
+ commit_list_free(*parents);
}
static void free_saved_parents(struct rev_info *revs)
@@ -4318,8 +4319,8 @@ static void track_linear(struct rev_info *revs, struct commit *commit)
if (revs->linear)
commit->object.flags |= TRACK_LINEAR;
}
- free_commit_list(revs->previous_parents);
- revs->previous_parents = copy_commit_list(commit->parents);
+ commit_list_free(revs->previous_parents);
+ revs->previous_parents = commit_list_copy(commit->parents);
}
static struct commit *get_revision_1(struct rev_info *revs)
@@ -4407,7 +4408,7 @@ static void create_boundary_commit_list(struct rev_info *revs)
* boundary commits anyway. (This is what the code has always
* done.)
*/
- free_commit_list(revs->commits);
+ commit_list_free(revs->commits);
revs->commits = NULL;
/*
@@ -4529,7 +4530,7 @@ struct commit *get_revision(struct rev_info *revs)
reversed = NULL;
while ((c = get_revision_internal(revs)))
commit_list_insert(c, &reversed);
- free_commit_list(revs->commits);
+ commit_list_free(revs->commits);
revs->commits = reversed;
revs->reverse = 0;
revs->reverse_output_stage = 1;
@@ -4547,7 +4548,7 @@ struct commit *get_revision(struct rev_info *revs)
graph_update(revs->graph, c);
if (!c) {
free_saved_parents(revs);
- free_commit_list(revs->previous_parents);
+ commit_list_free(revs->previous_parents);
revs->previous_parents = NULL;
}
return c;