]> git.proxmox.com Git - rustc.git/blame - vendor/gix/src/repository/index.rs
New upstream version 1.76.0+dfsg1
[rustc.git] / vendor / gix / src / repository / index.rs
CommitLineData
781aab86
FG
1use crate::{config::cache::util::ApplyLeniencyDefault, repository::IndexPersistedOrInMemory, worktree};
2
3/// Index access
4impl crate::Repository {
5 /// Open a new copy of the index file and decode it entirely.
6 ///
7 /// It will use the `index.threads` configuration key to learn how many threads to use.
8 /// Note that it may fail if there is no index.
9 pub fn open_index(&self) -> Result<gix_index::File, worktree::open_index::Error> {
10 let thread_limit = self
11 .config
12 .resolved
13 .string("index", None, "threads")
14 .map(|value| crate::config::tree::Index::THREADS.try_into_index_threads(value))
15 .transpose()
16 .with_lenient_default(self.config.lenient_config)?;
17 let skip_hash = self
18 .config
19 .resolved
20 .boolean("index", None, "skipHash")
21 .map(|res| crate::config::tree::Index::SKIP_HASH.enrich_error(res))
22 .transpose()
23 .with_lenient_default(self.config.lenient_config)?
24 .unwrap_or_default();
25
26 let index = gix_index::File::at(
27 self.index_path(),
28 self.object_hash(),
29 skip_hash,
30 gix_index::decode::Options {
31 thread_limit,
32 min_extension_block_in_bytes_for_threading: 0,
33 expected_checksum: None,
34 },
35 )?;
36
37 Ok(index)
38 }
39
40 /// Return a shared worktree index which is updated automatically if the in-memory snapshot has become stale as the underlying file
41 /// on disk has changed.
42 ///
43 /// The index file is shared across all clones of this repository.
44 pub fn index(&self) -> Result<worktree::Index, worktree::open_index::Error> {
45 self.try_index().and_then(|opt| match opt {
46 Some(index) => Ok(index),
47 None => Err(worktree::open_index::Error::IndexFile(
48 gix_index::file::init::Error::Io(std::io::Error::new(
49 std::io::ErrorKind::NotFound,
50 format!("Could not find index file at {:?} for opening.", self.index_path()),
51 )),
52 )),
53 })
54 }
55
ed00b5ec
FG
56 /// Return the shared worktree index if present, or return a new empty one which has an association to the place where the index would be.
57 pub fn index_or_empty(&self) -> Result<worktree::Index, worktree::open_index::Error> {
58 Ok(self.try_index()?.unwrap_or_else(|| {
59 worktree::Index::new(gix_fs::FileSnapshot::new(gix_index::File::from_state(
60 gix_index::State::new(self.object_hash()),
61 self.index_path(),
62 )))
63 }))
64 }
65
781aab86
FG
66 /// Return a shared worktree index which is updated automatically if the in-memory snapshot has become stale as the underlying file
67 /// on disk has changed, or `None` if no such file exists.
68 ///
69 /// The index file is shared across all clones of this repository.
70 pub fn try_index(&self) -> Result<Option<worktree::Index>, worktree::open_index::Error> {
71 self.index.recent_snapshot(
72 || self.index_path().metadata().and_then(|m| m.modified()).ok(),
73 || {
74 self.open_index().map(Some).or_else(|err| match err {
75 worktree::open_index::Error::IndexFile(gix_index::file::init::Error::Io(err))
76 if err.kind() == std::io::ErrorKind::NotFound =>
77 {
78 Ok(None)
79 }
80 err => Err(err),
81 })
82 },
83 )
84 }
85
86 /// Open the persisted worktree index or generate it from the current `HEAD^{tree}` to live in-memory only.
87 ///
88 /// Use this method to get an index in any repository, even bare ones that don't have one naturally.
89 ///
90 /// ### Note
91 ///
92 /// The locally stored index is not guaranteed to represent `HEAD^{tree}` if this repository is bare - bare repos
93 /// don't naturally have an index and if an index is present it must have been generated by hand.
94 pub fn index_or_load_from_head(
95 &self,
96 ) -> Result<IndexPersistedOrInMemory, crate::repository::index_or_load_from_head::Error> {
97 Ok(match self.try_index()? {
98 Some(index) => IndexPersistedOrInMemory::Persisted(index),
99 None => {
100 let tree = self.head_commit()?.tree_id()?;
101 IndexPersistedOrInMemory::InMemory(self.index_from_tree(&tree)?)
102 }
103 })
104 }
105
106 /// Create new index-file, which would live at the correct location, in memory from the given `tree`.
107 ///
108 /// Note that this is an expensive operation as it requires recursively traversing the entire tree to unpack it into the index.
109 pub fn index_from_tree(
110 &self,
111 tree: &gix_hash::oid,
112 ) -> Result<gix_index::File, gix_traverse::tree::breadthfirst::Error> {
113 Ok(gix_index::File::from_state(
4b012472 114 gix_index::State::from_tree(tree, &self.objects)?,
781aab86
FG
115 self.git_dir().join("index"),
116 ))
117 }
118}
119
120impl std::ops::Deref for IndexPersistedOrInMemory {
121 type Target = gix_index::File;
122
123 fn deref(&self) -> &Self::Target {
124 match self {
125 IndexPersistedOrInMemory::Persisted(i) => i,
126 IndexPersistedOrInMemory::InMemory(i) => i,
127 }
128 }
129}
130
131impl IndexPersistedOrInMemory {
132 /// Consume this instance and turn it into an owned index file.
133 ///
134 /// Note that this will cause the persisted index to be cloned, which would happen whenever the repository has a worktree.
135 pub fn into_owned(self) -> gix_index::File {
136 match self {
137 IndexPersistedOrInMemory::Persisted(i) => gix_index::File::clone(&i),
138 IndexPersistedOrInMemory::InMemory(i) => i,
139 }
140 }
141}