Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: zig on windows #3739

Merged
merged 4 commits into from
Dec 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions e2e-win/zig.Tests.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Describe 'zig' {
It 'executes zig 0.13.0' {
mise x zig@0.13.0 -- zig version | Should -be "0.13.0"
}
}
3 changes: 3 additions & 0 deletions mise.lock
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ backend = "aqua:cargo-bins/cargo-binstall"
"cargo-binstall-aarch64-apple-darwin.zip" = "sha256:0afb56acd834d7b0bc9a5293963da04abe48923d90f374bed98068b313a48f2c"
"cargo-binstall-aarch64-unknown-linux-musl.tgz" = "sha256:b44c167a2520701f1888e03d7b7355617926278e24e792eeb264333e94b6ae5a"
"cargo-binstall-x86_64-unknown-linux-musl.tgz" = "sha256:f333f552699e76e8fe570da6fb928c273c0c2d14e0955f6b79f7f59eb932ba73"
"cargo-binstall.exe-windows-aarch64" = "sha256:cda730ac19fafe200fe9fb12d6dddfb6a125b47ce9441d0f862f6d739ff486b3"

[tools."cargo:cargo-edit"]
version = "0.13.0"
Expand Down Expand Up @@ -135,6 +136,7 @@ backend = "ubi:tamasfe/taplo[matching=full]"
taplo-full-linux-aarch64 = "sha256:9ffa2a799ff0ca601a0e7ff93dcae64a34c81c677916e6f0d3c81d62e0670d83"
taplo-full-linux-x86_64 = "sha256:e89d2303ea9a5ec07971feec807fa493dc9ab6624c19b313ff90fdede247ee08"
taplo-full-macos-aarch64 = "sha256:cf55aa3e4c9b631c1fbb3f8a4adac59ca2ecc7898d26e749cd9b62d5ed858fce"
"taplo.exe-full-windows-aarch64" = "sha256:13eaa7f30f321a02a43bcc476450b9a79307f12addc25df132613cbb76d03f86"

[tools.wait-for-gh-rate-limit]
version = "0.1.8"
Expand All @@ -144,3 +146,4 @@ backend = "ubi:jdx/wait-for-gh-rate-limit"
wait-for-gh-rate-limit-linux-aarch64 = "sha256:a7e2fbbaa745dd33b94d8e530deb0f450e4ef3e994916a7394dac36d01ab79e4"
wait-for-gh-rate-limit-linux-x86_64 = "sha256:a3e7e966a8d681f30bb7887e471740607074ab7f28580dd926efc307b0d35c20"
wait-for-gh-rate-limit-macos-aarch64 = "sha256:94975cf4b05c29d1a2bf42ead5c07f297ab80169a3c1813bcbbbac35d9acf7cb"
"wait-for-gh-rate-limit.exe-windows-aarch64" = "sha256:2b6a48bc8f31388e1b8d66ccd6dd19c450a42e6ae0edb4b3072f3348735e4056"
50 changes: 47 additions & 3 deletions src/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use std::sync::Mutex;
use std::time::Duration;

use color_eyre::eyre::{Context, Result};
use eyre::bail;
use filetime::{set_file_times, FileTime};
use flate2::read::GzDecoder;
use itertools::Itertools;
Expand Down Expand Up @@ -591,7 +592,7 @@ pub fn un_bz2(input: &Path, dest: &Path) -> Result<()> {
Ok(())
}

#[derive(Default, Clone, Copy, strum::EnumString, strum::Display)]
#[derive(Default, Clone, Copy, PartialEq, strum::EnumString, strum::Display)]
pub enum TarFormat {
#[default]
Auto,
Expand All @@ -603,6 +604,20 @@ pub enum TarFormat {
TarBz2,
#[strum(serialize = "tar.zst")]
TarZst,
#[strum(serialize = "zip")]
Zip,
}

impl TarFormat {
pub fn from_ext(ext: &str) -> Self {
match ext {
"xz" => TarFormat::TarXz,
"bz2" => TarFormat::TarBz2,
"zst" => TarFormat::TarZst,
"zip" => TarFormat::Zip,
_ => TarFormat::TarGz,
}
}
}

#[derive(Default)]
Expand All @@ -613,14 +628,42 @@ pub struct TarOptions<'a> {
}

