Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
4 changes: 2 additions & 2 deletions crates/forge/src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,10 @@ pub fn run_command(args: Forge) -> Result<()> {
},
ForgeSubcommand::Create(cmd) => global.block_on(cmd.run()),
ForgeSubcommand::Update(cmd) => cmd.run(),
ForgeSubcommand::Install(cmd) => cmd.run(),
ForgeSubcommand::Install(cmd) => global.block_on(cmd.run()),
ForgeSubcommand::Remove(cmd) => cmd.run(),
ForgeSubcommand::Remappings(cmd) => cmd.run(),
ForgeSubcommand::Init(cmd) => cmd.run(),
ForgeSubcommand::Init(cmd) => global.block_on(cmd.run()),
ForgeSubcommand::Completions { shell } => {
generate(shell, &mut Forge::command(), "forge", &mut std::io::stdout());
Ok(())
Expand Down
13 changes: 9 additions & 4 deletions crates/forge/src/cmd/clone.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ impl CloneArgs {
let meta = Self::collect_metadata_from_client(address, &client).await?;

// step 2. initialize an empty project
Self::init_an_empty_project(&root, install)?;
Self::init_an_empty_project(&root, install).await?;
// canonicalize the root path
// note that at this point, the root directory must have been created
let root = dunce::canonicalize(&root)?;
Expand Down Expand Up @@ -160,11 +160,14 @@ impl CloneArgs {
/// * `root` - the root directory of the project.
/// * `enable_git` - whether to enable git for the project.
/// * `quiet` - whether to print messages.
pub(crate) fn init_an_empty_project(root: &Path, install: DependencyInstallOpts) -> Result<()> {
pub(crate) async fn init_an_empty_project(
root: &Path,
install: DependencyInstallOpts,
) -> Result<()> {
// Initialize the project with empty set to true to avoid creating example contracts
let init_args =
InitArgs { root: root.to_path_buf(), install, empty: true, ..Default::default() };
init_args.run().map_err(|e| eyre::eyre!("Project init error: {:?}", e))?;
init_args.run().await.map_err(|e| eyre::eyre!("Project init error: {:?}", e))?;

Ok(())
}
Expand Down Expand Up @@ -717,7 +720,9 @@ mod tests {
let mut project_root = tempfile::tempdir().unwrap().path().to_path_buf();
let client = mock_etherscan(address);
let meta = CloneArgs::collect_metadata_from_client(address, &client).await.unwrap();
CloneArgs::init_an_empty_project(&project_root, DependencyInstallOpts::default()).unwrap();
CloneArgs::init_an_empty_project(&project_root, DependencyInstallOpts::default())
.await
.unwrap();
project_root = dunce::canonicalize(&project_root).unwrap();
CloneArgs::parse_metadata(&meta, Chain::mainnet(), &project_root, false, false)
.await
Expand Down
6 changes: 3 additions & 3 deletions crates/forge/src/cmd/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ pub struct InitArgs {
}

impl InitArgs {
pub fn run(self) -> Result<()> {
pub async fn run(self) -> Result<()> {
let Self {
root,
template,
Expand Down Expand Up @@ -215,10 +215,10 @@ impl InitArgs {
if !offline {
if root.join("lib/forge-std").exists() {
sh_warn!("\"lib/forge-std\" already exists, skipping install...")?;
self.install.install(&mut config, vec![])?;
self.install.install(&mut config, vec![]).await?;
} else {
let dep = "https://github.com/foundry-rs/forge-std".parse()?;
self.install.install(&mut config, vec![dep])?;
self.install.install(&mut config, vec![dep]).await?;
}
}

Expand Down
47 changes: 43 additions & 4 deletions crates/forge/src/cmd/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use foundry_common::fs;
use foundry_config::{Config, impl_figment_convert_basic};
use regex::Regex;
use semver::Version;
use soldeer_commands::{Command, Verbosity, commands::install::Install};
use std::{
io::IsTerminal,
path::{Path, PathBuf},
Expand Down Expand Up @@ -59,9 +60,9 @@ pub struct InstallArgs {
impl_figment_convert_basic!(InstallArgs);

impl InstallArgs {
pub fn run(self) -> Result<()> {
pub async fn run(self) -> Result<()> {
let mut config = self.load_config()?;
self.opts.install(&mut config, self.dependencies)
self.opts.install(&mut config, self.dependencies).await
}
}

Expand Down Expand Up @@ -97,7 +98,10 @@ impl DependencyInstallOpts {
if self.git(config).has_missing_dependencies(Some(lib)).unwrap_or(false) {
// The extra newline is needed, otherwise the compiler output will overwrite the message
let _ = sh_println!("Missing dependencies found. Installing now...\n");
if self.install(config, Vec::new()).is_err() {

// Create a runtime to handle async install
let rt = tokio::runtime::Runtime::new().unwrap();
if rt.block_on(self.install(config, Vec::new())).is_err() {
let _ =
sh_warn!("Your project has missing dependencies that could not be installed.");
}
Expand All @@ -108,7 +112,7 @@ impl DependencyInstallOpts {
}

/// Installs all dependencies
pub fn install(self, config: &mut Config, dependencies: Vec<Dependency>) -> Result<()> {
pub async fn install(self, config: &mut Config, dependencies: Vec<Dependency>) -> Result<()> {
let Self { no_git, commit, .. } = self;

let git = self.git(config);
Expand Down Expand Up @@ -256,6 +260,11 @@ impl DependencyInstallOpts {
}
}
sh_println!("{msg}")?;

// Check if the dependency has soldeer.lock and install soldeer dependencies
if let Err(e) = install_soldeer_deps_if_needed(&path).await {
sh_warn!("Failed to install soldeer dependencies for {}: {e}", dep.name)?;
}
}

// update `libs` in config if not included yet
Expand All @@ -272,6 +281,36 @@ pub fn install_missing_dependencies(config: &mut Config) -> bool {
DependencyInstallOpts::default().install_missing_dependencies(config)
}

/// Checks if a dependency has soldeer.lock and installs soldeer dependencies if needed.
async fn install_soldeer_deps_if_needed(dep_path: &Path) -> Result<()> {
let soldeer_lock = dep_path.join("soldeer.lock");

if soldeer_lock.exists() {
sh_println!(" Found soldeer.lock, installing soldeer dependencies...")?;

// Change to the dependency directory and run soldeer install
let original_dir = std::env::current_dir()?;
std::env::set_current_dir(dep_path)?;

let result = soldeer_commands::run(
Command::Install(Install::default()),
Verbosity::new(
foundry_common::shell::verbosity(),
if foundry_common::shell::is_quiet() { 1 } else { 0 },
),
)
.await;

// Change back to original directory
std::env::set_current_dir(original_dir)?;

result.map_err(|e| eyre::eyre!("Failed to run soldeer install: {e}"))?;
sh_println!(" Soldeer dependencies installed successfully")?;
}

Ok(())
}

#[derive(Clone, Copy, Debug)]
struct Installer<'a> {
git: Git<'a>,
Expand Down
Loading