@@ -42,6 +42,11 @@ fn driver_exe() -> String {
42
42
exe
43
43
}
44
44
45
+ fn assure_is_empty ( dir : impl AsRef < Path > ) -> std:: io:: Result < ( ) > {
46
+ assert_eq ! ( std:: fs:: read_dir( dir) ?. count( ) , 0 ) ;
47
+ Ok ( ( ) )
48
+ }
49
+
45
50
#[ test]
46
51
fn submodules_are_instantiated_as_directories ( ) -> crate :: Result {
47
52
let mut opts = opts_from_probe ( ) ;
@@ -57,11 +62,6 @@ fn submodules_are_instantiated_as_directories() -> crate::Result {
57
62
Ok ( ( ) )
58
63
}
59
64
60
- fn assure_is_empty ( dir : impl AsRef < Path > ) -> std:: io:: Result < ( ) > {
61
- assert_eq ! ( std:: fs:: read_dir( dir) ?. count( ) , 0 ) ;
62
- Ok ( ( ) )
63
- }
64
-
65
65
#[ test]
66
66
fn accidental_writes_through_symlinks_are_prevented_if_overwriting_is_forbidden ( ) {
67
67
let mut opts = opts_from_probe ( ) ;
@@ -125,7 +125,7 @@ fn writes_through_symlinks_are_prevented_even_if_overwriting_is_allowed() {
125
125
if cfg!( windows) { "A-dir\\ a" } else { "A-dir/a" } ,
126
126
"A-file" ,
127
127
"FAKE-DIR" ,
128
- if cfg! ( windows ) { "fake-file" } else { " FAKE-FILE" }
128
+ " FAKE-FILE"
129
129
] ) ,
130
130
) ;
131
131
assert ! ( outcome. collisions. is_empty( ) ) ;
@@ -257,6 +257,30 @@ fn symlinks_become_files_if_disabled() -> crate::Result {
257
257
Ok ( ( ) )
258
258
}
259
259
260
+ #[ test]
261
+ fn dangling_symlinks_can_be_created ( ) -> crate :: Result {
262
+ let opts = opts_from_probe ( ) ;
263
+ if !opts. fs . symlink {
264
+ eprintln ! ( "Skipping dangling symlink test on filesystem that doesn't support it" ) ;
265
+ return Ok ( ( ) ) ;
266
+ }
267
+
268
+ let ( _source_tree, destination, _index, outcome) =
269
+ checkout_index_in_tmp_dir ( opts. clone ( ) , "make_dangling_symlink" ) ?;
270
+ let worktree_files = dir_structure ( & destination) ;
271
+ let worktree_files_stripped = stripped_prefix ( & destination, & worktree_files) ;
272
+
273
+ assert_eq ! ( worktree_files_stripped, paths( [ "dangling" ] ) ) ;
274
+ let symlink_path = & worktree_files[ 0 ] ;
275
+ assert ! ( symlink_path
276
+ . symlink_metadata( )
277
+ . expect( "dangling symlink is on disk" )
278
+ . is_symlink( ) ) ;
279
+ assert_eq ! ( std:: fs:: read_link( symlink_path) ?, Path :: new( "non-existing-target" ) ) ;
280
+ assert ! ( outcome. collisions. is_empty( ) ) ;
281
+ Ok ( ( ) )
282
+ }
283
+
260
284
#[ test]
261
285
fn allow_or_disallow_symlinks ( ) -> crate :: Result {
262
286
let mut opts = opts_from_probe ( ) ;
@@ -303,12 +327,7 @@ fn keep_going_collects_results() {
303
327
. iter( )
304
328
. map( |r| r. path. to_path_lossy( ) . into_owned( ) )
305
329
. collect:: <Vec <_>>( ) ,
306
- paths( if cfg!( unix) {
307
- [ ".gitattributes" , "dir/content" ]
308
- } else {
309
- // not actually a symlink anymore, even though symlinks are supported but git think differently.
310
- [ "dir/content" , "dir/sub-dir/symlink" ]
311
- } )
330
+ paths( [ ".gitattributes" , "dir/content" ] )
312
331
) ;
313
332
}
314
333
@@ -322,11 +341,15 @@ fn keep_going_collects_results() {
322
341
} else {
323
342
assert_eq ! (
324
343
stripped_prefix( & destination, & dir_structure( & destination) ) ,
325
- paths( if cfg!( unix) {
326
- Box :: new( [ "dir/sub-dir/symlink" , "empty" , "executable" ] . into_iter( ) ) as Box <dyn Iterator <Item = & str >>
327
- } else {
328
- Box :: new( [ "empty" , "executable" ] . into_iter( ) )
329
- } ) ,
344
+ paths( [
345
+ if cfg!( unix) {
346
+ "dir/sub-dir/symlink"
347
+ } else {
348
+ "dir\\ sub-dir\\ symlink"
349
+ } ,
350
+ "empty" ,
351
+ "executable" ,
352
+ ] ) ,
330
353
"some files could not be created"
331
354
) ;
332
355
}
@@ -550,8 +573,10 @@ fn probe_gitoxide_dir() -> crate::Result<gix_fs::Capabilities> {
550
573
}
551
574
552
575
fn opts_from_probe ( ) -> gix_worktree_state:: checkout:: Options {
576
+ static CAPABILITIES : Lazy < gix_fs:: Capabilities > = Lazy :: new ( || probe_gitoxide_dir ( ) . unwrap ( ) ) ;
577
+
553
578
gix_worktree_state:: checkout:: Options {
554
- fs : probe_gitoxide_dir ( ) . unwrap ( ) ,
579
+ fs : * CAPABILITIES ,
555
580
destination_is_initially_empty : true ,
556
581
thread_limit : gix_features:: parallel:: num_threads ( None ) . into ( ) ,
557
582
..Default :: default ( )
0 commit comments