pub fn untar(archive: &Path, dest: &Path, opts: &TarOptions) -> Result<()> {
let format = match opts.format {
TarFormat::Auto => {
TarFormat::from_ext(archive.extension().unwrap().to_string_lossy().as_ref())
}
_ => opts.format,
};
if format == TarFormat::Zip {
unzip(archive, dest)?;
match opts.strip_components {
0 => {}
1 => {
let entries = ls(dest)?
.into_iter()
.map(|p| ls(&p))
.collect::<Result<Vec<_>>>()?
.into_iter()
.flatten()
.collect::<Vec<_>>();
for entry in entries {
let mut new_dest = dest.to_path_buf();
new_dest.push(entry.file_name().unwrap());
fs::rename(entry, new_dest)?;
}
}
_ => bail!("strip-components not supported for zip archives"),
}
return Ok(());
}
debug!("tar -xf {} -C {}", archive.display(), dest.display());
if let Some(pr) = &opts.pr {
pr.set_message(format!(
"extract {}",
archive.file_name().unwrap().to_string_lossy()
));
}
let tar = open_tar(opts.format, archive)?;
let tar = open_tar(format, archive)?;
let err = || {
let archive = display_path(archive);
let dest = display_path(dest);
Expand Down Expand Up @@ -671,10 +714,12 @@ fn open_tar(format: TarFormat, archive: &Path) -> Result<Box<dyn std::io::Read>>
TarFormat::TarXz => Box::new(xz2::read::XzDecoder::new(f)),
TarFormat::TarBz2 => Box::new(bzip2::read::BzDecoder::new(f)),
TarFormat::TarZst => Box::new(zstd::stream::read::Decoder::new(f)?),
TarFormat::Zip => bail!("zip format not supported"),
TarFormat::Auto => match archive.extension().and_then(|s| s.to_str()) {
Some("xz") => open_tar(TarFormat::TarXz, archive)?,
Some("bz2") => open_tar(TarFormat::TarBz2, archive)?,
Some("zst") => open_tar(TarFormat::TarZst, archive)?,
Some("zip") => bail!("zip format not supported"),
_ => open_tar(TarFormat::TarGz, archive)?,
},
})
Expand Down Expand Up @@ -762,7 +807,6 @@ pub fn clone_dir(from: &PathBuf, to: &PathBuf) -> Result<()> {

#[cfg(test)]
mod tests {

use pretty_assertions::assert_eq;
use test_log::test;

Expand Down
64 changes: 24 additions & 40 deletions src/plugins/core/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,11 @@ use std::ffi::OsString;
use std::sync::Arc;
use std::sync::LazyLock as Lazy;

pub use python::PythonPlugin;

use crate::backend::{Backend, BackendMap};
use crate::cli::args::BackendArg;
use crate::config::SETTINGS;
use crate::env;
use crate::env::PATH_KEY;
use crate::plugins::core::bun::BunPlugin;
use crate::plugins::core::deno::DenoPlugin;
use crate::plugins::core::elixir::ElixirPlugin;
#[cfg(unix)]
use crate::plugins::core::erlang::ErlangPlugin;
use crate::plugins::core::go::GoPlugin;
use crate::plugins::core::java::JavaPlugin;
use crate::plugins::core::node::NodePlugin;
use crate::plugins::core::ruby::RubyPlugin;
use crate::plugins::core::rust::RustPlugin;
use crate::plugins::core::swift::SwiftPlugin;
#[cfg(unix)]
use crate::plugins::core::zig::ZigPlugin;
use crate::timeout::run_with_timeout;
use crate::toolset::ToolVersion;

Expand All @@ -39,39 +24,38 @@ mod python;
mod ruby;
mod rust;
mod swift;
#[cfg(unix)]
mod zig;

pub static CORE_PLUGINS: Lazy<BackendMap> = Lazy::new(|| {
#[cfg(unix)]
let plugins: Vec<Arc<dyn Backend>> = vec![
Arc::new(BunPlugin::new()),
Arc::new(DenoPlugin::new()),
Arc::new(ElixirPlugin::new()),
Arc::new(ErlangPlugin::new()),
Arc::new(GoPlugin::new()),
Arc::new(JavaPlugin::new()),
Arc::new(NodePlugin::new()),
Arc::new(PythonPlugin::new()),
Arc::new(RubyPlugin::new()),
Arc::new(RustPlugin::new()),
Arc::new(SwiftPlugin::new()),
Arc::new(ZigPlugin::new()),
Arc::new(bun::BunPlugin::new()),
Arc::new(deno::DenoPlugin::new()),
Arc::new(elixir::ElixirPlugin::new()),
Arc::new(erlang::ErlangPlugin::new()),
Arc::new(go::GoPlugin::new()),
Arc::new(java::JavaPlugin::new()),
Arc::new(node::NodePlugin::new()),
Arc::new(python::PythonPlugin::new()),
Arc::new(ruby::RubyPlugin::new()),
Arc::new(rust::RustPlugin::new()),
Arc::new(swift::SwiftPlugin::new()),
Arc::new(zig::ZigPlugin::new()),
];
#[cfg(windows)]
let plugins: Vec<Arc<dyn Backend>> = vec![
Arc::new(BunPlugin::new()),
Arc::new(DenoPlugin::new()),
// Arc::new(ErlangPlugin::new()),
Arc::new(ElixirPlugin::new()),
Arc::new(GoPlugin::new()),
Arc::new(JavaPlugin::new()),
Arc::new(NodePlugin::new()),
Arc::new(PythonPlugin::new()),
Arc::new(RubyPlugin::new()),
Arc::new(RustPlugin::new()),
Arc::new(SwiftPlugin::new()),
// Arc::new(ZigPlugin::new()),
Arc::new(bun::BunPlugin::new()),
Arc::new(deno::DenoPlugin::new()),
Arc::new(elixir::ElixirPlugin::new()),
// Arc::new(erlang::ErlangPlugin::new()),
Arc::new(go::GoPlugin::new()),
Arc::new(java::JavaPlugin::new()),
Arc::new(node::NodePlugin::new()),
Arc::new(python::PythonPlugin::new()),
Arc::new(ruby::RubyPlugin::new()),
Arc::new(rust::RustPlugin::new()),
Arc::new(swift::SwiftPlugin::new()),
Arc::new(zig::ZigPlugin::new()),
];
plugins
.into_iter()
Expand Down
80 changes: 35 additions & 45 deletions src/plugins/core/zig.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use crate::cli::args::BackendArg;
use crate::cli::version::OS;
use crate::cmd::CmdLineRunner;
use crate::config::SETTINGS;
use crate::file::TarOptions;
use crate::http::{HTTP, HTTP_FETCH};
use crate::install_context::InstallContext;
use crate::toolset::{ToolRequest, ToolVersion};
Expand All @@ -29,7 +30,11 @@ impl ZigPlugin {
}

fn zig_bin(&self, tv: &ToolVersion) -> PathBuf {
tv.install_path().join("zig")
if cfg!(windows) {
tv.install_path().join("zig.exe")
} else {
tv.install_path().join("bin").join("zig")
}
}

fn test_zig(&self, ctx: &InstallContext, tv: &ToolVersion) -> Result<()> {
Expand All @@ -41,23 +46,28 @@ impl ZigPlugin {
}

fn download(&self, tv: &ToolVersion, pr: &dyn SingleReport) -> Result<PathBuf> {
let archive_ext = if cfg!(target_os = "windows") {
"zip"
} else {
"tar.xz"
};
let url = if tv.version == "ref:master" {
format!(
"https://ziglang.org/builds/zig-{}-{}-{}.tar.xz",
"https://ziglang.org/builds/zig-{}-{}-{}.{archive_ext}",
os(),
arch(),
self.get_master_version()?
)
} else if regex!(r"^[0-9]+\.[0-9]+\.[0-9]+-dev.[0-9]+\+[0-9a-f]+$").is_match(&tv.version) {
format!(
"https://ziglang.org/builds/zig-{}-{}-{}.tar.xz",
"https://ziglang.org/builds/zig-{}-{}-{}.{archive_ext}",
os(),
arch(),
tv.version
)
} else {
format!(
"https://ziglang.org/download/{}/zig-{}-{}-{}.tar.xz",
"https://ziglang.org/download/{}/zig-{}-{}-{}.{archive_ext}",
tv.version,
os(),
arch(),
Expand All @@ -78,26 +88,21 @@ impl ZigPlugin {
let filename = tarball_path.file_name().unwrap().to_string_lossy();
ctx.pr.set_message(format!("extract {filename}"));
file::remove_all(tv.install_path())?;
untar_xy(tarball_path, &tv.download_path())?;
file::rename(
tv.download_path().join(format!(
"zig-{}-{}-{}",
os(),
arch(),
if tv.version == "ref:master" {
self.get_master_version()?
} else {
tv.version.clone()
}
)),
tv.install_path(),
)?;
file::create_dir_all(tv.install_path().join("bin"))?;
file::make_symlink(
self.zig_bin(tv).as_path(),
&tv.install_path().join("bin/zig"),
file::untar(
tarball_path,
&tv.install_path(),
&TarOptions {
strip_components: 1,
pr: Some(ctx.pr.as_ref()),
..Default::default()
},
)?;

if cfg!(unix) {
file::create_dir_all(tv.install_path().join("bin"))?;
file::make_symlink(Path::new("../zig"), &tv.install_path().join("bin/zig"))?;
}

Ok(())
}

Expand Down Expand Up @@ -131,6 +136,14 @@ impl Backend for ZigPlugin {
Ok(versions)
}

fn list_bin_paths(&self, tv: &ToolVersion) -> Result<Vec<PathBuf>> {
if cfg!(windows) {
Ok(vec![tv.install_path()])
} else {
Ok(vec![tv.install_path().join("bin")])
}
}

fn idiomatic_filenames(&self) -> Result<Vec<String>> {
Ok(vec![".zig-version".into()])
}
Expand Down Expand Up @@ -171,26 +184,3 @@ fn arch() -> &'static str {
arch
}
}

pub fn untar_xy(archive: &Path, dest: &Path) -> Result<()> {
let archive = archive
.to_str()
.ok_or(eyre::eyre!("Failed to read archive path"))?;
let dest = dest
.to_str()
.ok_or(eyre::eyre!("Failed to read destination path"))?;

let output = std::process::Command::new("tar")
.arg("-xf")
.arg(archive)
.arg("-C")
.arg(dest)
.output()?;

if !output.status.success() {
let err = String::from_utf8_lossy(&output.stderr);
return Err(eyre::eyre!("Failed to extract tar: {}", err));
}

Ok(())
}
Loading