Skip to main content

gix_transport/
lib.rs

1//! An implementation of the `git` transport layer, abstracting over all of its [versions][Protocol].
2//!
3//! Use `client::blocking_io::connect()` or `client::async_io::connect()` to establish a connection.
4//!
5//! All git transports are supported, including `ssh`, `git`, `http` and `https`, as well as local repository paths.
6//! ## Feature Flags
7#![cfg_attr(
8    all(doc, feature = "document-features"),
9    doc = ::document_features::document_features!()
10)]
11#![cfg_attr(all(doc, feature = "document-features"), feature(doc_cfg))]
12#![deny(missing_docs, rust_2018_idioms)]
13#![forbid(unsafe_code)]
14
15#[cfg(feature = "async-trait")]
16pub use async_trait;
17pub use bstr;
18#[cfg(feature = "futures-io")]
19pub use futures_io;
20pub use gix_packetline as packetline;
21
22/// The version of the way client and server communicate.
23#[derive(Default, PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone, Copy)]
24#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
25pub enum Protocol {
26    /// Version 0 is like V1, but doesn't show capabilities at all, at least when hosted without `git-daemon`.
27    V0 = 0,
28    /// Version 1 was the first one conceived, is stateful, and our implementation was seen to cause deadlocks. Prefer V2
29    V1 = 1,
30    /// A command-based and stateless protocol with clear semantics, and the one to use assuming the server isn't very old.
31    /// This is the default.
32    #[default]
33    V2 = 2,
34}
35
36/// The kind of service to invoke on the client or the server side.
37#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone, Copy)]
38#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
39pub enum Service {
40    /// The service sending packs from a server to the client. Used for fetching pack data.
41    UploadPack,
42    /// The service receiving packs produced by the client, who sends a pack to the server.
43    ReceivePack,
44}
45
46impl Service {
47    /// Render this instance as string recognized by the git transport layer.
48    pub fn as_str(&self) -> &'static str {
49        match self {
50            Service::ReceivePack => "git-receive-pack",
51            Service::UploadPack => "git-upload-pack",
52        }
53    }
54}
55
56mod traits {
57    use std::convert::Infallible;
58
59    /// An error which can tell whether it's worth retrying to maybe succeed next time.
60    pub trait IsSpuriousError: std::error::Error {
61        /// Return `true` if retrying might result in a different outcome due to IO working out differently.
62        fn is_spurious(&self) -> bool {
63            false
64        }
65    }
66
67    impl IsSpuriousError for Infallible {}
68
69    impl IsSpuriousError for std::io::Error {
70        fn is_spurious(&self) -> bool {
71            // TODO: also include the new special Kinds (currently unstable)
72            use std::io::ErrorKind::*;
73            match self.kind() {
74                Unsupported | WriteZero | InvalidInput | InvalidData | WouldBlock | AlreadyExists
75                | AddrNotAvailable | NotConnected | Other | PermissionDenied | NotFound => false,
76                Interrupted | UnexpectedEof | OutOfMemory | TimedOut | BrokenPipe | AddrInUse | ConnectionAborted
77                | ConnectionReset | ConnectionRefused => true,
78                _ => false,
79            }
80        }
81    }
82}
83pub use traits::IsSpuriousError;
84
85///
86pub mod client;