1 #![allow(missing_docs)]
2 use std
::path
::{Path, PathBuf}
;
4 use bstr
::{BStr, ByteSlice}
;
8 use crate::{fs, fs::PathOidMapping}
;
12 /// Useful for checkout where directories need creation, but we need to access attributes as well.
13 CreateDirectoryAndAttributesStack
{
14 /// If there is a symlink or a file in our path, try to unlink it before creating the directory.
15 unlink_on_collision
: bool
,
18 #[cfg(debug_assertions)]
19 test_mkdir_calls
: usize,
20 /// State to handle attribute information
21 attributes
: state
::Attributes
,
23 /// Used when adding files, requiring access to both attributes and ignore information, for example during add operations.
24 AttributesAndIgnoreStack
{
25 /// State to handle attribute information
26 attributes
: state
::Attributes
,
27 /// State to handle exclusion information
28 ignore
: state
::Ignore
,
30 /// Used when providing worktree status information.
31 IgnoreStack(state
::Ignore
),
34 #[cfg(debug_assertions)]
36 pub fn set_case(&mut self, case
: gix_glob
::pattern
::Case
) {
39 pub fn num_mkdir_calls(&self) -> usize {
41 State
::CreateDirectoryAndAttributesStack { test_mkdir_calls, .. }
=> test_mkdir_calls
,
46 pub fn reset_mkdir_calls(&mut self) {
47 if let State
::CreateDirectoryAndAttributesStack { test_mkdir_calls, .. }
= &mut self.state
{
48 *test_mkdir_calls
= 0;
52 pub fn unlink_on_collision(&mut self, value
: bool
) {
53 if let State
::CreateDirectoryAndAttributesStack
{
54 unlink_on_collision
, ..
57 *unlink_on_collision
= value
;
63 pub struct Platform
<'a
> {
69 /// Create a new instance with `worktree_root` being the base for all future paths we handle, assuming it to be valid which includes
70 /// symbolic links to be included in it as well.
71 /// The `case` configures attribute and exclusion query case sensitivity.
73 worktree_root
: impl Into
<PathBuf
>,
75 case
: gix_glob
::pattern
::Case
,
77 attribute_files_in_index
: Vec
<PathOidMapping
>,
79 let root
= worktree_root
.into();
81 stack
: fs
::Stack
::new(root
),
85 attribute_files_in_index
,
89 /// Append the `relative` path to the root directory the cache contains and efficiently create leading directories
90 /// unless `is_dir` is known (`Some(…)`) then `relative` points to a directory itself in which case the entire resulting
91 /// path is created as directory. If it's not known it is assumed to be a file.
93 /// Provide access to cached information for that `relative` entry via the platform returned.
94 pub fn at_path
<Find
, E
>(
96 relative
: impl AsRef
<Path
>,
99 ) -> std
::io
::Result
<Platform
<'_
>>
101 Find
: for<'a
> FnMut(&oid
, &'a
mut Vec
<u8>) -> Result
<gix_object
::BlobRef
<'a
>, E
>,
102 E
: std
::error
::Error
+ Send
+ Sync
+ '
static,
104 let mut delegate
= platform
::StackDelegate
{
105 state
: &mut self.state
,
107 is_dir
: is_dir
.unwrap_or(false),
108 attribute_files_in_index
: &self.attribute_files_in_index
,
111 self.stack
.make_relative_path_current(relative
, &mut delegate
)?
;
112 Ok(Platform { parent: self, is_dir }
)
115 /// **Panics** on illformed UTF8 in `relative`
117 pub fn at_entry
<'r
, Find
, E
>(
119 relative
: impl Into
<&'r BStr
>,
120 is_dir
: Option
<bool
>,
122 ) -> std
::io
::Result
<Platform
<'_
>>
124 Find
: for<'a
> FnMut(&oid
, &'a
mut Vec
<u8>) -> Result
<gix_object
::BlobRef
<'a
>, E
>,
125 E
: std
::error
::Error
+ Send
+ Sync
+ '
static,
127 let relative
= relative
.into();
128 let relative_path
= gix_path
::from_bstr(relative
);
132 is_dir
.or_else(|| relative
.ends_with_str("/").then_some(true)),
138 /// Return the base path against which all entries or paths should be relative to when querying.
140 /// Note that this path _may_ not be canonicalized.
141 pub fn base(&self) -> &Path
{