1
+ use std:: sync:: atomic:: Ordering ;
1
2
use std:: { io, marker:: PhantomData , path:: Path } ;
2
3
3
4
use bstr:: BStr ;
@@ -11,7 +12,7 @@ use crate::{
11
12
types:: { Error , Options } ,
12
13
Change , VisitEntry ,
13
14
} ,
14
- read,
15
+ read, Pathspec ,
15
16
} ;
16
17
17
18
/// Calculates the changes that need to be applied to an `index` to match the state of the `worktree` and makes them
@@ -24,12 +25,15 @@ use crate::{
24
25
/// Note that this isn't technically quite what this function does as this also provides some additional information,
25
26
/// like whether a file has conflicts, and files that were added with `git add` are shown as a special
26
27
/// changes despite not technically requiring a change to the index since `git add` already added the file to the index.
28
+ #[ allow( clippy:: too_many_arguments) ]
27
29
pub fn index_as_worktree < ' index , T , Find , E > (
28
30
index : & ' index mut gix_index:: State ,
29
31
worktree : & Path ,
30
32
collector : & mut impl VisitEntry < ' index , ContentChange = T > ,
31
33
compare : impl CompareBlobs < Output = T > + Send + Clone ,
32
34
find : Find ,
35
+ progress : & mut dyn gix_features:: progress:: Progress ,
36
+ pathspec : impl Pathspec + Send + Clone ,
33
37
options : Options ,
34
38
) -> Result < ( ) , Error >
35
39
where
@@ -43,14 +47,22 @@ where
43
47
let timestamp = index. timestamp ( ) ;
44
48
index. set_timestamp ( FileTime :: now ( ) ) ;
45
49
let ( chunk_size, thread_limit, _) = gix_features:: parallel:: optimize_chunk_size_and_thread_limit (
46
- 100 ,
50
+ 500 , // just like git
47
51
index. entries ( ) . len ( ) . into ( ) ,
48
52
options. thread_limit ,
49
53
None ,
50
54
) ;
55
+
56
+ let range = index
57
+ . prefixed_entries_range ( pathspec. common_prefix ( ) )
58
+ . unwrap_or ( 0 ..index. entries ( ) . len ( ) ) ;
51
59
let ( entries, path_backing) = index. entries_mut_and_pathbacking ( ) ;
60
+ let entries = & mut entries[ range] ;
61
+ progress. init ( entries. len ( ) . into ( ) , gix_features:: progress:: count ( "files" ) ) ;
62
+ let count = progress. counter ( ) ;
63
+
52
64
in_parallel_if (
53
- || true , // TODO: heuristic: when is parallelization not worth it?
65
+ || true , // TODO: heuristic: when is parallelization not worth it? Git says 500 items per thread, but to 20 threads, we can be more fine-grained though.
54
66
entries. chunks_mut ( chunk_size) ,
55
67
thread_limit,
56
68
{
@@ -65,15 +77,20 @@ where
65
77
worktree,
66
78
options,
67
79
} ,
68
- compare. clone ( ) ,
69
- find. clone ( ) ,
80
+ compare,
81
+ find,
82
+ pathspec,
70
83
)
71
84
}
72
85
} ,
73
- |entries, ( state, diff, find) | {
86
+ |entries, ( state, diff, find, pathspec ) | {
74
87
entries
75
88
. iter_mut ( )
76
- . filter_map ( |entry| state. process ( entry, diff, find) )
89
+ . filter_map ( |entry| {
90
+ let res = state. process ( entry, diff, find, pathspec) ;
91
+ count. fetch_add ( 1 , Ordering :: Relaxed ) ;
92
+ res
93
+ } )
77
94
. collect ( )
78
95
} ,
79
96
ReduceChange {
@@ -101,10 +118,11 @@ impl<'index> State<'_, 'index> {
101
118
entry : & ' index mut gix_index:: Entry ,
102
119
diff : & mut impl CompareBlobs < Output = T > ,
103
120
find : & mut Find ,
121
+ pathspec : & mut impl Pathspec ,
104
122
) -> Option < StatusResult < ' index , T > >
105
123
where
106
124
E : std:: error:: Error + Send + Sync + ' static ,
107
- Find : for < ' a > FnMut ( & gix_hash:: oid , & ' a mut Vec < u8 > ) -> Result < gix_object:: BlobRef < ' a > , E > + Send + Clone ,
125
+ Find : for < ' a > FnMut ( & gix_hash:: oid , & ' a mut Vec < u8 > ) -> Result < gix_object:: BlobRef < ' a > , E > ,
108
126
{
109
127
let conflict = match entry. stage ( ) {
110
128
0 => false ,
@@ -120,6 +138,9 @@ impl<'index> State<'_, 'index> {
120
138
return None ;
121
139
}
122
140
let path = entry. path_in ( self . path_backing ) ;
141
+ if !pathspec. is_included ( path, Some ( false ) ) {
142
+ return None ;
143
+ }
123
144
let status = self . compute_status ( & mut * entry, path, diff, find) ;
124
145
Some ( status. map ( move |status| ( & * entry, path, status, conflict) ) )
125
146
}
@@ -172,7 +193,7 @@ impl<'index> State<'_, 'index> {
172
193
) -> Result < Option < Change < T > > , Error >
173
194
where
174
195
E : std:: error:: Error + Send + Sync + ' static ,
175
- Find : for < ' a > FnMut ( & gix_hash:: oid , & ' a mut Vec < u8 > ) -> Result < gix_object:: BlobRef < ' a > , E > + Send + Clone ,
196
+ Find : for < ' a > FnMut ( & gix_hash:: oid , & ' a mut Vec < u8 > ) -> Result < gix_object:: BlobRef < ' a > , E > ,
176
197
{
177
198
// TODO fs cache
178
199
let worktree_path = gix_path:: try_from_bstr ( git_path) . map_err ( |_| Error :: IllformedUtf8 ) ?;
0 commit comments