]> git.proxmox.com Git - rustc.git/blame - vendor/gix/src/discover.rs
New upstream version 1.74.1+dfsg1
[rustc.git] / vendor / gix / src / discover.rs
CommitLineData
0a29b90c
FG
1#![allow(clippy::result_large_err)]
2use std::path::Path;
3
4pub use gix_discover::*;
781aab86 5use gix_macros::momo;
0a29b90c
FG
6
7use crate::{bstr::BString, ThreadSafeRepository};
8
9/// The error returned by [`crate::discover()`].
10#[derive(Debug, thiserror::Error)]
11#[allow(missing_docs)]
12pub enum Error {
13 #[error(transparent)]
14 Discover(#[from] upwards::Error),
15 #[error(transparent)]
16 Open(#[from] crate::open::Error),
17}
18
19impl ThreadSafeRepository {
20 /// Try to open a git repository in `directory` and search upwards through its parents until one is found,
21 /// using default trust options which matters in case the found repository isn't owned by the current user.
22 pub fn discover(directory: impl AsRef<Path>) -> Result<Self, Error> {
23 Self::discover_opts(directory, Default::default(), Default::default())
24 }
25
26 /// Try to open a git repository in `directory` and search upwards through its parents until one is found,
27 /// while applying `options`. Then use the `trust_map` to determine which of our own repository options to use
28 /// for instantiations.
29 ///
30 /// Note that [trust overrides](crate::open::Options::with()) in the `trust_map` are not effective here and we will
31 /// always override it with the determined trust value. This is a precaution as the API user is unable to actually know
32 /// if the directory that is discovered can indeed be trusted (or else they'd have to implement the discovery themselves
33 /// and be sure that no attacker ever gets access to a directory structure. The cost of this is a permission check, which
34 /// seems acceptable).
781aab86 35 #[momo]
0a29b90c
FG
36 pub fn discover_opts(
37 directory: impl AsRef<Path>,
38 options: upwards::Options<'_>,
39 trust_map: gix_sec::trust::Mapping<crate::open::Options>,
40 ) -> Result<Self, Error> {
781aab86
FG
41 let _span = gix_trace::coarse!("ThreadSafeRepository::discover()");
42 let (path, trust) = upwards_opts(directory.as_ref(), options)?;
0a29b90c
FG
43 let (git_dir, worktree_dir) = path.into_repository_and_work_tree_directories();
44 let mut options = trust_map.into_value_by_level(trust);
45 options.git_dir_trust = trust.into();
46 options.current_dir = Some(std::env::current_dir().map_err(upwards::Error::CurrentDir)?);
47 Self::open_from_paths(git_dir, worktree_dir, options).map_err(Into::into)
48 }
49
50 /// Try to open a git repository directly from the environment.
51 /// If that fails, discover upwards from `directory` until one is found,
52 /// while applying discovery options from the environment.
53 pub fn discover_with_environment_overrides(directory: impl AsRef<Path>) -> Result<Self, Error> {
54 Self::discover_with_environment_overrides_opts(directory, Default::default(), Default::default())
55 }
56
57 /// Try to open a git repository directly from the environment, which reads `GIT_DIR`
58 /// if it is set. If unset, discover upwards from `directory` until one is found,
59 /// while applying `options` with overrides from the environment which includes:
60 ///
61 /// - `GIT_DISCOVERY_ACROSS_FILESYSTEM`
62 /// - `GIT_CEILING_DIRECTORIES`
63 ///
64 /// Finally, use the `trust_map` to determine which of our own repository options to use
65 /// based on the trust level of the effective repository directory.
781aab86 66 #[momo]
0a29b90c
FG
67 pub fn discover_with_environment_overrides_opts(
68 directory: impl AsRef<Path>,
69 mut options: upwards::Options<'_>,
70 trust_map: gix_sec::trust::Mapping<crate::open::Options>,
71 ) -> Result<Self, Error> {
72 fn apply_additional_environment(mut opts: upwards::Options<'_>) -> upwards::Options<'_> {
73 use crate::bstr::ByteVec;
74
75 if let Some(cross_fs) = std::env::var_os("GIT_DISCOVERY_ACROSS_FILESYSTEM")
76 .and_then(|v| Vec::from_os_string(v).ok().map(BString::from))
77 {
78 if let Ok(b) = gix_config::Boolean::try_from(cross_fs.as_ref()) {
79 opts.cross_fs = b.into();
80 }
81 }
82 opts
83 }
84
85 if std::env::var_os("GIT_DIR").is_some() {
86 return Self::open_with_environment_overrides(directory.as_ref(), trust_map).map_err(Error::Open);
87 }
88
89 options = apply_additional_environment(options.apply_environment());
90 Self::discover_opts(directory, options, trust_map)
91 }
92}