pub struct ThreadSafeRepository {
    pub refs: RefStore,
    pub objects: OwnShared<Store>,
    pub work_tree: Option<PathBuf>,
    pub common_dir: Option<PathBuf>,
    /* private fields */
}
Expand description

An instance with access to everything a git repository entails, best imagined as container implementing Sync + Send for most for system resources required to interact with a git repository which are loaded in once the instance is created.

Use this type to reference it in a threaded context for creation the creation of a thread-local Repositories.

Note that this type purposefully isn’t very useful until it is converted into a thread-local repository with to_thread_local(), it’s merely meant to be able to exist in a Sync context.

Fields§

§refs: RefStore

A store for references to point at objects

§objects: OwnShared<Store>

A store for objects that contain data

§work_tree: Option<PathBuf>

The path to the worktree at which to find checked out files

§common_dir: Option<PathBuf>

The path to the common directory if this is a linked worktree repository or it is otherwise set.

Implementations§

Return the kind of repository, either bare or one with a work tree.

Add thread-local state to an easy-to-use thread-local repository for the most convenient API.

Examples found in repository?
src/clone/mod.rs (line 66)
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
    pub fn new<Url, E>(
        url: Url,
        path: impl AsRef<std::path::Path>,
        kind: crate::create::Kind,
        mut create_opts: crate::create::Options,
        open_opts: crate::open::Options,
    ) -> Result<Self, Error>
    where
        Url: TryInto<git_url::Url, Error = E>,
        git_url::parse::Error: From<E>,
    {
        let mut url = url.try_into().map_err(git_url::parse::Error::from)?;
        url.canonicalize().map_err(|err| Error::CanonicalizeUrl {
            url: url.clone(),
            source: err,
        })?;
        create_opts.destination_must_be_empty = true;
        let repo = crate::ThreadSafeRepository::init_opts(path, kind, create_opts, open_opts)?.to_thread_local();
        Ok(PrepareFetch {
            url,
            #[cfg(any(feature = "async-network-client", feature = "blocking-network-client"))]
            fetch_options: Default::default(),
            repo: Some(repo),
            remote_name: None,
            configure_remote: None,
        })
    }
More examples
Hide additional examples
src/init.rs (line 83)
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
    pub fn init_opts(
        directory: impl AsRef<Path>,
        kind: crate::create::Kind,
        create_options: crate::create::Options,
        mut open_options: crate::open::Options,
    ) -> Result<Self, Error> {
        let path = crate::create::into(directory.as_ref(), kind, create_options)?;
        let (git_dir, worktree_dir) = path.into_repository_and_work_tree_directories();
        open_options.git_dir_trust = Some(git_sec::Trust::Full);
        open_options.current_dir = std::env::current_dir()?.into();
        let repo = ThreadSafeRepository::open_from_paths(git_dir, worktree_dir, open_options)?;

        let branch_name = repo
            .config
            .resolved
            .string("init", None, "defaultBranch")
            .unwrap_or_else(|| Cow::Borrowed(DEFAULT_BRANCH_NAME.into()));
        if branch_name.as_ref() != DEFAULT_BRANCH_NAME {
            let sym_ref: FullName =
                format!("refs/heads/{branch_name}")
                    .try_into()
                    .map_err(|err| Error::InvalidBranchName {
                        name: branch_name.into_owned(),
                        source: err,
                    })?;
            let mut repo = repo.to_thread_local();
            let prev_write_reflog = repo.refs.write_reflog;
            repo.refs.write_reflog = WriteReflog::Disable;
            repo.edit_reference(RefEdit {
                change: git_ref::transaction::Change::Update {
                    log: Default::default(),
                    expected: PreviousValue::Any,
                    new: Target::Symbolic(sym_ref),
                },
                name: "HEAD".try_into().expect("valid"),
                deref: false,
            })?;
            repo.refs.write_reflog = prev_write_reflog;
        }

        Ok(repo)
    }

