pub struct PushReport {
pub unpack: String,
pub refs: Vec<RefStatus>,
pub progress: Vec<String>,
pub remote_errors: Vec<String>,
pub unreported: Vec<BString>,
}Expand description
The remote’s verdict on the push as a whole.
Fields§
§unpack: Stringreceive-pack’s verdict on the packfile: "ok", or its error text.
refs: Vec<RefStatus>One entry per ref the remote reported on.
progress: Vec<String>Band-2 output: the remote’s hooks and progress meters.
remote_errors: Vec<String>Band-3 output: fatal remote errors.
unreported: Vec<BString>Refs this client commanded that the remote’s report never mentioned.
Filled by PushReport::reconcile; empty until it is called, and empty
on the path where no report was negotiated at all.
Implementations§
Source§impl PushReport
impl PushReport
Sourcepub fn is_ok(&self) -> bool
pub fn is_ok(&self) -> bool
True only if the pack unpacked, every reported ref was accepted, and every ref this client commanded was reported on.
§The third clause is the one that was missing
refs is one entry per ref the remote chose to talk about, so
iter().all(…) over an empty list is vacuously true. A report of
exactly unpack ok + flush — no ok, no ng — therefore made
is_ok true, failure_summary
return None, and gunnar push exit 0, having moved nothing. The whole
verdict was computed from lines the remote was free not to send.
The same hole swallows a partial report: a ten-ref push whose remote reports on one is nine silent no-ops.
git closes it from the other end and does not trust the report either
(send-pack.c): every commanded ref is pre-seeded
REF_STATUS_EXPECTING_REPORT, receive_status() overwrites the ones it
hears about, and anything still expecting afterwards is printed as
remote failed to report status. transport.c:push_had_errors() then
whitelists only NONE/UPTODATE/OK, so it is a non-zero exit and not
a warning. reconcile is that pre-seeding, done
after the fact because this parser has no reason to know the command
list until it is handed one.
§The fourth clause
Sideband 3 is defined as “a fatal error message just before the stream
aborts”; git’s recv_sideband calls die on it. gunnar collected band
3 into remote_errors, printed it, and then
computed the verdict without it — so a remote that aborted with a
reason on band 3 while its band-1 report still said unpack ok exited
0. The reason was on the screen and the exit code disagreed with it.
Sourcepub fn reconcile(&mut self, commanded: &[BString])
pub fn reconcile(&mut self, commanded: &[BString])
Account the report against the refs that were actually commanded.
Anything commanded and not reported on lands in
unreported and fails the push. Anything reported
and not commanded is turned into a rejection rather than an
acceptance: git treats it as a protocol error, and the shape that
matters here is that such a line must never be what satisfies
all(|r| r.accepted) for a ref the remote said nothing about.
Idempotent, so a caller that reconciles twice does not double-count.
Sourcepub fn remote_lines(&self) -> impl Iterator<Item = &str>
pub fn remote_lines(&self) -> impl Iterator<Item = &str>
Everything the remote said in its own words, trimmed, in wire order:
band 2 first, then band 3. What git push prints prefixed remote:.
§Why this exists rather than two fields read separately
A pre-receive hook writes its refusal to stderr, and
receive-pack muxes stderr onto band 2, which lands in
progress. Band 3 is reserved for fatal protocol
errors and is usually empty. Every reader here looked only at
remote_errors, so a push refused by a policy
hook reported the machine reason (pre-receive hook declined) and threw
away the only sentence that said why — MEASURED against a real
git receive-pack on 2026-08-05, where stock git printed
remote: policy: this branch is protected by the fixture hook and
gunnar printed nothing.
One accessor rather than two field reads, so a third caller cannot reintroduce the same omission (LAW 5).
Sourcepub fn failure_summary(&self) -> Option<String>
pub fn failure_summary(&self) -> Option<String>
A one-line human summary of why the push failed, or None if it did not.
Trait Implementations§
Source§impl Clone for PushReport
impl Clone for PushReport
Source§fn clone(&self) -> PushReport
fn clone(&self) -> PushReport
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more