git-ents.gitmain
⌘K
foforge
commit db5955e
fix: gate unix-only permission and symlink calls in the toolchain registry

set_mode and unix::fs::symlink do not exist on Windows, breaking Windows CI compilation. Both call sites now go through small unix/windows-gated helpers; marking a file executable is a no-op on Windows, and symlinks use the windows-specific APIs there instead.

Assisted-by: Claude:claude-sonnet-5

Joseph D. Carpinelli · 1 month ago

Reviews

No reviews of this commit yet — record a verdict below.

Start a review

verdict

crates/git-ents/src/registry.rs @@ -8,7 +8,6 @@ //! a toolchain. use std::fs; -use std::os::unix::fs::PermissionsExt as _; use std::path::{Path, PathBuf}; use std::process::Command; @@ -408,12 +407,26 @@ let dest = staging.join("sccache"); fs::copy(&binary, &dest) .map_err(|error| format!("could not copy {}: {error}", binary.display()))?; - let mut perms = fs::metadata(&dest) - .map_err(|error| format!("could not read {}: {error}", dest.display()))? + make_executable(&dest) +} + +/// Mark `path` executable. A no-op on platforms without a permission bit for +/// it (Windows determines executability from the file extension instead). +#[cfg(unix)] +fn make_executable(path: &Path) -> Result<(), String> { + use std::os::unix::fs::PermissionsExt as _; + + let mut perms = fs::metadata(path) + .map_err(|error| format!("could not read {}: {error}", path.display()))? .permissions(); perms.set_mode(0o755); - fs::set_permissions(&dest, perms) - .map_err(|error| format!("could not set permissions on {}: {error}", dest.display())) + fs::set_permissions(path, perms) + .map_err(|error| format!("could not set permissions on {}: {error}", path.display())) +} + +#[cfg(windows)] +fn make_executable(_path: &Path) -> Result<(), String> { + Ok(()) } /// The manifest name for a version rustc reported: nightly builds collapse @@ -501,12 +514,7 @@ let dest = staging.join(entry.file_name()); fs::copy(entry.path(), &dest) .map_err(|error| format!("could not copy {}: {error}", entry.path().display()))?; - let mut perms = fs::metadata(&dest) - .map_err(|error| format!("could not read {}: {error}", dest.display()))? - .permissions(); - perms.set_mode(0o755); - fs::set_permissions(&dest, perms) - .map_err(|error| format!("could not set permissions on {}: {error}", dest.display()))?; + make_executable(&dest)?; relink_rpath(&dest)?; } copy_dir_all(lib_src, &staging.join("lib")) @@ -570,7 +578,7 @@ let target = fs::read_link(entry.path()).map_err(|error| { format!("could not read symlink {}: {error}", entry.path().display()) })?; - std::os::unix::fs::symlink(&target, &dest_path) + symlink(&target, &dest_path) .map_err(|error| format!("could not symlink {}: {error}", dest_path.display()))?; } else { fs::copy(entry.path(), &dest_path) @@ -589,6 +597,21 @@ Ok(()) } +/// Create a symlink at `link` pointing to `original`. +#[cfg(unix)] +fn symlink(original: &Path, link: &Path) -> std::io::Result<()> { + std::os::unix::fs::symlink(original, link) +} + +#[cfg(windows)] +fn symlink(original: &Path, link: &Path) -> std::io::Result<()> { + if original.is_dir() { + std::os::windows::fs::symlink_dir(original, link) + } else { + std::os::windows::fs::symlink_file(original, link) + } +} + /// Run `rustc <toolchain_arg> <args>` and return its stdout, so a missing /// toolchain or missing `rustc`/`rustup` shim surfaces as a plain error /// rather than a panic.