summaryrefslogtreecommitdiffstats
path: root/vendor/gix/src/repository/index.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/gix/src/repository/index.rs')
-rw-r--r--vendor/gix/src/repository/index.rs133
1 files changed, 133 insertions, 0 deletions
diff --git a/vendor/gix/src/repository/index.rs b/vendor/gix/src/repository/index.rs
new file mode 100644
index 000000000..a21b138a5
--- /dev/null
+++ b/vendor/gix/src/repository/index.rs
@@ -0,0 +1,133 @@
+use gix_odb::FindExt;
+
+use crate::{config::cache::util::ApplyLeniencyDefault, repository::IndexPersistedOrInMemory, worktree};
+
+/// Index access
+impl crate::Repository {
+ /// Open a new copy of the index file and decode it entirely.
+ ///
+ /// It will use the `index.threads` configuration key to learn how many threads to use.
+ /// Note that it may fail if there is no index.
+ pub fn open_index(&self) -> Result<gix_index::File, worktree::open_index::Error> {
+ let thread_limit = self
+ .config
+ .resolved
+ .string("index", None, "threads")
+ .map(|value| crate::config::tree::Index::THREADS.try_into_index_threads(value))
+ .transpose()
+ .with_lenient_default(self.config.lenient_config)?;
+ let skip_hash = self
+ .config
+ .resolved
+ .boolean("index", None, "skipHash")
+ .map(|res| crate::config::tree::Index::SKIP_HASH.enrich_error(res))
+ .transpose()
+ .with_lenient_default(self.config.lenient_config)?
+ .unwrap_or_default();
+
+ let index = gix_index::File::at(
+ self.index_path(),
+ self.object_hash(),
+ skip_hash,
+ gix_index::decode::Options {
+ thread_limit,
+ min_extension_block_in_bytes_for_threading: 0,
+ expected_checksum: None,
+ },
+ )?;
+
+ Ok(index)
+ }
+
+ /// Return a shared worktree index which is updated automatically if the in-memory snapshot has become stale as the underlying file
+ /// on disk has changed.
+ ///
+ /// The index file is shared across all clones of this repository.
+ pub fn index(&self) -> Result<worktree::Index, worktree::open_index::Error> {
+ self.try_index().and_then(|opt| match opt {
+ Some(index) => Ok(index),
+ None => Err(worktree::open_index::Error::IndexFile(
+ gix_index::file::init::Error::Io(std::io::Error::new(
+ std::io::ErrorKind::NotFound,
+ format!("Could not find index file at {:?} for opening.", self.index_path()),
+ )),
+ )),
+ })
+ }
+
+ /// Return a shared worktree index which is updated automatically if the in-memory snapshot has become stale as the underlying file
+ /// on disk has changed, or `None` if no such file exists.
+ ///
+ /// The index file is shared across all clones of this repository.
+ pub fn try_index(&self) -> Result<Option<worktree::Index>, worktree::open_index::Error> {
+ self.index.recent_snapshot(
+ || self.index_path().metadata().and_then(|m| m.modified()).ok(),
+ || {
+ self.open_index().map(Some).or_else(|err| match err {
+ worktree::open_index::Error::IndexFile(gix_index::file::init::Error::Io(err))
+ if err.kind() == std::io::ErrorKind::NotFound =>
+ {
+ Ok(None)
+ }
+ err => Err(err),
+ })
+ },
+ )
+ }
+
+ /// Open the persisted worktree index or generate it from the current `HEAD^{tree}` to live in-memory only.
+ ///
+ /// Use this method to get an index in any repository, even bare ones that don't have one naturally.
+ ///
+ /// ### Note
+ ///
+ /// The locally stored index is not guaranteed to represent `HEAD^{tree}` if this repository is bare - bare repos
+ /// don't naturally have an index and if an index is present it must have been generated by hand.
+ pub fn index_or_load_from_head(
+ &self,
+ ) -> Result<IndexPersistedOrInMemory, crate::repository::index_or_load_from_head::Error> {
+ Ok(match self.try_index()? {
+ Some(index) => IndexPersistedOrInMemory::Persisted(index),
+ None => {
+ let tree = self.head_commit()?.tree_id()?;
+ IndexPersistedOrInMemory::InMemory(self.index_from_tree(&tree)?)
+ }
+ })
+ }
+
+ /// Create new index-file, which would live at the correct location, in memory from the given `tree`.
+ ///
+ /// Note that this is an expensive operation as it requires recursively traversing the entire tree to unpack it into the index.
+ pub fn index_from_tree(
+ &self,
+ tree: &gix_hash::oid,
+ ) -> Result<gix_index::File, gix_traverse::tree::breadthfirst::Error> {
+ Ok(gix_index::File::from_state(
+ gix_index::State::from_tree(tree, |oid, buf| self.objects.find_tree_iter(oid, buf).ok())?,
+ self.git_dir().join("index"),
+ ))
+ }
+}
+
+impl std::ops::Deref for IndexPersistedOrInMemory {
+ type Target = gix_index::File;
+
+ fn deref(&self) -> &Self::Target {
+ match self {
+ IndexPersistedOrInMemory::Persisted(i) => i,
+ IndexPersistedOrInMemory::InMemory(i) => i,
+ }
+ }
+}
+
+impl IndexPersistedOrInMemory {
+ /// Consume this instance and turn it into an owned index file.
+ ///
+ /// Note that this will cause the persisted index to be cloned, which would happen whenever the repository has a worktree.
+ pub fn into_owned(self) -> gix_index::File {
+ match self {
+ IndexPersistedOrInMemory::Persisted(i) => gix_index::File::clone(&i),
+ IndexPersistedOrInMemory::InMemory(i) => i,
+ }
+ }
+}