forge/cmd/
remove.rs

1use crate::Lockfile;
2use clap::{Parser, ValueHint};
3use eyre::Result;
4use foundry_cli::{
5    opts::Dependency,
6    utils::{Git, LoadConfig},
7};
8use foundry_config::impl_figment_convert_basic;
9use std::path::PathBuf;
10
11/// CLI arguments for `forge remove`.
12#[derive(Clone, Debug, Parser)]
13pub struct RemoveArgs {
14    /// The dependencies you want to remove.
15    #[arg(required = true)]
16    dependencies: Vec<Dependency>,
17
18    /// The project's root path.
19    ///
20    /// By default root of the Git repository, if in one,
21    /// or the current working directory.
22    #[arg(long, value_hint = ValueHint::DirPath, value_name = "PATH")]
23    root: Option<PathBuf>,
24
25    /// Override the up-to-date check.
26    #[arg(short, long)]
27    force: bool,
28}
29impl_figment_convert_basic!(RemoveArgs);
30
31impl RemoveArgs {
32    pub fn run(self) -> Result<()> {
33        let config = self.load_config()?;
34        let (root, paths, _) = super::update::dependencies_paths(&self.dependencies, &config)?;
35        let git_modules = root.join(".git/modules");
36        let git = Git::new(&root);
37        let mut lockfile = Lockfile::new(&config.root).with_git(&git);
38        let _synced = lockfile.sync(config.install_lib_dir())?;
39
40        // remove all the dependencies by invoking `git rm` only once with all the paths
41        git.rm(self.force, &paths)?;
42
43        // remove all the dependencies from .git/modules
44        for (Dependency { name, tag, .. }, path) in self.dependencies.iter().zip(&paths) {
45            // Get the URL from git submodule config instead of using the parsed dependency URL
46            let url = git.submodule_url(path).unwrap_or(None);
47            sh_println!(
48                "Removing '{name}' in {}, (url: {}, tag: {})",
49                path.display(),
50                url.as_deref().unwrap_or("None"),
51                tag.as_deref().unwrap_or("None")
52            )?;
53            let _ = lockfile.remove(path);
54            std::fs::remove_dir_all(git_modules.join(path))?;
55        }
56
57        lockfile.write()?;
58
59        Ok(())
60    }
61}