GPT 5.6review151a0af4 months agoHistory
93 lines · 3.5 KB · Rust
RawDownload
//! An implementation of the `git` transport layer, abstracting over all of its [versions][Protocol].//!//! Use `client::blocking_io::connect()` or `client::async_io::connect()` to establish a connection.//!//! All git transports are supported, including `ssh`, `git`, `http` and `https`, as well as local repository paths.//! ## Feature Flags#![cfg_attr(    all(doc, feature = "document-features"),    doc = ::document_features::document_features!())]#![cfg_attr(all(doc, feature = "document-features"), feature(doc_cfg))]#![deny(missing_docs)]#![forbid(unsafe_code)] #[cfg(feature = "async-trait")]pub use async_trait;pub use bstr;#[cfg(feature = "futures-io")]pub use futures_io;pub use gix_packetline as packetline; /// The version of the way client and server communicate.#[derive(Default, PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone, Copy)]#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]pub enum Protocol {    /// Version 0 is like V1, but doesn't show capabilities at all, at least when hosted without `git-daemon`.    V0 = 0,    /// Version 1 was the first one conceived, is stateful, and our implementation was seen to cause deadlocks. Prefer V2    V1 = 1,    /// A command-based and stateless protocol with clear semantics, and the one to use assuming the server isn't very old.    /// This is the default.    #[default]    V2 = 2,} /// The kind of service to invoke on the client or the server side.#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone, Copy)]#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]pub enum Service {    /// The service sending packs from a server to the client. Used for fetching pack data.    UploadPack,    /// The service receiving packs produced by the client, who sends a pack to the server.    ReceivePack,} impl Service {    /// Render this instance as a string recognized by the git transport layer, like `git-upload-pack`.    pub fn as_str(&self) -> &'static str {        match self {            Service::ReceivePack => "git-receive-pack",            Service::UploadPack => "git-upload-pack",        }    }     /// Render this instance as a subcommand understood by the `git` program, like `upload-pack`.    pub fn as_git_subcommand(&self) -> &'static str {        self.as_str()            .strip_prefix("git-")            .expect("all services are 'git-*' subcommands")    }} mod traits {    use std::convert::Infallible;     /// An error which can tell whether it's worth retrying to maybe succeed next time.    pub trait IsSpuriousError: std::error::Error {        /// Return `true` if retrying might result in a different outcome due to IO working out differently.        fn is_spurious(&self) -> bool {            false        }    }     impl IsSpuriousError for Infallible {}     impl IsSpuriousError for std::io::Error {        fn is_spurious(&self) -> bool {            // TODO: also include the new special Kinds (currently unstable)            use std::io::ErrorKind::*;            match self.kind() {                Unsupported | WriteZero | InvalidInput | InvalidData | WouldBlock | AlreadyExists                | AddrNotAvailable | NotConnected | Other | PermissionDenied | NotFound => false,                Interrupted | UnexpectedEof | OutOfMemory | TimedOut | BrokenPipe | AddrInUse | ConnectionAborted                | ConnectionReset | ConnectionRefused => true,                _ => false,            }        }    }}pub use traits::IsSpuriousError; ///pub mod client;