@@ -4276,3 +4276,115 @@ fn type_mismatch_ignore_case_clash_file_is_dir() {
4276
4276
If there was no special handling for this, it would have found the file (`d` in the index, icase), which would have been wrong."
4277
4277
) ;
4278
4278
}
4279
+
4280
+ #[ test]
4281
+ fn top_level_slash_with_negations ( ) -> crate :: Result {
4282
+ for repo_name in [ "slash-in-root-and-negated" , "star-in-root-and-negated" ] {
4283
+ let root = fixture ( repo_name) ;
4284
+ let ( ( out, _root) , entries) = collect ( & root, None , |keep, ctx| walk ( & root, ctx, options_emit_all ( ) , keep) ) ;
4285
+ assert_eq ! (
4286
+ out,
4287
+ walk:: Outcome {
4288
+ read_dir_calls: 0 ,
4289
+ returned_entries: entries. len( ) ,
4290
+ seen_entries: 1 ,
4291
+ }
4292
+ ) ;
4293
+ assert_eq ! (
4294
+ entries,
4295
+ & [ entry( "" , Ignored ( Expendable ) , Directory ) ] ,
4296
+ "This is wrong - the root can never be listed"
4297
+ ) ;
4298
+
4299
+ let ( ( out, _root) , entries) = collect ( & root, None , |keep, ctx| {
4300
+ walk (
4301
+ & root,
4302
+ ctx,
4303
+ walk:: Options {
4304
+ for_deletion : Some ( ForDeletionMode :: FindRepositoriesInIgnoredDirectories ) ,
4305
+ emit_tracked : false ,
4306
+ ..options_emit_all ( )
4307
+ } ,
4308
+ keep,
4309
+ )
4310
+ } ) ;
4311
+ assert_eq ! (
4312
+ out,
4313
+ walk:: Outcome {
4314
+ read_dir_calls: 2 ,
4315
+ returned_entries: entries. len( ) ,
4316
+ seen_entries: 5 ,
4317
+ }
4318
+ ) ;
4319
+ assert_eq ! (
4320
+ entries,
4321
+ & [
4322
+ entry_nokind( ".git" , Ignored ( Expendable ) )
4323
+ . with_property( DotGit )
4324
+ . with_match( Always ) ,
4325
+ entry( "file" , Ignored ( Expendable ) , File )
4326
+ ] ,
4327
+ "This is still wrong, but consistent within what it should do.\
4328
+ Top-level `.git` should always be Pruned, even if ignored.\
4329
+ Except for `file` which should be untracked."
4330
+ ) ;
4331
+ }
4332
+ Ok ( ( ) )
4333
+ }
4334
+
4335
+ #[ test]
4336
+ fn subdir_slash_with_negations ( ) -> crate :: Result {
4337
+ for repo_name in [ "slash-in-subdir-and-negated" , "star-in-subdir-and-negated" ] {
4338
+ let root = fixture ( repo_name) ;
4339
+ let ( ( out, _root) , entries) = collect ( & root, None , |keep, ctx| walk ( & root, ctx, options_emit_all ( ) , keep) ) ;
4340
+ assert_eq ! (
4341
+ out,
4342
+ walk:: Outcome {
4343
+ read_dir_calls: 3 ,
4344
+ returned_entries: entries. len( ) ,
4345
+ seen_entries: 5 ,
4346
+ }
4347
+ ) ;
4348
+ assert_eq ! (
4349
+ entries,
4350
+ & [
4351
+ entry_nokind( ".git" , Pruned ) . with_property( DotGit ) . with_match( Always ) ,
4352
+ entry( "sub/.github/workflow.yml" , Tracked , File ) ,
4353
+ entry( "sub/.gitignore" , Tracked , File ) ,
4354
+ entry( "sub/file" , Untracked , File ) ,
4355
+ entry( "sub/readme.md" , Tracked , File ) ,
4356
+ ] ,
4357
+ "subdirectory matches work as expected, also with a `/` which has no bearing."
4358
+ ) ;
4359
+
4360
+ let ( ( out, _root) , entries) = collect ( & root, None , |keep, ctx| {
4361
+ walk (
4362
+ & root,
4363
+ ctx,
4364
+ walk:: Options {
4365
+ for_deletion : Some ( ForDeletionMode :: FindRepositoriesInIgnoredDirectories ) ,
4366
+ emit_tracked : false ,
4367
+ ..options_emit_all ( )
4368
+ } ,
4369
+ keep,
4370
+ )
4371
+ } ) ;
4372
+ assert_eq ! (
4373
+ out,
4374
+ walk:: Outcome {
4375
+ read_dir_calls: 3 ,
4376
+ returned_entries: entries. len( ) ,
4377
+ seen_entries: 5 ,
4378
+ }
4379
+ ) ;
4380
+ assert_eq ! (
4381
+ entries,
4382
+ & [
4383
+ entry_nokind( ".git" , Pruned ) . with_property( DotGit ) . with_match( Always ) ,
4384
+ entry( "sub/file" , Untracked , File )
4385
+ ] ,
4386
+ "This is expected, and the `.git` top-level is pruned."
4387
+ ) ;
4388
+ }
4389
+ Ok ( ( ) )
4390
+ }
0 commit comments