pack-bitmap: add function to iterate over filtered bitmapped objects
Introduce a function that allows the caller to iterate over all bitmapped objects that match a given filter. This mechanism will be used in a subsequent commit to optimize object filters in git-cat-file(1). Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Patrick Steinhardt committed
Apr 2, 2025 at 13:13 UTC
5420901bde8043a298b8ae5e5b3c3cfc1b67039b
2 files changed
+65
-6
pack-bitmap.c
+53
-6
@@ -1662,6 +1662,7 @@ static void init_type_iterator(struct ewah_or_iterator *it,
1662
1663
static void show_objects_for_type(
1664
struct bitmap_index *bitmap_git,
1665
+ struct bitmap *objects,
1666
enum object_type object_type,
1667
show_reachable_fn show_reach,
1668
void *payload)
@@ -1672,8 +1673,6 @@ static void show_objects_for_type(
1673
struct ewah_or_iterator it;
1674
eword_t filter;
1675
1675
- struct bitmap *objects = bitmap_git->result;
1676
-
1676
init_type_iterator(&it, bitmap_git, object_type);
1677
1678
for (i = 0; i < objects->word_alloc &&
@@ -2025,6 +2024,50 @@ static void filter_packed_objects_from_bitmap(struct bitmap_index *bitmap_git,
2024
}
2025
}
2026
2027
+int for_each_bitmapped_object(struct bitmap_index *bitmap_git,
2028
+ struct list_objects_filter_options *filter,
2029
+ show_reachable_fn show_reach,
2030
+ void *payload)
2031
+{
2032
+ struct bitmap *filtered_bitmap = NULL;
2033
+ uint32_t objects_nr;
2034
+ size_t full_word_count;
2035
+ int ret;
2036
+
2037
+ if (!can_filter_bitmap(filter)) {
2038
+ ret = -1;
2039
+ goto out;
2040
+ }
2041
+
2042
+ objects_nr = bitmap_num_objects(bitmap_git);
2043
+ full_word_count = objects_nr / BITS_IN_EWORD;
2044
+
2045
+ /* We start from the all-1 bitmap and then filter down from there. */
2046
+ filtered_bitmap = bitmap_word_alloc(full_word_count + !!(objects_nr % BITS_IN_EWORD));
2047
+ memset(filtered_bitmap->words, 0xff, full_word_count * sizeof(*filtered_bitmap->words));
2048
+ for (size_t i = full_word_count * BITS_IN_EWORD; i < objects_nr; i++)
2049
+ bitmap_set(filtered_bitmap, i);
2050
+
2051
+ if (filter_bitmap(bitmap_git, NULL, filtered_bitmap, filter) < 0) {
2052
+ ret = -1;
2053
+ goto out;
2054
+ }
2055
+
2056
+ show_objects_for_type(bitmap_git, filtered_bitmap,
2057
+ OBJ_COMMIT, show_reach, payload);
2058
+ show_objects_for_type(bitmap_git, filtered_bitmap,
2059
+ OBJ_TREE, show_reach, payload);
2060
+ show_objects_for_type(bitmap_git, filtered_bitmap,
2061
+ OBJ_BLOB, show_reach, payload);
2062
+ show_objects_for_type(bitmap_git, filtered_bitmap,
2063
+ OBJ_TAG, show_reach, payload);
2064
+
2065
+ ret = 0;
2066
+out:
2067
+ bitmap_free(filtered_bitmap);
2068
+ return ret;
2069
+}
2070
+
2071
struct bitmap_index *prepare_bitmap_walk(struct rev_info *revs,
2072
int filter_provided_objects)
2073
{
@@ -2519,13 +2562,17 @@ void traverse_bitmap_commit_list(struct bitmap_index *bitmap_git,
2562
{
2563
assert(bitmap_git->result);
2564
2522
- show_objects_for_type(bitmap_git, OBJ_COMMIT, show_reachable, NULL);
2565
+ show_objects_for_type(bitmap_git, bitmap_git->result,
2566
+ OBJ_COMMIT, show_reachable, NULL);
2567
if (revs->tree_objects)
2524
- show_objects_for_type(bitmap_git, OBJ_TREE, show_reachable, NULL);
2568
+ show_objects_for_type(bitmap_git, bitmap_git->result,
2569
+ OBJ_TREE, show_reachable, NULL);
2570
if (revs->blob_objects)
2526
- show_objects_for_type(bitmap_git, OBJ_BLOB, show_reachable, NULL);
2571
+ show_objects_for_type(bitmap_git, bitmap_git->result,
2572
+ OBJ_BLOB, show_reachable, NULL);
2573
if (revs->tag_objects)
2528
- show_objects_for_type(bitmap_git, OBJ_TAG, show_reachable, NULL);
2574
+ show_objects_for_type(bitmap_git, bitmap_git->result,
2575
+ OBJ_TAG, show_reachable, NULL);
2576
2577
show_extended_objects(bitmap_git, revs, show_reachable);
2578
}
pack-bitmap.h
+12
@@ -79,6 +79,18 @@ int test_bitmap_pseudo_merges(struct repository *r);
79
int test_bitmap_pseudo_merge_commits(struct repository *r, uint32_t n);
80
int test_bitmap_pseudo_merge_objects(struct repository *r, uint32_t n);
81
82
+struct list_objects_filter_options;
83
+
84
+/*
85
+ * Filter bitmapped objects and iterate through all resulting objects,
86
+ * executing `show_reach` for each of them. Returns `-1` in case the filter is
87
+ * not supported, `0` otherwise.
88
+ */
89
+int for_each_bitmapped_object(struct bitmap_index *bitmap_git,
90
+ struct list_objects_filter_options *filter,
91
+ show_reachable_fn show_reach,
92
+ void *payload);
93
+
94
#define GIT_TEST_PACK_USE_BITMAP_BOUNDARY_TRAVERSAL \
95
"GIT_TEST_PACK_USE_BITMAP_BOUNDARY_TRAVERSAL"
96