1
1
use crate :: bstr:: BStr ;
2
- use crate :: { config, dirwalk, Repository } ;
2
+ use crate :: { config, dirwalk, AttributeStack , Pathspec , Repository } ;
3
3
use std:: path:: PathBuf ;
4
4
5
5
/// The error returned by [dirwalk()](Repository::dirwalk()).
@@ -20,6 +20,19 @@ pub enum Error {
20
20
FilesystemOptions ( #[ from] config:: boolean:: Error ) ,
21
21
}
22
22
23
+ /// The outcome of the [dirwalk()](Repository::dirwalk).
24
+ pub struct Outcome < ' repo > {
25
+ /// The excludes stack used for the dirwalk, for access of `.gitignore` information.
26
+ pub excludes : AttributeStack < ' repo > ,
27
+ /// The pathspecs used to guide the operation,
28
+ pub pathspec : Pathspec < ' repo > ,
29
+ /// The root actually being used for the traversal, and useful to transform the paths returned for the user.
30
+ /// It's always within the [`work-dir`](Repository::work_dir).
31
+ pub traversal_root : PathBuf ,
32
+ /// The actual result of the dirwalk.
33
+ pub dirwalk : gix_dir:: walk:: Outcome ,
34
+ }
35
+
23
36
impl Repository {
24
37
/// Return default options suitable for performing a directory walk on this repository.
25
38
///
@@ -42,54 +55,61 @@ impl Repository {
42
55
patterns : impl IntoIterator < Item = impl AsRef < BStr > > ,
43
56
options : dirwalk:: Options ,
44
57
delegate : & mut dyn gix_dir:: walk:: Delegate ,
45
- ) -> Result < ( gix_dir :: walk :: Outcome , PathBuf ) , Error > {
58
+ ) -> Result < Outcome < ' _ > , Error > {
46
59
let _span = gix_trace:: coarse!( "gix::dirwalk" ) ;
47
60
let workdir = self . work_dir ( ) . ok_or ( Error :: MissinWorkDir ) ?;
48
- let mut excludes = self
49
- . excludes (
50
- index ,
51
- None ,
52
- crate :: worktree :: stack :: state :: ignore :: Source :: WorktreeThenIdMappingIfNotSkipped ,
53
- ) ?
54
- . detach ( ) ;
55
- let ( mut pathspec , mut maybe_attributes ) = self
56
- . pathspec (
57
- patterns ,
58
- true , /* inherit ignore case */
59
- index ,
60
- crate :: worktree :: stack :: state :: attributes :: Source :: WorktreeThenIdMapping ,
61
- ) ?
62
- . into_parts ( ) ;
63
- gix_trace :: debug! ( patterns = ?pathspec . patterns ( ) . map ( |p| p . path ( ) ) . collect :: < Vec <_>> ( ) ) ;
61
+ let mut excludes = self . excludes (
62
+ index ,
63
+ None ,
64
+ crate :: worktree :: stack :: state :: ignore :: Source :: WorktreeThenIdMappingIfNotSkipped ,
65
+ ) ? ;
66
+ let mut pathspec = self . pathspec (
67
+ patterns ,
68
+ true , /* inherit ignore case */
69
+ index ,
70
+ crate :: worktree :: stack :: state :: attributes :: Source :: WorktreeThenIdMapping ,
71
+ ) ? ;
72
+ gix_trace :: debug! (
73
+ longest_prefix = ?pathspec . search . longest_common_directory ( ) ,
74
+ prefix_dir = ?pathspec . search . prefix_directory ( ) ,
75
+ patterns = ?pathspec . search . patterns ( ) . map ( gix_pathspec :: Pattern :: path ) . collect :: < Vec <_>> ( )
76
+ ) ;
64
77
65
78
let git_dir_realpath =
66
79
crate :: path:: realpath_opts ( self . git_dir ( ) , self . current_dir ( ) , crate :: path:: realpath:: MAX_SYMLINKS ) ?;
67
80
let fs_caps = self . filesystem_options ( ) ?;
68
81
let accelerate_lookup = fs_caps. ignore_case . then ( || index. prepare_icase_backing ( ) ) ;
69
- gix_dir:: walk (
82
+ let ( outcome , traversal_root ) = gix_dir:: walk (
70
83
workdir,
71
84
gix_dir:: walk:: Context {
72
85
git_dir_realpath : git_dir_realpath. as_ref ( ) ,
73
86
current_dir : self . current_dir ( ) ,
74
87
index,
75
88
ignore_case_index_lookup : accelerate_lookup. as_ref ( ) ,
76
- pathspec : & mut pathspec,
89
+ pathspec : & mut pathspec. search ,
77
90
pathspec_attributes : & mut |relative_path, case, is_dir, out| {
78
- let stack = maybe_attributes
91
+ let stack = pathspec
92
+ . stack
79
93
. as_mut ( )
80
94
. expect ( "can only be called if attributes are used in patterns" ) ;
81
95
stack
82
96
. set_case ( case)
83
97
. at_entry ( relative_path, Some ( is_dir) , & self . objects )
84
98
. map_or ( false , |platform| platform. matching_attributes ( out) )
85
99
} ,
86
- excludes : Some ( & mut excludes) ,
100
+ excludes : Some ( & mut excludes. inner ) ,
87
101
objects : & self . objects ,
88
- explicit_traversal_root : None ,
102
+ explicit_traversal_root : ( !options . use_prefix ) . then_some ( workdir ) ,
89
103
} ,
90
104
options. into ( ) ,
91
105
delegate,
92
- )
93
- . map_err ( Into :: into)
106
+ ) ?;
107
+
108
+ Ok ( Outcome {
109
+ dirwalk : outcome,
110
+ traversal_root,
111
+ excludes,
112
+ pathspec,
113
+ } )
94
114
}
95
115
}
0 commit comments