Merge branch 'main' into jsdw-use-mode-solc-version

Note: some reporting in cached_compiler.rs is commented out and needs handling
This commit is contained in:
James Wilson
2025-08-26 11:34:32 +01:00
33 changed files with 2546 additions and 708 deletions
+45 -8
View File
@@ -12,6 +12,7 @@ use std::{
use tokio::sync::Mutex;
use crate::download::SolcDownloader;
use anyhow::Context;
pub const SOLC_CACHE_DIRECTORY: &str = "solc";
pub(crate) static SOLC_CACHER: LazyLock<Mutex<HashSet<PathBuf>>> = LazyLock::new(Default::default);
@@ -31,8 +32,20 @@ pub(crate) async fn get_or_download(
return Ok(target_file);
}
create_dir_all(target_directory)?;
download_to_file(&target_file, downloader).await?;
create_dir_all(&target_directory).with_context(|| {
format!(
"Failed to create solc cache directory: {}",
target_directory.display()
)
})?;
download_to_file(&target_file, downloader)
.await
.with_context(|| {
format!(
"Failed to write downloaded solc to {}",
target_file.display()
)
})?;
cache.insert(target_file.clone());
Ok(target_file)
@@ -45,14 +58,26 @@ async fn download_to_file(path: &Path, downloader: &SolcDownloader) -> anyhow::R
#[cfg(unix)]
{
let mut permissions = file.metadata()?.permissions();
let mut permissions = file
.metadata()
.with_context(|| format!("Failed to read metadata for {}", path.display()))?
.permissions();
permissions.set_mode(permissions.mode() | 0o111);
file.set_permissions(permissions)?;
file.set_permissions(permissions).with_context(|| {
format!("Failed to set executable permissions on {}", path.display())
})?;
}
let mut file = BufWriter::new(file);
file.write_all(&downloader.download().await?)?;
file.flush()?;
file.write_all(
&downloader
.download()
.await
.context("Failed to download solc binary bytes")?,
)
.with_context(|| format!("Failed to write solc binary to {}", path.display()))?;
file.flush()
.with_context(|| format!("Failed to flush file {}", path.display()))?;
drop(file);
#[cfg(target_os = "macos")]
@@ -63,8 +88,20 @@ async fn download_to_file(path: &Path, downloader: &SolcDownloader) -> anyhow::R
.stderr(std::process::Stdio::null())
.stdout(std::process::Stdio::null())
.stdout(std::process::Stdio::null())
.spawn()?
.wait()?;
.spawn()
.with_context(|| {
format!(
"Failed to spawn xattr to remove quarantine attribute on {}",
path.display()
)
})?
.wait()
.with_context(|| {
format!(
"Failed waiting for xattr operation to complete on {}",
path.display()
)
})?;
Ok(())
}
+27 -5
View File
@@ -11,6 +11,7 @@ use semver::Version;
use sha2::{Digest, Sha256};
use crate::list::List;
use anyhow::Context;
pub static LIST_CACHE: LazyLock<Mutex<HashMap<&'static str, List>>> =
LazyLock::new(Default::default);
@@ -30,7 +31,12 @@ impl List {
return Ok(list.clone());
}
let body: List = reqwest::get(url).await?.json().await?;
let body: List = reqwest::get(url)
.await
.with_context(|| format!("Failed to GET solc list from {url}"))?
.json()
.await
.with_context(|| format!("Failed to deserialize solc list JSON from {url}"))?;
LIST_CACHE.lock().unwrap().insert(url, body.clone());
@@ -68,7 +74,8 @@ impl SolcDownloader {
}),
VersionOrRequirement::Requirement(requirement) => {
let Some(version) = List::download(list)
.await?
.await
.with_context(|| format!("Failed to download solc builds list from {list}"))?
.builds
.into_iter()
.map(|build| build.version)
@@ -107,11 +114,20 @@ impl SolcDownloader {
/// Errors out if the download fails or the digest of the downloaded file
/// mismatches the expected digest from the release [List].
pub async fn download(&self) -> anyhow::Result<Vec<u8>> {
let builds = List::download(self.list).await?.builds;
let builds = List::download(self.list)
.await
.with_context(|| format!("Failed to download solc builds list from {}", self.list))?
.builds;
let build = builds
.iter()
.find(|build| build.version == self.version)
.ok_or_else(|| anyhow::anyhow!("solc v{} not found builds", self.version))?;
.ok_or_else(|| anyhow::anyhow!("solc v{} not found builds", self.version))
.with_context(|| {
format!(
"Requested solc version {} was not found in builds list fetched from {}",
self.version, self.list
)
})?;
let path = build.path.clone();
let expected_digest = build
@@ -121,7 +137,13 @@ impl SolcDownloader {
.to_string();
let url = format!("{}/{}/{}", Self::BASE_URL, self.target, path.display());
let file = reqwest::get(url).await?.bytes().await?.to_vec();
let file = reqwest::get(&url)
.await
.with_context(|| format!("Failed to GET solc binary from {url}"))?
.bytes()
.await
.with_context(|| format!("Failed to read solc binary bytes from {url}"))?
.to_vec();
if hex::encode(Sha256::digest(&file)) != expected_digest {
anyhow::bail!("sha256 mismatch for solc version {}", self.version);
-1
View File
@@ -4,7 +4,6 @@
//! [0]: https://binaries.soliditylang.org
use std::path::{Path, PathBuf};
use cache::get_or_download;
use download::SolcDownloader;
use semver::Version;