Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/edda

crates/gunnar-pack/src/error.rs

//! The crate's error type.

/// The result type used throughout this crate.
pub type Result<T, E = Error> = std::result::Result<T, E>;

/// Everything that can go wrong while writing or indexing a pack.
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum Error {
    /// An object that was asked for is not in the object source.
    ///
    /// For `upload-pack` this is the "not our ref" case and must be reported to the
    /// client rather than producing a short pack.
    #[error("object {id} is not present in the object source")]
    ObjectMissing {
        /// The id that could not be found.
        id: gix_hash::ObjectId,
    },
    /// The object source failed while looking an object up.
    #[error("looking up object {id} failed")]
    Find {
        /// The id whose lookup failed.
        id: gix_hash::ObjectId,
        /// The underlying failure. gix reports object-access failures as
        /// `gix_error` exceptions since gix-object 0.65 (gix 0.88); this is that
        /// exception converted into an `std::error::Error`.
        source: gix_error::Error,
    },
    /// An object id does not use the hash kind the pack is being written with.
    ///
    /// Mixing hash kinds silently is how a sha256 repository ends up being served a
    /// sha1 answer, which yields an empty response and no error at all.
    #[error("object id {id} is {actual:?}, but this pack is being written as {expected:?}")]
    HashKindMismatch {
        /// The offending id.
        id: gix_hash::ObjectId,
        /// The kind the id actually has.
        actual: gix_hash::Kind,
        /// The kind the pack declared.
        expected: gix_hash::Kind,
    },
    /// More objects were handed to a [`PackWriter`](crate::PackWriter) than its header
    /// declared. The count is in the header and cannot be revised afterwards.
    #[error("the pack header declared {declared} objects, cannot write another one")]
    PackFull {
        /// The count written into the pack header.
        declared: u32,
    },
    /// A [`PackWriter`](crate::PackWriter) was finished before its declared number of
    /// objects had been written, which would produce a truncated, invalid pack.
    #[error("the pack header declared {declared} objects but only {written} were written")]
    ObjectCountMismatch {
        /// The count written into the pack header.
        declared: u32,
        /// How many objects actually made it in.
        written: u32,
    },
    /// A pack's object count is a `u32`.
    #[error("a pack can hold at most 4294967295 objects, was given {0}")]
    TooManyObjects(usize),
    /// The pack-copy generator failed while producing entries.
    #[error("failed to produce pack entries")]
    Generate(#[source] gix_error::Error),
    /// An object the pack was to contain could not be located while it was
    /// being generated.
    ///
    /// [`write_pack`](crate::write_pack)'s [`Error::ObjectMissing`] with the id
    /// dropped: gix's generator marks an object it could not find with a null
    /// id, so there is nothing honest left to name. The pack is abandoned
    /// rather than shortened either way.
    #[error("an object vanished from the store while its pack was being generated")]
    ObjectVanished,
    /// Writing pack bytes failed.
    #[error("failed to write pack data")]
    Io(#[from] std::io::Error),
    /// Computing the pack's trailing checksum failed, which for SHA-1 means a
    /// collision attack was detected.
    #[error("failed to compute the pack checksum")]
    Hasher(#[source] gix_error::Error),
    /// The delta encoder refused or failed.
    ///
    /// Chiefly [`gunnar_delta::Error::Refused`], which names the parameter, the
    /// value and the cap it exceeded. A refusal is deliberate and is not
    /// downgraded into a whole-object pack here: a caller that asked for a
    /// window of a million objects should learn that it did not get one.
    #[cfg(feature = "delta")]
    #[error("computing pack deltas failed")]
    Delta(#[from] gunnar_delta::Error),
    /// gix refused to index the pack.
    ///
    /// This is the receive-pack rejection path: a corrupt, truncated or
    /// unresolvable-thin pack lands here.
    #[error("failed to index the pack")]
    Index(#[source] gix_error::Error),
}

// No `#[from]` on the gix-backed variants (2026-10-02, gix 0.88): since
// gix-pack 0.75 / gix-hash 0.27 every one of them reports a `gix_error::Exn`
// (a `gix_error::Error` since gix-pack 0.77 / gix 0.90)
// instead of its own error enum, so the generator, the hasher and the indexer
// would all convert from the SAME type and a blanket `From` could only pick one
// meaning. Each call site names the variant instead.