about summary refs log tree commit diff
path: root/third_party/git/builtin/rev-list.c
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/git/builtin/rev-list.c')
-rw-r--r--third_party/git/builtin/rev-list.c126
1 files changed, 29 insertions, 97 deletions
diff --git a/third_party/git/builtin/rev-list.c b/third_party/git/builtin/rev-list.c
index f520111eda09..301ccb970bb3 100644
--- a/third_party/git/builtin/rev-list.c
+++ b/third_party/git/builtin/rev-list.c
@@ -18,6 +18,7 @@
 #include "reflog-walk.h"
 #include "oidset.h"
 #include "packfile.h"
+#include "object-store.h"
 
 static const char rev_list_usage[] =
 "git rev-list [OPTION] <commit-id>... [ -- paths... ]\n"
@@ -253,26 +254,11 @@ static int finish_object(struct object *obj, const char *name, void *cb_data)
 static void show_object(struct object *obj, const char *name, void *cb_data)
 {
 	struct rev_list_info *info = cb_data;
-	struct rev_info *revs = info->revs;
-
 	if (finish_object(obj, name, cb_data))
 		return;
 	display_progress(progress, ++progress_counter);
 	if (info->flags & REV_LIST_QUIET)
 		return;
-
-	if (revs->count) {
-		/*
-		 * The object count is always accumulated in the .count_right
-		 * field for traversal that is not a left-right traversal,
-		 * and cmd_rev_list() made sure that a .count request that
-		 * wants to count non-commit objects, which is handled by
-		 * the show_object() callback, does not ask for .left_right.
-		 */
-		revs->count_right++;
-		return;
-	}
-
 	if (arg_show_object_names)
 		show_object_with_name(stdout, obj, name);
 	else
@@ -379,79 +365,6 @@ static inline int parse_missing_action_value(const char *value)
 	return 0;
 }
 
-static int try_bitmap_count(struct rev_info *revs,
-			    struct list_objects_filter_options *filter)
-{
-	uint32_t commit_count = 0,
-		 tag_count = 0,
-		 tree_count = 0,
-		 blob_count = 0;
-	int max_count;
-	struct bitmap_index *bitmap_git;
-
-	/* This function only handles counting, not general traversal. */
-	if (!revs->count)
-		return -1;
-
-	/*
-	 * A bitmap result can't know left/right, etc, because we don't
-	 * actually traverse.
-	 */
-	if (revs->left_right || revs->cherry_mark)
-		return -1;
-
-	/*
-	 * If we're counting reachable objects, we can't handle a max count of
-	 * commits to traverse, since we don't know which objects go with which
-	 * commit.
-	 */
-	if (revs->max_count >= 0 &&
-	    (revs->tag_objects || revs->tree_objects || revs->blob_objects))
-		return -1;
-
-	/*
-	 * This must be saved before doing any walking, since the revision
-	 * machinery will count it down to zero while traversing.
-	 */
-	max_count = revs->max_count;
-
-	bitmap_git = prepare_bitmap_walk(revs, filter);
-	if (!bitmap_git)
-		return -1;
-
-	count_bitmap_commit_list(bitmap_git, &commit_count,
-				 revs->tree_objects ? &tree_count : NULL,
-				 revs->blob_objects ? &blob_count : NULL,
-				 revs->tag_objects ? &tag_count : NULL);
-	if (max_count >= 0 && max_count < commit_count)
-		commit_count = max_count;
-
-	printf("%d\n", commit_count + tree_count + blob_count + tag_count);
-	free_bitmap_index(bitmap_git);
-	return 0;
-}
-
-static int try_bitmap_traversal(struct rev_info *revs,
-				struct list_objects_filter_options *filter)
-{
-	struct bitmap_index *bitmap_git;
-
-	/*
-	 * We can't use a bitmap result with a traversal limit, since the set
-	 * of commits we'd get would be essentially random.
-	 */
-	if (revs->max_count >= 0)
-		return -1;
-
-	bitmap_git = prepare_bitmap_walk(revs, filter);
-	if (!bitmap_git)
-		return -1;
-
-	traverse_bitmap_commit_list(bitmap_git, revs, &show_object_fast);
-	free_bitmap_index(bitmap_git);
-	return 0;
-}
-
 int cmd_rev_list(int argc, const char **argv, const char *prefix)
 {
 	struct rev_info revs;
@@ -558,6 +471,10 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
 			parse_list_objects_filter(&filter_options, arg);
 			if (filter_options.choice && !revs.blob_objects)
 				die(_("object filtering requires --objects"));
+			if (filter_options.choice == LOFC_SPARSE_OID &&
+			    !filter_options.sparse_oid_value)
+				die(_("invalid sparse value '%s'"),
+				    filter_options.filter_spec);
 			continue;
 		}
 		if (!strcmp(arg, ("--no-" CL_ARG__FILTER))) {
@@ -609,10 +526,8 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
 	if (revs.show_notes)
 		die(_("rev-list does not support display of notes"));
 
-	if (revs.count &&
-	    (revs.tag_objects || revs.tree_objects || revs.blob_objects) &&
-	    (revs.left_right || revs.cherry_mark))
-		die(_("marked counting is incompatible with --objects"));
+	if (filter_options.choice && use_bitmap_index)
+		die(_("cannot combine --use-bitmap-index with object filtering"));
 
 	save_commit_buffer = (revs.verbose_header ||
 			      revs.grep_filter.pattern_list ||
@@ -623,11 +538,28 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
 	if (show_progress)
 		progress = start_delayed_progress(show_progress, 0);
 
-	if (use_bitmap_index) {
-		if (!try_bitmap_count(&revs, &filter_options))
-			return 0;
-		if (!try_bitmap_traversal(&revs, &filter_options))
-			return 0;
+	if (use_bitmap_index && !revs.prune) {
+		if (revs.count && !revs.left_right && !revs.cherry_mark) {
+			uint32_t commit_count;
+			int max_count = revs.max_count;
+			struct bitmap_index *bitmap_git;
+			if ((bitmap_git = prepare_bitmap_walk(&revs))) {
+				count_bitmap_commit_list(bitmap_git, &commit_count, NULL, NULL, NULL);
+				if (max_count >= 0 && max_count < commit_count)
+					commit_count = max_count;
+				printf("%d\n", commit_count);
+				free_bitmap_index(bitmap_git);
+				return 0;
+			}
+		} else if (revs.max_count < 0 &&
+			   revs.tag_objects && revs.tree_objects && revs.blob_objects) {
+			struct bitmap_index *bitmap_git;
+			if ((bitmap_git = prepare_bitmap_walk(&revs))) {
+				traverse_bitmap_commit_list(bitmap_git, &show_object_fast);
+				free_bitmap_index(bitmap_git);
+				return 0;
+			}
+		}
 	}
 
 	if (prepare_revision_walk(&revs))