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.
Showing the changes to git-worktree/src (5 of 6 files). Show all
Unified · Split
| @@ -1,6 +1,7 @@ | ||
| 1 | 1 | use super::Cache; |
| 2 | 2 | use crate::fs; |
| 3 | −use crate::fs::PathIdMapping; | |
| 3 | +use crate::fs::PathOidMapping; | |
| 4 | +use git_hash::oid; | |
| 4 | 5 | use std::path::{Path, PathBuf}; |
| 5 | 6 | |
| 6 | 7 | #[derive(Clone)] |
| @@ -66,7 +67,7 @@ impl<'paths> Cache<'paths> { · 59 unmodified lines | ||
| 66 | 67 | state: State, |
| 67 | 68 | case: git_glob::pattern::Case, |
| 68 | 69 | buf: Vec<u8>, |
| 69 | − attribute_files_in_index: Vec<PathIdMapping<'paths>>, | |
| 70 | + attribute_files_in_index: Vec<PathOidMapping<'paths>>, | |
| 70 | 71 | ) -> Self { |
| 71 | 72 | let root = worktree_root.into(); |
| 72 | 73 | Cache { |
| @@ -83,15 +84,21 @@ impl<'paths> Cache<'paths> { · 10 unmodified lines | ||
| 83 | 84 | /// path is created as directory. If it's not known it is assumed to be a file. |
| 84 | 85 | /// |
| 85 | 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 | 88 | &mut self, |
| 88 | 89 | relative: impl AsRef<Path>, |
| 89 | 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 | 96 | let mut platform = platform::StackDelegate { |
| 92 | 97 | state: &mut self.state, |
| 93 | 98 | buf: &mut self.buf, |
| 94 | 99 | is_dir, |
| 100 | + attribute_files_in_index: &self.attribute_files_in_index, | |
| 101 | + find, | |
| 95 | 102 | }; |
| 96 | 103 | self.stack.make_relative_path_current(relative, &mut platform)?; |
| 97 | 104 | Ok(Platform { parent: self, is_dir }) |
| @@ -1,5 +1,7 @@ | ||
| 1 | 1 | use crate::fs; |
| 2 | 2 | use crate::fs::cache::{Platform, State}; |
| 3 | +use crate::fs::PathOidMapping; | |
| 4 | +use git_hash::oid; | |
| 3 | 5 | use std::path::Path; |
| 4 | 6 | |
| 5 | 7 | impl<'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 | |
| 46 | −pub struct StackDelegate<'a> { | |
| 48 | +pub struct StackDelegate<'a, 'paths, Find> { | |
| 47 | 49 | pub state: &'a mut State, |
| 48 | 50 | pub buf: &'a mut Vec<u8>, |
| 49 | 51 | pub is_dir: Option<bool>, |
| 52 | + pub attribute_files_in_index: &'a Vec<PathOidMapping<'paths>>, | |
| 53 | + pub find: Find, | |
| 50 | 54 | } |
| 51 | 55 | |
| 52 | −impl<'a> fs::stack::Delegate for StackDelegate<'a> { | |
| 56 | +impl<'a, 'paths, Find, E> fs::stack::Delegate for StackDelegate<'a, 'paths, Find> | |
| 57 | +where | |
| 58 | + Find: for<'b> FnMut(&oid, &'b mut Vec<u8>) -> Result<git_object::BlobRef<'b>, E>, | |
| 59 | +{ | |
| 53 | 60 | fn push(&mut self, is_last_component: bool, stack: &fs::Stack) -> std::io::Result<()> { |
| 54 | 61 | match &mut self.state { |
| 55 | 62 | State::CreateDirectoryAndAttributesStack { |
| @@ -77,11 +84,15 @@ impl<'a> fs::stack::Delegate for StackDelegate<'a> { · 21 unmodified lines | ||
| 77 | 84 | &stack.root, |
| 78 | 85 | stack.current.parent().expect("component was just pushed"), |
| 79 | 86 | self.buf, |
| 87 | + self.attribute_files_in_index, | |
| 88 | + &mut self.find, | |
| 80 | 89 | )?, |
| 81 | 90 | State::IgnoreStack(ignore) => ignore.push( |
| 82 | 91 | &stack.root, |
| 83 | 92 | stack.current.parent().expect("component was just pushed"), |
| 84 | 93 | self.buf, |
| 94 | + self.attribute_files_in_index, | |
| 95 | + &mut self.find, | |
| 85 | 96 | )?, |
| 86 | 97 | } |
| 87 | 98 | Ok(()) |
| @@ -1,7 +1,8 @@ | ||
| 1 | 1 | use crate::fs::cache::{state, State}; |
| 2 | −use crate::fs::PathIdMapping; | |
| 2 | +use crate::fs::PathOidMapping; | |
| 3 | 3 | use bstr::{BStr, BString, ByteSlice}; |
| 4 | 4 | use git_glob::pattern::Case; |
| 5 | +use git_hash::oid; | |
| 5 | 6 | use std::path::Path; |
| 6 | 7 | |
| 7 | 8 | type 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 | − let follow_symlinks = true; | |
| 55 | + pub fn push<Find, E>( | |
| 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 | 72 | if !self |
| 57 | 73 | .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. | |
| 61 | − self.stack.patterns.push(Default::default()); | |
| 76 | + match ignore_file_in_index { | |
| 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 | 89 | Ok(()) |
| 65 | 90 | } |
| 66 | 91 | } |
| @@ -108,12 +133,12 @@ impl State { · 41 unmodified lines | ||
| 108 | 133 | /// - ignores entries which aren't blobs |
| 109 | 134 | /// - ignores ignore entries which are not skip-worktree |
| 110 | 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 | 137 | &self, |
| 113 | 138 | index: &git_index::State, |
| 114 | 139 | paths: &'paths git_index::PathStorage, |
| 115 | 140 | case: git_glob::pattern::Case, |
| 116 | − ) -> Vec<PathIdMapping<'paths>> { | |
| 141 | + ) -> Vec<PathOidMapping<'paths>> { | |
| 117 | 142 | let a1_backing; |
| 118 | 143 | let a2_backing; |
| 119 | 144 | let names = match self { |
| @@ -65,10 +65,10 @@ pub struct Cache<'paths> { · 64 unmodified lines | ||
| 65 | 65 | /// If case folding should happen when looking up attributes or exclusions. |
| 66 | 66 | case: git_glob::pattern::Case, |
| 67 | 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 | |
| 71 | −pub(crate) type PathIdMapping<'paths> = (&'paths BStr, git_hash::ObjectId); | |
| 71 | +pub(crate) type PathOidMapping<'paths> = (&'paths BStr, git_hash::ObjectId); | |
| 72 | 72 | |
| 73 | 73 | /// |
| 74 | 74 | pub mod cache; |
| @@ -38,7 +38,7 @@ where · 37 unmodified lines | ||
| 38 | 38 | path: entry_path.to_owned(), |
| 39 | 39 | })?; |
| 40 | 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 | 43 | let object_size = match entry.mode { |
| 44 | 44 | git_index::entry::Mode::FILE | git_index::entry::Mode::FILE_EXECUTABLE => { |