diff options
Diffstat (limited to 'builtin/rev-list.c')
| -rw-r--r-- | builtin/rev-list.c | 233 |
1 files changed, 170 insertions, 63 deletions
diff --git a/builtin/rev-list.c b/builtin/rev-list.c index ff715d6918..bb26bee0d4 100644 --- a/builtin/rev-list.c +++ b/builtin/rev-list.c @@ -1,3 +1,6 @@ +#define USE_THE_REPOSITORY_VARIABLE +#define DISABLE_SIGN_COMPARE_WARNINGS + #include "builtin.h" #include "config.h" #include "commit.h" @@ -7,13 +10,11 @@ #include "hex.h" #include "revision.h" #include "list-objects.h" -#include "list-objects-filter.h" #include "list-objects-filter-options.h" #include "object.h" #include "object-name.h" #include "object-file.h" #include "object-store-ll.h" -#include "pack.h" #include "pack-bitmap.h" #include "log-tree.h" #include "graph.h" @@ -21,7 +22,10 @@ #include "progress.h" #include "reflog-walk.h" #include "oidset.h" +#include "oidmap.h" #include "packfile.h" +#include "quote.h" +#include "strbuf.h" static const char rev_list_usage[] = "git rev-list [<options>] <commit>... [--] [<path>...]\n" @@ -72,11 +76,17 @@ static unsigned progress_counter; static struct oidset omitted_objects; static int arg_print_omitted; /* print objects omitted by filter */ -static struct oidset missing_objects; +struct missing_objects_map_entry { + struct oidmap_entry entry; + const char *path; + unsigned type; +}; +static struct oidmap missing_objects; enum missing_action { MA_ERROR = 0, /* fail if any missing objects are encountered */ MA_ALLOW_ANY, /* silently allow ALL missing objects */ MA_PRINT, /* print ALL missing objects in special section */ + MA_PRINT_INFO, /* same as MA_PRINT but also prints missing object info */ MA_ALLOW_PROMISOR, /* silently allow all missing PROMISOR objects */ }; static enum missing_action arg_missing_action; @@ -100,7 +110,91 @@ static off_t get_object_disk_usage(struct object *obj) return size; } -static void finish_commit(struct commit *commit); +static void add_missing_object_entry(struct object_id *oid, const char *path, + unsigned type) +{ + struct missing_objects_map_entry *entry; + + if (oidmap_get(&missing_objects, oid)) + return; + + CALLOC_ARRAY(entry, 1); + entry->entry.oid = *oid; + entry->type = type; + if (path) + entry->path = xstrdup(path); + oidmap_put(&missing_objects, entry); +} + +static void print_missing_object(struct missing_objects_map_entry *entry, + int print_missing_info) +{ + struct strbuf sb = STRBUF_INIT; + + if (!print_missing_info) { + printf("?%s\n", oid_to_hex(&entry->entry.oid)); + return; + } + + if (entry->path && *entry->path) { + struct strbuf path = STRBUF_INIT; + + strbuf_addstr(&sb, " path="); + quote_path(entry->path, NULL, &path, QUOTE_PATH_QUOTE_SP); + strbuf_addbuf(&sb, &path); + + strbuf_release(&path); + } + if (entry->type) + strbuf_addf(&sb, " type=%s", type_name(entry->type)); + + printf("?%s%s\n", oid_to_hex(&entry->entry.oid), sb.buf); + strbuf_release(&sb); +} + +static inline void finish_object__ma(struct object *obj, const char *name) +{ + /* + * Whether or not we try to dynamically fetch missing objects + * from the server, we currently DO NOT have the object. We + * can either print, allow (ignore), or conditionally allow + * (ignore) them. + */ + switch (arg_missing_action) { + case MA_ERROR: + die("missing %s object '%s'", + type_name(obj->type), oid_to_hex(&obj->oid)); + return; + + case MA_ALLOW_ANY: + return; + + case MA_PRINT: + case MA_PRINT_INFO: + add_missing_object_entry(&obj->oid, name, obj->type); + return; + + case MA_ALLOW_PROMISOR: + if (is_promisor_object(the_repository, &obj->oid)) + return; + die("unexpected missing %s object '%s'", + type_name(obj->type), oid_to_hex(&obj->oid)); + return; + + default: + BUG("unhandled missing_action"); + return; + } +} + +static void finish_commit(struct commit *commit) +{ + free_commit_list(commit->parents); + commit->parents = NULL; + free_commit_buffer(the_repository->parsed_objects, + commit); +} + static void show_commit(struct commit *commit, void *data) { struct rev_list_info *info = data; @@ -108,6 +202,12 @@ static void show_commit(struct commit *commit, void *data) display_progress(progress, ++progress_counter); + if (revs->do_not_die_on_missing_objects && + oidset_contains(&revs->missing_commits, &commit->object.oid)) { + finish_object__ma(&commit->object, NULL); + return; + } + if (show_disk_usage) total_disk_usage += get_object_disk_usage(&commit->object); @@ -174,6 +274,7 @@ static void show_commit(struct commit *commit, void *data) ctx.fmt = revs->commit_format; ctx.output_encoding = get_log_output_encoding(); ctx.color = revs->diffopt.use_color; + ctx.rev = revs; pretty_print_commit(&ctx, commit, &buf); if (buf.len) { if (revs->commit_format != CMIT_FMT_ONELINE) @@ -219,54 +320,11 @@ static void show_commit(struct commit *commit, void *data) finish_commit(commit); } -static void finish_commit(struct commit *commit) -{ - free_commit_list(commit->parents); - commit->parents = NULL; - free_commit_buffer(the_repository->parsed_objects, - commit); -} - -static inline void finish_object__ma(struct object *obj) -{ - /* - * Whether or not we try to dynamically fetch missing objects - * from the server, we currently DO NOT have the object. We - * can either print, allow (ignore), or conditionally allow - * (ignore) them. - */ - switch (arg_missing_action) { - case MA_ERROR: - die("missing %s object '%s'", - type_name(obj->type), oid_to_hex(&obj->oid)); - return; - - case MA_ALLOW_ANY: - return; - - case MA_PRINT: - oidset_insert(&missing_objects, &obj->oid); - return; - - case MA_ALLOW_PROMISOR: - if (is_promisor_object(&obj->oid)) - return; - die("unexpected missing %s object '%s'", - type_name(obj->type), oid_to_hex(&obj->oid)); - return; - - default: - BUG("unhandled missing_action"); - return; - } -} - -static int finish_object(struct object *obj, const char *name UNUSED, - void *cb_data) +static int finish_object(struct object *obj, const char *name, void *cb_data) { struct rev_list_info *info = cb_data; if (oid_object_info_extended(the_repository, &obj->oid, NULL, 0) < 0) { - finish_object__ma(obj); + finish_object__ma(obj, name); return 1; } if (info->revs->verify_objects && !obj->parsed && obj->type != OBJ_COMMIT) @@ -407,6 +465,12 @@ static inline int parse_missing_action_value(const char *value) return 1; } + if (!strcmp(value, "print-info")) { + arg_missing_action = MA_PRINT_INFO; + fetch_if_missing = 0; + return 1; + } + if (!strcmp(value, "allow-promisor")) { arg_missing_action = MA_ALLOW_PROMISOR; fetch_if_missing = 0; @@ -480,6 +544,13 @@ static int try_bitmap_traversal(struct rev_info *revs, if (revs->max_count >= 0) return -1; + /* + * We can't know which commits were left/right in a single traversal, + * and we don't yet know how to traverse them separately. + */ + if (revs->left_right) + return -1; + bitmap_git = prepare_bitmap_walk(revs, filter_provided_objects); if (!bitmap_git) return -1; @@ -504,10 +575,15 @@ static int try_bitmap_disk_usage(struct rev_info *revs, size_from_bitmap = get_disk_usage_from_bitmap(bitmap_git, revs); print_disk_usage(size_from_bitmap); + + free_bitmap_index(bitmap_git); return 0; } -int cmd_rev_list(int argc, const char **argv, const char *prefix) +int cmd_rev_list(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct rev_info revs; struct rev_list_info info; @@ -523,8 +599,7 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix) const char *show_progress = NULL; int ret = 0; - if (argc == 2 && !strcmp(argv[1], "-h")) - usage(rev_list_usage); + show_usage_if_asked(argc, argv, rev_list_usage); git_config(git_default_config, NULL); repo_init_revisions(the_repository, &revs, prefix); @@ -542,6 +617,18 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix) * * Let "--missing" to conditionally set fetch_if_missing. */ + /* + * NEEDSWORK: These loops that attempt to find presence of + * options without understanding that the options they are + * skipping are broken (e.g., it would not know "--grep + * --exclude-promisor-objects" is not triggering + * "--exclude-promisor-objects" option). We really need + * setup_revisions() to have a mechanism to allow and disallow + * some sets of options for different commands (like rev-list, + * replay, etc). Such a mechanism should do an early parsing + * of options and be able to manage the `--missing=...` and + * `--exclude-promisor-objects` options below. + */ for (i = 1; i < argc; i++) { const char *arg = argv[i]; if (!strcmp(arg, "--exclude-promisor-objects")) { @@ -561,7 +648,7 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix) } if (arg_missing_action) - revs.do_not_die_on_missing_tree = 1; + revs.do_not_die_on_missing_objects = 1; argc = setup_revisions(argc, argv, &revs, &s_r_opt); @@ -704,7 +791,8 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix) revs.limited = 1; if (show_progress) - progress = start_delayed_progress(show_progress, 0); + progress = start_delayed_progress(the_repository, + show_progress, 0); if (use_bitmap_index) { if (!try_bitmap_count(&revs, filter_provided_objects)) @@ -750,8 +838,20 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix) if (arg_print_omitted) oidset_init(&omitted_objects, DEFAULT_OIDSET_SIZE); - if (arg_missing_action == MA_PRINT) - oidset_init(&missing_objects, DEFAULT_OIDSET_SIZE); + if (arg_missing_action == MA_PRINT || + arg_missing_action == MA_PRINT_INFO) { + struct oidset_iter iter; + struct object_id *oid; + + oidmap_init(&missing_objects, DEFAULT_OIDSET_SIZE); + oidset_iter_init(&revs.missing_commits, &iter); + + /* Add missing tips */ + while ((oid = oidset_iter_next(&iter))) + add_missing_object_entry(oid, NULL, 0); + + oidset_clear(&revs.missing_commits); + } traverse_commit_list_filtered( &revs, show_commit, show_object, &info, @@ -765,13 +865,20 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix) printf("~%s\n", oid_to_hex(oid)); oidset_clear(&omitted_objects); } - if (arg_missing_action == MA_PRINT) { - struct oidset_iter iter; - struct object_id *oid; - oidset_iter_init(&missing_objects, &iter); - while ((oid = oidset_iter_next(&iter))) - printf("?%s\n", oid_to_hex(oid)); - oidset_clear(&missing_objects); + if (arg_missing_action == MA_PRINT || + arg_missing_action == MA_PRINT_INFO) { + struct missing_objects_map_entry *entry; + struct oidmap_iter iter; + + oidmap_iter_init(&missing_objects, &iter); + + while ((entry = oidmap_iter_next(&iter))) { + print_missing_object(entry, arg_missing_action == + MA_PRINT_INFO); + free((void *)entry->path); + } + + oidmap_free(&missing_objects, true); } stop_progress(&progress); |
