summaryrefslogtreecommitdiff
path: root/pack-bitmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'pack-bitmap.c')
-rw-r--r--pack-bitmap.c382
1 files changed, 225 insertions, 157 deletions
diff --git a/pack-bitmap.c b/pack-bitmap.c
index 9270983e5f..5848cc93aa 100644
--- a/pack-bitmap.c
+++ b/pack-bitmap.c
@@ -10,6 +10,8 @@
#include "pack-revindex.h"
#include "pack-objects.h"
#include "packfile.h"
+#include "repository.h"
+#include "object-store.h"
/*
* An entry on the bitmap index, representing the bitmap for a given
@@ -23,14 +25,14 @@ struct stored_bitmap {
};
/*
- * The currently active bitmap index. By design, repositories only have
+ * The active bitmap index for a repository. By design, repositories only have
* a single bitmap index available (the index for the biggest packfile in
* the repository), since bitmap indexes need full closure.
*
* If there is more than one bitmap index available (e.g. because of alternates),
* the active bitmap index is the largest one.
*/
-static struct bitmap_index {
+struct bitmap_index {
/* Packfile to which this bitmap index belongs to */
struct packed_git *pack;
@@ -64,7 +66,7 @@ static struct bitmap_index {
/* Number of bitmapped commits */
uint32_t entry_count;
- /* Name-hash cache (or NULL if not present). */
+ /* If not NULL, this is a name-hash cache pointing into map. */
uint32_t *hashes;
/*
@@ -84,12 +86,12 @@ static struct bitmap_index {
/* Bitmap result of the last performed walk */
struct bitmap *result;
+ /* "have" bitmap from the last performed walk */
+ struct bitmap *haves;
+
/* Version of the bitmap index */
unsigned int version;
-
- unsigned loaded : 1;
-
-} bitmap_git;
+};
static struct ewah_bitmap *lookup_stored_bitmap(struct stored_bitmap *st)
{
@@ -118,7 +120,7 @@ static struct ewah_bitmap *read_bitmap_1(struct bitmap_index *index)
{
struct ewah_bitmap *b = ewah_pool_new();
- int bitmap_size = ewah_read_mmap(b,
+ ssize_t bitmap_size = ewah_read_mmap(b,
index->map + index->map_pos,
index->map_size - index->map_pos);
@@ -253,11 +255,11 @@ static char *pack_bitmap_filename(struct packed_git *p)
size_t len;
if (!strip_suffix(p->pack_name, ".pack", &len))
- die("BUG: pack_name does not end in .pack");
+ BUG("pack_name does not end in .pack");
return xstrfmt("%.*s.bitmap", (int)len, p->pack_name);
}
-static int open_pack_bitmap_1(struct packed_git *packfile)
+static int open_pack_bitmap_1(struct bitmap_index *bitmap_git, struct packed_git *packfile)
{
int fd;
struct stat st;
@@ -278,118 +280,121 @@ static int open_pack_bitmap_1(struct packed_git *packfile)
return -1;
}
- if (bitmap_git.pack) {
+ if (bitmap_git->pack) {
warning("ignoring extra bitmap file: %s", packfile->pack_name);
close(fd);
return -1;
}
- bitmap_git.pack = packfile;
- bitmap_git.map_size = xsize_t(st.st_size);
- bitmap_git.map = xmmap(NULL, bitmap_git.map_size, PROT_READ, MAP_PRIVATE, fd, 0);
- bitmap_git.map_pos = 0;
+ bitmap_git->pack = packfile;
+ bitmap_git->map_size = xsize_t(st.st_size);
+ bitmap_git->map = xmmap(NULL, bitmap_git->map_size, PROT_READ, MAP_PRIVATE, fd, 0);
+ bitmap_git->map_pos = 0;
close(fd);
- if (load_bitmap_header(&bitmap_git) < 0) {
- munmap(bitmap_git.map, bitmap_git.map_size);
- bitmap_git.map = NULL;
- bitmap_git.map_size = 0;
+ if (load_bitmap_header(bitmap_git) < 0) {
+ munmap(bitmap_git->map, bitmap_git->map_size);
+ bitmap_git->map = NULL;
+ bitmap_git->map_size = 0;
return -1;
}
return 0;
}
-static int load_pack_bitmap(void)
+static int load_pack_bitmap(struct bitmap_index *bitmap_git)
{
- assert(bitmap_git.map && !bitmap_git.loaded);
+ assert(bitmap_git->map);
- bitmap_git.bitmaps = kh_init_sha1();
- bitmap_git.ext_index.positions = kh_init_sha1_pos();
- load_pack_revindex(bitmap_git.pack);
+ bitmap_git->bitmaps = kh_init_sha1();
+ bitmap_git->ext_index.positions = kh_init_sha1_pos();
+ load_pack_revindex(bitmap_git->pack);
- if (!(bitmap_git.commits = read_bitmap_1(&bitmap_git)) ||
- !(bitmap_git.trees = read_bitmap_1(&bitmap_git)) ||
- !(bitmap_git.blobs = read_bitmap_1(&bitmap_git)) ||
- !(bitmap_git.tags = read_bitmap_1(&bitmap_git)))
+ if (!(bitmap_git->commits = read_bitmap_1(bitmap_git)) ||
+ !(bitmap_git->trees = read_bitmap_1(bitmap_git)) ||
+ !(bitmap_git->blobs = read_bitmap_1(bitmap_git)) ||
+ !(bitmap_git->tags = read_bitmap_1(bitmap_git)))
goto failed;
- if (load_bitmap_entries_v1(&bitmap_git) < 0)
+ if (load_bitmap_entries_v1(bitmap_git) < 0)
goto failed;
- bitmap_git.loaded = 1;
return 0;
failed:
- munmap(bitmap_git.map, bitmap_git.map_size);
- bitmap_git.map = NULL;
- bitmap_git.map_size = 0;
+ munmap(bitmap_git->map, bitmap_git->map_size);
+ bitmap_git->map = NULL;
+ bitmap_git->map_size = 0;
return -1;
}
-static int open_pack_bitmap(void)
+static int open_pack_bitmap(struct bitmap_index *bitmap_git)
{
struct packed_git *p;
int ret = -1;
- assert(!bitmap_git.map && !bitmap_git.loaded);
+ assert(!bitmap_git->map);
- prepare_packed_git();
- for (p = packed_git; p; p = p->next) {
- if (open_pack_bitmap_1(p) == 0)
+ for (p = get_all_packs(the_repository); p; p = p->next) {
+ if (open_pack_bitmap_1(bitmap_git, p) == 0)
ret = 0;
}
return ret;
}
-int prepare_bitmap_git(void)
+struct bitmap_index *prepare_bitmap_git(void)
{
- if (bitmap_git.loaded)
- return 0;
+ struct bitmap_index *bitmap_git = xcalloc(1, sizeof(*bitmap_git));
- if (!open_pack_bitmap())
- return load_pack_bitmap();
+ if (!open_pack_bitmap(bitmap_git) && !load_pack_bitmap(bitmap_git))
+ return bitmap_git;
- return -1;
+ free_bitmap_index(bitmap_git);
+ return NULL;
}
struct include_data {
+ struct bitmap_index *bitmap_git;
struct bitmap *base;
struct bitmap *seen;
};
-static inline int bitmap_position_extended(const unsigned char *sha1)
+static inline int bitmap_position_extended(struct bitmap_index *bitmap_git,
+ const unsigned char *sha1)
{
- khash_sha1_pos *positions = bitmap_git.ext_index.positions;
+ khash_sha1_pos *positions = bitmap_git->ext_index.positions;
khiter_t pos = kh_get_sha1_pos(positions, sha1);
if (pos < kh_end(positions)) {
int bitmap_pos = kh_value(positions, pos);
- return bitmap_pos + bitmap_git.pack->num_objects;
+ return bitmap_pos + bitmap_git->pack->num_objects;
}
return -1;
}
-static inline int bitmap_position_packfile(const unsigned char *sha1)
+static inline int bitmap_position_packfile(struct bitmap_index *bitmap_git,
+ const unsigned char *sha1)
{
- off_t offset = find_pack_entry_one(sha1, bitmap_git.pack);
+ off_t offset = find_pack_entry_one(sha1, bitmap_git->pack);
if (!offset)
return -1;
- return find_revindex_position(bitmap_git.pack, offset);
+ return find_revindex_position(bitmap_git->pack, offset);
}
-static int bitmap_position(const unsigned char *sha1)
+static int bitmap_position(struct bitmap_index *bitmap_git,
+ const unsigned char *sha1)
{
- int pos = bitmap_position_packfile(sha1);
- return (pos >= 0) ? pos : bitmap_position_extended(sha1);
+ int pos = bitmap_position_packfile(bitmap_git, sha1);
+ return (pos >= 0) ? pos : bitmap_position_extended(bitmap_git, sha1);
}
-static int ext_index_add_object(struct object *object, const char *name)
+static int ext_index_add_object(struct bitmap_index *bitmap_git,
+ struct object *object, const char *name)
{
- struct eindex *eindex = &bitmap_git.ext_index;
+ struct eindex *eindex = &bitmap_git->ext_index;
khiter_t hash_pos;
int hash_ret;
@@ -412,27 +417,34 @@ static int ext_index_add_object(struct object *object, const char *name)
bitmap_pos = kh_value(eindex->positions, hash_pos);
}
- return bitmap_pos + bitmap_git.pack->num_objects;
+ return bitmap_pos + bitmap_git->pack->num_objects;
}
-static void show_object(struct object *object, const char *name, void *data)
+struct bitmap_show_data {
+ struct bitmap_index *bitmap_git;
+ struct bitmap *base;
+};
+
+static void show_object(struct object *object, const char *name, void *data_)
{
- struct bitmap *base = data;
+ struct bitmap_show_data *data = data_;
int bitmap_pos;
- bitmap_pos = bitmap_position(object->oid.hash);
+ bitmap_pos = bitmap_position(data->bitmap_git, object->oid.hash);
if (bitmap_pos < 0)
- bitmap_pos = ext_index_add_object(object, name);
+ bitmap_pos = ext_index_add_object(data->bitmap_git, object,
+ name);
- bitmap_set(base, bitmap_pos);
+ bitmap_set(data->base, bitmap_pos);
}
static void show_commit(struct commit *commit, void *data)
{
}
-static int add_to_include_set(struct include_data *data,
+static int add_to_include_set(struct bitmap_index *bitmap_git,
+ struct include_data *data,
const unsigned char *sha1,
int bitmap_pos)
{
@@ -444,9 +456,9 @@ static int add_to_include_set(struct include_data *data,
if (bitmap_get(data->base, bitmap_pos))
return 0;
- hash_pos = kh_get_sha1(bitmap_git.bitmaps, sha1);
- if (hash_pos < kh_end(bitmap_git.bitmaps)) {
- struct stored_bitmap *st = kh_value(bitmap_git.bitmaps, hash_pos);
+ hash_pos = kh_get_sha1(bitmap_git->bitmaps, sha1);
+ if (hash_pos < kh_end(bitmap_git->bitmaps)) {
+ struct stored_bitmap *st = kh_value(bitmap_git->bitmaps, hash_pos);
bitmap_or_ewah(data->base, lookup_stored_bitmap(st));
return 0;
}
@@ -460,11 +472,14 @@ static int should_include(struct commit *commit, void *_data)
struct include_data *data = _data;
int bitmap_pos;
- bitmap_pos = bitmap_position(commit->object.oid.hash);
+ bitmap_pos = bitmap_position(data->bitmap_git, commit->object.oid.hash);
if (bitmap_pos < 0)
- bitmap_pos = ext_index_add_object((struct object *)commit, NULL);
+ bitmap_pos = ext_index_add_object(data->bitmap_git,
+ (struct object *)commit,
+ NULL);
- if (!add_to_include_set(data, commit->object.oid.hash, bitmap_pos)) {
+ if (!add_to_include_set(data->bitmap_git, data, commit->object.oid.hash,
+ bitmap_pos)) {
struct commit_list *parent = commit->parents;
while (parent) {
@@ -478,7 +493,8 @@ static int should_include(struct commit *commit, void *_data)
return 1;
}
-static struct bitmap *find_objects(struct rev_info *revs,
+static struct bitmap *find_objects(struct bitmap_index *bitmap_git,
+ struct rev_info *revs,
struct object_list *roots,
struct bitmap *seen)
{
@@ -500,10 +516,10 @@ static struct bitmap *find_objects(struct rev_info *revs,
roots = roots->next;
if (object->type == OBJ_COMMIT) {
- khiter_t pos = kh_get_sha1(bitmap_git.bitmaps, object->oid.hash);
+ khiter_t pos = kh_get_sha1(bitmap_git->bitmaps, object->oid.hash);
- if (pos < kh_end(bitmap_git.bitmaps)) {
- struct stored_bitmap *st = kh_value(bitmap_git.bitmaps, pos);
+ if (pos < kh_end(bitmap_git->bitmaps)) {
+ struct stored_bitmap *st = kh_value(bitmap_git->bitmaps, pos);
struct ewah_bitmap *or_with = lookup_stored_bitmap(st);
if (base == NULL)
@@ -542,7 +558,7 @@ static struct bitmap *find_objects(struct rev_info *revs,
int pos;
roots = roots->next;
- pos = bitmap_position(object->oid.hash);
+ pos = bitmap_position(bitmap_git, object->oid.hash);
if (pos < 0 || base == NULL || !bitmap_get(base, pos)) {
object->flags &= ~UNINTERESTING;
@@ -555,10 +571,12 @@ static struct bitmap *find_objects(struct rev_info *revs,
if (needs_walk) {
struct include_data incdata;
+ struct bitmap_show_data show_data;
if (base == NULL)
base = bitmap_new();
+ incdata.bitmap_git = bitmap_git;
incdata.base = base;
incdata.seen = seen;
@@ -568,22 +586,27 @@ static struct bitmap *find_objects(struct rev_info *revs,
if (prepare_revision_walk(revs))
die("revision walk setup failed");
- traverse_commit_list(revs, show_commit, show_object, base);
+ show_data.bitmap_git = bitmap_git;
+ show_data.base = base;
+
+ traverse_commit_list(revs, show_commit, show_object,
+ &show_data);
}
return base;
}
-static void show_extended_objects(struct bitmap *objects,
+static void show_extended_objects(struct bitmap_index *bitmap_git,
show_reachable_fn show_reach)
{
- struct eindex *eindex = &bitmap_git.ext_index;
+ struct bitmap *objects = bitmap_git->result;
+ struct eindex *eindex = &bitmap_git->ext_index;
uint32_t i;
for (i = 0; i < eindex->count; ++i) {
struct object *obj;
- if (!bitmap_get(objects, bitmap_git.pack->num_objects + i))
+ if (!bitmap_get(objects, bitmap_git->pack->num_objects + i))
continue;
obj = eindex->objects[i];
@@ -592,7 +615,7 @@ static void show_extended_objects(struct bitmap *objects,
}
static void show_objects_for_type(
- struct bitmap *objects,
+ struct bitmap_index *bitmap_git,
struct ewah_bitmap *type_filter,
enum object_type object_type,
show_reachable_fn show_reach)
@@ -603,7 +626,9 @@ static void show_objects_for_type(
struct ewah_iterator it;
eword_t filter;
- if (bitmap_git.reuse_objects == bitmap_git.pack->num_objects)
+ struct bitmap *objects = bitmap_git->result;
+
+ if (bitmap_git->reuse_objects == bitmap_git->pack->num_objects)
return;
ewah_iterator_init(&it, type_filter);
@@ -621,16 +646,16 @@ static void show_objects_for_type(
offset += ewah_bit_ctz64(word >> offset);
- if (pos + offset < bitmap_git.reuse_objects)
+ if (pos + offset < bitmap_git->reuse_objects)
continue;
- entry = &bitmap_git.pack->revindex[pos + offset];
- nth_packed_object_oid(&oid, bitmap_git.pack, entry->nr);
+ entry = &bitmap_git->pack->revindex[pos + offset];
+ nth_packed_object_oid(&oid, bitmap_git->pack, entry->nr);
- if (bitmap_git.hashes)
- hash = get_be32(bitmap_git.hashes + entry->nr);
+ if (bitmap_git->hashes)
+ hash = get_be32(bitmap_git->hashes + entry->nr);
- show_reach(&oid, object_type, 0, hash, bitmap_git.pack, entry->offset);
+ show_reach(&oid, object_type, 0, hash, bitmap_git->pack, entry->offset);
}
pos += BITS_IN_EWORD;
@@ -638,20 +663,21 @@ static void show_objects_for_type(
}
}
-static int in_bitmapped_pack(struct object_list *roots)
+static int in_bitmapped_pack(struct bitmap_index *bitmap_git,
+ struct object_list *roots)
{
while (roots) {
struct object *object = roots->item;
roots = roots->next;
- if (find_pack_entry_one(object->oid.hash, bitmap_git.pack) > 0)
+ if (find_pack_entry_one(object->oid.hash, bitmap_git->pack) > 0)
return 1;
}
return 0;
}
-int prepare_bitmap_walk(struct rev_info *revs)
+struct bitmap_index *prepare_bitmap_walk(struct rev_info *revs)
{
unsigned int i;
@@ -661,12 +687,11 @@ int prepare_bitmap_walk(struct rev_info *revs)
struct bitmap *wants_bitmap = NULL;
struct bitmap *haves_bitmap = NULL;
- if (!bitmap_git.loaded) {
- /* try to open a bitmapped pack, but don't parse it yet
- * because we may not need to use it */
- if (open_pack_bitmap() < 0)
- return -1;
- }
+ struct bitmap_index *bitmap_git = xcalloc(1, sizeof(*bitmap_git));
+ /* try to open a bitmapped pack, but don't parse it yet
+ * because we may not need to use it */
+ if (open_pack_bitmap(bitmap_git) < 0)
+ goto cleanup;
for (i = 0; i < revs->pending.nr; ++i) {
struct object *object = revs->pending.objects[i].item;
@@ -698,48 +723,53 @@ int prepare_bitmap_walk(struct rev_info *revs)
* in the packfile that has a bitmap, we don't have anything to
* optimize here
*/
- if (haves && !in_bitmapped_pack(haves))
- return -1;
+ if (haves && !in_bitmapped_pack(bitmap_git, haves))
+ goto cleanup;
/* if we don't want anything, we're done here */
if (!wants)
- return -1;
+ goto cleanup;
/*
* now we're going to use bitmaps, so load the actual bitmap entries
* from disk. this is the point of no return; after this the rev_list
* becomes invalidated and we must perform the revwalk through bitmaps
*/
- if (!bitmap_git.loaded && load_pack_bitmap() < 0)
- return -1;
+ if (load_pack_bitmap(bitmap_git) < 0)
+ goto cleanup;
object_array_clear(&revs->pending);
if (haves) {
revs->ignore_missing_links = 1;
- haves_bitmap = find_objects(revs, haves, NULL);
+ haves_bitmap = find_objects(bitmap_git, revs, haves, NULL);
reset_revision_walk();
revs->ignore_missing_links = 0;
if (haves_bitmap == NULL)
- die("BUG: failed to perform bitmap walk");
+ BUG("failed to perform bitmap walk");
}
- wants_bitmap = find_objects(revs, wants, haves_bitmap);
+ wants_bitmap = find_objects(bitmap_git, revs, wants, haves_bitmap);
if (!wants_bitmap)
- die("BUG: failed to perform bitmap walk");
+ BUG("failed to perform bitmap walk");
if (haves_bitmap)
bitmap_and_not(wants_bitmap, haves_bitmap);
- bitmap_git.result = wants_bitmap;
+ bitmap_git->result = wants_bitmap;
+ bitmap_git->haves = haves_bitmap;
- bitmap_free(haves_bitmap);
- return 0;
+ return bitmap_git;
+
+cleanup:
+ free_bitmap_index(bitmap_git);
+ return NULL;
}
-int reuse_partial_packfile_from_bitmap(struct packed_git **packfile,
+int reuse_partial_packfile_from_bitmap(struct bitmap_index *bitmap_git,
+ struct packed_git **packfile,
uint32_t *entries,
off_t *up_to)
{
@@ -749,7 +779,7 @@ int reuse_partial_packfile_from_bitmap(struct packed_git **packfile,
*/
static const double REUSE_PERCENT = 0.9;
- struct bitmap *result = bitmap_git.result;
+ struct bitmap *result = bitmap_git->result;
uint32_t reuse_threshold;
uint32_t i, reuse_objects = 0;
@@ -769,8 +799,8 @@ int reuse_partial_packfile_from_bitmap(struct packed_git **packfile,
const unsigned char *sha1;
struct revindex_entry *entry;
- entry = &bitmap_git.reverse_index->revindex[reuse_objects];
- sha1 = nth_packed_object_sha1(bitmap_git.pack, entry->nr);
+ entry = &bitmap_git->reverse_index->revindex[reuse_objects];
+ sha1 = nth_packed_object_sha1(bitmap_git->pack, entry->nr);
fprintf(stderr, "Failed to reuse at %d (%016llx)\n",
reuse_objects, result->words[i]);
@@ -781,48 +811,47 @@ int reuse_partial_packfile_from_bitmap(struct packed_git **packfile,
if (!reuse_objects)
return -1;
- if (reuse_objects >= bitmap_git.pack->num_objects) {
- bitmap_git.reuse_objects = *entries = bitmap_git.pack->num_objects;
+ if (reuse_objects >= bitmap_git->pack->num_objects) {
+ bitmap_git->reuse_objects = *entries = bitmap_git->pack->num_objects;
*up_to = -1; /* reuse the full pack */
- *packfile = bitmap_git.pack;
+ *packfile = bitmap_git->pack;
return 0;
}
- reuse_threshold = bitmap_popcount(bitmap_git.result) * REUSE_PERCENT;
+ reuse_threshold = bitmap_popcount(bitmap_git->result) * REUSE_PERCENT;
if (reuse_objects < reuse_threshold)
return -1;
- bitmap_git.reuse_objects = *entries = reuse_objects;
- *up_to = bitmap_git.pack->revindex[reuse_objects].offset;
- *packfile = bitmap_git.pack;
+ bitmap_git->reuse_objects = *entries = reuse_objects;
+ *up_to = bitmap_git->pack->revindex[reuse_objects].offset;
+ *packfile = bitmap_git->pack;
return 0;
}
-void traverse_bitmap_commit_list(show_reachable_fn show_reachable)
+void traverse_bitmap_commit_list(struct bitmap_index *bitmap_git,
+ show_reachable_fn show_reachable)
{
- assert(bitmap_git.result);
+ assert(bitmap_git->result);
- show_objects_for_type(bitmap_git.result, bitmap_git.commits,
+ show_objects_for_type(bitmap_git, bitmap_git->commits,
OBJ_COMMIT, show_reachable);
- show_objects_for_type(bitmap_git.result, bitmap_git.trees,
+ show_objects_for_type(bitmap_git, bitmap_git->trees,
OBJ_TREE, show_reachable);
- show_objects_for_type(bitmap_git.result, bitmap_git.blobs,
+ show_objects_for_type(bitmap_git, bitmap_git->blobs,
OBJ_BLOB, show_reachable);
- show_objects_for_type(bitmap_git.result, bitmap_git.tags,
+ show_objects_for_type(bitmap_git, bitmap_git->tags,
OBJ_TAG, show_reachable);
- show_extended_objects(bitmap_git.result, show_reachable);
-
- bitmap_free(bitmap_git.result);
- bitmap_git.result = NULL;
+ show_extended_objects(bitmap_git, show_reachable);
}
-static uint32_t count_object_type(struct bitmap *objects,
+static uint32_t count_object_type(struct bitmap_index *bitmap_git,
enum object_type type)
{
- struct eindex *eindex = &bitmap_git.ext_index;
+ struct bitmap *objects = bitmap_git->result;
+ struct eindex *eindex = &bitmap_git->ext_index;
uint32_t i = 0, count = 0;
struct ewah_iterator it;
@@ -830,19 +859,19 @@ static uint32_t count_object_type(struct bitmap *objects,
switch (type) {
case OBJ_COMMIT:
- ewah_iterator_init(&it, bitmap_git.commits);
+ ewah_iterator_init(&it, bitmap_git->commits);
break;
case OBJ_TREE:
- ewah_iterator_init(&it, bitmap_git.trees);
+ ewah_iterator_init(&it, bitmap_git->trees);
break;
case OBJ_BLOB:
- ewah_iterator_init(&it, bitmap_git.blobs);
+ ewah_iterator_init(&it, bitmap_git->blobs);
break;
case OBJ_TAG:
- ewah_iterator_init(&it, bitmap_git.tags);
+ ewah_iterator_init(&it, bitmap_git->tags);
break;
default:
@@ -856,32 +885,34 @@ static uint32_t count_object_type(struct bitmap *objects,
for (i = 0; i < eindex->count; ++i) {
if (eindex->objects[i]->type == type &&
- bitmap_get(objects, bitmap_git.pack->num_objects + i))
+ bitmap_get(objects, bitmap_git->pack->num_objects + i))
count++;
}
return count;
}
-void count_bitmap_commit_list(uint32_t *commits, uint32_t *trees,
+void count_bitmap_commit_list(struct bitmap_index *bitmap_git,
+ uint32_t *commits, uint32_t *trees,
uint32_t *blobs, uint32_t *tags)
{
- assert(bitmap_git.result);
+ assert(bitmap_git->result);
if (commits)
- *commits = count_object_type(bitmap_git.result, OBJ_COMMIT);
+ *commits = count_object_type(bitmap_git, OBJ_COMMIT);
if (trees)
- *trees = count_object_type(bitmap_git.result, OBJ_TREE);
+ *trees = count_object_type(bitmap_git, OBJ_TREE);
if (blobs)
- *blobs = count_object_type(bitmap_git.result, OBJ_BLOB);
+ *blobs = count_object_type(bitmap_git, OBJ_BLOB);
if (tags)
- *tags = count_object_type(bitmap_git.result, OBJ_TAG);
+ *tags = count_object_type(bitmap_git, OBJ_TAG);
}
struct bitmap_test_data {
+ struct bitmap_index *bitmap_git;
struct bitmap *base;
struct progress *prg;
size_t seen;
@@ -893,7 +924,7 @@ static void test_show_object(struct object *object, const char *name,
struct bitmap_test_data *tdata = data;
int bitmap_pos;
- bitmap_pos = bitmap_position(object->oid.hash);
+ bitmap_pos = bitmap_position(tdata->bitmap_git, object->oid.hash);
if (bitmap_pos < 0)
die("Object not in bitmap: %s\n", oid_to_hex(&object->oid));
@@ -906,7 +937,8 @@ static void test_show_commit(struct commit *commit, void *data)
struct bitmap_test_data *tdata = data;
int bitmap_pos;
- bitmap_pos = bitmap_position(commit->object.oid.hash);
+ bitmap_pos = bitmap_position(tdata->bitmap_git,
+ commit->object.oid.hash);
if (bitmap_pos < 0)
die("Object not in bitmap: %s\n", oid_to_hex(&commit->object.oid));
@@ -921,21 +953,22 @@ void test_bitmap_walk(struct rev_info *revs)
khiter_t pos;
size_t result_popcnt;
struct bitmap_test_data tdata;
+ struct bitmap_index *bitmap_git;
- if (prepare_bitmap_git())
+ if (!(bitmap_git = prepare_bitmap_git()))
die("failed to load bitmap indexes");
if (revs->pending.nr != 1)
die("you must specify exactly one commit to test");
fprintf(stderr, "Bitmap v%d test (%d entries loaded)\n",
- bitmap_git.version, bitmap_git.entry_count);
+ bitmap_git->version, bitmap_git->entry_count);
root = revs->pending.objects[0].item;
- pos = kh_get_sha1(bitmap_git.bitmaps, root->oid.hash);
+ pos = kh_get_sha1(bitmap_git->bitmaps, root->oid.hash);
- if (pos < kh_end(bitmap_git.bitmaps)) {
- struct stored_bitmap *st = kh_value(bitmap_git.bitmaps, pos);
+ if (pos < kh_end(bitmap_git->bitmaps)) {
+ struct stored_bitmap *st = kh_value(bitmap_git->bitmaps, pos);
struct ewah_bitmap *bm = lookup_stored_bitmap(st);
fprintf(stderr, "Found bitmap for %s. %d bits / %08x checksum\n",
@@ -956,6 +989,7 @@ void test_bitmap_walk(struct rev_info *revs)
if (prepare_revision_walk(revs))
die("revision walk setup failed");
+ tdata.bitmap_git = bitmap_git;
tdata.base = bitmap_new();
tdata.prg = start_progress("Verifying bitmap entries", result_popcnt);
tdata.seen = 0;
@@ -969,7 +1003,7 @@ void test_bitmap_walk(struct rev_info *revs)
else
fprintf(stderr, "Mismatch!\n");
- bitmap_free(result);
+ free_bitmap_index(bitmap_git);
}
static int rebuild_bitmap(uint32_t *reposition,
@@ -1003,7 +1037,8 @@ static int rebuild_bitmap(uint32_t *reposition,
return 0;
}
-int rebuild_existing_bitmaps(struct packing_data *mapping,
+int rebuild_existing_bitmaps(struct bitmap_index *bitmap_git,
+ struct packing_data *mapping,
khash_sha1 *reused_bitmaps,
int show_progress)
{
@@ -1016,10 +1051,7 @@ int rebuild_existing_bitmaps(struct packing_data *mapping,
khiter_t hash_pos;
int hash_ret;
- if (prepare_bitmap_git() < 0)
- return -1;
-
- num_objects = bitmap_git.pack->num_objects;
+ num_objects = bitmap_git->pack->num_objects;
reposition = xcalloc(num_objects, sizeof(uint32_t));
for (i = 0; i < num_objects; ++i) {
@@ -1027,12 +1059,12 @@ int rebuild_existing_bitmaps(struct packing_data *mapping,
struct revindex_entry *entry;
struct object_entry *oe;
- entry = &bitmap_git.pack->revindex[i];
- sha1 = nth_packed_object_sha1(bitmap_git.pack, entry->nr);
+ entry = &bitmap_git->pack->revindex[i];
+ sha1 = nth_packed_object_sha1(bitmap_git->pack, entry->nr);
oe = packlist_find(mapping, sha1, NULL);
if (oe)
- reposition[i] = oe->in_pack_pos + 1;
+ reposition[i] = oe_in_pack_pos(mapping, oe) + 1;
}
rebuild = bitmap_new();
@@ -1041,7 +1073,7 @@ int rebuild_existing_bitmaps(struct packing_data *mapping,
if (show_progress)
progress = start_progress("Reusing bitmaps", 0);
- kh_foreach_value(bitmap_git.bitmaps, stored, {
+ kh_foreach_value(bitmap_git->bitmaps, stored, {
if (stored->flags & BITMAP_FLAG_REUSE) {
if (!rebuild_bitmap(reposition,
lookup_stored_bitmap(stored),
@@ -1063,3 +1095,39 @@ int rebuild_existing_bitmaps(struct packing_data *mapping,
bitmap_free(rebuild);
return 0;
}
+
+void free_bitmap_index(struct bitmap_index *b)
+{
+ if (!b)
+ return;
+
+ if (b->map)
+ munmap(b->map, b->map_size);
+ ewah_pool_free(b->commits);
+ ewah_pool_free(b->trees);
+ ewah_pool_free(b->blobs);
+ ewah_pool_free(b->tags);
+ kh_destroy_sha1(b->bitmaps);
+ free(b->ext_index.objects);
+ free(b->ext_index.hashes);
+ bitmap_free(b->result);
+ bitmap_free(b->haves);
+ free(b);
+}
+
+int bitmap_has_sha1_in_uninteresting(struct bitmap_index *bitmap_git,
+ const unsigned char *sha1)
+{
+ int pos;
+
+ if (!bitmap_git)
+ return 0; /* no bitmap loaded */
+ if (!bitmap_git->haves)
+ return 0; /* walk had no "haves" */
+
+ pos = bitmap_position_packfile(bitmap_git, sha1);
+ if (pos < 0)
+ return 0;
+
+ return bitmap_get(bitmap_git->haves, pos);
+}