History

feat: support for separating lifetimes of entries and path-backing (#301)

This way it should be possible to access paths immutably even while entries are available mutably, assuming we stagger accesses to put mutation of entries last.

Sebastian Thiel committed 4 years ago

Commit 645ed501 parent 514e2f43 files · +35 −2Browse files

Unified · Split

3 files
  1. git-index/src/access.rs +27 −1
  2. git-index/src/entry.rs +4 −0
  3. git-index/src/lib.rs +4 −1
git-index/src/access.rs+27−1
@@ -1,6 +1,6 @@
11 use bstr::{BStr, ByteSlice};
22
3−use crate::{extension, Entry, State, Version};
3+use crate::{extension, Entry, PathStorage, State, Version};
44
55 impl State {
66 pub fn version(&self) -> Version {
@@ -10,6 +10,23 @@ impl State { · 3 unmodified lines
1010 pub fn entries(&self) -> &[Entry] {
1111 &self.entries
1212 }
13+ pub fn take_path_backing(&mut self) -> PathStorage {
14+ assert_eq!(
15+ self.entries.is_empty(),
16+ self.path_backing.is_empty(),
17+ "BUG: cannot take out backing multiple times"
18+ );
19+ std::mem::take(&mut self.path_backing)
20+ }
21+
22+ pub fn return_path_backing(&mut self, backing: PathStorage) {
23+ assert!(
24+ self.path_backing.is_empty(),
25+ "BUG: return path backing only after taking it, once"
26+ );
27+ self.path_backing = backing;
28+ }
29+
1330 pub fn entries_with_paths_by_filter_map<'a, T>(
1431 &'a self,
1532 mut filter_map: impl FnMut(&'a BStr, &Entry) -> Option<T> + 'a,
@@ -29,6 +46,15 @@ impl State { · 13 unmodified lines
2946 (e, path)
3047 })
3148 }
49+ pub fn entries_mut_with_paths_in<'state, 'backing>(
50+ &'state mut self,
51+ backing: &'backing PathStorage,
52+ ) -> impl Iterator<Item = (&'state mut Entry, &'backing BStr)> {
53+ self.entries.iter_mut().map(move |e| {
54+ let path = (&backing[e.path.clone()]).as_bstr();
55+ (e, path)
56+ })
57+ }
3258 pub fn tree(&self) -> Option<&extension::Tree> {
3359 self.tree.as_ref()
3460 }
git-index/src/entry.rs+4−0
@@ -143,6 +143,10 @@ mod access { · 142 unmodified lines
143143 (&state.path_backing[self.path.clone()]).as_bstr()
144144 }
145145
146+ pub fn path_in<'backing>(&self, backing: &'backing crate::PathStorage) -> &'backing BStr {
147+ (backing[self.path.clone()]).as_bstr()
148+ }
149+
146150 pub fn stage(&self) -> u32 {
147151 self.flags.stage()
148152 }
git-index/src/lib.rs+4−1
@@ -51,6 +51,9 @@ pub struct File { · 50 unmodified lines
5151 pub checksum: git_hash::ObjectId,
5252 }
5353
54+/// The type to use and store paths to all entries.
55+pub type PathStorage = Vec<u8>;
56+
5457 /// An in-memory cache of a fully parsed git index file.
5558 ///
5659 /// As opposed to a snapshot, it's meant to be altered and eventually be written back to disk or converted into a tree.
@@ -65,7 +68,7 @@ pub struct State { · 8 unmodified lines
6568 version: Version,
6669 entries: Vec<Entry>,
6770 /// A memory area keeping all index paths, in full length, independently of the index version.
68− path_backing: Vec<u8>,
71+ path_backing: PathStorage,
6972 /// True if one entry in the index has a special marker mode
7073 #[allow(dead_code)]
7174 is_sparse: bool,