Skip to content

Commit fb1e614

Browse files
committed
Test symlinks to invalid and reserved Windows targets
These are effectively special cases of dangling symlinks. They should be treated the same as ordinary dangling symlinks, but the error kind isn't NotFound for these, so currently they are not created. The new tests should pass once that is fixed. See #1420.
1 parent d944598 commit fb1e614

File tree

3 files changed

+74
-0
lines changed

3 files changed

+74
-0
lines changed
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#!/usr/bin/env bash
2+
set -eu -o pipefail
3+
4+
git init -q
5+
6+
# On Windows, the target is an invalid file name.
7+
qmarks_oid=$(echo -n "???" | git hash-object -w --stdin)
8+
9+
git update-index --index-info <<EOF
10+
120000 $qmarks_oid dangling-qmarks-symlink
11+
EOF
12+
13+
git commit -m "dangling symlinks with Windows invalid target in index"
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#!/usr/bin/env bash
2+
set -eu -o pipefail
3+
4+
git init -q
5+
6+
# On Windows, the target is a reserved legacy DOS device name.
7+
con_oid=$(echo -n "CON" | git hash-object -w --stdin)
8+
9+
git update-index --index-info <<EOF
10+
120000 $con_oid dangling-con-symlink
11+
EOF
12+
13+
git commit -m "dangling symlinks with Widnows reserved target in index"

gix-worktree-state/tests/state/checkout.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,54 @@ fn dangling_symlinks_can_be_created() -> crate::Result {
291291
Ok(())
292292
}
293293

294+
#[test]
295+
fn dangling_symlink_to_windows_invalid_target_can_be_created() -> crate::Result {
296+
let opts = opts_from_probe();
297+
if !opts.fs.symlink {
298+
eprintln!("Skipping dangling symlink test on filesystem that doesn't support it");
299+
return Ok(());
300+
}
301+
302+
let (_source_tree, destination, _index, outcome) =
303+
checkout_index_in_tmp_dir(opts.clone(), "make_dangling_symlink_to_windows_invalid", None)?;
304+
let worktree_files = dir_structure(&destination);
305+
let worktree_files_stripped = stripped_prefix(&destination, &worktree_files);
306+
307+
assert_eq!(worktree_files_stripped, paths(["dangling-qmarks-symlink"]));
308+
let symlink_path = &worktree_files[0];
309+
assert!(symlink_path
310+
.symlink_metadata()
311+
.expect("dangling symlink is on disk")
312+
.is_symlink());
313+
assert_eq!(std::fs::read_link(symlink_path)?, Path::new("???"));
314+
assert!(outcome.collisions.is_empty());
315+
Ok(())
316+
}
317+
318+
#[test]
319+
fn dangling_symlink_to_windows_reserved_target_can_be_created() -> crate::Result {
320+
let opts = opts_from_probe();
321+
if !opts.fs.symlink {
322+
eprintln!("Skipping dangling symlink test on filesystem that doesn't support it");
323+
return Ok(());
324+
}
325+
326+
let (_source_tree, destination, _index, outcome) =
327+
checkout_index_in_tmp_dir(opts.clone(), "make_dangling_symlink_to_windows_reserved", None)?;
328+
let worktree_files = dir_structure(&destination);
329+
let worktree_files_stripped = stripped_prefix(&destination, &worktree_files);
330+
331+
assert_eq!(worktree_files_stripped, paths(["dangling-con-symlink"]));
332+
let symlink_path = &worktree_files[0];
333+
assert!(symlink_path
334+
.symlink_metadata()
335+
.expect("dangling symlink is on disk")
336+
.is_symlink());
337+
assert_eq!(std::fs::read_link(symlink_path)?, Path::new("CON"));
338+
assert!(outcome.collisions.is_empty());
339+
Ok(())
340+
}
341+
294342
#[test]
295343
fn allow_or_disallow_symlinks() -> crate::Result {
296344
let mut opts = opts_from_probe();

0 commit comments

Comments
 (0)