idx_name = keep_pack(create_index());
/* Register the packfile with core git's machinery. */
- new_p = packfile_store_load_pack(pack_data->repo->objects->packfiles,
+ new_p = packfile_store_load_pack(pack_data->repo->objects->sources->packfiles,
idx_name, 1);
if (!new_p)
die(_("core Git rejected index %s"), idx_name);
struct object_id *oidout,
uintmax_t mark)
{
- struct packfile_store *packs = the_repository->objects->packfiles;
+ struct odb_source *source;
void *out, *delta;
struct object_entry *e;
unsigned char hdr[96];
if (e->idx.offset) {
duplicate_count_by_type[type]++;
return 1;
- } else if (packfile_list_find_oid(packfile_store_get_packs(packs), &oid)) {
+ }
+
+ for (source = the_repository->objects->sources; source; source = source->next) {
+ if (!packfile_list_find_oid(packfile_store_get_packs(source->packfiles), &oid))
+ continue;
e->type = type;
e->pack_id = MAX_PACK_ID;
e->idx.offset = 1; /* just not zero! */
static void stream_blob(uintmax_t len, struct object_id *oidout, uintmax_t mark)
{
- struct packfile_store *packs = the_repository->objects->packfiles;
size_t in_sz = 64 * 1024, out_sz = 64 * 1024;
unsigned char *in_buf = xmalloc(in_sz);
unsigned char *out_buf = xmalloc(out_sz);
+ struct odb_source *source;
struct object_entry *e;
struct object_id oid;
unsigned long hdrlen;
if (e->idx.offset) {
duplicate_count_by_type[OBJ_BLOB]++;
truncate_pack(&checkpoint);
+ goto out;
+ }
- } else if (packfile_list_find_oid(packfile_store_get_packs(packs), &oid)) {
+ for (source = the_repository->objects->sources; source; source = source->next) {
+ if (!packfile_list_find_oid(packfile_store_get_packs(source->packfiles), &oid))
+ continue;
e->type = OBJ_BLOB;
e->pack_id = MAX_PACK_ID;
e->idx.offset = 1; /* just not zero! */
duplicate_count_by_type[OBJ_BLOB]++;
truncate_pack(&checkpoint);
-
- } else {
- e->depth = 0;
- e->type = OBJ_BLOB;
- e->pack_id = pack_id;
- e->idx.offset = offset;
- e->idx.crc32 = crc32_end(pack_file);
- object_count++;
- object_count_by_type[OBJ_BLOB]++;
+ goto out;
}
+ e->depth = 0;
+ e->type = OBJ_BLOB;
+ e->pack_id = pack_id;
+ e->idx.offset = offset;
+ e->idx.crc32 = crc32_end(pack_file);
+ object_count++;
+ object_count_by_type[OBJ_BLOB]++;
+
+out:
free(in_buf);
free(out_buf);
}
*/
if (recurse_submodules)
repo_read_gitmodules(the_repository, 1);
+ /*
+ * Note: `packfile_store_prepare()` prepares stores from all
+ * sources. This will be fixed in a subsequent commit.
+ */
if (startup_info->have_repository)
- packfile_store_prepare(the_repository->objects->packfiles);
+ packfile_store_prepare(the_repository->objects->sources->packfiles);
start_threads(&opt);
} else {
hash, "idx", 1);
if (do_fsck_object && startup_info->have_repository)
- packfile_store_load_pack(the_repository->objects->packfiles,
+ packfile_store_load_pack(the_repository->objects->sources->packfiles,
final_index_name, 0);
if (!from_stdin) {
const struct object_id *oid,
unsigned flags, uint32_t mtime)
{
- struct packed_git **cache = packfile_store_get_kept_pack_cache(r->objects->packfiles, flags);
+ struct odb_source *source;
- for (; *cache; cache++) {
- struct packed_git *p = *cache;
- off_t ofs;
- uint32_t candidate_mtime;
+ for (source = r->objects->sources; source; source = source->next) {
+ struct packed_git **cache = packfile_store_get_kept_pack_cache(source->packfiles, flags);
- ofs = find_pack_entry_one(oid, p);
- if (!ofs)
- continue;
+ for (; *cache; cache++) {
+ struct packed_git *p = *cache;
+ off_t ofs;
+ uint32_t candidate_mtime;
- /*
- * We have a copy of the object 'oid' in a non-cruft
- * pack. We can avoid packing an additional copy
- * regardless of what the existing copy's mtime is since
- * it is outside of a cruft pack.
- */
- if (!p->is_cruft)
- return 0;
-
- /*
- * If we have a copy of the object 'oid' in a cruft
- * pack, then either read the cruft pack's mtime for
- * that object, or, if that can't be loaded, assume the
- * pack's mtime itself.
- */
- if (!load_pack_mtimes(p)) {
- uint32_t pos;
- if (offset_to_pack_pos(p, ofs, &pos) < 0)
+ ofs = find_pack_entry_one(oid, p);
+ if (!ofs)
continue;
- candidate_mtime = nth_packed_mtime(p, pos);
- } else {
- candidate_mtime = p->mtime;
- }
- /*
- * We have a surviving copy of the object in a cruft
- * pack whose mtime is greater than or equal to the one
- * we are considering. We can thus avoid packing an
- * additional copy of that object.
- */
- if (mtime <= candidate_mtime)
- return 0;
+ /*
+ * We have a copy of the object 'oid' in a non-cruft
+ * pack. We can avoid packing an additional copy
+ * regardless of what the existing copy's mtime is since
+ * it is outside of a cruft pack.
+ */
+ if (!p->is_cruft)
+ return 0;
+
+ /*
+ * If we have a copy of the object 'oid' in a cruft
+ * pack, then either read the cruft pack's mtime for
+ * that object, or, if that can't be loaded, assume the
+ * pack's mtime itself.
+ */
+ if (!load_pack_mtimes(p)) {
+ uint32_t pos;
+ if (offset_to_pack_pos(p, ofs, &pos) < 0)
+ continue;
+ candidate_mtime = nth_packed_mtime(p, pos);
+ } else {
+ candidate_mtime = p->mtime;
+ }
+
+ /*
+ * We have a surviving copy of the object in a cruft
+ * pack whose mtime is greater than or equal to the one
+ * we are considering. We can thus avoid packing an
+ * additional copy of that object.
+ */
+ if (mtime <= candidate_mtime)
+ return 0;
+ }
}
return -1;
}
}
- for (e = the_repository->objects->packfiles->packs.head; e; e = e->next) {
- struct packed_git *p = e->pack;
- want = want_object_in_pack_one(p, oid, exclude, found_pack, found_offset, found_mtime);
- if (!exclude && want > 0)
- packfile_list_prepend(&the_repository->objects->packfiles->packs, p);
- if (want != -1)
- return want;
+ for (source = the_repository->objects->sources; source; source = source->next) {
+ for (e = source->packfiles->packs.head; e; e = e->next) {
+ struct packed_git *p = e->pack;
+ want = want_object_in_pack_one(p, oid, exclude, found_pack, found_offset, found_mtime);
+ if (!exclude && want > 0)
+ packfile_list_prepend(&source->packfiles->packs, p);
+ if (want != -1)
+ return want;
+ }
}
if (uri_protocols.nr) {
struct packfile_list *list_to_remove_from)
{
packfile_list_remove(list_to_remove_from, p);
- packfile_store_add_pack(the_repository->objects->packfiles, p);
+ packfile_store_add_pack(the_repository->objects->sources->packfiles, p);
}
struct http_pack_request *new_http_pack_request(
struct multi_pack_index *get_multi_pack_index(struct odb_source *source)
{
- packfile_store_prepare(source->odb->packfiles);
+ packfile_store_prepare(source->packfiles);
return source->midx;
}
int prepare_midx_pack(struct multi_pack_index *m,
uint32_t pack_int_id)
{
- struct repository *r = m->source->odb->repo;
struct strbuf pack_name = STRBUF_INIT;
struct packed_git *p;
strbuf_addf(&pack_name, "%s/pack/%s", m->source->path,
m->pack_names[pack_int_id]);
- p = packfile_store_load_pack(r->objects->packfiles,
+ p = packfile_store_load_pack(m->source->packfiles,
pack_name.buf, m->source->local);
strbuf_release(&pack_name);
source->local = local;
source->path = xstrdup(path);
source->loose = odb_source_loose_new(source);
+ source->packfiles = packfile_store_new(source);
return source;
}
{
free(source->path);
odb_source_loose_free(source->loose);
+ packfile_store_free(source->packfiles);
free(source);
}
while (1) {
struct odb_source *source;
- if (!packfile_store_read_object_info(odb->packfiles, real, oi, flags))
- return 0;
-
/* Most likely it's a loose object. */
- for (source = odb->sources; source; source = source->next)
- if (!odb_source_loose_read_object_info(source, real, oi, flags))
+ for (source = odb->sources; source; source = source->next) {
+ if (!packfile_store_read_object_info(source->packfiles, real, oi, flags) ||
+ !odb_source_loose_read_object_info(source, real, oi, flags))
return 0;
+ }
/* Not a loose object; someone else may have just packed it. */
if (!(flags & OBJECT_INFO_QUICK)) {
odb_reprepare(odb->repo->objects);
- if (!packfile_store_read_object_info(odb->packfiles, real, oi, flags))
- return 0;
+ for (source = odb->sources; source; source = source->next)
+ if (!packfile_store_read_object_info(source->packfiles, real, oi, flags))
+ return 0;
}
/*
{
struct odb_source *source;
- if (packfile_store_freshen_object(odb->packfiles, oid))
- return 1;
-
odb_prepare_alternates(odb);
- for (source = odb->sources; source; source = source->next)
+ for (source = odb->sources; source; source = source->next) {
+ if (packfile_store_freshen_object(source->packfiles, oid))
+ return 1;
+
if (odb_source_loose_freshen_object(source, oid))
return 1;
+ }
return 0;
}
o->sources = odb_source_new(o, primary_source, true);
o->sources_tail = &o->sources->next;
o->alternate_db = xstrdup_or_null(secondary_sources);
- o->packfiles = packfile_store_new(o->sources);
free(to_free);
{
struct odb_source *source;
- packfile_store_close(o->packfiles);
-
for (source = o->sources; source; source = source->next) {
+ packfile_store_close(source->packfiles);
if (source->midx)
close_midx(source->midx);
source->midx = NULL;
free((char *) o->cached_objects[i].value.buf);
free(o->cached_objects);
- packfile_store_free(o->packfiles);
string_list_clear(&o->submodule_source_paths, 0);
chdir_notify_unregister(NULL, odb_update_commondir, o);
o->loaded_alternates = 0;
odb_prepare_alternates(o);
- for (source = o->sources; source; source = source->next)
+ for (source = o->sources; source; source = source->next) {
odb_source_loose_reprepare(source);
+ packfile_store_reprepare(source->packfiles);
+ }
o->approximate_object_count_valid = 0;
- packfile_store_reprepare(o->packfiles);
-
obj_read_unlock();
}
/* Private state for loose objects. */
struct odb_source_loose *loose;
+ /* Should only be accessed directly by packfile.c and midx.c. */
+ struct packfile_store *packfiles;
+
/*
* private data
*
struct commit_graph *commit_graph;
unsigned commit_graph_attempted : 1; /* if loading has been attempted */
- /* Should only be accessed directly by packfile.c and midx.c. */
- struct packfile_store *packfiles;
-
/*
* This is meant to hold a *small* number of objects that you would
* want odb_read_object() to be able to return, but yet you do not want
{
struct odb_source *source;
- if (!packfile_store_read_object_stream(out, odb->packfiles, oid))
- return 0;
-
odb_prepare_alternates(odb);
- for (source = odb->sources; source; source = source->next)
- if (!odb_source_loose_read_object_stream(out, source, oid))
+ for (source = odb->sources; source; source = source->next) {
+ if (!packfile_store_read_object_stream(out, source->packfiles, oid) ||
+ !odb_source_loose_read_object_stream(out, source, oid))
return 0;
+ }
return open_istream_incore(out, odb, oid);
}
static int unuse_one_window(struct object_database *odb)
{
+ struct odb_source *source;
struct packfile_list_entry *e;
struct packed_git *lru_p = NULL;
struct pack_window *lru_w = NULL, *lru_l = NULL;
- for (e = odb->packfiles->packs.head; e; e = e->next)
- scan_windows(e->pack, &lru_p, &lru_w, &lru_l);
+ for (source = odb->sources; source; source = source->next)
+ for (e = source->packfiles->packs.head; e; e = e->next)
+ scan_windows(e->pack, &lru_p, &lru_w, &lru_l);
if (lru_p) {
munmap(lru_w->base, lru_w->len);
static int close_one_pack(struct repository *r)
{
+ struct odb_source *source;
struct packfile_list_entry *e;
struct packed_git *lru_p = NULL;
struct pack_window *mru_w = NULL;
int accept_windows_inuse = 1;
- for (e = r->objects->packfiles->packs.head; e; e = e->next) {
- if (e->pack->pack_fd == -1)
- continue;
- find_lru_pack(e->pack, &lru_p, &mru_w, &accept_windows_inuse);
+ for (source = r->objects->sources; source; source = source->next) {
+ for (e = source->packfiles->packs.head; e; e = e->next) {
+ if (e->pack->pack_fd == -1)
+ continue;
+ find_lru_pack(e->pack, &lru_p, &mru_w, &accept_windows_inuse);
+ }
}
if (lru_p)
if (strip_suffix_mem(full_name, &base_len, ".idx") &&
!(data->source->midx && midx_contains_pack(data->source->midx, file_name))) {
char *trimmed_path = xstrndup(full_name, full_name_len);
- packfile_store_load_pack(data->source->odb->packfiles,
+ packfile_store_load_pack(data->source->packfiles,
trimmed_path, data->source->local);
free(trimmed_path);
}
const struct packed_git *has_packed_and_bad(struct repository *r,
const struct object_id *oid)
{
- struct packfile_list_entry *e;
+ struct odb_source *source;
+
+ for (source = r->objects->sources; source; source = source->next) {
+ struct packfile_list_entry *e;
+ for (e = source->packfiles->packs.head; e; e = e->next)
+ if (oidset_contains(&e->pack->bad_objects, oid))
+ return e->pack;
+ }
- for (e = r->objects->packfiles->packs.head; e; e = e->next)
- if (oidset_contains(&e->pack->bad_objects, oid))
- return e->pack;
return NULL;
}
const struct object_id *oid,
struct pack_entry *e)
{
- struct packfile_list_entry *l;
+ struct odb_source *source;
- packfile_store_prepare(r->objects->packfiles);
+ /*
+ * Note: `packfile_store_prepare()` prepares stores from all sources.
+ * This will be fixed in a subsequent commit.
+ */
+ packfile_store_prepare(r->objects->sources->packfiles);
- for (struct odb_source *source = r->objects->sources; source; source = source->next)
+ for (source = r->objects->sources; source; source = source->next)
if (source->midx && fill_midx_entry(source->midx, oid, e))
return 1;
- if (!r->objects->packfiles->packs.head)
- return 0;
+ for (source = r->objects->sources; source; source = source->next) {
+ struct packfile_list_entry *l;
- for (l = r->objects->packfiles->packs.head; l; l = l->next) {
- struct packed_git *p = l->pack;
+ for (l = source->packfiles->packs.head; l; l = l->next) {
+ struct packed_git *p = l->pack;
- if (!p->multi_pack_index && fill_pack_entry(oid, e, p)) {
- if (!r->objects->packfiles->skip_mru_updates)
- packfile_list_prepend(&r->objects->packfiles->packs, p);
- return 1;
+ if (!p->multi_pack_index && fill_pack_entry(oid, e, p)) {
+ if (!source->packfiles->skip_mru_updates)
+ packfile_list_prepend(&source->packfiles->packs, p);
+ return 1;
+ }
}
}
+
return 0;
}
unsigned flags,
struct pack_entry *e)
{
- struct packed_git **cache = packfile_store_get_kept_pack_cache(r->objects->packfiles, flags);
+ struct odb_source *source;
- for (; *cache; cache++) {
- struct packed_git *p = *cache;
- if (fill_pack_entry(oid, e, p))
- return 1;
+ for (source = r->objects->sources; source; source = source->next) {
+ struct packed_git **cache;
+
+ cache = packfile_store_get_kept_pack_cache(source->packfiles, flags);
+
+ for (; *cache; cache++) {
+ struct packed_git *p = *cache;
+ if (fill_pack_entry(oid, e, p))
+ return 1;
+ }
}
return 0;
int for_each_packed_object(struct repository *repo, each_packed_object_fn cb,
void *data, enum for_each_object_flags flags)
{
- struct packed_git *p;
+ struct odb_source *source;
int r = 0;
int pack_errors = 0;
- repo->objects->packfiles->skip_mru_updates = true;
- repo_for_each_pack(repo, p) {
- if ((flags & FOR_EACH_OBJECT_LOCAL_ONLY) && !p->pack_local)
- continue;
- if ((flags & FOR_EACH_OBJECT_PROMISOR_ONLY) &&
- !p->pack_promisor)
- continue;
- if ((flags & FOR_EACH_OBJECT_SKIP_IN_CORE_KEPT_PACKS) &&
- p->pack_keep_in_core)
- continue;
- if ((flags & FOR_EACH_OBJECT_SKIP_ON_DISK_KEPT_PACKS) &&
- p->pack_keep)
- continue;
- if (open_pack_index(p)) {
- pack_errors = 1;
- continue;
+ odb_prepare_alternates(repo->objects);
+
+ for (source = repo->objects->sources; source; source = source->next) {
+ struct packfile_list_entry *e;
+
+ source->packfiles->skip_mru_updates = true;
+
+ for (e = packfile_store_get_packs(source->packfiles); e; e = e->next) {
+ struct packed_git *p = e->pack;
+
+ if ((flags & FOR_EACH_OBJECT_LOCAL_ONLY) && !p->pack_local)
+ continue;
+ if ((flags & FOR_EACH_OBJECT_PROMISOR_ONLY) &&
+ !p->pack_promisor)
+ continue;
+ if ((flags & FOR_EACH_OBJECT_SKIP_IN_CORE_KEPT_PACKS) &&
+ p->pack_keep_in_core)
+ continue;
+ if ((flags & FOR_EACH_OBJECT_SKIP_ON_DISK_KEPT_PACKS) &&
+ p->pack_keep)
+ continue;
+ if (open_pack_index(p)) {
+ pack_errors = 1;
+ continue;
+ }
+
+ r = for_each_object_in_pack(p, cb, data, flags);
+ if (r)
+ break;
}
- r = for_each_object_in_pack(p, cb, data, flags);
+
+ source->packfiles->skip_mru_updates = false;
+
if (r)
break;
}
- repo->objects->packfiles->skip_mru_updates = false;
return r ? r : pack_errors;
}
#include "object.h"
#include "odb.h"
#include "oidset.h"
+#include "repository.h"
#include "strmap.h"
/* in odb.h */
void packfile_store_add_pack(struct packfile_store *store,
struct packed_git *pack);
+/*
+ * Get all packs managed by the given store, including packfiles that are
+ * referenced by multi-pack indices.
+ */
+struct packfile_list_entry *packfile_store_get_packs(struct packfile_store *store);
+
+struct repo_for_each_pack_data {
+ struct odb_source *source;
+ struct packfile_list_entry *entry;
+};
+
+static inline struct repo_for_each_pack_data repo_for_eack_pack_data_init(struct repository *repo)
+{
+ struct repo_for_each_pack_data data = { 0 };
+
+ odb_prepare_alternates(repo->objects);
+
+ for (struct odb_source *source = repo->objects->sources; source; source = source->next) {
+ struct packfile_list_entry *entry = packfile_store_get_packs(source->packfiles);
+ if (!entry)
+ continue;
+ data.source = source;
+ data.entry = entry;
+ break;
+ }
+
+ return data;
+}
+
+static inline void repo_for_each_pack_data_next(struct repo_for_each_pack_data *data)
+{
+ struct odb_source *source;
+
+ data->entry = data->entry->next;
+ if (data->entry)
+ return;
+
+ for (source = data->source->next; source; source = source->next) {
+ struct packfile_list_entry *entry = packfile_store_get_packs(source->packfiles);
+ if (!entry)
+ continue;
+ data->source = source;
+ data->entry = entry;
+ return;
+ }
+
+ data->source = NULL;
+ data->entry = NULL;
+}
+
/*
* Load and iterate through all packs of the given repository. This helper
* function will yield packfiles from all object sources connected to the
* repository.
*/
#define repo_for_each_pack(repo, p) \
- for (struct packfile_list_entry *e = packfile_store_get_packs(repo->objects->packfiles); \
- ((p) = (e ? e->pack : NULL)); e = e->next)
+ for (struct repo_for_each_pack_data eack_pack_data = repo_for_eack_pack_data_init(repo); \
+ ((p) = (eack_pack_data.entry ? eack_pack_data.entry->pack : NULL)); \
+ repo_for_each_pack_data_next(&eack_pack_data))
int packfile_store_read_object_stream(struct odb_read_stream **out,
struct packfile_store *store,
struct object_info *oi,
unsigned flags);
-/*
- * Get all packs managed by the given store, including packfiles that are
- * referenced by multi-pack indices.
- */
-struct packfile_list_entry *packfile_store_get_packs(struct packfile_store *store);
-
/*
* Open the packfile and add it to the store if it isn't yet known. Returns
* either the newly opened packfile or the preexisting packfile. Returns a