diff options
Diffstat (limited to 'vendor/gix/src/discover.rs')
-rw-r--r-- | vendor/gix/src/discover.rs | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/vendor/gix/src/discover.rs b/vendor/gix/src/discover.rs new file mode 100644 index 000000000..fa0edfd5f --- /dev/null +++ b/vendor/gix/src/discover.rs @@ -0,0 +1,88 @@ +#![allow(clippy::result_large_err)] +use std::path::Path; + +pub use gix_discover::*; + +use crate::{bstr::BString, ThreadSafeRepository}; + +/// The error returned by [`crate::discover()`]. +#[derive(Debug, thiserror::Error)] +#[allow(missing_docs)] +pub enum Error { + #[error(transparent)] + Discover(#[from] upwards::Error), + #[error(transparent)] + Open(#[from] crate::open::Error), +} + +impl ThreadSafeRepository { + /// Try to open a git repository in `directory` and search upwards through its parents until one is found, + /// using default trust options which matters in case the found repository isn't owned by the current user. + pub fn discover(directory: impl AsRef<Path>) -> Result<Self, Error> { + Self::discover_opts(directory, Default::default(), Default::default()) + } + + /// Try to open a git repository in `directory` and search upwards through its parents until one is found, + /// while applying `options`. Then use the `trust_map` to determine which of our own repository options to use + /// for instantiations. + /// + /// Note that [trust overrides](crate::open::Options::with()) in the `trust_map` are not effective here and we will + /// always override it with the determined trust value. This is a precaution as the API user is unable to actually know + /// if the directory that is discovered can indeed be trusted (or else they'd have to implement the discovery themselves + /// and be sure that no attacker ever gets access to a directory structure. The cost of this is a permission check, which + /// seems acceptable). + pub fn discover_opts( + directory: impl AsRef<Path>, + options: upwards::Options<'_>, + trust_map: gix_sec::trust::Mapping<crate::open::Options>, + ) -> Result<Self, Error> { + let (path, trust) = upwards_opts(directory, options)?; + let (git_dir, worktree_dir) = path.into_repository_and_work_tree_directories(); + let mut options = trust_map.into_value_by_level(trust); + options.git_dir_trust = trust.into(); + options.current_dir = Some(std::env::current_dir().map_err(upwards::Error::CurrentDir)?); + Self::open_from_paths(git_dir, worktree_dir, options).map_err(Into::into) + } + + /// Try to open a git repository directly from the environment. + /// If that fails, discover upwards from `directory` until one is found, + /// while applying discovery options from the environment. + pub fn discover_with_environment_overrides(directory: impl AsRef<Path>) -> Result<Self, Error> { + Self::discover_with_environment_overrides_opts(directory, Default::default(), Default::default()) + } + + /// Try to open a git repository directly from the environment, which reads `GIT_DIR` + /// if it is set. If unset, discover upwards from `directory` until one is found, + /// while applying `options` with overrides from the environment which includes: + /// + /// - `GIT_DISCOVERY_ACROSS_FILESYSTEM` + /// - `GIT_CEILING_DIRECTORIES` + /// + /// Finally, use the `trust_map` to determine which of our own repository options to use + /// based on the trust level of the effective repository directory. + pub fn discover_with_environment_overrides_opts( + directory: impl AsRef<Path>, + mut options: upwards::Options<'_>, + trust_map: gix_sec::trust::Mapping<crate::open::Options>, + ) -> Result<Self, Error> { + fn apply_additional_environment(mut opts: upwards::Options<'_>) -> upwards::Options<'_> { + use crate::bstr::ByteVec; + + if let Some(cross_fs) = std::env::var_os("GIT_DISCOVERY_ACROSS_FILESYSTEM") + .and_then(|v| Vec::from_os_string(v).ok().map(BString::from)) + { + if let Ok(b) = gix_config::Boolean::try_from(cross_fs.as_ref()) { + opts.cross_fs = b.into(); + } + } + opts + } + + if std::env::var_os("GIT_DIR").is_some() { + return Self::open_with_environment_overrides(directory.as_ref(), trust_map).map_err(Error::Open); + } + + options = apply_additional_environment(options.apply_environment()); + Self::discover_opts(directory, options, trust_map) + } +} |