diff --git a/crates/common/src/compile.rs b/crates/common/src/compile.rs index a498a61b34a7..3b1d83c18250 100644 --- a/crates/common/src/compile.rs +++ b/crates/common/src/compile.rs @@ -560,19 +560,35 @@ pub fn etherscan_project(metadata: &Metadata, target_path: impl AsRef) -> /// Bundles multiple `SkipBuildFilter` into a single `FileFilter` #[derive(Clone, Debug)] -pub struct SkipBuildFilters(Vec); +pub struct SkipBuildFilters { + /// All provided filters. + pub matchers: Vec, + /// Root of the project. + pub project_root: PathBuf, +} impl FileFilter for SkipBuildFilters { /// Only returns a match if _no_ exclusion filter matches fn is_match(&self, file: &Path) -> bool { - self.0.iter().all(|matcher| is_match_exclude(matcher, file)) + self.matchers.iter().all(|matcher| { + if !is_match_exclude(matcher, file) { + false + } else { + file.strip_prefix(&self.project_root) + .map_or(true, |stripped| is_match_exclude(matcher, stripped)) + } + }) } } impl SkipBuildFilters { /// Creates a new `SkipBuildFilters` from multiple `SkipBuildFilter`. - pub fn new(matchers: impl IntoIterator) -> Result { - matchers.into_iter().map(|m| m.compile()).collect::>().map(Self) + pub fn new( + filters: impl IntoIterator, + project_root: PathBuf, + ) -> Result { + let matchers = filters.into_iter().map(|m| m.compile()).collect::>(); + matchers.map(|filters| Self { matchers: filters, project_root }) } } diff --git a/crates/forge/bin/cmd/build.rs b/crates/forge/bin/cmd/build.rs index 66dae630e1b0..c2e6715a4615 100644 --- a/crates/forge/bin/cmd/build.rs +++ b/crates/forge/bin/cmd/build.rs @@ -94,7 +94,8 @@ impl BuildArgs { .bail(!self.format_json); if let Some(skip) = self.skip { if !skip.is_empty() { - compiler = compiler.filter(Box::new(SkipBuildFilters::new(skip)?)); + compiler = compiler + .filter(Box::new(SkipBuildFilters::new(skip, project.root().to_path_buf())?)); } } let output = compiler.compile(&project)?; diff --git a/crates/forge/tests/cli/cmd.rs b/crates/forge/tests/cli/cmd.rs index 0da6191b0e60..ab1583d2c9d0 100644 --- a/crates/forge/tests/cli/cmd.rs +++ b/crates/forge/tests/cli/cmd.rs @@ -1620,7 +1620,12 @@ function test_run() external {} // only builds the single template contract `src/*` even if `*.t.sol` or `.s.sol` is absent prj.clear(); - cmd.args(["build", "--skip", "*/test/**", "--skip", "*/script/**"]); + cmd.args(["build", "--skip", "*/test/**", "--skip", "*/script/**", "--force"]); + cmd.unchecked_output().stdout_matches_path( + PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("tests/fixtures/can_build_skip_glob.stdout"), + ); + + cmd.forge_fuse().args(["build", "--skip", "./test/**", "--skip", "./script/**", "--force"]); cmd.unchecked_output().stdout_matches_path( PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("tests/fixtures/can_build_skip_glob.stdout"), ); diff --git a/crates/verify/src/bytecode.rs b/crates/verify/src/bytecode.rs index d84acbccc998..b89fc91f13a6 100644 --- a/crates/verify/src/bytecode.rs +++ b/crates/verify/src/bytecode.rs @@ -373,7 +373,10 @@ impl VerifyBytecodeArgs { if let Some(skip) = &self.skip { if !skip.is_empty() { - compiler = compiler.filter(Box::new(SkipBuildFilters::new(skip.to_owned())?)); + compiler = compiler.filter(Box::new(SkipBuildFilters::new( + skip.to_owned(), + project.root().to_path_buf(), + )?)); } } let output = compiler.compile(&project)?;