Package: the Windows redirect test falls back to a directory junction

package_refuses_windows_directory_redirects made its redirect with
symlink_dir. Without Developer Mode or elevation that call fails with
os error 1314 (ERROR_PRIVILEGE_NOT_HELD), which std does not report as
PermissionDenied, so the skip arm did not match and the test panicked.

When symlink_dir fails, the test now makes a directory junction with
mklink /J, which needs no privilege. is_redirect treats a junction as
a redirect, so the test still checks that File > Package refuses the
redirected folder. It skips only when neither can be made. The package
code is unchanged.
This commit is contained in:
dotCooCoo committed 2026-10-24 01:53:04 -07:00
1 parent e651c637f4
commit 333cdf116f
1 file changed
+19 -7
+19 -7
View File
@@ -907,13 +907,12 @@ mod tests {
let outside = base.join("separate");
std::fs::create_dir_all(&outside).unwrap();
let redirected = base.join("Package");
match symlink_dir(&outside, &redirected) {
Ok(()) => {}
Err(e) if e.kind() == std::io::ErrorKind::PermissionDenied => {
let _ = std::fs::remove_dir_all(&base);
return;
}
Err(e) => panic!("could not create directory redirect: {e}"),
// A symbolic link needs Developer Mode or elevation (os error 1314 without them); a
// directory junction needs neither, and `is_redirect` treats both as redirects.
if symlink_dir(&outside, &redirected).is_err() && !make_junction(&outside, &redirected) {
eprintln!("skipped: directory redirects can't be made here");
let _ = std::fs::remove_dir_all(&base);
return;
}
let mut s = Session::new();
s.execute("file.new", &json!({"title": "Annual"})).unwrap();
@@ -922,4 +921,17 @@ mod tests {
std::fs::remove_dir(&redirected).unwrap();
let _ = std::fs::remove_dir_all(&base);
}
/// Makes `link` a directory junction to `target` with `mklink /J`, and reports whether it was made.
#[cfg(windows)]
fn make_junction(target: &Path, link: &Path) -> bool {
use std::os::windows::process::CommandExt;
// Windows paths can't hold `"`, so quoting each one keeps `&` and spaces in it literal for cmd.
std::process::Command::new("cmd")
.args(["/D", "/C"])
.raw_arg(format!("mklink /J \"{}\" \"{}\"", link.display(), target.display()))
.output()
.is_ok_and(|output| output.status.success())
}
}