summaryrefslogtreecommitdiffstats
path: root/vendor/gix/src/env.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/gix/src/env.rs')
-rw-r--r--vendor/gix/src/env.rs129
1 files changed, 129 insertions, 0 deletions
diff --git a/vendor/gix/src/env.rs b/vendor/gix/src/env.rs
new file mode 100644
index 000000000..4c61ceb4e
--- /dev/null
+++ b/vendor/gix/src/env.rs
@@ -0,0 +1,129 @@
+//! Utilities to handle program arguments and other values of interest.
+use std::ffi::{OsStr, OsString};
+
+use crate::bstr::{BString, ByteVec};
+
+/// Returns the name of the agent for identification towards a remote server as statically known when compiling the crate.
+/// Suitable for both `git` servers and HTTP servers, and used unless configured otherwise.
+///
+/// Note that it's meant to be used in conjunction with [`protocol::agent()`][crate::protocol::agent()] which
+/// prepends `git/`.
+pub fn agent() -> &'static str {
+ concat!("oxide-", env!("CARGO_PKG_VERSION"))
+}
+
+/// Equivalent to `std::env::args_os()`, but with precomposed unicode on MacOS and other apple platforms.
+#[cfg(not(target_vendor = "apple"))]
+pub fn args_os() -> impl Iterator<Item = OsString> {
+ std::env::args_os()
+}
+
+/// Equivalent to `std::env::args_os()`, but with precomposed unicode on MacOS and other apple platforms.
+///
+/// Note that this ignores `core.precomposeUnicode` as gix-config isn't available yet. It's default enabled in modern git though.
+#[cfg(target_vendor = "apple")]
+pub fn args_os() -> impl Iterator<Item = OsString> {
+ use unicode_normalization::UnicodeNormalization;
+ std::env::args_os().map(|arg| match arg.to_str() {
+ Some(arg) => arg.nfc().collect::<String>().into(),
+ None => arg,
+ })
+}
+
+/// Convert the given `input` into a `BString`, useful for usage in `clap`.
+pub fn os_str_to_bstring(input: &OsStr) -> Option<BString> {
+ Vec::from_os_string(input.into()).map(Into::into).ok()
+}
+
+/// Utilities to collate errors of common operations into one error type.
+///
+/// This is useful as this type can present an API to answer common questions, like whether a network request seems to have failed
+/// spuriously or if the underlying repository seems to be corrupted.
+/// Error collation supports all operations, including opening the repository.
+///
+/// ### Usage
+///
+/// The caller may define a function that specifies the result type as `Result<T, gix::env::collate::{operation}::Error>` to collect
+/// errors into a well-known error type which provides an API for simple queries.
+pub mod collate {
+
+ ///
+ pub mod fetch {
+ /// An error which combines all possible errors when opening a repository, finding remotes and using them to fetch.
+ ///
+ /// It can be used to detect if the repository is likely be corrupted in some way, or if the fetch failed spuriously
+ /// and thus can be retried.
+ #[derive(Debug, thiserror::Error)]
+ #[allow(missing_docs)]
+ pub enum Error<E: std::error::Error + Send + Sync + 'static = std::convert::Infallible> {
+ #[error(transparent)]
+ Open(#[from] crate::open::Error),
+ #[error(transparent)]
+ FindExistingReference(#[from] crate::reference::find::existing::Error),
+ #[error(transparent)]
+ RemoteInit(#[from] crate::remote::init::Error),
+ #[error(transparent)]
+ FindExistingRemote(#[from] crate::remote::find::existing::Error),
+ #[error(transparent)]
+ CredentialHelperConfig(#[from] crate::config::credential_helpers::Error),
+ #[cfg(any(feature = "blocking-network-client", feature = "async-network-client"))]
+ #[error(transparent)]
+ Connect(#[from] crate::remote::connect::Error),
+ #[cfg(any(feature = "blocking-network-client", feature = "async-network-client"))]
+ #[error(transparent)]
+ PrepareFetch(#[from] crate::remote::fetch::prepare::Error),
+ #[cfg(any(feature = "blocking-network-client", feature = "async-network-client"))]
+ #[error(transparent)]
+ Fetch(#[from] crate::remote::fetch::Error),
+ #[error(transparent)]
+ Other(E),
+ }
+
+ #[cfg(any(feature = "async-network-client", feature = "blocking-network-client"))]
+ impl<E> crate::protocol::transport::IsSpuriousError for Error<E>
+ where
+ E: std::error::Error + Send + Sync + 'static,
+ {
+ fn is_spurious(&self) -> bool {
+ match self {
+ Error::Open(_)
+ | Error::CredentialHelperConfig(_)
+ | Error::RemoteInit(_)
+ | Error::FindExistingReference(_)
+ | Error::FindExistingRemote(_)
+ | Error::Other(_) => false,
+ Error::Connect(err) => err.is_spurious(),
+ Error::PrepareFetch(err) => err.is_spurious(),
+ Error::Fetch(err) => err.is_spurious(),
+ }
+ }
+ }
+
+ /// Queries
+ impl<E> Error<E>
+ where
+ E: std::error::Error + Send + Sync + 'static,
+ {
+ /// Return true if repository corruption caused the failure.
+ pub fn is_corrupted(&self) -> bool {
+ match self {
+ Error::Open(crate::open::Error::NotARepository { .. } | crate::open::Error::Config(_)) => true,
+ #[cfg(any(feature = "async-network-client", feature = "blocking-network-client"))]
+ Error::PrepareFetch(crate::remote::fetch::prepare::Error::RefMap(
+ // Configuration couldn't be accessed or was incomplete.
+ crate::remote::ref_map::Error::GatherTransportConfig { .. }
+ | crate::remote::ref_map::Error::ConfigureCredentials(_),
+ )) => true,
+ // Maybe the value of the configuration was corrupted, or a file couldn't be removed.
+ #[cfg(any(feature = "async-network-client", feature = "blocking-network-client"))]
+ Error::Fetch(
+ crate::remote::fetch::Error::PackThreads(_)
+ | crate::remote::fetch::Error::PackIndexVersion(_)
+ | crate::remote::fetch::Error::RemovePackKeepFile { .. },
+ ) => true,
+ _ => false,
+ }
+ }
+ }
+ }
+}