Skip to content

Commit

Permalink
Test symlinks to invalid and reserved Windows targets
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
EliahKagan committed Jun 25, 2024
1 parent d944598 commit 4b3c9b2
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/usr/bin/env bash
set -eu -o pipefail

git init -q

# On Windows, the target is an invalid file name.
qmarks_oid=$(echo -n "???" | git hash-object -w --stdin)

git update-index --index-info <<EOF
120000 $qmarks_oid dangling-qmarks-symlink
EOF

git commit -m "dangling symlinks with Windows invalid target in index"
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/usr/bin/env bash
set -eu -o pipefail

git init -q

# On Windows, the target is a reserved legacy DOS device name.
con_oid=$(echo -n "CON" | git hash-object -w --stdin)

git update-index --index-info <<EOF
120000 $con_oid dangling-con-symlink
EOF

git commit -m "dangling symlinks with Widnows reserved target in index"
48 changes: 48 additions & 0 deletions gix-worktree-state/tests/state/checkout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,54 @@ fn dangling_symlinks_can_be_created() -> crate::Result {
Ok(())
}

#[test]
fn dangling_symlink_to_windows_invalid_target_can_be_created() -> crate::Result {
let opts = opts_from_probe();
if !opts.fs.symlink {
eprintln!("Skipping dangling symlink test on filesystem that doesn't support it");
return Ok(());
}

let (_source_tree, destination, _index, outcome) =
checkout_index_in_tmp_dir(opts.clone(), "make_dangling_symlink_to_windows_invalid", None)?;
let worktree_files = dir_structure(&destination);
let worktree_files_stripped = stripped_prefix(&destination, &worktree_files);

assert_eq!(worktree_files_stripped, paths(["dangling-qmarks-symlink"]));
let symlink_path = &worktree_files[0];
assert!(symlink_path
.symlink_metadata()
.expect("dangling symlink is on disk")
.is_symlink());
assert_eq!(std::fs::read_link(symlink_path)?, Path::new("???"));
assert!(outcome.collisions.is_empty());
Ok(())
}

#[test]
fn dangling_symlink_to_windows_reserved_target_can_be_created() -> crate::Result {
let opts = opts_from_probe();
if !opts.fs.symlink {
eprintln!("Skipping dangling symlink test on filesystem that doesn't support it");
return Ok(());
}

let (_source_tree, destination, _index, outcome) =
checkout_index_in_tmp_dir(opts.clone(), "make_dangling_symlink_to_windows_reserved", None)?;
let worktree_files = dir_structure(&destination);
let worktree_files_stripped = stripped_prefix(&destination, &worktree_files);

assert_eq!(worktree_files_stripped, paths(["dangling-con-symlink"]));
let symlink_path = &worktree_files[0];
assert!(symlink_path
.symlink_metadata()
.expect("dangling symlink is on disk")
.is_symlink());
assert_eq!(std::fs::read_link(symlink_path)?, Path::new("CON"));
assert!(outcome.collisions.is_empty());
Ok(())
}

#[test]
fn allow_or_disallow_symlinks() -> crate::Result {
let mut opts = opts_from_probe();
Expand Down

0 comments on commit 4b3c9b2

Please sign in to comment.