diff --git a/ethers-solc/src/compile/output/contracts.rs b/ethers-solc/src/compile/output/contracts.rs index f90f931b5..2945cd19e 100644 --- a/ethers-solc/src/compile/output/contracts.rs +++ b/ethers-solc/src/compile/output/contracts.rs @@ -4,7 +4,7 @@ use crate::artifacts::{ }; use semver::Version; use serde::{Deserialize, Serialize}; -use std::collections::BTreeMap; +use std::{collections::BTreeMap, path::Path}; /// file -> [(contract name -> Contract + solc version)] #[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] @@ -129,6 +129,36 @@ impl VersionedContracts { .flat_map(|(name, c)| c.into_iter().map(move |c| (name.clone(), c.contract))) }) } + + /// Sets the contract's file paths to `root` adjoined to `self.file`. + pub fn join_all(&mut self, root: impl AsRef) -> &mut Self { + let root = root.as_ref(); + self.0 = std::mem::take(&mut self.0) + .into_iter() + .map(|(contract_path, contracts)| { + (root.join(contract_path).to_string_lossy().to_string(), contracts) + }) + .collect(); + self + } + + /// Removes `base` from all contract paths + pub fn strip_prefix_all(&mut self, base: impl AsRef) -> &mut Self { + let base = base.as_ref(); + self.0 = std::mem::take(&mut self.0) + .into_iter() + .map(|(contract_path, contracts)| { + let p = Path::new(&contract_path); + ( + p.strip_prefix(base) + .map(|p| p.to_string_lossy().to_string()) + .unwrap_or(contract_path), + contracts, + ) + }) + .collect(); + self + } } impl AsRef>> for VersionedContracts { diff --git a/ethers-solc/src/compile/output/mod.rs b/ethers-solc/src/compile/output/mod.rs index 57d121bb3..7730df882 100644 --- a/ethers-solc/src/compile/output/mod.rs +++ b/ethers-solc/src/compile/output/mod.rs @@ -92,10 +92,9 @@ impl ProjectCompileOutput { /// /// # Example /// - /// Make all artifact files relative tot the project's root directory + /// Make all artifact files relative to the project's root directory /// /// ```no_run - /// use ethers_solc::artifacts::contract::CompactContractBytecode; /// use ethers_solc::Project; /// /// let project = Project::builder().build().unwrap(); @@ -105,6 +104,7 @@ impl ProjectCompileOutput { let base = base.as_ref(); self.cached_artifacts = self.cached_artifacts.into_stripped_file_prefixes(base); self.compiled_artifacts = self.compiled_artifacts.into_stripped_file_prefixes(base); + self.compiler_output.strip_prefix_all(base); self } @@ -360,6 +360,36 @@ impl AggregatedCompilerOutput { pub fn split(self) -> (VersionedSourceFiles, VersionedContracts) { (self.sources, self.contracts) } + + /// Strips the given prefix from all file paths to make them relative to the given + /// `base` argument. + /// + /// Convenience method for [Self::strip_prefix_all()] that consumes the type. + /// + /// # Example + /// + /// Make all sources and contracts relative to the project's root directory + /// + /// ```no_run + /// use ethers_solc::Project; + /// + /// let project = Project::builder().build().unwrap(); + /// let output = project.compile().unwrap().output().with_stripped_file_prefixes(project.root()); + /// ``` + pub fn with_stripped_file_prefixes(mut self, base: impl AsRef) -> Self { + let base = base.as_ref(); + self.contracts.strip_prefix_all(base); + self.sources.strip_prefix_all(base); + self + } + + /// Removes `base` from all contract paths + pub fn strip_prefix_all(&mut self, base: impl AsRef) -> &mut Self { + let base = base.as_ref(); + self.contracts.strip_prefix_all(base); + self.sources.strip_prefix_all(base); + self + } } /// Helper type to implement display for solc errors diff --git a/ethers-solc/src/compile/output/sources.rs b/ethers-solc/src/compile/output/sources.rs index 811690fd9..4a9a556eb 100644 --- a/ethers-solc/src/compile/output/sources.rs +++ b/ethers-solc/src/compile/output/sources.rs @@ -1,7 +1,7 @@ use crate::SourceFile; use semver::Version; use serde::{Deserialize, Serialize}; -use std::collections::BTreeMap; +use std::{collections::BTreeMap, path::Path}; /// (source_file path -> `SourceFile` + solc version) #[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] @@ -223,6 +223,36 @@ impl VersionedSourceFiles { .map(move |source| (path.clone(), source.source_file, source.version)) }) } + + /// Sets the sources' file paths to `root` adjoined to `self.file`. + pub fn join_all(&mut self, root: impl AsRef) -> &mut Self { + let root = root.as_ref(); + self.0 = std::mem::take(&mut self.0) + .into_iter() + .map(|(file_path, sources)| { + (root.join(file_path).to_string_lossy().to_string(), sources) + }) + .collect(); + self + } + + /// Removes `base` from all source file paths + pub fn strip_prefix_all(&mut self, base: impl AsRef) -> &mut Self { + let base = base.as_ref(); + self.0 = std::mem::take(&mut self.0) + .into_iter() + .map(|(file_path, sources)| { + let p = Path::new(&file_path); + ( + p.strip_prefix(base) + .map(|p| p.to_string_lossy().to_string()) + .unwrap_or(file_path), + sources, + ) + }) + .collect(); + self + } } impl AsRef>> for VersionedSourceFiles {