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 @@
1use bstr::{BStr, ByteSlice};1use bstr::{BStr, ByteSlice};
2 2
3use crate::{extension, Entry, State, Version};3use crate::{extension, Entry, PathStorage, State, Version};
4 4
5impl State {5impl State {
6 pub fn version(&self) -> Version {6 pub fn version(&self) -> Version {
@@ -10,6 +10,23 @@ impl State { · 3 unmodified lines
10 pub fn entries(&self) -> &[Entry] {10 pub fn entries(&self) -> &[Entry] {
11 &self.entries11 &self.entries
12 }12 }
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
13 pub fn entries_with_paths_by_filter_map<'a, T>(30 pub fn entries_with_paths_by_filter_map<'a, T>(
14 &'a self,31 &'a self,
15 mut filter_map: impl FnMut(&'a BStr, &Entry) -> Option<T> + 'a,32 mut filter_map: impl FnMut(&'a BStr, &Entry) -> Option<T> + 'a,
@@ -29,6 +46,15 @@ impl State { · 13 unmodified lines
29 (e, path)46 (e, path)
30 })47 })
31 }48 }
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 }
32 pub fn tree(&self) -> Option<&extension::Tree> {58 pub fn tree(&self) -> Option<&extension::Tree> {
33 self.tree.as_ref()59 self.tree.as_ref()
34 }60 }
git-index/src/entry.rs+4−0
@@ -143,6 +143,10 @@ mod access { · 142 unmodified lines
143 (&state.path_backing[self.path.clone()]).as_bstr()143 (&state.path_backing[self.path.clone()]).as_bstr()
144 }144 }
145 145
146 pub fn path_in<'backing>(&self, backing: &'backing crate::PathStorage) -> &'backing BStr {
147 (backing[self.path.clone()]).as_bstr()
148 }
149
146 pub fn stage(&self) -> u32 {150 pub fn stage(&self) -> u32 {
147 self.flags.stage()151 self.flags.stage()
148 }152 }
git-index/src/lib.rs+4−1
@@ -51,6 +51,9 @@ pub struct File { · 50 unmodified lines
51 pub checksum: git_hash::ObjectId,51 pub checksum: git_hash::ObjectId,
52}52}
53 53
54/// The type to use and store paths to all entries.
55pub type PathStorage = Vec<u8>;
56
54/// An in-memory cache of a fully parsed git index file.57/// An in-memory cache of a fully parsed git index file.
55///58///
56/// As opposed to a snapshot, it's meant to be altered and eventually be written back to disk or converted into a tree.59/// 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
65 version: Version,68 version: Version,
66 entries: Vec<Entry>,69 entries: Vec<Entry>,
67 /// A memory area keeping all index paths, in full length, independently of the index version.70 /// A memory area keeping all index paths, in full length, independently of the index version.
68 path_backing: Vec<u8>,71 path_backing: PathStorage,
69 /// True if one entry in the index has a special marker mode72 /// True if one entry in the index has a special marker mode
70 #[allow(dead_code)]73 #[allow(dead_code)]
71 is_sparse: bool,74 is_sparse: bool,