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
37        let git = Git::new(&root);
38        let mut lockfile = Lockfile::new(&config.root).with_git(&git);
39        let _synced = lockfile.sync(config.install_lib_dir())?;
40
41        // remove all the dependencies by invoking `git rm` only once with all the paths
42        git.rm(self.force, &paths)?;
43
44        // remove all the dependencies from .git/modules
45        for (Dependency { name, url, tag, .. }, path) in self.dependencies.iter().zip(&paths) {
46            sh_println!("Removing '{name}' in {}, (url: {url:?}, tag: {tag:?})", path.display())?;
47            let _ = lockfile.remove(path);
48            std::fs::remove_dir_all(git_modules.join(path))?;
49        }
50
51        lockfile.write()?;
52
53        Ok(())
54    }
55}