new: skip the git-init question inside existing repositories

This commit is contained in:
2026-09-17 10:37:54 +02:00
parent 05e7c55d32
commit bac82f0afe
2 changed files with 74 additions and 2 deletions
+39 -2
View File
@@ -23,6 +23,7 @@ use std::path::PathBuf;
use indicatif::MultiProgress;
use crate::new::detect::{self, Detection};
use crate::new::git;
use crate::new::options::{self, NewCli, NewOptions, SourceDir, SourceFormat, TemplateId};
use crate::new::origin::GitOrigin;
use crate::new::templates::{self, ProbeResult, ScaffoldOutcome};
@@ -467,8 +468,21 @@ async fn run_wizard(mut cli: NewCli) -> Result<NewOptions, Box<dyn Error>> {
}
}
// 14. Git init.
cli.git = prompt::confirm("Initialize a git repository?", cli.git)?;
// 14. Git init — asked only when a git init would actually happen
// (outside any repository, without `--no-git`). Inside an existing
// git work tree there is nothing to initialize: the question is
// skipped, the run assumes No and the scaffold logs its usual skip
// (the .gitignore files are written regardless). The probe looks at
// the packaged directory — or, for a skeleton, at the directory it
// would be created in.
let probe_dir = cli.source.clone().unwrap_or_else(|| cwd.clone());
let inside_repo = cli.git && git::inside_work_tree(&probe_dir);
if git_init_answer(!cli.git, inside_repo).is_some() {
// `--no-git` already declined, or there is nothing to initialize.
cli.git = false;
} else {
cli.git = prompt::confirm("Initialize a git repository?", cli.git)?;
}
// Resolve through the same pipeline as the non-interactive path: one
// source of truth for defaults and validation.
@@ -826,6 +840,16 @@ fn orig_origin_choices(origin: Option<&GitOrigin>) -> Vec<(String, &'static str)
choices
}
/// The git-init answer when the question must not be asked: `Some(false)`
/// both for `--no-git` (already declined) and inside an existing git work
/// tree (nothing to initialize — the scaffold logs the skip and writes the
/// `.gitignore` files anyway). `None` asks the wizard question, i.e.
/// whenever a git init would actually happen (fresh skeleton or packaged
/// directory outside any repository).
fn git_init_answer(no_git: bool, inside_repo: bool) -> Option<bool> {
(no_git || inside_repo).then_some(false)
}
/// A `debian/watch` template for GitHub/GitLab-hosted projects; `None` when
/// the homepage is not one of those hosts (the wizard skips the question).
pub fn watch_template(homepage: Option<&str>) -> Option<String> {
@@ -1250,6 +1274,19 @@ mod tests {
assert!(!summary_text(&opts(Tid::Go), Some("1.98.0")).contains("rust-toolchain"));
}
/// The git-init question is only asked when a git init would actually
/// happen: inside an existing work tree it is skipped with the assumed
/// No (with or without `--no-git`), and `--no-git` has already answered
/// it on its own.
#[test]
fn git_init_question_decision() {
assert_eq!(git_init_answer(false, true), Some(false));
assert_eq!(git_init_answer(true, true), Some(false));
assert_eq!(git_init_answer(true, false), Some(false));
// Outside any repository without --no-git: the wizard asks.
assert_eq!(git_init_answer(false, false), None);
}
#[test]
fn answer_validators() {
assert!(validate_revision_answer("1").is_ok());