I think that both bisection results are equally valid for different reasons.
Before 8384cbcb4c, 'find_pack_entry()' did
packfile_store_prepare(r->objects->sources->packfiles);
, then tried each of the stores in order to first see if (1) a MIDX was available to locate the object in some pack, or (2) failing that, if there exists some non-MIDX'd pack which could do the same.
Worth noting is that 'packfile_store_prepare()' effectively did:
for (s = store->source->odb->sources; s; s = s->next) {
prepare_multi_pack_index_one(s);
prepare_packed_git_one(s);
}Thus preparing the first store also prepared every alternate store, enabling 'find_pack_entry()' to search through all store's MIDX and pack lists/sources.
8384cbcb4c changes this such that 'packfile_store_prepare()' now only prepares its owning source:
prepare_multi_pack_index_one(store->source);
prepare_packed_git_one(store->source);, which is reasonable, but 'find_pack_entry()' still loops over all sources starting from 'r->objects->sources' and calls the function 'packfile_store_prepare()'. But! It calls that function over the same argument each time, like so:
for (source = r->objects->sources; source; source = source->next) {
packfile_store_prepare(r->objects->sources->packfiles);
if (source->midx && fill_midx_entry(source->midx, oid, e))
return 1;
}So we never prepare the packfile store from other sources!
In Wolfgang's case, if we have an quarantine store followed by the main object store, our lookup order will be:
1. prepare the quarantine object store
2. search packs in the quarantine object store
3. search packs in the main object store (which will fail, since this
list is guaranteed to be empty since we never called
'packfile_store_prepare()')
4. search loose objects in the quarantine object store
5. search loose objects in the main object store
6. haven't found anything, so we must reprepare
7. search packs in the main object store, which will now succeed, as
the previous reprepare called 'packfile_store_prepare()' on the main
object store's packfile source.Commit a593373b09 changes things, since it makes 'find_pack_entry()' no longer operate over the entire repository, but over a single store. Before searching that store, it prepares it, like so:
static int find_pack_entry(struct packfile_store *store,
const struct object_id *oid,
sturct pack_entry *e)
{
struct packfile_list_entry *l; packfile_store_prepare(store);
if (store->source->midx && fill_midx_entry(...))
return 1; for (l = store->packs.head; l; l = l->next) {
struct packed_git *p = l->pack;
if (!p->multi_pack_index && fill_pack_entry(oid, e, p)) {
/* ... */
return 1;
}
} return 0;
}So commit a593373b09 indeed squashes the bug introduced by 8384cbcb4c, and when lookup reaches the main store, it prepares the main store correctly.
But a593373b09 also changes the lookup order, because the caller in 'do_oid_object_info_extended()` already loops over sources!
static int do_oid_object_info_extended(struct object_database *odb,
const struct object_id *oid,
struct object_info *oi, unsigned flags)
{
/* replace objects, cached lookups, etc., ... */ odb_prepare_alterantes(odb);
while (1) {
struct odb_source *source; 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;
}
}
}Before a593373b09, that call to 'packfile_store_read_object_info()' looped over all sources, since it still called 'find_pack_entry()'.
In other words, prior to a593373b09, the lookup proceeded like so:
1. search packfiles in quarantine
2. search packfiles in the main object store
3. search loose objects in quarantine
4. search loose objects in the main object store
But a593373b09 changes that to instead proceed store-by-store, as follows:
1. search packfiles in quarantine
2. search loose objects in quarantine
3. search packfiles in the main object store
4. search loose objects in the main object store
So even with all object sources prepared, every object found in a later source pays a failed loose object lookup in an earlier one, which I believe matches what Peff strace'd above.
So both bisections make sense. If the later store has not been prepared yet, commit 8384cbcb4c is where Git first fails to see its packs and falls through to loose object checks. If the stores are already prepared, that problem does not show up, and a593373b09 is where Git first starts checking loose objects in an earlier source before looking in a later source's packs.
I think that something like the following (untested) would fix the immediate issue:
--- 8< ---