Init scratch repos with an empty template directory

improvise-pr3i, found reviewing #255. git init copies GIT_TEMPLATE_DIR
into the new .git. That variable is not in --local-env-vars, and it
bypasses config, so a template whose info/exclude holds *.gz still broke
a_gzipped_document_is_walked at git add. scratch_repo now runs
`git init -q --template=`, which copies no template at all, including a
distribution's compiled-in default. Stripping the variable would still
copy that default.

Also: rerun_with_env's callers print the child's stderr as well as its
stdout (told), because the child's panic goes to stderr.

Stacked on #255 (fix/vwjj-default-excludes).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VdfEGXA7aJ6ftMsCc9PJze
This commit is contained in:
Edward Langley
2026-09-23 17:01:33 -07:00
parent 56ac72a291
commit 322de37053
2 changed files with 58 additions and 5 deletions
+28
View File
@@ -582,6 +582,34 @@ Rivals, each run against the fixed file:
- Drop `core.attributesFile=/dev/null`: red, `fails under a default
git/attributes`.
### a_scratch_repo_ignores_the_users_template_dir
improvise-pr3i, found reviewing PR #255 at `56ac72a2`. This is a third path to the
53zz symptom. `git init` copies a template directory into the new `.git`, and
`GIT_TEMPLATE_DIR` names one. The variable is not in
`git rev-parse --local-env-vars`, so `git(root)` does not remove it. It also
bypasses config, so `GIT_CONFIG_GLOBAL=/dev/null` (which nulls
`init.templateDir`) does not reach it either. A template whose `info/exclude`
holds `*.gz` therefore became the scratch repository's own exclude file, and
`git add` refused the gzipped document.
The test points `GIT_TEMPLATE_DIR` at such a template and re-runs
`a_gzipped_document_is_walked` in a child. Red at `56ac72a2`, failing at `git add`
with `Use -f if you really want to add them`. That line appears in the failure
message only because this PR also makes `rerun_with_env`'s callers print the
child's **stderr** (`told`). The child's panic goes to stderr, and before this
change the message printed an empty stdout.
The fix is `git init -q --template=`. An empty template directory copies nothing,
whatever the environment, config or compiled-in default says. The obvious
alternative, `env_remove("GIT_TEMPLATE_DIR")`, passes this test equally well, so
the choice between them is made by argument, not by the test. Removing the
variable still lets git copy its compiled-in default template, which a
distribution may have edited. `--template=` closes that too, for the same reason
the `-c` arguments in `run_git` beat relying on the absence of a config file.
Rival: drop `--template=`. Red, as above.
---
## `tests/web_demo_model.rs`
+30 -5
View File
@@ -66,7 +66,7 @@ fn git(root: &Path) -> std::process::Command {
/// A scratch repository, so each way of shipping a document is set up for real.
fn scratch_repo() -> tempfile::TempDir {
let dir = tempfile::tempdir().expect("a temp dir");
run_git(dir.path(), &["init", "-q"]);
run_git(dir.path(), &["init", "-q", "--template="]);
dir
}
@@ -165,11 +165,36 @@ fn rerun_with_env(test: &str, env: &[(&str, &Path)]) -> std::process::Output {
let stdout = String::from_utf8_lossy(&out.stdout);
assert!(
stdout.contains("running 1 test"),
"{test} did not run: {stdout}"
"{test} did not run: {}",
told(&out)
);
out
}
/// Everything a child test said, both streams: its panic lands on stderr.
fn told(out: &std::process::Output) -> String {
let stdout = String::from_utf8_lossy(&out.stdout);
let stderr = String::from_utf8_lossy(&out.stderr);
format!("\n--- stdout\n{stdout}\n--- stderr\n{stderr}")
}
/// improvise-pr3i: `git init` copies `GIT_TEMPLATE_DIR`, which no config null
/// reaches. Evidence: `context/test-evidence/tui.md`.
#[test]
fn a_scratch_repo_ignores_the_users_template_dir() {
let templates = tempfile::tempdir().expect("a temp dir");
write(templates.path(), "info/exclude", "*.gz\n");
let out = rerun_with_env(
"a_gzipped_document_is_walked",
&[("GIT_TEMPLATE_DIR", templates.path())],
);
assert!(
out.status.success(),
"the gzip shape test fails under a template info/exclude: {}",
told(&out)
);
}
/// improvise-53zz: a hook in a linked worktree exports `GIT_DIR`, which beats
/// `-C`. Evidence: `context/test-evidence/tui.md`.
#[test]
@@ -186,7 +211,7 @@ fn a_scratch_repo_ignores_an_inherited_git_dir() {
assert!(
out.status.success(),
"the shape test fails under an inherited GIT_DIR: {}",
String::from_utf8_lossy(&out.stdout)
told(&out)
);
let staged = git(outer.path())
.args(["ls-files"])
@@ -214,7 +239,7 @@ fn a_scratch_repo_ignores_the_users_global_and_system_excludes() {
assert!(
out.status.success(),
"the gzip shape test fails under a `*.gz` exclude in {scope}: {}",
String::from_utf8_lossy(&out.stdout)
told(&out)
);
}
}
@@ -237,7 +262,7 @@ fn a_scratch_repo_ignores_the_users_default_ignore_and_attributes_files() {
assert!(
out.status.success(),
"the gzip shape test fails under a default git/{name}: {}",
String::from_utf8_lossy(&out.stdout)
told(&out)
);
}
}