diff options
Diffstat (limited to 'revision.c')
| -rw-r--r-- | revision.c | 83 |
1 files changed, 56 insertions, 27 deletions
diff --git a/revision.c b/revision.c index 99c859f797..0dabb5a0bc 100644 --- a/revision.c +++ b/revision.c @@ -316,9 +316,10 @@ static void add_pending_object_with_path(struct rev_info *revs, revs->no_walk = 0; if (revs->reflog_info && obj->type == OBJ_COMMIT) { struct strbuf buf = STRBUF_INIT; - int len = interpret_branch_name(name, 0, &buf, &options); + size_t namelen = strlen(name); + int len = interpret_branch_name(name, namelen, &buf, &options); - if (0 < len && name[len] && buf.len) + if (0 < len && len < namelen && buf.len) strbuf_addstr(&buf, name + len); add_reflog_for_walk(revs->reflog_info, (struct commit *)obj, @@ -359,20 +360,18 @@ static struct object *get_reference(struct rev_info *revs, const char *name, unsigned int flags) { struct object *object; + struct commit *commit; /* - * If the repository has commit graphs, repo_parse_commit() avoids - * reading the object buffer, so use it whenever possible. + * If the repository has commit graphs, we try to opportunistically + * look up the object ID in those graphs. Like this, we can avoid + * parsing commit data from disk. */ - if (oid_object_info(revs->repo, oid, NULL) == OBJ_COMMIT) { - struct commit *c = lookup_commit(revs->repo, oid); - if (!repo_parse_commit(revs->repo, c)) - object = (struct object *) c; - else - object = NULL; - } else { + commit = lookup_commit_in_graph(revs->repo, oid); + if (commit) + object = &commit->object; + else object = parse_object(revs->repo, oid); - } if (!object) { if (revs->ignore_missing) @@ -1123,7 +1122,7 @@ static int process_parents(struct rev_info *revs, struct commit *commit, mark_parents_uninteresting(p); if (p->object.flags & SEEN) continue; - p->object.flags |= SEEN; + p->object.flags |= (SEEN | NOT_USER_GIVEN); if (list) commit_list_insert_by_date(p, list); if (queue) @@ -1165,7 +1164,7 @@ static int process_parents(struct rev_info *revs, struct commit *commit, } p->object.flags |= left_flag; if (!(p->object.flags & SEEN)) { - p->object.flags |= SEEN; + p->object.flags |= (SEEN | NOT_USER_GIVEN); if (list) commit_list_insert_by_date(p, list); if (queue) @@ -1393,20 +1392,20 @@ static int limit_list(struct rev_info *revs) { int slop = SLOP; timestamp_t date = TIME_MAX; - struct commit_list *list = revs->commits; + struct commit_list *original_list = revs->commits; struct commit_list *newlist = NULL; struct commit_list **p = &newlist; struct commit_list *bottom = NULL; struct commit *interesting_cache = NULL; if (revs->ancestry_path) { - bottom = collect_bottom_commits(list); + bottom = collect_bottom_commits(original_list); if (!bottom) die("--ancestry-path given but there are no bottom commits"); } - while (list) { - struct commit *commit = pop_commit(&list); + while (original_list) { + struct commit *commit = pop_commit(&original_list); struct object *obj = &commit->object; show_early_output_fn_t show; @@ -1415,11 +1414,11 @@ static int limit_list(struct rev_info *revs) if (revs->max_age != -1 && (commit->date < revs->max_age)) obj->flags |= UNINTERESTING; - if (process_parents(revs, commit, &list, NULL) < 0) + if (process_parents(revs, commit, &original_list, NULL) < 0) return -1; if (obj->flags & UNINTERESTING) { mark_parents_uninteresting(commit); - slop = still_interesting(list, date, slop, &interesting_cache); + slop = still_interesting(original_list, date, slop, &interesting_cache); if (slop) continue; break; @@ -1452,14 +1451,17 @@ static int limit_list(struct rev_info *revs) * Check if any commits have become TREESAME by some of their parents * becoming UNINTERESTING. */ - if (limiting_can_increase_treesame(revs)) + if (limiting_can_increase_treesame(revs)) { + struct commit_list *list = NULL; for (list = newlist; list; list = list->next) { struct commit *c = list->item; if (c->object.flags & (UNINTERESTING | TREESAME)) continue; update_treesame(revs, c); } + } + free_commit_list(original_list); revs->commits = newlist; return 0; } @@ -1530,7 +1532,7 @@ static int handle_one_ref(const char *path, const struct object_id *oid, 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_oid(cb->all_revs, path, oid, cb->all_flags); + add_pending_object(cb->all_revs, object, path); return 0; } @@ -1680,6 +1682,8 @@ static void do_add_index_objects_to_pending(struct rev_info *revs, { int i; + /* TODO: audit for interaction with sparse-index. */ + ensure_full_index(istate); for (i = 0; i < istate->cache_nr; i++) { struct cache_entry *ce = istate->cache[i]; struct blob *blob; @@ -2250,6 +2254,10 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg } else if (!strcmp(arg, "--author-date-order")) { revs->sort_order = REV_SORT_BY_AUTHOR_DATE; revs->topo_order = 1; + } else if (!strcmp(arg, "--unsorted-input")) { + if (revs->no_walk) + die(_("--unsorted-input is incompatible with --no-walk")); + revs->unsorted_input = 1; } else if (!strcmp(arg, "--early-output")) { revs->early_output = 100; revs->topo_order = 1; @@ -2336,6 +2344,16 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg revs->unpacked = 1; } else if (starts_with(arg, "--unpacked=")) { 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; + } 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; + if (!strcmp(optarg, "on-disk")) + revs->keep_pack_cache_flags |= ON_DISK_KEEP_PACKS; } else if (!strcmp(arg, "-r")) { revs->diff = 1; revs->diffopt.flags.recursive = 1; @@ -2635,16 +2653,22 @@ static int handle_revision_pseudo_opt(const char *submodule, } else if (!strcmp(arg, "--not")) { *flags ^= UNINTERESTING | BOTTOM; } else if (!strcmp(arg, "--no-walk")) { - revs->no_walk = REVISION_WALK_NO_WALK_SORTED; + if (!revs->no_walk && revs->unsorted_input) + die(_("--no-walk is incompatible with --unsorted-input")); + revs->no_walk = 1; } else if (skip_prefix(arg, "--no-walk=", &optarg)) { + if (!revs->no_walk && revs->unsorted_input) + die(_("--no-walk is incompatible with --unsorted-input")); + /* * Detached form ("--no-walk X" as opposed to "--no-walk=X") * not allowed, since the argument is optional. */ + revs->no_walk = 1; if (!strcmp(optarg, "sorted")) - revs->no_walk = REVISION_WALK_NO_WALK_SORTED; + revs->unsorted_input = 0; else if (!strcmp(optarg, "unsorted")) - revs->no_walk = REVISION_WALK_NO_WALK_UNSORTED; + revs->unsorted_input = 1; else return error("invalid argument to --no-walk"); } else if (!strcmp(arg, "--do-walk")) { @@ -3261,7 +3285,7 @@ static int mark_uninteresting(const struct object_id *oid, void *cb) { struct rev_info *revs = cb; - struct object *o = parse_object(revs->repo, oid); + struct object *o = lookup_unknown_object(revs->repo, oid); o->flags |= UNINTERESTING | SEEN; return 0; } @@ -3568,7 +3592,7 @@ int prepare_revision_walk(struct rev_info *revs) if (!revs->reflog_info) prepare_to_use_bloom_filter(revs); - if (revs->no_walk != REVISION_WALK_NO_WALK_UNSORTED) + if (!revs->unsorted_input) commit_list_sort_by_date(&revs->commits); if (revs->no_walk) return 0; @@ -3795,6 +3819,11 @@ enum commit_action get_commit_action(struct rev_info *revs, struct commit *commi return commit_ignore; if (revs->unpacked && has_object_pack(&commit->object.oid)) return commit_ignore; + if (revs->no_kept_objects) { + if (has_object_kept_pack(&commit->object.oid, + revs->keep_pack_cache_flags)) + return commit_ignore; + } if (commit->object.flags & UNINTERESTING) return commit_ignore; if (revs->line_level_traverse && !want_ancestry(revs)) { |
