History

provide a platform for multiple queries at a dir cache level (#301)

This allows to perform work only once while allowing subsequent queries to the cached information, like `is_excluded()` or `attributes()`.

Sebastian Thiel committed 4 years ago

Commit 48be3821 parent dc12f883 files · +29 −20Browse files

Unified · Split

3 files
  1. git-worktree/src/fs/cache.rs +21 −4
  2. git-worktree/src/index/entry.rs +1 −1
  3. git-worktree/tests/worktree/fs/cache.rs +7 −15
git-worktree/src/fs/cache.rs+21−4
@@ -11,6 +11,23 @@ pub enum Mode { · 10 unmodified lines
11 ProvideAttributesAndIgnore,11 ProvideAttributesAndIgnore,
12}12}
13 13
14pub struct Platform<'a> {
15 parent: &'a Cache,
16}
17
18impl<'a> Platform<'a> {
19 /// The full path to `relative` will be returned for use on the file system.
20 pub fn leading_dir(&self) -> &'a Path {
21 self.parent.stack.current()
22 }
23}
24
25impl<'a> std::fmt::Debug for Platform<'a> {
26 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
27 std::fmt::Debug::fmt(&self.leading_dir(), f)
28 }
29}
30
14impl Cache {31impl Cache {
15 /// Create a new instance with `root` being the base for all future paths we handle, assuming it to be valid which includes32 /// Create a new instance with `root` being the base for all future paths we handle, assuming it to be valid which includes
16 /// symbolic links to be included in it as well.33 /// symbolic links to be included in it as well.
@@ -28,12 +45,12 @@ impl Cache { · 11 unmodified lines
28 /// Append the `relative` path to the root directory the cache contains and efficiently create leading directories45 /// Append the `relative` path to the root directory the cache contains and efficiently create leading directories
29 /// unless `mode` indicates `relative` points to a directory itself in which case the entire resulting path is created as directory.46 /// unless `mode` indicates `relative` points to a directory itself in which case the entire resulting path is created as directory.
30 ///47 ///
31 /// The full path to `relative` will be returned for use on the file system.48 /// Provide access to cached information for that `relative` entry via the platform returned.
32 pub fn append_relative_path_assure_leading_dir(49 pub fn at_entry(
33 &mut self,50 &mut self,
34 relative: impl AsRef<Path>,51 relative: impl AsRef<Path>,
35 mode: git_index::entry::Mode,52 mode: git_index::entry::Mode,
36 ) -> std::io::Result<&Path> {53 ) -> std::io::Result<Platform<'_>> {
37 #[cfg(debug_assertions)]54 #[cfg(debug_assertions)]
38 let mkdir_calls = &mut self.test_mkdir_calls;55 let mkdir_calls = &mut self.test_mkdir_calls;
39 let unlink_on_collision = self.unlink_on_collision;56 let unlink_on_collision = self.unlink_on_collision;
@@ -51,7 +68,7 @@ impl Cache { · 11 unmodified lines
51 },68 },
52 |_| {},69 |_| {},
53 )?;70 )?;
54 Ok(self.stack.current())71 Ok(Platform { parent: self })
55 }72 }
56}73}
57 74
git-worktree/src/index/entry.rs+1−1
@@ -37,7 +37,7 @@ where · 36 unmodified lines
37 git_features::path::from_byte_slice(entry_path).map_err(|_| index::checkout::Error::IllformedUtf8 {37 git_features::path::from_byte_slice(entry_path).map_err(|_| index::checkout::Error::IllformedUtf8 {
38 path: entry_path.to_owned(),38 path: entry_path.to_owned(),
39 })?;39 })?;
40 let dest = path_cache.append_relative_path_assure_leading_dir(dest_relative, entry.mode)?;40 let dest = path_cache.at_entry(dest_relative, entry.mode)?.leading_dir();
41 41
42 let object_size = match entry.mode {42 let object_size = match entry.mode {
43 git_index::entry::Mode::FILE | git_index::entry::Mode::FILE_EXECUTABLE => {43 git_index::entry::Mode::FILE | git_index::entry::Mode::FILE_EXECUTABLE => {
git-worktree/tests/worktree/fs/cache.rs+7−15
@@ -15,9 +15,7 @@ mod create_directory { · 14 unmodified lines
15 );15 );
16 assert_eq!(cache.test_mkdir_calls, 0);16 assert_eq!(cache.test_mkdir_calls, 0);
17 17
18 let path = cache18 let path = cache.at_entry("hello", Mode::FILE).unwrap().leading_dir();
19 .append_relative_path_assure_leading_dir("hello", Mode::FILE)
20 .unwrap();
21 assert!(!path.parent().unwrap().exists(), "prefix itself is never created");19 assert!(!path.parent().unwrap().exists(), "prefix itself is never created");
22 assert_eq!(cache.test_mkdir_calls, 0);20 assert_eq!(cache.test_mkdir_calls, 0);
23 }21 }
@@ -34,8 +32,9 @@ mod create_directory { · 10 unmodified lines
34 ("link", Mode::SYMLINK),32 ("link", Mode::SYMLINK),
35 ] {33 ] {
36 let path = cache34 let path = cache
37 .append_relative_path_assure_leading_dir(Path::new("dir").join(name), *mode)35 .at_entry(Path::new("dir").join(name), *mode)
38 .unwrap();36 .unwrap()
37 .leading_dir();
39 assert!(path.parent().unwrap().is_dir(), "dir exists");38 assert!(path.parent().unwrap().is_dir(), "dir exists");
40 }39 }
41 40
@@ -47,9 +46,7 @@ mod create_directory { · 5 unmodified lines
47 let (mut cache, tmp) = new_cache();46 let (mut cache, tmp) = new_cache();
48 std::fs::create_dir(tmp.path().join("dir")).unwrap();47 std::fs::create_dir(tmp.path().join("dir")).unwrap();
49 48
50 let path = cache49 let path = cache.at_entry("dir/file", Mode::FILE).unwrap().leading_dir();
51 .append_relative_path_assure_leading_dir("dir/file", Mode::FILE)
52 .unwrap();
53 assert!(path.parent().unwrap().is_dir(), "directory is still present");50 assert!(path.parent().unwrap().is_dir(), "directory is still present");
54 assert!(!path.exists(), "it won't create the file");51 assert!(!path.exists(), "it won't create the file");
55 assert_eq!(cache.test_mkdir_calls, 1);52 assert_eq!(cache.test_mkdir_calls, 1);
@@ -67,10 +64,7 @@ mod create_directory { · 11 unmodified lines
67 cache.unlink_on_collision = false;64 cache.unlink_on_collision = false;
68 let relative_path = format!("{}/file", dirname);65 let relative_path = format!("{}/file", dirname);
69 assert_eq!(66 assert_eq!(
70 cache67 cache.at_entry(&relative_path, Mode::FILE).unwrap_err().kind(),
71 .append_relative_path_assure_leading_dir(&relative_path, Mode::FILE)
72 .unwrap_err()
73 .kind(),
74 std::io::ErrorKind::AlreadyExists68 std::io::ErrorKind::AlreadyExists
75 );69 );
76 }70 }
@@ -82,9 +76,7 @@ mod create_directory { · 5 unmodified lines
82 for dirname in &["link-to-dir", "file-in-dir"] {76 for dirname in &["link-to-dir", "file-in-dir"] {
83 cache.unlink_on_collision = true;77 cache.unlink_on_collision = true;
84 let relative_path = format!("{}/file", dirname);78 let relative_path = format!("{}/file", dirname);
85 let path = cache79 let path = cache.at_entry(&relative_path, Mode::FILE).unwrap().leading_dir();
86 .append_relative_path_assure_leading_dir(&relative_path, Mode::FILE)
87 .unwrap();
88 assert!(path.parent().unwrap().is_dir(), "directory was forcefully created");80 assert!(path.parent().unwrap().is_dir(), "directory was forcefully created");
89 assert!(!path.exists());81 assert!(!path.exists());
90 }82 }