Skip to content
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/forge/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ opener = "0.8"

# soldeer
soldeer-commands.workspace = true
soldeer-core.workspace = true
quick-junit = "0.5.1"

[dev-dependencies]
Expand Down
98 changes: 97 additions & 1 deletion crates/forge/src/cmd/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use eyre::{Context, Result};
use forge_lint::{linter::Linter, sol::SolidityLinter};
use foundry_cli::{
opts::{BuildOpts, configure_pcx_from_solc, get_solar_sources_from_compile_output},
utils::{LoadConfig, cache_local_signatures},
utils::{Git, LoadConfig, cache_local_signatures},,
};
use foundry_common::{compile::ProjectCompiler, shell};
use foundry_compilers::{
Expand Down Expand Up @@ -80,6 +80,9 @@ impl BuildArgs {
config = self.load_config()?;
}

self.check_soldeer_lock_consistency(&config).await;
self.check_foundry_lock_consistency(&config);

let project = config.project()?;

// Collect sources to compile if build subdirectories specified.
Expand Down Expand Up @@ -228,6 +231,99 @@ impl BuildArgs {
Ok([config.src, config.test, config.script, foundry_toml])
})
}

/// Check soldeer.lock file consistency using soldeer_core APIs
async fn check_soldeer_lock_consistency(&self, config: &Config) {
let soldeer_lock_path = config.root.join("soldeer.lock");
if !soldeer_lock_path.exists() {
return;
}

let lockfile = match soldeer_core::lock::read_lockfile(&soldeer_lock_path) {
Ok(lock) => lock,
Err(_) => return,
};

let deps_dir = config.root.join("dependencies");
for entry in &lockfile.entries {
let dep_name = entry.name();

// Use soldeer_core's integrity check
match soldeer_core::install::check_dependency_integrity(entry, &deps_dir).await {
Ok(status) => {
use soldeer_core::install::DependencyStatus;
// Check if status indicates a problem
if matches!(
status,
DependencyStatus::Missing | DependencyStatus::FailedIntegrity
) {
sh_warn!("Dependency '{}' integrity check failed: {:?}", dep_name, status)
.ok();
}
}
Err(e) => {
sh_warn!("Dependency '{}' integrity check error: {}", dep_name, e).ok();
}
}
}
}

/// Check foundry.lock file consistency with git submodules
fn check_foundry_lock_consistency(&self, config: &Config) {
use crate::lockfile::{DepIdentifier, FOUNDRY_LOCK, Lockfile};

let foundry_lock_path = config.root.join(FOUNDRY_LOCK);
if !foundry_lock_path.exists() {
return;
}

let git = match Git::new(&config.root) {
Ok(git) => git,
Err(_) => return, // Skip if not a git repo
};

let mut lockfile = Lockfile::new(&config.root).with_git(&git);
if lockfile.read().is_err() {
return;
}

let deps = lockfile.dependencies();

for (dep_path, dep_identifier) in deps {
let full_path = config.root.join(&dep_path);

if !full_path.exists() {
sh_warn!("Dependency '{}' not found at expected path", dep_path.display()).ok();
continue;
}

let actual_rev = match git.get_rev("HEAD", &full_path) {
Ok(rev) => rev,
Err(_) => {
sh_warn!("Failed to get git revision for dependency '{}'", dep_path.display())
.ok();
continue;
}
};

// Compare with the expected revision from lockfile
let expected_rev = match dep_identifier {
DepIdentifier::Branch { rev, .. }
| DepIdentifier::Tag { rev, .. }
| DepIdentifier::Rev { rev, .. } => rev.clone(),
};

if actual_rev != expected_rev {
sh_warn!(
"Dependency '{}' revision mismatch: expected '{}', found '{}'",
dep_path.display(),
expected_rev,
actual_rev
)
.ok();
}
}
}
}

// Make this args a `figment::Provider` so that it can be merged into the `Config`
Expand Down
Loading