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§

Returns the top-level path of the stack.

Examples found in repository?
src/fs/cache/mod.rs (line 142)
141
142
143
    pub fn base(&self) -> &Path {
        self.stack.root()
    }

Returns the absolute path the currently set path.

Examples found in repository?
src/fs/cache/platform.rs (line 17)
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),
    }
}

Returns the currently set path relative to the root().

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?
src/fs/cache/mod.rs (line 81)
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,
        }
    }

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?
src/fs/cache/mod.rs (line 111)
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 })
    }

Trait Implementations§

Returns a copy of the value. Read more
Performs copy-assignment from source. Read more

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

The resulting type after obtaining ownership.
Creates owned data from borrowed data, usually by cloning. Read more
Uses borrowed data to replace owned data, usually by cloning. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.