@@ -120,17 +120,21 @@ impl<'cfg> PathSource<'cfg> {
120
120
}
121
121
let ignore_include = include_builder. build ( ) ?;
122
122
123
- let ignore_should_package = |relative_path : & Path | -> CargoResult < bool > {
123
+ let ignore_should_package = |relative_path : & Path , is_dir : bool | -> CargoResult < bool > {
124
124
// "Include" and "exclude" options are mutually exclusive.
125
125
if no_include_option {
126
- match ignore_exclude
127
- . matched_path_or_any_parents ( relative_path, /* is_dir */ false )
128
- {
126
+ match ignore_exclude. matched_path_or_any_parents ( relative_path, is_dir) {
129
127
Match :: None => Ok ( true ) ,
130
128
Match :: Ignore ( _) => Ok ( false ) ,
131
129
Match :: Whitelist ( _) => Ok ( true ) ,
132
130
}
133
131
} else {
132
+ if is_dir {
133
+ // Generally, include directives don't list every
134
+ // directory (nor should they!). Just skip all directory
135
+ // checks, and only check files.
136
+ return Ok ( true ) ;
137
+ }
134
138
match ignore_include
135
139
. matched_path_or_any_parents ( relative_path, /* is_dir */ false )
136
140
{
@@ -141,7 +145,7 @@ impl<'cfg> PathSource<'cfg> {
141
145
}
142
146
} ;
143
147
144
- let mut filter = |path : & Path | -> CargoResult < bool > {
148
+ let mut filter = |path : & Path , is_dir : bool | -> CargoResult < bool > {
145
149
let relative_path = path. strip_prefix ( root) ?;
146
150
147
151
let rel = relative_path. as_os_str ( ) ;
@@ -151,7 +155,7 @@ impl<'cfg> PathSource<'cfg> {
151
155
return Ok ( true ) ;
152
156
}
153
157
154
- ignore_should_package ( relative_path)
158
+ ignore_should_package ( relative_path, is_dir )
155
159
} ;
156
160
157
161
// Attempt Git-prepopulate only if no `include` (see rust-lang/cargo#4135).
@@ -171,7 +175,7 @@ impl<'cfg> PathSource<'cfg> {
171
175
& self ,
172
176
pkg : & Package ,
173
177
root : & Path ,
174
- filter : & mut dyn FnMut ( & Path ) -> CargoResult < bool > ,
178
+ filter : & mut dyn FnMut ( & Path , bool ) -> CargoResult < bool > ,
175
179
) -> Option < CargoResult < Vec < PathBuf > > > {
176
180
// If this package is in a Git repository, then we really do want to
177
181
// query the Git repository as it takes into account items such as
@@ -214,7 +218,7 @@ impl<'cfg> PathSource<'cfg> {
214
218
& self ,
215
219
pkg : & Package ,
216
220
repo : & git2:: Repository ,
217
- filter : & mut dyn FnMut ( & Path ) -> CargoResult < bool > ,
221
+ filter : & mut dyn FnMut ( & Path , bool ) -> CargoResult < bool > ,
218
222
) -> CargoResult < Vec < PathBuf > > {
219
223
warn ! ( "list_files_git {}" , pkg. package_id( ) ) ;
220
224
let index = repo. index ( ) ?;
@@ -298,7 +302,10 @@ impl<'cfg> PathSource<'cfg> {
298
302
continue ;
299
303
}
300
304
301
- if is_dir. unwrap_or_else ( || file_path. is_dir ( ) ) {
305
+ // `is_dir` is None for symlinks. The `unwrap` checks if the
306
+ // symlink points to a directory.
307
+ let is_dir = is_dir. unwrap_or_else ( || file_path. is_dir ( ) ) ;
308
+ if is_dir {
302
309
warn ! ( " found submodule {}" , file_path. display( ) ) ;
303
310
let rel = file_path. strip_prefix ( root) ?;
304
311
let rel = rel. to_str ( ) . ok_or_else ( || {
@@ -316,7 +323,8 @@ impl<'cfg> PathSource<'cfg> {
316
323
PathSource :: walk ( & file_path, & mut ret, false , filter) ?;
317
324
}
318
325
}
319
- } else if ( * filter) ( & file_path) ? {
326
+ } else if ( * filter) ( & file_path, is_dir) ? {
327
+ assert ! ( !is_dir) ;
320
328
// We found a file!
321
329
warn ! ( " found {}" , file_path. display( ) ) ;
322
330
ret. push ( file_path) ;
@@ -347,29 +355,28 @@ impl<'cfg> PathSource<'cfg> {
347
355
fn list_files_walk_except_dot_files_and_dirs (
348
356
& self ,
349
357
pkg : & Package ,
350
- filter : & mut dyn FnMut ( & Path ) -> CargoResult < bool > ,
358
+ filter : & mut dyn FnMut ( & Path , bool ) -> CargoResult < bool > ,
351
359
) -> CargoResult < Vec < PathBuf > > {
352
360
let root = pkg. root ( ) ;
353
361
let mut exclude_dot_files_dir_builder = GitignoreBuilder :: new ( root) ;
354
362
exclude_dot_files_dir_builder. add_line ( None , ".*" ) ?;
355
363
let ignore_dot_files_and_dirs = exclude_dot_files_dir_builder. build ( ) ?;
356
364
357
- let mut filter_ignore_dot_files_and_dirs = |path : & Path | -> CargoResult < bool > {
358
- let relative_path = path. strip_prefix ( root) ?;
359
- match ignore_dot_files_and_dirs
360
- . matched_path_or_any_parents ( relative_path, /* is_dir */ false )
361
- {
362
- Match :: Ignore ( _) => Ok ( false ) ,
363
- _ => filter ( path) ,
364
- }
365
- } ;
365
+ let mut filter_ignore_dot_files_and_dirs =
366
+ |path : & Path , is_dir : bool | -> CargoResult < bool > {
367
+ let relative_path = path. strip_prefix ( root) ?;
368
+ match ignore_dot_files_and_dirs. matched_path_or_any_parents ( relative_path, is_dir) {
369
+ Match :: Ignore ( _) => Ok ( false ) ,
370
+ _ => filter ( path, is_dir) ,
371
+ }
372
+ } ;
366
373
self . list_files_walk ( pkg, & mut filter_ignore_dot_files_and_dirs)
367
374
}
368
375
369
376
fn list_files_walk (
370
377
& self ,
371
378
pkg : & Package ,
372
- filter : & mut dyn FnMut ( & Path ) -> CargoResult < bool > ,
379
+ filter : & mut dyn FnMut ( & Path , bool ) -> CargoResult < bool > ,
373
380
) -> CargoResult < Vec < PathBuf > > {
374
381
let mut ret = Vec :: new ( ) ;
375
382
PathSource :: walk ( pkg. root ( ) , & mut ret, true , filter) ?;
@@ -380,12 +387,14 @@ impl<'cfg> PathSource<'cfg> {
380
387
path : & Path ,
381
388
ret : & mut Vec < PathBuf > ,
382
389
is_root : bool ,
383
- filter : & mut dyn FnMut ( & Path ) -> CargoResult < bool > ,
390
+ filter : & mut dyn FnMut ( & Path , bool ) -> CargoResult < bool > ,
384
391
) -> CargoResult < ( ) > {
385
- if !path. is_dir ( ) {
386
- if ( * filter) ( path) ? {
387
- ret. push ( path. to_path_buf ( ) ) ;
388
- }
392
+ let is_dir = path. is_dir ( ) ;
393
+ if !is_root && !( * filter) ( path, is_dir) ? {
394
+ return Ok ( ( ) ) ;
395
+ }
396
+ if !is_dir {
397
+ ret. push ( path. to_path_buf ( ) ) ;
389
398
return Ok ( ( ) ) ;
390
399
}
391
400
// Don't recurse into any sub-packages that we have.
0 commit comments