The path to the .git directory itself, or equivalent if this is a bare repository.

Return the path to the repository itself, containing objects, references, configuration, and more.

Synonymous to path().

Examples found in repository?
src/repository/thread_safe.rs (line 9)
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
        pub fn kind(&self) -> Kind {
            match self.work_tree {
                Some(_) => Kind::WorkTree {
                    is_linked: crate::worktree::id(self.git_dir(), self.common_dir.is_some()).is_some(),
                },
                None => Kind::Bare,
            }
        }

        /// Add thread-local state to an easy-to-use thread-local repository for the most convenient API.
        pub fn to_thread_local(&self) -> crate::Repository {
            self.into()
        }
    }
}

mod location {

    impl crate::ThreadSafeRepository {
        /// The path to the `.git` directory itself, or equivalent if this is a bare repository.
        pub fn path(&self) -> &std::path::Path {
            self.git_dir()
        }

        /// Return the path to the repository itself, containing objects, references, configuration, and more.
        ///
        /// Synonymous to [`path()`][crate::ThreadSafeRepository::path()].
        pub fn git_dir(&self) -> &std::path::Path {
            self.refs.git_dir()
        }

        /// Return the path to the working directory if this is not a bare repository.
        pub fn work_dir(&self) -> Option<&std::path::Path> {
            self.work_tree.as_deref()
        }

        /// Return the path to the directory containing all objects.
        pub fn objects_dir(&self) -> &std::path::Path {
            self.objects.path()
        }
    }
}

mod impls {
    impl std::fmt::Debug for crate::ThreadSafeRepository {
        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
            write!(
                f,
                "Repository(git = '{}', working_tree: {:?}",
                self.git_dir().display(),
                self.work_tree
            )
        }
    }

    impl PartialEq<crate::ThreadSafeRepository> for crate::ThreadSafeRepository {
        fn eq(&self, other: &crate::ThreadSafeRepository) -> bool {
            self.git_dir() == other.git_dir() && self.work_tree == other.work_tree
        }

Return the path to the working directory if this is not a bare repository.

Return the path to the directory containing all objects.

Open a git repository at the given path, possibly expanding it to path/.git if path is a work tree dir.

Examples found in repository?
src/lib.rs (line 236)
235
236
237
pub fn open(directory: impl Into<std::path::PathBuf>) -> Result<Repository, open::Error> {
    ThreadSafeRepository::open(directory).map(Into::into)
}

Open a git repository at the given path, possibly expanding it to path/.git if path is a work tree dir, and use options for fine-grained control.

Note that you should use crate::discover() if security should be adjusted by ownership.

Examples found in repository?
src/open/repository.rs (line 41)
40
41
42
    pub fn open(path: impl Into<PathBuf>) -> Result<Self, Error> {
        Self::open_opts(path, Options::default())
    }
More examples
Hide additional examples
src/open/options.rs (line 144)
143
144
145
    pub fn open(self, path: impl Into<PathBuf>) -> Result<ThreadSafeRepository, Error> {
        ThreadSafeRepository::open_opts(path, self)
    }
src/repository/worktree.rs (line 37)
36
37
38
    pub fn main_repo(&self) -> Result<crate::Repository, crate::open::Error> {
        crate::ThreadSafeRepository::open_opts(self.common_dir(), self.options.clone()).map(Into::into)
    }
src/lib.rs (line 241)
240
241
242
pub fn open_opts(directory: impl Into<std::path::PathBuf>, options: open::Options) -> Result<Repository, open::Error> {
    ThreadSafeRepository::open_opts(directory, options).map(Into::into)
}

Try to open a git repository in fallback_directory (can be worktree or .git directory) only if there is no override from of the gitdir using git environment variables.

Use the trust_map to apply options depending in the trust level for directory or the directory it’s overridden with. The .git directory whether given or computed is used for trust checks.

Note that this will read various GIT_* environment variables to check for overrides, and is probably most useful when implementing custom hooks.

Examples found in repository?
src/discover.rs (line 81)
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
    pub fn discover_with_environment_overrides_opts(
        directory: impl AsRef<Path>,
        mut options: upwards::Options<'_>,
        trust_map: git_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) = git_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)
    }

