diff --git a/Cargo.lock b/Cargo.lock index a148222..a995a14 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,24 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "aes" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", + "opaque-debug", +] + [[package]] name = "anyhow" version = "1.0.51" @@ -31,6 +49,12 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" +[[package]] +name = "base64ct" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a32fd6af2b5827bce66c29053ba0e7c42b9dcab01835835058558c10851a46b" + [[package]] name = "bitflags" version = "1.3.2" @@ -46,6 +70,15 @@ dependencies = [ "generic-array", ] +[[package]] +name = "block-buffer" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324" +dependencies = [ + "generic-array", +] + [[package]] name = "build_const" version = "0.2.2" @@ -58,17 +91,47 @@ version = "3.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f1e260c3a9040a7c19a12468758f4c16f31a81a1fe087482be9570ec864bb6c" +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + [[package]] name = "bytes" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" +[[package]] +name = "bzip2" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6afcd980b5f3a45017c57e57a2fcccbb351cc43a356ce117ef760ef8052b89b0" +dependencies = [ + "bzip2-sys", + "libc", +] + +[[package]] +name = "bzip2-sys" +version = "0.1.11+1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc" +dependencies = [ + "cc", + "libc", + "pkg-config", +] + [[package]] name = "cc" version = "1.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee" +dependencies = [ + "jobserver", +] [[package]] name = "cfg-if" @@ -76,6 +139,15 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cipher" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7" +dependencies = [ + "generic-array", +] + [[package]] name = "clap" version = "3.0.6" @@ -134,6 +206,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "constant_time_eq" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" + [[package]] name = "core-foundation" version = "0.9.2" @@ -159,6 +237,35 @@ dependencies = [ "libc", ] +[[package]] +name = "crc32fast" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ff1f980957787286a554052d03c7aee98d99cc32e09f6d45f0a814133c87978" +dependencies = [ + "cfg-if", + "once_cell", +] + +[[package]] +name = "crypto-common" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57952ca27b5e3606ff4dd79b0020231aaf9d6aa76dc05fd30137538c50bd3ce8" +dependencies = [ + "generic-array", + "typenum", +] + [[package]] name = "dialoguer" version = "0.8.0" @@ -180,6 +287,17 @@ dependencies = [ "generic-array", ] +[[package]] +name = "digest" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506" +dependencies = [ + "block-buffer 0.10.2", + "crypto-common", + "subtle", +] + [[package]] name = "either" version = "1.6.1" @@ -201,6 +319,16 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "flate2" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f82b0f4c27ad9f8bfd1f3208d882da2b09c301bc1c828fd3a00d0216d2fbbff6" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + [[package]] name = "fnv" version = "1.0.7" @@ -358,6 +486,15 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest 0.10.3", +] + [[package]] name = "home" version = "0.5.3" @@ -520,6 +657,15 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" +[[package]] +name = "jobserver" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af25a77299a7f711a01975c35a6a424eb6862092cc2d6c72c4ed6cbc56dfc1fa" +dependencies = [ + "libc", +] + [[package]] name = "js-sys" version = "0.3.55" @@ -577,6 +723,15 @@ version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" +[[package]] +name = "miniz_oxide" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f5c75688da582b8ffc1f1799e9db273f32133c49e048f614d22ec3256773ccc" +dependencies = [ + "adler", +] + [[package]] name = "mio" version = "0.7.14" @@ -636,6 +791,15 @@ dependencies = [ "libc", ] +[[package]] +name = "num_threads" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" +dependencies = [ + "libc", +] + [[package]] name = "number_prefix" version = "0.4.0" @@ -721,6 +885,29 @@ dependencies = [ "winapi", ] +[[package]] +name = "password-hash" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d791538a6dcc1e7cb7fe6f6b58aca40e7f79403c45b2bc274008b5e647af1d8" +dependencies = [ + "base64ct", + "rand_core", + "subtle", +] + +[[package]] +name = "pbkdf2" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271779f35b581956db91a3e55737327a03aa051e90b1c47aeb189508533adfd7" +dependencies = [ + "digest 0.10.3", + "hmac", + "password-hash", + "sha2 0.10.2", +] + [[package]] name = "percent-encoding" version = "2.1.0" @@ -1049,20 +1236,42 @@ dependencies = [ "serde", ] +[[package]] +name = "sha1" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c77f4e7f65455545c2153c1253d25056825e77ee2533f0e41deb65a93a34852f" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.3", +] + [[package]] name = "sha2" version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" dependencies = [ - "block-buffer", + "block-buffer 0.9.0", "cfg-if", "cpufeatures", - "digest", + "digest 0.9.0", "opaque-debug", "sha2-asm", ] +[[package]] +name = "sha2" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55deaec60f81eefe3cce0dc50bda92d6d8e88f2a27df7c5033b42afeb1ed2676" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.3", +] + [[package]] name = "sha2-asm" version = "0.6.2" @@ -1115,6 +1324,12 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +[[package]] +name = "subtle" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" + [[package]] name = "svm-rs" version = "0.2.12" @@ -1135,12 +1350,13 @@ dependencies = [ "semver", "serde", "serde_json", - "sha2", + "sha2 0.9.9", "tempfile", "thiserror", "tokio", "tracing", "url", + "zip", ] [[package]] @@ -1224,6 +1440,24 @@ dependencies = [ "syn", ] +[[package]] +name = "time" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72c91f41dcb2f096c05f0873d667dceec1087ce5bcf984ec8ffb19acddbb3217" +dependencies = [ + "itoa 1.0.1", + "libc", + "num_threads", + "time-macros", +] + +[[package]] +name = "time-macros" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42657b1a6f4d817cda8e7a0ace261fe0cc946cf3a80314390b22cc61ae080792" + [[package]] name = "tinyvec" version = "1.5.1" @@ -1577,3 +1811,52 @@ name = "zeroize" version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d68d9dcec5f9b43a30d38c49f91dfedfaac384cb8f085faca366c26207dd1619" + +[[package]] +name = "zip" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf225bcf73bb52cbb496e70475c7bd7a3f769df699c0020f6c7bd9a96dcf0b8d" +dependencies = [ + "aes", + "byteorder", + "bzip2", + "constant_time_eq", + "crc32fast", + "crossbeam-utils", + "flate2", + "hmac", + "pbkdf2", + "sha1", + "time", + "zstd", +] + +[[package]] +name = "zstd" +version = "0.10.2+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f4a6bd64f22b5e3e94b4e238669ff9f10815c27a5180108b849d24174a83847" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "4.1.6+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94b61c51bb270702d6167b8ce67340d2754b088d0c091b06e593aa772c3ee9bb" +dependencies = [ + "libc", + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "1.6.3+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc49afa5c8d634e75761feda8c592051e7eeb4683ba827211eb0d731d3402ea8" +dependencies = [ + "cc", + "libc", +] diff --git a/Cargo.toml b/Cargo.toml index f4c5e6a..0205080 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -49,6 +49,9 @@ tokio = { version = "1.11.0", features = ["full"] } tracing = "0.1.30" url = { version = "2.2.2", default-features = false } +[target.'cfg(all(target_os = "windows", target_arch = "x86_64"))'.dependencies] +zip = "0.6.2" + [build-dependencies] home = { version = "0.5.3", default-features = false } diff --git a/src/error.rs b/src/error.rs index 2354f2c..a6818f2 100644 --- a/src/error.rs +++ b/src/error.rs @@ -27,4 +27,7 @@ pub enum SolcVmError { UrlError(#[from] url::ParseError), #[error("Received unsuccessful response with code {1} for {0}")] UnsuccessfulResponse(Url, StatusCode), + #[cfg(all(target_os = "windows", target_arch = "x86_64"))] + #[error(transparent)] + ZipError(#[from] zip::result::ZipError), } diff --git a/src/lib.rs b/src/lib.rs index c5334dc..af191a3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -70,6 +70,24 @@ impl Installer { Ok(solc_path) } + + /// Extracts the solc archive at the version specified destination and returns the path to the + /// installed solc binary. + #[cfg(all(target_os = "windows", target_arch = "x86_64"))] + fn install_zip(&self) -> Result { + let version_path = version_path(self.version.to_string().as_str()); + let solc_path = version_path.join(&format!("solc-{}", self.version)); + + // extract archive + let mut content = Cursor::new(&self.binbytes); + let mut archive = zip::ZipArchive::new(&mut content)?; + archive.extract(version_path.as_path())?; + + // rename solc binary + std::fs::rename(version_path.join("solc.exe"), solc_path.as_path())?; + + Ok(solc_path) + } } /// Derive path to a specific Solc version's binary. @@ -182,7 +200,11 @@ pub fn blocking_install(version: &Version) -> Result { // same version of solc. let _lock = try_lock_file(lock_path)?; - do_install(version.clone(), binbytes.to_vec()) + do_install( + version.clone(), + binbytes.to_vec(), + artifact.to_string().as_str(), + ) } /// Installs the provided version of Solc in the machine. @@ -227,16 +249,30 @@ pub async fn install(version: &Version) -> Result { // same version of solc. let _lock = try_lock_file(lock_path)?; - do_install(version.clone(), binbytes.to_vec()) + do_install( + version.clone(), + binbytes.to_vec(), + artifact.to_string().as_str(), + ) } -fn do_install(version: Version, binbytes: Vec) -> Result { +fn do_install( + version: Version, + binbytes: Vec, + _artifact: &str, +) -> Result { let installer = { setup_version(version.to_string().as_str())?; Installer { version, binbytes } }; + // Solc versions <= 0.7.1 are .zip files for Windows only + #[cfg(target_os = "windows")] + if _artifact.ends_with(".zip") { + return installer.install_zip(); + } + installer.install() } @@ -446,4 +482,24 @@ mod tests { let binbytes = resp.bytes().await.unwrap(); ensure_checksum(&binbytes, &latest, checksum).unwrap(); } + + #[tokio::test] + #[cfg(all(target_os = "windows", target_arch = "x86_64"))] + async fn can_install_windows_zip_release() { + let version = "0.7.1".parse().unwrap(); + install(&version).await.unwrap(); + let solc_path = + version_path(version.to_string().as_str()).join(&format!("solc-{}", version)); + let output = Command::new(&solc_path) + .arg("--version") + .stdin(Stdio::piped()) + .stderr(Stdio::piped()) + .stdout(Stdio::piped()) + .output() + .unwrap(); + + assert!(String::from_utf8_lossy(&output.stdout) + .as_ref() + .contains("0.7.1")); + } }