Skip to main content

PushReport

Struct PushReport 

Source
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: String

receive-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

Source

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.

Source

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.

Source

pub fn rejected(&self) -> impl Iterator<Item = &RefStatus>

The refs the remote refused.

Source

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).

Source

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

Source§

fn clone(&self) -> PushReport

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for PushReport

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for PushReport

Source§

fn default() -> PushReport

Returns the “default value” for a type. Read more
Source§

impl Eq for PushReport

Source§

impl PartialEq for PushReport

Source§

fn eq(&self, other: &PushReport) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl StructuralPartialEq for PushReport

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.