Skip to content

Commit bb8d585

Browse files
authored
Fix esbuild install (#813)
1 parent eee6946 commit bb8d585

File tree

1 file changed

+66
-45
lines changed

1 file changed

+66
-45
lines changed

worker-build/src/install.rs

Lines changed: 66 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,61 +1,68 @@
1-
use std::{fs::OpenOptions, io::Write, path::PathBuf};
1+
use std::{
2+
fs::{create_dir_all, read_dir, remove_file, OpenOptions},
3+
io::Write,
4+
path::{Path, PathBuf},
5+
};
26

3-
use anyhow::Result;
7+
use anyhow::{Context, Result};
48
use flate2::read::GzDecoder;
59

6-
/// Checks if a binary with the specified name is on the user's path.
7-
pub fn is_installed(name: &str) -> Result<Option<PathBuf>> {
8-
let path = std::env::var_os("PATH").expect("could not read PATH environment variable");
9-
let path_directories = std::env::split_paths(&path).filter_map(|path| {
10-
std::fs::metadata(&path)
11-
.ok()
12-
.map(|meta| meta.is_dir())
13-
.unwrap_or(false)
14-
.then_some(path)
15-
});
16-
17-
for dir in path_directories {
18-
for entry in dir.read_dir()? {
19-
let entry = entry?;
20-
let file_type = entry.file_type()?;
21-
let is_file_or_symlink = file_type.is_symlink() || file_type.is_file();
22-
23-
if is_file_or_symlink
24-
&& entry.file_name() == format!("{name}{BINARY_EXTENSION}").as_str()
25-
{
26-
return Ok(Some(entry.path()));
10+
fn cache_path(name: &str) -> Result<PathBuf> {
11+
let path = dirs_next::cache_dir()
12+
.unwrap_or_else(std::env::temp_dir)
13+
.join("worker-build")
14+
.join(name);
15+
let parent = path.parent().unwrap();
16+
if !parent.exists() {
17+
create_dir_all(parent)?;
18+
}
19+
Ok(path)
20+
}
21+
22+
fn remove_files_with_prefix(path: &Path) -> Result<usize> {
23+
let dir = path.parent().unwrap_or(Path::new("."));
24+
let prefix = path.file_name().unwrap().to_str().unwrap();
25+
26+
let mut deleted_count = 0;
27+
28+
for entry in read_dir(dir)? {
29+
let entry = entry?;
30+
let file_name = entry.file_name();
31+
32+
if let Some(name_str) = file_name.to_str() {
33+
if name_str.starts_with(prefix) {
34+
remove_file(entry.path())?;
35+
deleted_count += 1;
2736
}
2837
}
2938
}
3039

31-
Ok(None)
40+
Ok(deleted_count)
3241
}
3342

34-
const ESBUILD_VERSION: &str = "0.25.9";
43+
const ESBUILD_VERSION: &str = "0.25.10";
3544
const BINARY_EXTENSION: &str = if cfg!(windows) { ".exe" } else { "" };
3645

3746
pub fn ensure_esbuild() -> Result<PathBuf> {
38-
// If we already have it we can skip the download.
39-
if let Some(path) = is_installed("esbuild")? {
40-
return Ok(path);
41-
};
47+
let esbuild_prefix = format!("esbuild-{}{BINARY_EXTENSION}", esbuild_platform_pkg());
4248

43-
let esbuild_binary = format!("esbuild-{}{BINARY_EXTENSION}", platform());
44-
let esbuild_bin_path = dirs_next::cache_dir()
45-
.unwrap_or_else(std::env::temp_dir)
46-
.join(esbuild_binary);
49+
let esbuild_binary = format!("{esbuild_prefix}-{ESBUILD_VERSION}");
50+
51+
let esbuild_bin_path = cache_path(&esbuild_binary)?;
4752

4853
if esbuild_bin_path.exists() {
4954
return Ok(esbuild_bin_path);
5055
}
5156

52-
let mut options = &mut std::fs::OpenOptions::new();
57+
// Clear old versions cache
58+
remove_files_with_prefix(&cache_path(&esbuild_prefix)?)?;
5359

60+
let mut options = &mut std::fs::OpenOptions::new();
5461
options = fix_permissions(options);
5562

5663
let mut file = options.create(true).write(true).open(&esbuild_bin_path)?;
5764

58-
println!("Installing esbuild...");
65+
println!("Installing esbuild {ESBUILD_VERSION}...");
5966

6067
if let Err(e) = download_esbuild(&mut file) {
6168
// Make sure we close the file before we remove it.
@@ -70,11 +77,13 @@ pub fn ensure_esbuild() -> Result<PathBuf> {
7077

7178
fn download_esbuild(writer: &mut impl Write) -> Result<()> {
7279
let esbuild_url = format!(
73-
"https://registry.npmjs.org/esbuild-{0}/-/esbuild-{0}-{ESBUILD_VERSION}.tgz",
74-
platform()
80+
"https://registry.npmjs.org/@esbuild/{0}/-/{0}-{ESBUILD_VERSION}.tgz",
81+
esbuild_platform_pkg()
7582
);
7683

77-
let mut res = ureq::get(&esbuild_url).call()?;
84+
let mut res = ureq::get(&esbuild_url)
85+
.call()
86+
.with_context(|| format!("Failed to fetch URL {esbuild_url}"))?;
7887
let body = res.body_mut().as_reader();
7988
let deflater = GzDecoder::new(body);
8089
let mut archive = tar::Archive::new(deflater);
@@ -109,17 +118,29 @@ fn fix_permissions(options: &mut OpenOptions) -> &mut OpenOptions {
109118

110119
/// Converts the user's platform from their Rust representation to their esbuild representation.
111120
/// https://esbuild.github.io/getting-started/#download-a-build
112-
pub fn platform() -> &'static str {
121+
pub fn esbuild_platform_pkg() -> &'static str {
113122
match (std::env::consts::OS, std::env::consts::ARCH) {
114-
("macos", "x86_64") => "darwin-64",
123+
("android", "arm") => "android-arm",
124+
("android", "aarch64") => "android-arm64",
125+
("android", "x86_64") => "android-x64",
115126
("macos", "aarch64") => "darwin-arm64",
116-
("linux", "x86") => "linux-32",
117-
("linux", "x86_64") => "linux-64",
127+
("macos", "x86_64") => "darwin-x64",
128+
("freebsd", "aarch64") => "freebsd-arm64",
129+
("freebsd", "x86_64") => "freebsd-x64",
118130
("linux", "arm") => "linux-arm",
119131
("linux", "aarch64") => "linux-arm64",
120-
("windows", "x86") => "windows-32",
121-
("windows", "x86_64") => "windows-64",
122-
("windows", "aarch64") => "windows-arm64",
132+
("linux", "x86") => "linux-ia32",
133+
("linux", "powerpc64") => "linux-ppc64",
134+
("linux", "s390x") => "linux-s390x",
135+
("linux", "x86_64") => "linux-x64",
136+
("netbsd", "aarch64") => "netbsd-arm64",
137+
("netbsd", "x86_64") => "netbsd-x64",
138+
("openbsd", "aarch64") => "openbsd-arm64",
139+
("openbsd", "x86_64") => "openbsd-x64",
140+
("solaris", "x86_64") => "sunos-x64",
141+
("windows", "aarch64") => "win32-arm64",
142+
("windows", "x86") => "win32-ia32",
143+
("windows", "x86_64") => "win32-x64",
123144
_ => panic!("Platform unsupported by esbuild."),
124145
}
125146
}

0 commit comments

Comments
 (0)