Skip to content

Commit 4f7dba2

Browse files
committed
fix(forge): init a git repo at root during init unless explicitely stated
1 parent 55badd4 commit 4f7dba2

File tree

3 files changed

+58
-5
lines changed

3 files changed

+58
-5
lines changed

crates/cli/src/utils/mod.rs

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

443+
pub fn is_repo_root(self) -> Result<bool> {
444+
self.cmd().args(["rev-parse", "--show-cdup"]).exec().map(|out| out.stdout.is_empty())
445+
}
446+
443447
pub fn is_clean(self) -> Result<bool> {
444448
self.cmd().args(["status", "--porcelain"]).exec().map(|out| out.stdout.is_empty())
445449
}

crates/forge/bin/cmd/init.rs

Lines changed: 17 additions & 5 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+
/// Do not initialize a new git repository. Only valid if the target is in a git repository.
41+
/// If not in a git repository, a repo will still be initialized.
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, no_commit } = install;
4853

4954
// create the root dir if it does not exist
@@ -138,7 +143,7 @@ impl InitArgs {
138143

139144
// set up the repo
140145
if !no_git {
141-
init_git_repo(git, no_commit)?;
146+
init_git_repo(git, no_commit, use_parent_git)?;
142147
}
143148

144149
// install forge-std
@@ -163,15 +168,22 @@ impl InitArgs {
163168
}
164169
}
165170

166-
/// Initialises `root` as a git repository, if it isn't one already.
171+
/// Initialises `root` as a git repository, if it isn't one already, unless 'use_parent_git' is
172+
/// true.
167173
///
168174
/// Creates `.gitignore` and `.github/workflows/test.yml`, if they don't exist already.
169175
///
170-
/// Commits everything in `root` if `no_commit` is false.
171-
fn init_git_repo(git: Git<'_>, no_commit: bool) -> Result<()> {
176+
/// Commits everything if `no_commit` is false.
177+
fn init_git_repo(git: Git<'_>, no_commit: bool, use_parent_git: bool) -> Result<()> {
172178
// git init
179+
// if not in a git repo, initialize one
173180
if !git.is_in_repo()? {
174181
git.init()?;
182+
} else {
183+
// if target is not the repo root init a new one unless `use_parent_git` is true
184+
if !git.is_repo_root()? && !use_parent_git {
185+
git.init()?;
186+
}
175187
}
176188

177189
// .gitignore

crates/forge/tests/cli/cmd.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,43 @@ 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+
504541
// Checks that remappings.txt and .vscode/settings.json is generated
505542
forgetest!(can_init_vscode, |prj, cmd| {
506543
prj.wipe();

0 commit comments

Comments
 (0)