Repository: gakonst/ethers-rs
Pull request #810 (2022-01-18 21:40:20)

chore(solc): add more convenience functions
**Breaks Interface**

**Do not merge until** https://github.com/gakonst/foundry/pull/297 is ready


Patch:
diff --git a/ethers-solc/src/cache.rs b/ethers-solc/src/cache.rs
index 4fd0074e..027c1587 100644
--- a/ethers-solc/src/cache.rs
+++ b/ethers-solc/src/cache.rs
@@ -307,8 +307,7 @@ impl SolFilesCacheBuilder {
         cache_file: Option<PathBuf>,
     ) -> Result<SolFilesCache> {
         let format = self.format.unwrap_or_else(|| ETHERS_FORMAT_VERSION.to_string());
-        let solc_config =
-            self.solc_config.map(Ok).unwrap_or_else(|| SolcConfig::builder().build())?;
+        let solc_config = self.solc_config.unwrap_or_else(|| SolcConfig::builder().build());
 
         let root = self
             .root
diff --git a/ethers-solc/src/compile.rs b/ethers-solc/src/compile.rs
index 153274dc..0acbfc9d 100644
--- a/ethers-solc/src/compile.rs
+++ b/ethers-solc/src/compile.rs
@@ -55,9 +55,8 @@ static LOCK: Lazy<Mutex<()>> = Lazy::new(|| Mutex::new(()));
 /// installation is detected.
 #[cfg(any(test, feature = "tests"))]
 #[allow(unused)]
-pub(crate) fn take_solc_installer_lock() -> std::sync::LockResult<std::sync::MutexGuard<'static, ()>>
-{
-    LOCK.lock()
+pub(crate) fn take_solc_installer_lock() -> std::sync::MutexGuard<'static, ()> {
+    LOCK.lock().unwrap()
 }
 
 #[cfg(all(feature = "svm", feature = "async"))]
diff --git a/ethers-solc/src/config.rs b/ethers-solc/src/config.rs
index 6308fdf2..ba2e26dd 100644
--- a/ethers-solc/src/config.rs
+++ b/ethers-solc/src/config.rs
@@ -415,7 +415,7 @@ impl SolcConfig {
     ///
     /// ```rust
     /// use ethers_solc::SolcConfig;
-    /// let config = SolcConfig::builder().build().unwrap();
+    /// let config = SolcConfig::builder().build();
     /// ```
     pub fn builder() -> SolcConfigBuilder {
         SolcConfigBuilder::default()
@@ -436,9 +436,9 @@ impl SolcConfigBuilder {
     /// Creates the solc config
     ///
     /// If no solc version is configured then it will be determined by calling `solc --version`.
-    pub fn build(self) -> Result<SolcConfig> {
+    pub fn build(self) -> SolcConfig {
         let Self { settings } = self;
-        Ok(SolcConfig { settings: settings.unwrap_or_default() })
+        SolcConfig { settings: settings.unwrap_or_default() }
     }
 }
 
diff --git a/ethers-solc/src/error.rs b/ethers-solc/src/error.rs
index 943c7644..72f8d940 100644
--- a/ethers-solc/src/error.rs
+++ b/ethers-solc/src/error.rs
@@ -46,7 +46,7 @@ impl SolcError {
     pub(crate) fn solc(msg: impl Into<String>) -> Self {
         SolcError::SolcError(msg.into())
     }
-    pub(crate) fn msg(msg: impl Into<String>) -> Self {
+    pub fn msg(msg: impl Into<String>) -> Self {
         SolcError::Message(msg.into())
     }
 }
diff --git a/ethers-solc/src/lib.rs b/ethers-solc/src/lib.rs
index d68e7cd8..86bde1ff 100644
--- a/ethers-solc/src/lib.rs
+++ b/ethers-solc/src/lib.rs
@@ -576,27 +576,53 @@ impl<Artifacts: ArtifactOutput> ProjectBuilder<Artifacts> {
         self
     }
 
+    #[must_use]
+    pub fn ignore_error_codes(mut self, codes: impl IntoIterator<Item = u64>) -> Self {
+        for code in codes {
+            self = self.ignore_error_code(code);
+        }
+        self
+    }
+
     /// Disables cached builds
     #[must_use]
-    pub fn ephemeral(mut self) -> Self {
-        self.cached = false;
+    pub fn ephemeral(self) -> Self {
+        self.set_cached(false)
+    }
+
+    /// Sets the cache status
+    #[must_use]
+    pub fn set_cached(mut self, cached: bool) -> Self {
+        self.cached = cached;
         self
     }
 
     /// Disables writing artifacts to disk
     #[must_use]
-    pub fn no_artifacts(mut self) -> Self {
-        self.no_artifacts = true;
+    pub fn no_artifacts(self) -> Self {
+        self.set_no_artifacts(true)
+    }
+
+    /// Sets the no artifacts status
+    #[must_use]
+    pub fn set_no_artifacts(mut self, artifacts: bool) -> Self {
+        self.no_artifacts = artifacts;
         self
     }
 
-    /// Disables automatic solc version detection
+    /// Sets automatic solc version detection
     #[must_use]
-    pub fn no_auto_detect(mut self) -> Self {
-        self.auto_detect = false;
+    pub fn set_auto_detect(mut self, auto_detect: bool) -> Self {
+        self.auto_detect = auto_detect;
         self
     }
 
+    /// Disables automatic solc version detection
+    #[must_use]
+    pub fn no_auto_detect(self) -> Self {
+        self.set_auto_detect(false)
+    }
+
     /// Sets the maximum number of parallel `solc` processes to run simultaneously.
     ///
     /// # Panics
@@ -678,7 +704,7 @@ impl<Artifacts: ArtifactOutput> ProjectBuilder<Artifacts> {
         } = self;
 
         let solc = solc.unwrap_or_default();
-        let solc_config = solc_config.map(Ok).unwrap_or_else(|| SolcConfig::builder().build())?;
+        let solc_config = solc_config.unwrap_or_else(|| SolcConfig::builder().build());
 
         let paths = paths.map(Ok).unwrap_or_else(ProjectPathsConfig::current_hardhat)?;
 
diff --git a/ethers-solc/src/project_util.rs b/ethers-solc/src/project_util.rs
index a3effc74..aee3f2e8 100644
--- a/ethers-solc/src/project_util.rs
+++ b/ethers-solc/src/project_util.rs
@@ -199,7 +199,7 @@ fn dir_copy_options() -> dir::CopyOptions {
         skip_exist: false,
         buffer_size: 64000, //64kb
         copy_inside: true,
-        content_only: false,
+        content_only: true,
         depth: 0,
     }
 }
diff --git a/ethers-solc/src/remappings.rs b/ethers-solc/src/remappings.rs
index ede372fd..6492a018 100644
--- a/ethers-solc/src/remappings.rs
+++ b/ethers-solc/src/remappings.rs
@@ -2,6 +2,7 @@ use serde::{Deserialize, Serialize};
 use std::{
     collections::{hash_map::Entry, HashMap},
     fmt,
+    fmt::Write,
     path::{Path, PathBuf},
     str::FromStr,
 };
@@ -93,7 +94,11 @@ impl<'de> Deserialize<'de> for Remapping {
 // Remappings are printed as `prefix=target`
 impl fmt::Display for Remapping {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "{}={}", self.name, self.path)
+        write!(f, "{}={}", self.name, self.path)?;
+        if !self.path.ends_with('/') {
+            f.write_char('/')?;
+        }
+        Ok(())
     }
 }
 
@@ -220,13 +225,25 @@ impl RelativeRemapping {
 // Remappings are printed as `prefix=target`
 impl fmt::Display for RelativeRemapping {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "{}={}", self.name, self.path.original().display())
+        let mut s = format!("{}={}", self.name, self.path.original().display());
+        if !s.ends_with('/') {
+            s.push('/');
+        }
+        f.write_str(&s)
     }
 }
 
 impl From<RelativeRemapping> for Remapping {
     fn from(r: RelativeRemapping) -> Self {
-        Remapping { name: r.name, path: r.path.relative().to_string_lossy().to_string() }
+        let RelativeRemapping { mut name, path } = r;
+        let mut path = format!("{}", path.relative().display());
+        if !path.ends_with('/') {
+            path.push('/');
+        }
+        if !name.ends_with('/') {
+            name.push('/');
+        }
+        Remapping { name, path }
     }
 }
 


Test patch:
diff --git a/ethers-solc/tests/project.rs b/ethers-solc/tests/project.rs
index 0025c77e..c50fd3eb 100644
--- a/ethers-solc/tests/project.rs
+++ b/ethers-solc/tests/project.rs
@@ -322,8 +322,8 @@ fn can_flatten_file() {
     assert!(result.is_ok());
 
     let result = result.unwrap();
-    assert!(result.find("contract Foo").is_some());
-    assert!(result.find("contract Bar").is_some());
+    assert!(result.contains("contract Foo"));
+    assert!(result.contains("contract Bar"));
 }
 
 #[test]
@@ -340,8 +340,8 @@ fn can_flatten_file_with_external_lib() {
     assert!(result.is_ok());
 
     let result = result.unwrap();
-    assert!(result.find("library console").is_some());
-    assert!(result.find("contract Greeter").is_some());
+    assert!(result.contains("library console"));
+    assert!(result.contains("contract Greeter"));
 }
 
 #[test]
@@ -356,9 +356,9 @@ fn can_flatten_file_in_dapp_sample() {
     assert!(result.is_ok());
 
     let result = result.unwrap();
-    assert!(result.find("contract DSTest").is_some());
-    assert!(result.find("contract Dapp").is_some());
-    assert!(result.find("contract DappTest").is_some());
+    assert!(result.contains("contract DSTest"));
+    assert!(result.contains("contract Dapp"));
+    assert!(result.contains("contract DappTest"));
 }
 
 #[test]
@@ -373,7 +373,7 @@ fn can_flatten_file_with_duplicates() {
     assert!(result.is_ok());
 
     let result = result.unwrap();
-    assert!(result.matches("contract Foo {").collect::<Vec<_>>().len() == 1);
-    assert!(result.matches("contract Bar {").collect::<Vec<_>>().len() == 1);
-    assert!(result.matches("contract FooBar {").collect::<Vec<_>>().len() == 1);
+    assert_eq!(result.matches("contract Foo {").count(), 1);
+    assert_eq!(result.matches("contract Bar {").count(), 1);
+    assert_eq!(result.matches("contract FooBar {").count(), 1);
 }