Skip to main content

objects_to_send

Function objects_to_send 

Source
pub fn objects_to_send(
    store: &dyn GitServe,
    hash_kind: Kind,
    want: &[&[u8]],
    have: &[&[u8]],
) -> Result<Vec<Vec<u8>>>
Expand description

The objects one push must carry: everything reachable from want that is not reachable from have, in this store’s ids.

§Why replication comes through here rather than calling the store

🔴 MEASURED on the reference appliance 2026-08-31. A resync of 25 repositories left six failing, every one of them on an annotated tag, every one refused by the standby’s own receive-pack with missing necessary objects: <oid> is not in this repository (peeling a tag) — where <oid> is the commit the tag names and the primary holds.

The mirror built its object list from GitOps::reachable, handing it the ref tips unpeeled. For an annotated tag that tip is the tag object, and the shipped storage engine contributes a non-commit tip’s own id and stops: the tag went into the pack and the commit under it did not. It only showed where the tagged commit was on no branch — skade’s v0.9.10, edda’s twenty-five tags on 2c7f9919… — because otherwise a branch tip in the same push carried it by accident.

A clone of those same repositories has always worked, and this function is why: [select_objects] peels its tips (step 1) and puts the tag objects it walked through into the answer, and so does the store-answered fast path in [crate::reachable::select]. Replication asking the store directly was a second definition of “what does this ref tip reach”, and the two definitions disagreed about exactly one edge. There is one now (one implementation).

have is tolerant by construction: a tip the far end advertised and this store does not hold contributes nothing rather than failing, which is what a standby whose history diverged looks like. A want this store does not hold is an error, because that pack cannot be built.

§No object budget and no byte ceiling, deliberately

[Graph::with_budget] and [Graph::with_walk_limit] are what an operator aims at a client: a fetch that would cost more than this machine will spend is refused, and the client is told to ask for less. A mirror cannot ask for less — there is no smaller request that still leaves the standby holding the repository — so a ceiling here would not bound the work, it would only make one repository permanently unreplicable. That is what GitOps::reachable did before this function existed, over the same objects, so this changes nothing about what the replicator may consume.