Skip to content

Commit 036fff5

Browse files
committed
feat: warn on soldeer.lock revision mismatch during build
1 parent d8020e3 commit 036fff5

File tree

3 files changed

+70
-2
lines changed

3 files changed

+70
-2
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/forge/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ solar.workspace = true
7979
strum = { workspace = true, features = ["derive"] }
8080
thiserror.workspace = true
8181
tokio = { workspace = true, features = ["time"] }
82+
toml.workspace = true
8283
toml_edit.workspace = true
8384
watchexec = "8.0"
8485
watchexec-events = "6.0"

crates/forge/src/cmd/build.rs

Lines changed: 68 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,25 @@ use foundry_config::{
2222
},
2323
filter::expand_globs,
2424
};
25-
use serde::Serialize;
26-
use std::path::PathBuf;
25+
use serde::{Deserialize, Serialize};
26+
use std::{path::PathBuf, process::Command};
2727

2828
foundry_config::merge_impl_figment_convert!(BuildArgs, build);
2929

30+
#[derive(Debug, Deserialize)]
31+
struct SoldeerLockEntry {
32+
name: String,
33+
version: String,
34+
source: String,
35+
#[serde(default, rename = "checksum")]
36+
_checksum: Option<String>,
37+
}
38+
39+
#[derive(Debug, Deserialize)]
40+
struct SoldeerLock {
41+
dependencies: Vec<SoldeerLockEntry>,
42+
}
43+
3044
/// CLI arguments for `forge build`.
3145
///
3246
/// CLI arguments take the highest precedence in the Config/Figment hierarchy.
@@ -80,6 +94,8 @@ impl BuildArgs {
8094
config = self.load_config()?;
8195
}
8296

97+
self.check_soldeer_lock_consistency(&config);
98+
8399
let project = config.project()?;
84100

85101
// Collect sources to compile if build subdirectories specified.
@@ -207,6 +223,56 @@ impl BuildArgs {
207223
Ok([config.src, config.test, config.script, foundry_toml])
208224
})
209225
}
226+
227+
/// Check soldeer.lock file consistency with actual git revisions
228+
fn check_soldeer_lock_consistency(&self, config: &Config) {
229+
let soldeer_lock_path = config.root.join("soldeer.lock");
230+
if !soldeer_lock_path.exists() {
231+
return;
232+
}
233+
234+
let lock_content = match foundry_common::fs::read_to_string(&soldeer_lock_path) {
235+
Ok(content) => content,
236+
Err(_) => return,
237+
};
238+
239+
let soldeer_lock: SoldeerLock = match toml::from_str(&lock_content) {
240+
Ok(lock) => lock,
241+
Err(_) => return,
242+
};
243+
244+
for dep in &soldeer_lock.dependencies {
245+
if let Some((_, expected_rev)) = dep.source.split_once('#') {
246+
let dep_dir_name = format!("{}-{}", dep.name, dep.version);
247+
let dep_path = config.root.join("dependencies").join(&dep_dir_name);
248+
249+
if dep_path.exists() {
250+
let actual_rev = Command::new("git")
251+
.args(["rev-parse", "HEAD"])
252+
.current_dir(&dep_path)
253+
.output();
254+
255+
if let Ok(output) = actual_rev
256+
&& output.status.success()
257+
{
258+
let actual_rev = String::from_utf8_lossy(&output.stdout).trim().to_string();
259+
260+
if !actual_rev.starts_with(expected_rev)
261+
&& !expected_rev.starts_with(&actual_rev)
262+
{
263+
sh_warn!(
264+
"Dependency '{}' revision mismatch: \n Expected (from soldeer.lock): {}\n Actual (in {}): {}",
265+
dep.name,
266+
expected_rev,
267+
dep_dir_name,
268+
actual_rev
269+
).ok();
270+
}
271+
}
272+
}
273+
}
274+
}
275+
}
210276
}
211277

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

0 commit comments

Comments
 (0)