for (source = the_repository->objects->sources; source; source = source->next) {
struct odb_source_files *files = odb_source_files_downcast(source);
- int ret = packfile_store_for_each_object(files->packed, &oi,
- batch_one_object_oi, &payload, &opts);
+ int ret = odb_source_for_each_object(&files->packed->base, &oi,
+ batch_one_object_oi, &payload, &opts);
if (ret)
break;
}
if (!source->local)
continue;
- if (packfile_store_for_each_object(files->packed, &oi,
- add_object_in_unpacked_pack, NULL, &opts))
+ if (odb_source_for_each_object(&files->packed->base, &oi,
+ add_object_in_unpacked_pack, NULL, &opts))
die(_("cannot open pack index"));
}
}
odb_prepare_alternates(ctx->r->objects);
for (source = ctx->r->objects->sources; source; source = source->next) {
struct odb_source_files *files = odb_source_files_downcast(source);
- packfile_store_for_each_object(files->packed, &oi, add_packed_commits_oi,
- ctx, &opts);
+ odb_source_for_each_object(&files->packed->base, &oi, add_packed_commits_oi,
+ ctx, &opts);
}
if (ctx->progress_done < ctx->approx_nr_objects)
return ret;
}
- ret = packfile_store_for_each_object(files->packed, request, cb, cb_data, opts);
+ ret = odb_source_for_each_object(&files->packed->base, request, cb, cb_data, opts);
if (ret)
return ret;
return packfile_read_object_stream(out, oid, e.p, e.offset);
}
+struct odb_source_packed_for_each_object_wrapper_data {
+ struct odb_source_packed *store;
+ const struct object_info *request;
+ odb_for_each_object_cb cb;
+ void *cb_data;
+};
+
+static int odb_source_packed_for_each_object_wrapper(const struct object_id *oid,
+ struct packed_git *pack,
+ uint32_t index_pos,
+ void *cb_data)
+{
+ struct odb_source_packed_for_each_object_wrapper_data *data = cb_data;
+
+ if (data->request) {
+ off_t offset = nth_packed_object_offset(pack, index_pos);
+ struct object_info oi = *data->request;
+
+ if (packed_object_info_with_index_pos(pack, offset,
+ &index_pos, &oi) < 0) {
+ mark_bad_packed_object(pack, oid);
+ return -1;
+ }
+
+ return data->cb(oid, &oi, data->cb_data);
+ } else {
+ return data->cb(oid, NULL, data->cb_data);
+ }
+}
+
+static int match_hash(unsigned len, const unsigned char *a, const unsigned char *b)
+{
+ do {
+ if (*a != *b)
+ return 0;
+ a++;
+ b++;
+ len -= 2;
+ } while (len > 1);
+ if (len)
+ if ((*a ^ *b) & 0xf0)
+ return 0;
+ return 1;
+}
+
+static int for_each_prefixed_object_in_midx(
+ struct odb_source_packed *store,
+ struct multi_pack_index *m,
+ const struct odb_for_each_object_options *opts,
+ struct odb_source_packed_for_each_object_wrapper_data *data)
+{
+ int ret;
+
+ for (; m; m = m->base_midx) {
+ uint32_t num, i, first = 0;
+ int len = opts->prefix_hex_len > m->source->odb->repo->hash_algo->hexsz ?
+ m->source->odb->repo->hash_algo->hexsz : opts->prefix_hex_len;
+
+ if (!m->num_objects)
+ continue;
+
+ num = m->num_objects + m->num_objects_in_base;
+
+ bsearch_one_midx(opts->prefix, m, &first);
+
+ /*
+ * At this point, "first" is the location of the lowest
+ * object with an object name that could match "opts->prefix".
+ * See if we have 0, 1 or more objects that actually match(es).
+ */
+ for (i = first; i < num; i++) {
+ const struct object_id *current = NULL;
+ struct object_id oid;
+
+ current = nth_midxed_object_oid(&oid, m, i);
+
+ if (!match_hash(len, opts->prefix->hash, current->hash))
+ break;
+
+ if (data->request) {
+ struct object_info oi = *data->request;
+
+ ret = odb_source_read_object_info(&store->base, current,
+ &oi, 0);
+ if (ret)
+ goto out;
+
+ ret = data->cb(&oid, &oi, data->cb_data);
+ if (ret)
+ goto out;
+ } else {
+ ret = data->cb(&oid, NULL, data->cb_data);
+ if (ret)
+ goto out;
+ }
+ }
+ }
+
+ ret = 0;
+
+out:
+ return ret;
+}
+
+static int for_each_prefixed_object_in_pack(
+ struct odb_source_packed *store,
+ struct packed_git *p,
+ const struct odb_for_each_object_options *opts,
+ struct odb_source_packed_for_each_object_wrapper_data *data)
+{
+ uint32_t num, i, first = 0;
+ int len = opts->prefix_hex_len > p->repo->hash_algo->hexsz ?
+ p->repo->hash_algo->hexsz : opts->prefix_hex_len;
+ int ret;
+
+ num = p->num_objects;
+ bsearch_pack(opts->prefix, p, &first);
+
+ /*
+ * At this point, "first" is the location of the lowest object
+ * with an object name that could match "bin_pfx". See if we have
+ * 0, 1 or more objects that actually match(es).
+ */
+ for (i = first; i < num; i++) {
+ struct object_id oid;
+
+ nth_packed_object_id(&oid, p, i);
+ if (!match_hash(len, opts->prefix->hash, oid.hash))
+ break;
+
+ if (data->request) {
+ struct object_info oi = *data->request;
+
+ ret = odb_source_read_object_info(&store->base, &oid, &oi, 0);
+ if (ret)
+ goto out;
+
+ ret = data->cb(&oid, &oi, data->cb_data);
+ if (ret)
+ goto out;
+ } else {
+ ret = data->cb(&oid, NULL, data->cb_data);
+ if (ret)
+ goto out;
+ }
+ }
+
+ ret = 0;
+
+out:
+ return ret;
+}
+
+static int odb_source_packed_for_each_prefixed_object(
+ struct odb_source_packed *store,
+ const struct odb_for_each_object_options *opts,
+ struct odb_source_packed_for_each_object_wrapper_data *data)
+{
+ struct packfile_list_entry *e;
+ struct multi_pack_index *m;
+ bool pack_errors = false;
+ int ret;
+
+ if (opts->flags)
+ BUG("flags unsupported");
+
+ store->skip_mru_updates = true;
+
+ m = get_multi_pack_index(&store->files->base);
+ if (m) {
+ ret = for_each_prefixed_object_in_midx(store, m, opts, data);
+ if (ret)
+ goto out;
+ }
+
+ for (e = packfile_store_get_packs(store); e; e = e->next) {
+ if (e->pack->multi_pack_index)
+ continue;
+
+ if (open_pack_index(e->pack)) {
+ pack_errors = true;
+ continue;
+ }
+
+ if (!e->pack->num_objects)
+ continue;
+
+ ret = for_each_prefixed_object_in_pack(store, e->pack, opts, data);
+ if (ret)
+ goto out;
+ }
+
+ ret = 0;
+
+out:
+ store->skip_mru_updates = false;
+ if (!ret && pack_errors)
+ ret = -1;
+ return ret;
+}
+
+static int odb_source_packed_for_each_object(struct odb_source *source,
+ const struct object_info *request,
+ odb_for_each_object_cb cb,
+ void *cb_data,
+ const struct odb_for_each_object_options *opts)
+{
+ struct odb_source_packed *packed = odb_source_packed_downcast(source);
+ struct odb_source_packed_for_each_object_wrapper_data data = {
+ .store = packed,
+ .request = request,
+ .cb = cb,
+ .cb_data = cb_data,
+ };
+ struct packfile_list_entry *e;
+ int pack_errors = 0, ret;
+
+ if (opts->prefix)
+ return odb_source_packed_for_each_prefixed_object(packed, opts, &data);
+
+ packed->skip_mru_updates = true;
+
+ for (e = packfile_store_get_packs(packed); e; e = e->next) {
+ struct packed_git *p = e->pack;
+
+ if ((opts->flags & ODB_FOR_EACH_OBJECT_LOCAL_ONLY) && !p->pack_local)
+ continue;
+ if ((opts->flags & ODB_FOR_EACH_OBJECT_PROMISOR_ONLY) &&
+ !p->pack_promisor)
+ continue;
+ if ((opts->flags & ODB_FOR_EACH_OBJECT_SKIP_IN_CORE_KEPT_PACKS) &&
+ p->pack_keep_in_core)
+ continue;
+ if ((opts->flags & ODB_FOR_EACH_OBJECT_SKIP_ON_DISK_KEPT_PACKS) &&
+ p->pack_keep)
+ continue;
+ if (open_pack_index(p)) {
+ pack_errors = 1;
+ continue;
+ }
+
+ ret = for_each_object_in_pack(p, odb_source_packed_for_each_object_wrapper,
+ &data, opts->flags);
+ if (ret)
+ goto out;
+ }
+
+ ret = 0;
+
+out:
+ packed->skip_mru_updates = false;
+
+ if (!ret && pack_errors)
+ ret = -1;
+ return ret;
+}
+
void (*report_garbage)(unsigned seen_bits, const char *path);
static void report_helper(const struct string_list *list,
packed->base.reprepare = odb_source_packed_reprepare;
packed->base.read_object_info = odb_source_packed_read_object_info;
packed->base.read_object_stream = odb_source_packed_read_object_stream;
+ packed->base.for_each_object = odb_source_packed_for_each_object;
if (!is_absolute_path(parent->base.path))
chdir_notify_register(NULL, odb_source_packed_reparent, packed);
hashmap_add(&delta_base_cache, &ent->ent);
}
-static int packed_object_info_with_index_pos(struct packed_git *p, off_t obj_offset,
- uint32_t *maybe_index_pos, struct object_info *oi)
+int packed_object_info_with_index_pos(struct packed_git *p, off_t obj_offset,
+ uint32_t *maybe_index_pos, struct object_info *oi)
{
struct pack_window *w_curs = NULL;
size_t size;
return r;
}
-struct odb_source_packed_for_each_object_wrapper_data {
- struct odb_source_packed *store;
- const struct object_info *request;
- odb_for_each_object_cb cb;
- void *cb_data;
-};
-
-static int packfile_store_for_each_object_wrapper(const struct object_id *oid,
- struct packed_git *pack,
- uint32_t index_pos,
- void *cb_data)
-{
- struct odb_source_packed_for_each_object_wrapper_data *data = cb_data;
-
- if (data->request) {
- off_t offset = nth_packed_object_offset(pack, index_pos);
- struct object_info oi = *data->request;
-
- if (packed_object_info_with_index_pos(pack, offset,
- &index_pos, &oi) < 0) {
- mark_bad_packed_object(pack, oid);
- return -1;
- }
-
- return data->cb(oid, &oi, data->cb_data);
- } else {
- return data->cb(oid, NULL, data->cb_data);
- }
-}
-
-static int match_hash(unsigned len, const unsigned char *a, const unsigned char *b)
-{
- do {
- if (*a != *b)
- return 0;
- a++;
- b++;
- len -= 2;
- } while (len > 1);
- if (len)
- if ((*a ^ *b) & 0xf0)
- return 0;
- return 1;
-}
-
-static int for_each_prefixed_object_in_midx(
- struct odb_source_packed *store,
- struct multi_pack_index *m,
- const struct odb_for_each_object_options *opts,
- struct odb_source_packed_for_each_object_wrapper_data *data)
-{
- int ret;
-
- for (; m; m = m->base_midx) {
- uint32_t num, i, first = 0;
- int len = opts->prefix_hex_len > m->source->odb->repo->hash_algo->hexsz ?
- m->source->odb->repo->hash_algo->hexsz : opts->prefix_hex_len;
-
- if (!m->num_objects)
- continue;
-
- num = m->num_objects + m->num_objects_in_base;
-
- bsearch_one_midx(opts->prefix, m, &first);
-
- /*
- * At this point, "first" is the location of the lowest
- * object with an object name that could match "opts->prefix".
- * See if we have 0, 1 or more objects that actually match(es).
- */
- for (i = first; i < num; i++) {
- const struct object_id *current = NULL;
- struct object_id oid;
-
- current = nth_midxed_object_oid(&oid, m, i);
-
- if (!match_hash(len, opts->prefix->hash, current->hash))
- break;
-
- if (data->request) {
- struct object_info oi = *data->request;
-
- ret = odb_source_read_object_info(&store->base, current,
- &oi, 0);
- if (ret)
- goto out;
-
- ret = data->cb(&oid, &oi, data->cb_data);
- if (ret)
- goto out;
- } else {
- ret = data->cb(&oid, NULL, data->cb_data);
- if (ret)
- goto out;
- }
- }
- }
-
- ret = 0;
-
-out:
- return ret;
-}
-
-static int for_each_prefixed_object_in_pack(
- struct odb_source_packed *store,
- struct packed_git *p,
- const struct odb_for_each_object_options *opts,
- struct odb_source_packed_for_each_object_wrapper_data *data)
-{
- uint32_t num, i, first = 0;
- int len = opts->prefix_hex_len > p->repo->hash_algo->hexsz ?
- p->repo->hash_algo->hexsz : opts->prefix_hex_len;
- int ret;
-
- num = p->num_objects;
- bsearch_pack(opts->prefix, p, &first);
-
- /*
- * At this point, "first" is the location of the lowest object
- * with an object name that could match "bin_pfx". See if we have
- * 0, 1 or more objects that actually match(es).
- */
- for (i = first; i < num; i++) {
- struct object_id oid;
-
- nth_packed_object_id(&oid, p, i);
- if (!match_hash(len, opts->prefix->hash, oid.hash))
- break;
-
- if (data->request) {
- struct object_info oi = *data->request;
-
- ret = odb_source_read_object_info(&store->base, &oid, &oi, 0);
- if (ret)
- goto out;
-
- ret = data->cb(&oid, &oi, data->cb_data);
- if (ret)
- goto out;
- } else {
- ret = data->cb(&oid, NULL, data->cb_data);
- if (ret)
- goto out;
- }
- }
-
- ret = 0;
-
-out:
- return ret;
-}
-
-static int packfile_store_for_each_prefixed_object(
- struct odb_source_packed *store,
- const struct odb_for_each_object_options *opts,
- struct odb_source_packed_for_each_object_wrapper_data *data)
-{
- struct packfile_list_entry *e;
- struct multi_pack_index *m;
- bool pack_errors = false;
- int ret;
-
- if (opts->flags)
- BUG("flags unsupported");
-
- store->skip_mru_updates = true;
-
- m = get_multi_pack_index(&store->files->base);
- if (m) {
- ret = for_each_prefixed_object_in_midx(store, m, opts, data);
- if (ret)
- goto out;
- }
-
- for (e = packfile_store_get_packs(store); e; e = e->next) {
- if (e->pack->multi_pack_index)
- continue;
-
- if (open_pack_index(e->pack)) {
- pack_errors = true;
- continue;
- }
-
- if (!e->pack->num_objects)
- continue;
-
- ret = for_each_prefixed_object_in_pack(store, e->pack, opts, data);
- if (ret)
- goto out;
- }
-
- ret = 0;
-
-out:
- store->skip_mru_updates = false;
- if (!ret && pack_errors)
- ret = -1;
- return ret;
-}
-
-int packfile_store_for_each_object(struct odb_source_packed *store,
- const struct object_info *request,
- odb_for_each_object_cb cb,
- void *cb_data,
- const struct odb_for_each_object_options *opts)
-{
- struct odb_source_packed_for_each_object_wrapper_data data = {
- .store = store,
- .request = request,
- .cb = cb,
- .cb_data = cb_data,
- };
- struct packfile_list_entry *e;
- int pack_errors = 0, ret;
-
- if (opts->prefix)
- return packfile_store_for_each_prefixed_object(store, opts, &data);
-
- store->skip_mru_updates = true;
-
- for (e = packfile_store_get_packs(store); e; e = e->next) {
- struct packed_git *p = e->pack;
-
- if ((opts->flags & ODB_FOR_EACH_OBJECT_LOCAL_ONLY) && !p->pack_local)
- continue;
- if ((opts->flags & ODB_FOR_EACH_OBJECT_PROMISOR_ONLY) &&
- !p->pack_promisor)
- continue;
- if ((opts->flags & ODB_FOR_EACH_OBJECT_SKIP_IN_CORE_KEPT_PACKS) &&
- p->pack_keep_in_core)
- continue;
- if ((opts->flags & ODB_FOR_EACH_OBJECT_SKIP_ON_DISK_KEPT_PACKS) &&
- p->pack_keep)
- continue;
- if (open_pack_index(p)) {
- pack_errors = 1;
- continue;
- }
-
- ret = for_each_object_in_pack(p, packfile_store_for_each_object_wrapper,
- &data, opts->flags);
- if (ret)
- goto out;
- }
-
- ret = 0;
-
-out:
- store->skip_mru_updates = false;
-
- if (!ret && pack_errors)
- ret = -1;
- return ret;
-}
-
static int extend_abbrev_len(const struct object_id *a,
const struct object_id *b,
unsigned *out)
each_packed_object_fn, void *data,
enum odb_for_each_object_flags flags);
-/*
- * Iterate through all packed objects in the given packfile store and invoke
- * the callback function for each of them. If an object info request is given,
- * then the object info will be read for every individual object and passed to
- * the callback as if `packfile_store_read_object_info()` was called for the
- * object.
- *
- * The flags parameter is a combination of `odb_for_each_object_flags`.
- */
-int packfile_store_for_each_object(struct odb_source_packed *store,
- const struct object_info *request,
- odb_for_each_object_cb cb,
- void *cb_data,
- const struct odb_for_each_object_options *opts);
-
int packfile_store_find_abbrev_len(struct odb_source_packed *store,
const struct object_id *oid,
unsigned min_len,
*/
int packed_object_info(struct packed_git *pack,
off_t offset, struct object_info *);
+int packed_object_info_with_index_pos(struct packed_git *p, off_t obj_offset,
+ uint32_t *maybe_index_pos, struct object_info *oi);
void mark_bad_packed_object(struct packed_git *, const struct object_id *);
const struct packed_git *has_packed_and_bad(struct repository *, const struct object_id *);