use std::{
env, fs,
io::Write,
path::Path,
process::{Command, Stdio},
};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let args = env::args().skip(1).collect::<Vec<_>>();
let path = args
.first()
.ok_or("usage: create_fixture <new-path> [commits]")?;
let commits = args
.get(1)
.map(|value| value.parse())
.transpose()?
.unwrap_or(2_000);
if Path::new(path).exists() {
return Err("fixture path already exists; refusing to overwrite it".into());
}
fs::create_dir_all(path)?;
run(path, &["init", "-q"])?;
let mut child = Command::new("git")
.args(["fast-import", "--quiet"])
.current_dir(path)
.stdin(Stdio::piped())
.spawn()?;
let mut input = child.stdin.take().ok_or("fast-import stdin unavailable")?;
input.write_all(b"feature done\n")?;
for index in 0..commits {
let blob_mark = index * 2 + 1;
let commit_mark = blob_mark + 1;
let content = format!(
"revision={index:06}\n{}\n",
"stable architecture evidence ".repeat(120)
);
write!(
input,
"blob\nmark :{blob_mark}\ndata {}\n{content}\n",
content.len()
)?;
let message = format!("revision {index}");
write!(
input,
"commit refs/heads/main\nmark :{commit_mark}\n\
committer Weavatrix <bench@weavatrix.local> {} +0000\n\
data {}\n{message}\n",
1_700_000_000 + index,
message.len()
)?;
if index > 0 {
writeln!(input, "from :{}", commit_mark - 2)?;
}
writeln!(input, "M 100644 :{blob_mark} tracked.txt")?;
}
input.write_all(b"done\n")?;
drop(input);
if !child.wait()?.success() {
return Err("git fast-import failed".into());
}
run(path, &["symbolic-ref", "HEAD", "refs/heads/main"])?;
run(path, &["reset", "--hard", "--quiet", "HEAD"])?;
run(path, &["gc", "--aggressive", "--prune=now"])?;
println!("{}", Path::new(path).canonicalize()?.display());
Ok(())
}
fn run(path: &str, args: &[&str]) -> Result<(), Box<dyn std::error::Error>> {
let output = Command::new("git").args(args).current_dir(path).output()?;
if !output.status.success() {
return Err(String::from_utf8_lossy(&output.stderr).into_owned().into());
}
Ok(())
}