Create a repository with work-tree within directory, creating intermediate directories as needed.

Fails without action if there is already a .git repository inside of directory, but won’t mind if the directory otherwise is non-empty.

Examples found in repository?
src/lib.rs (line 178)
177
178
179
180
181
182
183
184
pub fn init(directory: impl AsRef<std::path::Path>) -> Result<Repository, init::Error> {
    ThreadSafeRepository::init(directory, create::Kind::WithWorktree, create::Options::default()).map(Into::into)
}

/// See [ThreadSafeRepository::init()], but returns a [`Repository`] instead.
pub fn init_bare(directory: impl AsRef<std::path::Path>) -> Result<Repository, init::Error> {
    ThreadSafeRepository::init(directory, create::Kind::Bare, create::Options::default()).map(Into::into)
}

Similar to init, but allows to determine how exactly to open the newly created repository.

Deviation

Instead of naming the default branch master, we name it main unless configured explicitly using the init.defaultBranch configuration key.

Examples found in repository?
src/init.rs (line 49)
42
43
44
45
46
47
48
49
50
    pub fn init(
        directory: impl AsRef<Path>,
        kind: crate::create::Kind,
        options: crate::create::Options,
    ) -> Result<Self, Error> {
        use git_sec::trust::DefaultForLevel;
        let open_options = crate::open::Options::default_for_level(git_sec::Trust::Full);
        Self::init_opts(directory, kind, options, open_options)
    }
More examples
Hide additional examples
src/clone/mod.rs (line 66)
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
    pub fn new<Url, E>(
        url: Url,
        path: impl AsRef<std::path::Path>,
        kind: crate::create::Kind,
        mut create_opts: crate::create::Options,
        open_opts: crate::open::Options,
    ) -> Result<Self, Error>
    where
        Url: TryInto<git_url::Url, Error = E>,
        git_url::parse::Error: From<E>,
    {
        let mut url = url.try_into().map_err(git_url::parse::Error::from)?;
        url.canonicalize().map_err(|err| Error::CanonicalizeUrl {
            url: url.clone(),
            source: err,
        })?;
        create_opts.destination_must_be_empty = true;
        let repo = crate::ThreadSafeRepository::init_opts(path, kind, create_opts, open_opts)?.to_thread_local();
        Ok(PrepareFetch {
            url,
            #[cfg(any(feature = "async-network-client", feature = "blocking-network-client"))]
            fetch_options: Default::default(),
            repo: Some(repo),
            remote_name: None,
            configure_remote: None,
        })
    }

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.

Examples found in repository?
src/lib.rs (line 173)
172
173
174
pub fn discover(directory: impl AsRef<std::path::Path>) -> Result<Repository, discover::Error> {
    ThreadSafeRepository::discover(directory).map(Into::into)
}

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 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).

Examples found in repository?
src/discover.rs (line 21)
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
    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: git_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: git_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) = git_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)
    }

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.

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.

Examples found in repository?
src/discover.rs (line 50)
49
50
51
    pub fn discover_with_environment_overrides(directory: impl AsRef<Path>) -> Result<Self, Error> {
        Self::discover_with_environment_overrides_opts(directory, Default::default(), Default::default())
    }

Trait Implementations§

Formats the value using the given formatter. Read more
Converts to this type from the input type.
Converts to this type from the input type.
Converts to this type from the input type.
This method tests for self and other values to be equal, and is used by ==.
This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

The alignment of pointer.
The type for initializers.
Initializes a with the given initializer. Read more
Dereferences the given pointer. Read more
Mutably dereferences the given pointer. Read more
Drops the object pointed to by the given pointer. Read more
Should always be Self
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.