@@ -8,13 +8,13 @@ use crate::{entry, EntryRef};
8
8
9
9
/// A function to perform a git-style, unsorted, directory walk.
10
10
///
11
- /// * `root` - the starting point of the walk and a readable directory.
12
- /// - Note that if the path leading to this directory or `root` itself is excluded, it will be provided to [`Delegate::emit()`]
13
- /// without further traversal.
14
- /// - If [`Options::precompose_unicode`] is enabled, this path must be precomposed.
15
- /// - Must be contained in `worktree_root`.
16
11
/// * `worktree_root` - the top-most root of the worktree, which must be a prefix to `root`.
17
12
/// - If [`Options::precompose_unicode`] is enabled, this path must be precomposed.
13
+ /// - The starting point of the traversal (traversal root) is calculated from by doing `worktree_root + pathspec.common_prefix()`.
14
+ /// - Note that if the traversal root leading to this directory or it itself is excluded, it will be provided to [`Delegate::emit()`]
15
+ /// without further traversal.
16
+ /// - If [`Options::precompose_unicode`] is enabled, all involved paths must be precomposed.
17
+ /// - Must be contained in `worktree_root`.
18
18
/// * `ctx` - everything needed to classify the paths seen during the traversal.
19
19
/// * `delegate` - an implementation of [`Delegate`] to control details of the traversal and receive its results.
20
20
///
@@ -36,14 +36,24 @@ use crate::{entry, EntryRef};
36
36
/// or 0.25s for optimal multi-threaded performance, all in the WebKit directory with 388k items to traverse.
37
37
/// Thus, the speedup could easily be 2x or more and thus worth investigating in due time.
38
38
pub fn walk (
39
- root : & Path ,
40
39
worktree_root : & Path ,
41
40
mut ctx : Context < ' _ > ,
42
41
options : Options ,
43
42
delegate : & mut dyn Delegate ,
44
43
) -> Result < Outcome , Error > {
44
+ let root = match ctx. explicit_traversal_root {
45
+ Some ( root) => root. to_owned ( ) ,
46
+ None => ctx
47
+ . pathspec
48
+ . longest_common_directory ( )
49
+ . and_then ( |candidate| {
50
+ let candidate = worktree_root. join ( candidate) ;
51
+ candidate. is_dir ( ) . then_some ( candidate)
52
+ } )
53
+ . unwrap_or_else ( || worktree_root. join ( ctx. pathspec . prefix_directory ( ) ) ) ,
54
+ } ;
45
55
let _span = gix_trace:: coarse!( "walk" , root = ?root, worktree_root = ?worktree_root, options = ?options) ;
46
- let ( mut current, worktree_root_relative) = assure_no_symlink_in_root ( worktree_root, root) ?;
56
+ let ( mut current, worktree_root_relative) = assure_no_symlink_in_root ( worktree_root, & root) ?;
47
57
let mut out = Outcome :: default ( ) ;
48
58
let mut buf = BString :: default ( ) ;
49
59
let root_info = classify:: root (
@@ -73,7 +83,7 @@ pub fn walk(
73
83
74
84
let mut state = readdir:: State :: default ( ) ;
75
85
let _ = readdir:: recursive (
76
- root == worktree_root ,
86
+ true ,
77
87
& mut current,
78
88
& mut buf,
79
89
root_info,
@@ -95,10 +105,9 @@ fn assure_no_symlink_in_root<'root>(
95
105
root : & ' root Path ,
96
106
) -> Result < ( PathBuf , Cow < ' root , Path > ) , Error > {
97
107
let mut current = worktree_root. to_owned ( ) ;
98
- let worktree_relative = root. strip_prefix ( worktree_root) . map_err ( |_| Error :: RootNotInWorktree {
99
- worktree_root : worktree_root. to_owned ( ) ,
100
- root : root. to_owned ( ) ,
101
- } ) ?;
108
+ let worktree_relative = root
109
+ . strip_prefix ( worktree_root)
110
+ . expect ( "BUG: root was created from worktree_root + prefix" ) ;
102
111
let worktree_relative = gix_path:: normalize ( worktree_relative. into ( ) , Path :: new ( "" ) )
103
112
. ok_or ( Error :: NormalizeRoot { root : root. to_owned ( ) } ) ?;
104
113
0 commit comments