check the supported solc version

Signed-off-by: Cyrill Leutwiler <bigcyrill@hotmail.com>
This commit is contained in:
Cyrill Leutwiler
2025-03-25 11:20:00 +01:00
parent 382b944bd1
commit a835754d41
7 changed files with 87 additions and 73 deletions
+49 -63
View File
@@ -1,84 +1,70 @@
//! Helper for caching the solc binaries.
use std::{
cell::OnceCell,
collections::HashSet,
fs::{File, create_dir_all},
io::Write,
io::{BufWriter, Write},
os::unix::fs::PermissionsExt,
path::{Path, PathBuf},
sync::Mutex,
sync::{LazyLock, Mutex},
};
use crate::download::GHDownloader;
pub const SOLC_CACHE_DIRECTORY: &str = "solc";
pub const SOLC_CACHER: OnceCell<Mutex<SolcCacher>> = OnceCell::new();
pub(crate) static SOLC_CACHER: LazyLock<Mutex<HashSet<PathBuf>>> = LazyLock::new(Default::default);
pub fn get_or_download(
pub(crate) fn get_or_download(
working_directory: &Path,
downloader: &GHDownloader,
) -> anyhow::Result<PathBuf> {
SOLC_CACHER
.get_or_init(|| {
Mutex::new(SolcCacher::new(
working_directory.join(SOLC_CACHE_DIRECTORY),
))
})
.lock()
.unwrap()
.get_or_download(downloader)
}
let target_directory = working_directory
.join(SOLC_CACHE_DIRECTORY)
.join(downloader.version.to_string());
let target_file = target_directory.join(downloader.target);
pub struct SolcCacher {
cache_directory: PathBuf,
cached_binaries: HashSet<PathBuf>,
}
impl SolcCacher {
fn new(cache_directory: PathBuf) -> Self {
Self {
cache_directory,
cached_binaries: Default::default(),
}
let mut cache = SOLC_CACHER.lock().unwrap();
if cache.contains(&target_file) {
return Ok(target_file);
}
fn get_or_download(&mut self, downloader: &GHDownloader) -> anyhow::Result<PathBuf> {
let directory = self.cache_directory.join(downloader.version.to_string());
let file_path = directory.join(downloader.target);
create_dir_all(target_directory)?;
download_to_file(&target_file, downloader)?;
cache.insert(target_file.clone());
if self.cached_binaries.contains(&file_path) {
return Ok(file_path);
}
create_dir_all(directory)?;
let Ok(mut file) = File::create_new(&file_path) else {
self.cached_binaries.insert(file_path.clone());
return Ok(file_path);
};
file.write_all(&downloader.download()?)?;
#[cfg(unix)]
{
let mut permissions = file.metadata()?.permissions();
let mode = permissions.mode() | 0o111;
permissions.set_mode(mode);
file.set_permissions(permissions)?;
}
#[cfg(target_os = "macos")]
std::process::Command::new("xattr")
.arg("-d")
.arg("com.apple.quarantine")
.arg(&file_path)
.stderr(std::process::Stdio::null())
.stdout(std::process::Stdio::null())
.stdout(std::process::Stdio::null())
.spawn()?
.wait()?;
Ok(file_path)
}
Ok(target_file)
}
fn download_to_file(path: &Path, downloader: &GHDownloader) -> anyhow::Result<()> {
log::info!("caching file: {}", path.display());
let Ok(file) = File::create_new(path) else {
log::warn!("cache file already exists: {}", path.display());
return Ok(());
};
#[cfg(unix)]
{
let mut permissions = file.metadata()?.permissions();
permissions.set_mode(permissions.mode() | 0o111);
file.set_permissions(permissions)?;
}
let mut file = BufWriter::new(file);
file.write_all(&downloader.download()?)?;
file.flush()?;
drop(file);
#[cfg(target_os = "macos")]
std::process::Command::new("xattr")
.arg("-d")
.arg("com.apple.quarantine")
.arg(&path)
.stderr(std::process::Stdio::null())
.stdout(std::process::Stdio::null())
.stdout(std::process::Stdio::null())
.spawn()?
.wait()?;
Ok(())
}
+8 -3
View File
@@ -1,14 +1,17 @@
//! This module downloads solc binaries.
use std::{collections::HashMap, sync::Mutex};
use std::{
collections::HashMap,
sync::{LazyLock, Mutex},
};
use once_cell::sync::Lazy;
use semver::Version;
use sha2::{Digest, Sha256};
use crate::list::List;
pub static LIST_CACHE: Lazy<Mutex<HashMap<&'static str, List>>> = Lazy::new(Default::default);
pub static LIST_CACHE: LazyLock<Mutex<HashMap<&'static str, List>>> =
LazyLock::new(Default::default);
impl List {
pub const LINUX_URL: &str = "https://binaries.soliditylang.org/linux-amd64/list.json";
@@ -34,6 +37,7 @@ impl List {
}
/// Download solc binaries from GitHub releases (IPFS links aren't reliable).
#[derive(Clone, Debug)]
pub struct GHDownloader {
pub version: Version,
pub target: &'static str,
@@ -82,6 +86,7 @@ impl GHDownloader {
/// Errors out if the download fails or the digest of the downloaded file
/// mismatches the expected digest from the release [List].
pub fn download(&self) -> anyhow::Result<Vec<u8>> {
log::info!("downloading solc: {self:?}");
let expected_digest = List::download(self.list)?
.builds
.iter()
+2 -2
View File
@@ -19,7 +19,7 @@ pub mod list;
/// Subsequent calls for the same version will use a cached artifact
/// and not download it again.
pub fn download_solc(
working_directory: &Path,
cache_directory: &Path,
version: Version,
wasm: bool,
) -> anyhow::Result<PathBuf> {
@@ -35,5 +35,5 @@ pub fn download_solc(
unimplemented!()
};
get_or_download(working_directory, &downloader)
get_or_download(cache_directory, &downloader)
}