Skip to content

Commit c802f29

Browse files
0xvvgrandizzyDaniPopes
authored
fix(forge): init a git repo at root during init unless explicitely stated (#9695)
Co-authored-by: grandizzy <[email protected]> Co-authored-by: DaniPopes <[email protected]>
1 parent 2df81c2 commit c802f29

File tree

3 files changed

+63
-6
lines changed

3 files changed

+63
-6
lines changed

crates/cli/src/utils/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -489,6 +489,10 @@ impl<'a> Git<'a> {
489489
self.cmd().args(["rev-parse", "--is-inside-work-tree"]).status().map(|s| s.success())
490490
}
491491

492+
pub fn is_repo_root(self) -> Result<bool> {
493+
self.cmd().args(["rev-parse", "--show-cdup"]).exec().map(|out| out.stdout.is_empty())
494+
}
495+
492496
pub fn is_clean(self) -> Result<bool> {
493497
self.cmd().args(["status", "--porcelain"]).exec().map(|out| out.stdout.is_empty())
494498
}

crates/forge/src/cmd/init.rs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,18 @@ pub struct InitArgs {
3737
#[arg(long, conflicts_with = "template")]
3838
pub vscode: bool,
3939

40+
/// Use the parent git repository instead of initializing a new one.
41+
/// Only valid if the target is in a git repository.
42+
#[arg(long, conflicts_with = "template")]
43+
pub use_parent_git: bool,
44+
4045
#[command(flatten)]
4146
pub install: DependencyInstallOpts,
4247
}
4348

4449
impl InitArgs {
4550
pub fn run(self) -> Result<()> {
46-
let Self { root, template, branch, install, offline, force, vscode } = self;
51+
let Self { root, template, branch, install, offline, force, vscode, use_parent_git } = self;
4752
let DependencyInstallOpts { shallow, no_git, commit } = install;
4853

4954
// create the root dir if it does not exist
@@ -141,7 +146,7 @@ impl InitArgs {
141146

142147
// set up the repo
143148
if !no_git {
144-
init_git_repo(git, commit)?;
149+
init_git_repo(git, commit, use_parent_git)?;
145150
}
146151

147152
// install forge-std
@@ -166,14 +171,15 @@ impl InitArgs {
166171
}
167172
}
168173

169-
/// Initialises `root` as a git repository, if it isn't one already.
174+
/// Initialises `root` as a git repository, if it isn't one already, unless 'use_parent_git' is
175+
/// true.
170176
///
171177
/// Creates `.gitignore` and `.github/workflows/test.yml`, if they don't exist already.
172178
///
173179
/// Commits everything in `root` if `commit` is true.
174-
fn init_git_repo(git: Git<'_>, commit: bool) -> Result<()> {
175-
// git init
176-
if !git.is_in_repo()? {
180+
fn init_git_repo(git: Git<'_>, commit: bool, use_parent_git: bool) -> Result<()> {
181+
// `git init`
182+
if !git.is_in_repo()? || (!use_parent_git && !git.is_repo_root()?) {
177183
git.init()?;
178184
}
179185

crates/forge/tests/cli/cmd.rs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,53 @@ Warning: Target directory is not empty, but `--force` was specified
501501
assert_eq!(gitignore, "not foundry .gitignore");
502502
});
503503

504+
// `forge init --use-parent-git` works on already initialized git repository
505+
forgetest!(can_init_using_parent_repo, |prj, cmd| {
506+
let root = prj.root();
507+
508+
// initialize new git repo
509+
let status = Command::new("git")
510+
.arg("init")
511+
.current_dir(root)
512+
.stdout(Stdio::null())
513+
.stderr(Stdio::null())
514+
.status()
515+
.expect("could not run git init");
516+
assert!(status.success());
517+
assert!(root.join(".git").exists());
518+
519+
prj.create_file("README.md", "non-empty dir");
520+
prj.create_file(".gitignore", "not foundry .gitignore");
521+
522+
let folder = "foundry-folder";
523+
cmd.arg("init").arg(folder).arg("--force").arg("--use-parent-git").assert_success().stdout_eq(
524+
str![[r#"
525+
Initializing [..]...
526+
Installing forge-std in [..] (url: Some("https://github.com/foundry-rs/forge-std"), tag: None)
527+
Installed forge-std[..]
528+
Initialized forge project
529+
530+
"#]],
531+
);
532+
533+
assert!(root.join(folder).join("lib/forge-std").exists());
534+
535+
// not overwritten
536+
let gitignore = root.join(".gitignore");
537+
let gitignore = fs::read_to_string(gitignore).unwrap();
538+
assert_eq!(gitignore, "not foundry .gitignore");
539+
540+
// submodules are registered at root
541+
let gitmodules = root.join(".gitmodules");
542+
let gitmodules = fs::read_to_string(gitmodules).unwrap();
543+
assert!(gitmodules.contains(
544+
"
545+
path = foundry-folder/lib/forge-std
546+
url = https://github.com/foundry-rs/forge-std
547+
"
548+
));
549+
});
550+
504551
// Checks that remappings.txt and .vscode/settings.json is generated
505552
forgetest!(can_init_vscode, |prj, cmd| {
506553
prj.wipe();

0 commit comments

Comments
 (0)