This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

core / knot2 / crates / knot-fixtures / src / lib.rs
4.2 kB 138 lines
1use std::io::Write; 2use std::path::Path; 3use std::process::{Command, Output, Stdio}; 4 5pub const AUTHOR_NAME: &str = "nel"; 6pub const AUTHOR_EMAIL: &str = "nel@oyster.cafe"; 7pub const PINNED_DATE: &str = "2026-01-01T00:00:00 +0000"; 8 9pub fn command(cwd: &Path) -> Command { 10 let mut command = Command::new("git"); 11 command 12 .current_dir(cwd) 13 .env("GIT_CONFIG_GLOBAL", "/dev/null") 14 .env("GIT_CONFIG_SYSTEM", "/dev/null") 15 .env("GIT_CONFIG_COUNT", "2") 16 .env("GIT_CONFIG_KEY_0", "maintenance.auto") 17 .env("GIT_CONFIG_VALUE_0", "false") 18 .env("GIT_CONFIG_KEY_1", "gc.autoDetach") 19 .env("GIT_CONFIG_VALUE_1", "false") 20 .env("GIT_TERMINAL_PROMPT", "0") 21 .env("GIT_ASKPASS", "true") 22 .env("GIT_AUTHOR_NAME", AUTHOR_NAME) 23 .env("GIT_AUTHOR_EMAIL", AUTHOR_EMAIL) 24 .env("GIT_COMMITTER_NAME", AUTHOR_NAME) 25 .env("GIT_COMMITTER_EMAIL", AUTHOR_EMAIL); 26 command 27} 28 29pub fn command_at(cwd: &Path, stamp: &str) -> Command { 30 let mut command = command(cwd); 31 command 32 .env("GIT_AUTHOR_DATE", stamp) 33 .env("GIT_COMMITTER_DATE", stamp); 34 command 35} 36 37pub fn available() -> bool { 38 Command::new("git") 39 .arg("--version") 40 .output() 41 .map(|out| out.status.success()) 42 .unwrap_or(false) 43} 44 45fn combined(out: &Output) -> String { 46 format!( 47 "{}{}", 48 String::from_utf8_lossy(&out.stdout), 49 String::from_utf8_lossy(&out.stderr) 50 ) 51} 52 53pub fn run(cwd: &Path, args: &[&str]) -> (bool, String) { 54 let out = command_at(cwd, PINNED_DATE) 55 .args(args) 56 .output() 57 .expect("git is available"); 58 (out.status.success(), combined(&out)) 59} 60 61pub fn must(cwd: &Path, args: &[&str]) -> String { 62 let out = command_at(cwd, PINNED_DATE) 63 .args(args) 64 .output() 65 .expect("git is available"); 66 assert!(out.status.success(), "git {args:?}:\n{}", combined(&out)); 67 String::from_utf8_lossy(&out.stdout).trim().to_string() 68} 69 70pub fn feed(cwd: &Path, args: &[&str], stdin: &[u8]) -> (bool, String) { 71 let mut child = command_at(cwd, PINNED_DATE) 72 .args(args) 73 .stdin(Stdio::piped()) 74 .stdout(Stdio::piped()) 75 .stderr(Stdio::piped()) 76 .spawn() 77 .expect("git is available"); 78 child 79 .stdin 80 .take() 81 .expect("stdin was piped") 82 .write_all(stdin) 83 .expect("the write to git's stdin succeeds"); 84 let out = child.wait_with_output().expect("git exits"); 85 (out.status.success(), combined(&out)) 86} 87 88pub fn fsck(bare: &Path) -> Result<(), String> { 89 match run( 90 bare, 91 &["fsck", "--no-dangling", "--no-reflogs", "--no-progress"], 92 ) { 93 (true, _) => Ok(()), 94 (false, report) => Err(report), 95 } 96} 97 98pub fn commit(work: &Path, file: &str, contents: &str, message: &str) { 99 std::fs::write(work.join(file), contents).expect("fixture file is writable"); 100 must(work, &["add", "-A"]); 101 must(work, &["commit", "-q", "-m", message]); 102} 103 104pub fn contains(haystack: &[u8], needle: &[u8]) -> bool { 105 haystack 106 .windows(needle.len()) 107 .any(|window| window == needle) 108} 109 110#[cfg(test)] 111mod tests { 112 use super::*; 113 114 #[test] 115 fn every_helper_pins_its_dates_so_the_same_sequence_yields_the_same_oid() { 116 if !available() { 117 return; 118 } 119 let oids = || { 120 let dir = tempfile::tempdir().unwrap(); 121 must(dir.path(), &["init", "-q", "-b", "main"]); 122 commit(dir.path(), "README.md", "kelp\n", "initial"); 123 let tree = must(dir.path(), &["hash-object", "-t", "tree", "-w", "--stdin"]); 124 let (ok, from_stdin) = feed(dir.path(), &["commit-tree", &tree, "-F", "-"], b"empty\n"); 125 assert!(ok, "{from_stdin}"); 126 ( 127 must(dir.path(), &["rev-parse", "HEAD"]), 128 from_stdin.trim().to_string(), 129 ) 130 }; 131 assert_eq!( 132 oids(), 133 oids(), 134 "an unpinned committer date would make every differential run disagree, \ 135 so a fixture writing through stdin pins the same dates as one that doesn't" 136 ); 137 } 138}