Struct git_worktree::fs::Stack
source · pub struct Stack { /* private fields */ }
Expand description
A stack of path components with the delegation of side-effects as the currently set path changes, component by component.
Implementations§
source§impl Stack
impl Stack
sourcepub fn current(&self) -> &Path
pub fn current(&self) -> &Path
Returns the absolute path the currently set path.
Examples found in repository?
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
pub fn path(&self) -> &'a Path {
self.parent.stack.current()
}
/// See if the currently set entry is excluded as per exclude and git-ignore files.
///
/// # Panics
///
/// If the cache was configured without exclude patterns.
pub fn is_excluded(&self) -> bool {
self.matching_exclude_pattern()
.map_or(false, |m| !m.pattern.is_negative())
}
/// Check all exclude patterns to see if the currently set path matches any of them.
///
/// Note that this pattern might be negated, and means this path in included.
///
/// # Panics
///
/// If the cache was configured without exclude patterns.
pub fn matching_exclude_pattern(&self) -> Option<git_attributes::Match<'_, ()>> {
let ignore = self.parent.state.ignore_or_panic();
let relative_path =
git_path::to_unix_separators_on_windows(git_path::into_bstr(self.parent.stack.current_relative.as_path()));
ignore.matching_exclude_pattern(relative_path.as_bstr(), self.is_dir, self.parent.case)
}
}
impl<'a, 'paths> std::fmt::Debug for Platform<'a, 'paths> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Debug::fmt(&self.path(), f)
}
}
pub struct StackDelegate<'a, 'paths, Find> {
pub state: &'a mut State,
pub buf: &'a mut Vec<u8>,
pub is_dir: bool,
pub attribute_files_in_index: &'a Vec<PathOidMapping<'paths>>,
pub find: Find,
}
impl<'a, 'paths, Find, E> fs::stack::Delegate for StackDelegate<'a, 'paths, Find>
where
Find: for<'b> FnMut(&oid, &'b mut Vec<u8>) -> Result<git_object::BlobRef<'b>, E>,
E: std::error::Error + Send + Sync + 'static,
{
fn push_directory(&mut self, stack: &fs::Stack) -> std::io::Result<()> {
match &mut self.state {
State::CreateDirectoryAndAttributesStack { attributes: _, .. } => {
// TODO: attributes
}
State::AttributesAndIgnoreStack { ignore, attributes: _ } => {
// TODO: attributes
ignore.push_directory(
&stack.root,
&stack.current,
self.buf,
self.attribute_files_in_index,
&mut self.find,
)?
}
State::IgnoreStack(ignore) => ignore.push_directory(
&stack.root,
&stack.current,
self.buf,
self.attribute_files_in_index,
&mut self.find,
)?,
}
Ok(())
}
fn push(&mut self, is_last_component: bool, stack: &fs::Stack) -> std::io::Result<()> {
match &mut self.state {
State::CreateDirectoryAndAttributesStack {
#[cfg(debug_assertions)]
test_mkdir_calls,
unlink_on_collision,
attributes: _,
} => {
#[cfg(debug_assertions)]
{
create_leading_directory(
is_last_component,
stack,
self.is_dir,
test_mkdir_calls,
*unlink_on_collision,
)?
}
#[cfg(not(debug_assertions))]
{
create_leading_directory(is_last_component, stack, self.is_dir, *unlink_on_collision)?
}
}
State::AttributesAndIgnoreStack { .. } | State::IgnoreStack(_) => {}
}
Ok(())
}
fn pop_directory(&mut self) {
match &mut self.state {
State::CreateDirectoryAndAttributesStack { attributes: _, .. } => {
// TODO: attributes
}
State::AttributesAndIgnoreStack { attributes: _, ignore } => {
// TODO: attributes
ignore.pop_directory();
}
State::IgnoreStack(ignore) => {
ignore.pop_directory();
}
}
}
}
fn create_leading_directory(
is_last_component: bool,
stack: &fs::Stack,
is_dir: bool,
#[cfg(debug_assertions)] mkdir_calls: &mut usize,
unlink_on_collision: bool,
) -> std::io::Result<()> {
if is_last_component && !is_dir {
return Ok(());
}
#[cfg(debug_assertions)]
{
*mkdir_calls += 1;
}
match std::fs::create_dir(stack.current()) {
Ok(()) => Ok(()),
Err(err) if err.kind() == std::io::ErrorKind::AlreadyExists => {
let meta = stack.current().symlink_metadata()?;
if meta.is_dir() {
Ok(())
} else if unlink_on_collision {
if meta.file_type().is_symlink() {
crate::os::remove_symlink(stack.current())?;
} else {
std::fs::remove_file(stack.current())?;
}
#[cfg(debug_assertions)]
{
*mkdir_calls += 1;
}
std::fs::create_dir(stack.current())
} else {
Err(err)
}
}
Err(err) => Err(err),
}
}
sourcepub fn current_relative(&self) -> &Path
pub fn current_relative(&self) -> &Path
Returns the currently set path relative to the root()
.
source§impl Stack
impl Stack
sourcepub fn new(root: impl Into<PathBuf>) -> Self
pub fn new(root: impl Into<PathBuf>) -> Self
Create a new instance with root
being the base for all future paths we handle, assuming it to be valid which includes
symbolic links to be included in it as well.
Examples found in repository?
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
pub fn new(
worktree_root: impl Into<PathBuf>,
state: State,
case: git_glob::pattern::Case,
buf: Vec<u8>,
attribute_files_in_index: Vec<PathOidMapping<'paths>>,
) -> Self {
let root = worktree_root.into();
Cache {
stack: fs::Stack::new(root),
state,
case,
buf,
attribute_files_in_index,
}
}
sourcepub fn make_relative_path_current(
&mut self,
relative: impl AsRef<Path>,
delegate: &mut impl Delegate
) -> Result<()>
pub fn make_relative_path_current(
&mut self,
relative: impl AsRef<Path>,
delegate: &mut impl Delegate
) -> Result<()>
Set the current stack to point to the relative
path and call push_comp()
each time a new path component is popped
along with the stacks state for inspection to perform an operation that produces some data.
The full path to relative
will be returned along with the data returned by push_comp.
Note that this only works correctly for the delegate’s push_directory()
and pop_directory()
methods if
relative
paths are terminal, so point to their designated file or directory.
Examples found in repository?
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
pub fn at_path<Find, E>(
&mut self,
relative: impl AsRef<Path>,
is_dir: Option<bool>,
find: Find,
) -> std::io::Result<Platform<'_, 'paths>>
where
Find: for<'a> FnMut(&oid, &'a mut Vec<u8>) -> Result<git_object::BlobRef<'a>, E>,
E: std::error::Error + Send + Sync + 'static,
{
let mut delegate = platform::StackDelegate {
state: &mut self.state,
buf: &mut self.buf,
is_dir: is_dir.unwrap_or(false),
attribute_files_in_index: &self.attribute_files_in_index,
find,
};
self.stack.make_relative_path_current(relative, &mut delegate)?;
Ok(Platform { parent: self, is_dir })
}