Skip to content

Commit

Permalink
fix(forge): pre-emptively create lib dir if it doesn't exist for …
Browse files Browse the repository at this point in the history
…updating submodules (#6521)

* fix(forge): pre-emptively create lib dir if it doesn't exist for updating submodules

* chore: only run submodule update if the dir is not empty

* chore: revert to prev behavior

* chore: add extra check for .gitmodules

* chore: remove useless checks

* fix: only update submodules if there are any

* fix: only search for top git repo if its being used

* relax error and add test

---------

Co-authored-by: Matthias Seitz <matthias.seitz@outlook.de>
  • Loading branch information
Evalir and mattsse authored Dec 4, 2023
1 parent 677e810 commit 13af418
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 3 deletions.
13 changes: 13 additions & 0 deletions crates/cli/src/utils/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,19 @@ https://github.com/foundry-rs/foundry/issues/new/choose"
.map(|stdout| stdout.lines().any(|line| line.starts_with('-')))
}

/// Returns true if the given path has no submodules by checking `git submodule status`
pub fn has_submodules<I, S>(self, paths: I) -> Result<bool>
where
I: IntoIterator<Item = S>,
S: AsRef<OsStr>,
{
self.cmd()
.args(["submodule", "status"])
.args(paths)
.get_stdout_lossy()
.map(|stdout| stdout.trim().lines().next().is_some())
}

pub fn submodule_add(
self,
force: bool,
Expand Down
20 changes: 17 additions & 3 deletions crates/forge/bin/cmd/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,10 +124,24 @@ impl DependencyInstallOpts {
let libs = git.root.join(install_lib_dir);

if dependencies.is_empty() && !self.no_git {
p_println!(!self.quiet => "Updating dependencies in {}", libs.display());
// recursively fetch all submodules (without fetching latest)
git.submodule_update(false, false, false, true, Some(&libs))?;
// Use the root of the git repository to look for submodules.
let root = Git::root_of(git.root)?;
match git.has_submodules(Some(&root)) {
Ok(true) => {
p_println!(!quiet => "Updating dependencies in {}", libs.display());
// recursively fetch all submodules (without fetching latest)
git.submodule_update(false, false, false, true, Some(&libs))?;
}

Err(err) => {
warn!(?err, "Failed to check for submodules");
}
_ => {
// no submodules, nothing to do
}
}
}

fs::create_dir_all(&libs)?;

let installer = Installer { git, no_commit };
Expand Down
17 changes: 17 additions & 0 deletions crates/forge/tests/cli/cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -895,6 +895,23 @@ forgetest!(can_install_and_remove, |prj, cmd| {
remove(&mut cmd, "lib/forge-std");
});

// test to check we can run `forge install` in an empty dir <https://github.com/foundry-rs/foundry/issues/6519>
forgetest!(can_install_empty, |prj, cmd| {
// create
cmd.git_init();
cmd.forge_fuse().args(["install"]);
cmd.assert_empty_stdout();

// create initial commit
fs::write(prj.root().join("README.md"), "Initial commit").unwrap();

cmd.git_add().unwrap();
cmd.git_commit("Initial commit").unwrap();

cmd.forge_fuse().args(["install"]);
cmd.assert_empty_stdout();
});

// test to check that package can be reinstalled after manually removing the directory
forgetest!(can_reinstall_after_manual_remove, |prj, cmd| {
cmd.git_init();
Expand Down
25 changes: 25 additions & 0 deletions crates/test-utils/src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -680,6 +680,31 @@ impl TestCommand {
output
}

/// Returns a new [Command] that is inside the current project dir
pub fn cmd_in_current_dir(&self, program: &str) -> Command {
let mut cmd = Command::new(program);
cmd.current_dir(self.project.root());
cmd
}

/// Runs `git add .` inside the project's dir
#[track_caller]
pub fn git_add(&self) -> Result<()> {
let mut cmd = self.cmd_in_current_dir("git");
cmd.arg("add").arg(".");
let output = cmd.output()?;
self.ensure_success(&output)
}

/// Runs `git commit .` inside the project's dir
#[track_caller]
pub fn git_commit(&self, msg: &str) -> Result<()> {
let mut cmd = self.cmd_in_current_dir("git");
cmd.arg("commit").arg("-m").arg(msg);
let output = cmd.output()?;
self.ensure_success(&output)
}

/// Executes the command and returns the `(stdout, stderr)` of the output as lossy `String`s.
///
/// Expects the command to be successful.
Expand Down

0 comments on commit 13af418

Please sign in to comment.