History

wire everything up to have all data where it needs to be, but… (#301)

proper error handling needs more bounds on error E which can be done but really is a lot of typing. Nothing to be done here except for doing it I guess.

Sebastian Thiel committed 4 years ago

Commit 34d0d5c1 parent 883d78d6 files · +100 −37Browse files

Showing the changes to git-worktree/src (5 of 6 files). Show all

Unified · Split

5 files
  1. git-worktree/src/fs/cache/mod.rs +11 −4
  2. git-worktree/src/fs/cache/platform.rs +13 −2
  3. git-worktree/src/fs/cache/state.rs +34 −9
  4. git-worktree/src/fs/mod.rs +2 −2
  5. git-worktree/src/index/entry.rs +1 −1
git-worktree/src/fs/cache/mod.rs+11−4
@@ -1,6 +1,7 @@
1use super::Cache;1use super::Cache;
2use crate::fs;2use crate::fs;
3use crate::fs::PathIdMapping;3use crate::fs::PathOidMapping;
4use git_hash::oid;
4use std::path::{Path, PathBuf};5use std::path::{Path, PathBuf};
5 6
6#[derive(Clone)]7#[derive(Clone)]
@@ -66,7 +67,7 @@ impl<'paths> Cache<'paths> { · 59 unmodified lines
66 state: State,67 state: State,
67 case: git_glob::pattern::Case,68 case: git_glob::pattern::Case,
68 buf: Vec<u8>,69 buf: Vec<u8>,
69 attribute_files_in_index: Vec<PathIdMapping<'paths>>,70 attribute_files_in_index: Vec<PathOidMapping<'paths>>,
70 ) -> Self {71 ) -> Self {
71 let root = worktree_root.into();72 let root = worktree_root.into();
72 Cache {73 Cache {
@@ -83,15 +84,21 @@ impl<'paths> Cache<'paths> { · 10 unmodified lines
83 /// path is created as directory. If it's not known it is assumed to be a file.84 /// path is created as directory. If it's not known it is assumed to be a file.
84 ///85 ///
85 /// Provide access to cached information for that `relative` entry via the platform returned.86 /// Provide access to cached information for that `relative` entry via the platform returned.
86 pub fn at_entry(87 pub fn at_entry<Find, E>(
87 &mut self,88 &mut self,
88 relative: impl AsRef<Path>,89 relative: impl AsRef<Path>,
89 is_dir: Option<bool>,90 is_dir: Option<bool>,
90 ) -> std::io::Result<Platform<'_, 'paths>> {91 find: Find,
92 ) -> std::io::Result<Platform<'_, 'paths>>
93 where
94 Find: for<'a> FnMut(&oid, &'a mut Vec<u8>) -> Result<git_object::BlobRef<'a>, E>,
95 {
91 let mut platform = platform::StackDelegate {96 let mut platform = platform::StackDelegate {
92 state: &mut self.state,97 state: &mut self.state,
93 buf: &mut self.buf,98 buf: &mut self.buf,
94 is_dir,99 is_dir,
100 attribute_files_in_index: &self.attribute_files_in_index,
101 find,
95 };102 };
96 self.stack.make_relative_path_current(relative, &mut platform)?;103 self.stack.make_relative_path_current(relative, &mut platform)?;
97 Ok(Platform { parent: self, is_dir })104 Ok(Platform { parent: self, is_dir })
git-worktree/src/fs/cache/platform.rs+13−2
@@ -1,5 +1,7 @@
1use crate::fs;1use crate::fs;
2use crate::fs::cache::{Platform, State};2use crate::fs::cache::{Platform, State};
3use crate::fs::PathOidMapping;
4use git_hash::oid;
3use std::path::Path;5use std::path::Path;
4 6
5impl<'a, 'paths> Platform<'a, 'paths> {7impl<'a, 'paths> Platform<'a, 'paths> {
@@ -43,13 +45,18 @@ impl<'a, 'paths> std::fmt::Debug for Platform<'a, 'paths> { · 37 unmodified lines
43 }45 }
44}46}
45 47
46pub struct StackDelegate<'a> {48pub struct StackDelegate<'a, 'paths, Find> {
47 pub state: &'a mut State,49 pub state: &'a mut State,
48 pub buf: &'a mut Vec<u8>,50 pub buf: &'a mut Vec<u8>,
49 pub is_dir: Option<bool>,51 pub is_dir: Option<bool>,
52 pub attribute_files_in_index: &'a Vec<PathOidMapping<'paths>>,
53 pub find: Find,
50}54}
51 55
52impl<'a> fs::stack::Delegate for StackDelegate<'a> {56impl<'a, 'paths, Find, E> fs::stack::Delegate for StackDelegate<'a, 'paths, Find>
57where
58 Find: for<'b> FnMut(&oid, &'b mut Vec<u8>) -> Result<git_object::BlobRef<'b>, E>,
59{
53 fn push(&mut self, is_last_component: bool, stack: &fs::Stack) -> std::io::Result<()> {60 fn push(&mut self, is_last_component: bool, stack: &fs::Stack) -> std::io::Result<()> {
54 match &mut self.state {61 match &mut self.state {
55 State::CreateDirectoryAndAttributesStack {62 State::CreateDirectoryAndAttributesStack {
@@ -77,11 +84,15 @@ impl<'a> fs::stack::Delegate for StackDelegate<'a> { · 21 unmodified lines
77 &stack.root,84 &stack.root,
78 stack.current.parent().expect("component was just pushed"),85 stack.current.parent().expect("component was just pushed"),
79 self.buf,86 self.buf,
87 self.attribute_files_in_index,
88 &mut self.find,
80 )?,89 )?,
81 State::IgnoreStack(ignore) => ignore.push(90 State::IgnoreStack(ignore) => ignore.push(
82 &stack.root,91 &stack.root,
83 stack.current.parent().expect("component was just pushed"),92 stack.current.parent().expect("component was just pushed"),
84 self.buf,93 self.buf,
94 self.attribute_files_in_index,
95 &mut self.find,
85 )?,96 )?,
86 }97 }
87 Ok(())98 Ok(())
git-worktree/src/fs/cache/state.rs+34−9
@@ -1,7 +1,8 @@
1use crate::fs::cache::{state, State};1use crate::fs::cache::{state, State};
2use crate::fs::PathIdMapping;2use crate::fs::PathOidMapping;
3use bstr::{BStr, BString, ByteSlice};3use bstr::{BStr, BString, ByteSlice};
4use git_glob::pattern::Case;4use git_glob::pattern::Case;
5use git_hash::oid;
5use std::path::Path;6use std::path::Path;
6 7
7type AttributeMatchGroup = git_attributes::MatchGroup<git_attributes::Attributes>;8type AttributeMatchGroup = git_attributes::MatchGroup<git_attributes::Attributes>;
@@ -51,16 +52,40 @@ impl Ignore { · 43 unmodified lines
51 }52 }
52 }53 }
53 54
54 pub fn push(&mut self, root: &Path, dir: &Path, buf: &mut Vec<u8>) -> std::io::Result<()> {55 pub fn push<Find, E>(
55 let follow_symlinks = true;56 &mut self,
57 root: &Path,
58 dir: &Path,
59 buf: &mut Vec<u8>,
60 attribute_files_in_index: &Vec<PathOidMapping<'_>>,
61 _find: Find,
62 ) -> std::io::Result<()>
63 where
64 Find: for<'b> FnMut(&oid, &'b mut Vec<u8>) -> Result<git_object::BlobRef<'b>, E>,
65 {
66 let ignore_path = git_features::path::convert::to_unix_separators(
67 git_features::path::into_bytes_or_panic_on_windows(dir.join(".gitignore")),
68 );
69 let ignore_file_in_index = attribute_files_in_index.binary_search_by(|t| t.0.cmp(ignore_path.as_bstr()));
70 let ignore_path = git_features::path::from_byte_vec_or_panic_on_windows(ignore_path);
71 let follow_symlinks = ignore_file_in_index.is_err();
56 if !self72 if !self
57 .stack73 .stack
58 .add_patterns_file(dir.join(".gitignore"), follow_symlinks, Some(root), buf)?74 .add_patterns_file(ignore_path, follow_symlinks, Some(root), buf)?
59 {75 {
60 // Need one stack level per component so push and pop matches.76 match ignore_file_in_index {
61 self.stack.patterns.push(Default::default());77 Ok(_idx) => {
78 // let ignore_blob = find(&attribute_files_in_index[0].1, buf)
79 // .map_err(|err| std::io::Error::new(std::io::ErrorKind::Other, err))?;
80 // self.stack.add_patterns_buffer(ignore_blob.data);
81 todo!()
82 }
83 Err(_) => {
84 // Need one stack level per component so push and pop matches.
85 self.stack.patterns.push(Default::default())
86 }
87 }
62 }88 }
63 // TODO: from index
64 Ok(())89 Ok(())
65 }90 }
66}91}
@@ -108,12 +133,12 @@ impl State { · 41 unmodified lines
108 /// - ignores entries which aren't blobs133 /// - ignores entries which aren't blobs
109 /// - ignores ignore entries which are not skip-worktree134 /// - ignores ignore entries which are not skip-worktree
110 /// - within merges, picks 'our' stage both for ignore and attribute files.135 /// - within merges, picks 'our' stage both for ignore and attribute files.
111 pub(crate) fn build_attribute_list<'paths>(136 pub fn build_attribute_list<'paths>(
112 &self,137 &self,
113 index: &git_index::State,138 index: &git_index::State,
114 paths: &'paths git_index::PathStorage,139 paths: &'paths git_index::PathStorage,
115 case: git_glob::pattern::Case,140 case: git_glob::pattern::Case,
116 ) -> Vec<PathIdMapping<'paths>> {141 ) -> Vec<PathOidMapping<'paths>> {
117 let a1_backing;142 let a1_backing;
118 let a2_backing;143 let a2_backing;
119 let names = match self {144 let names = match self {
git-worktree/src/fs/mod.rs+2−2
@@ -65,10 +65,10 @@ pub struct Cache<'paths> { · 64 unmodified lines
65 /// If case folding should happen when looking up attributes or exclusions.65 /// If case folding should happen when looking up attributes or exclusions.
66 case: git_glob::pattern::Case,66 case: git_glob::pattern::Case,
67 /// A lookup table for object ids to read from in some situations when looking up attributes or exclusions.67 /// A lookup table for object ids to read from in some situations when looking up attributes or exclusions.
68 attribute_files_in_index: Vec<PathIdMapping<'paths>>,68 attribute_files_in_index: Vec<PathOidMapping<'paths>>,
69}69}
70 70
71pub(crate) type PathIdMapping<'paths> = (&'paths BStr, git_hash::ObjectId);71pub(crate) type PathOidMapping<'paths> = (&'paths BStr, git_hash::ObjectId);
72 72
73///73///
74pub mod cache;74pub mod cache;
git-worktree/src/index/entry.rs+1−1
@@ -38,7 +38,7 @@ where · 37 unmodified lines
38 path: entry_path.to_owned(),38 path: entry_path.to_owned(),
39 })?;39 })?;
40 let is_dir = Some(entry.mode == git_index::entry::Mode::COMMIT || entry.mode == git_index::entry::Mode::DIR);40 let is_dir = Some(entry.mode == git_index::entry::Mode::COMMIT || entry.mode == git_index::entry::Mode::DIR);
41 let dest = path_cache.at_entry(dest_relative, is_dir)?.path();41 let dest = path_cache.at_entry(dest_relative, is_dir, &mut *find)?.path();
42 42
43 let object_size = match entry.mode {43 let object_size = match entry.mode {
44 git_index::entry::Mode::FILE | git_index::entry::Mode::FILE_EXECUTABLE => {44 git_index::entry::Mode::FILE | git_index::entry::Mode::FILE_EXECUTABLE => {