1use crate::fixtures;
2use crate::paths::App;
3use std::path::Path;
4
5const REFUSAL: &str = "rig: refusing to boot: a fixture is named but /tmp is not the tree's tmp/";
6
7pub fn guard(app: &App, data_dir: &Path) {
8 if let Err(error) = guard_at(
9 Path::new("/tmp/.rig"),
10 fixtures::requested(app).is_some(),
11 data_dir,
12 ) {
13 eprintln!("{error}");
14 std::process::exit(2);
15 }
16}
17
18pub fn guard_at(stamp: &Path, requested: bool, data_dir: &Path) -> Result<(), String> {
19 if !requested {
20 return Ok(());
21 }
22 let rig = std::fs::read_to_string(stamp).map_err(|_| REFUSAL.to_owned())?;
23 let rig = rig.trim();
24 if rig.is_empty() || !data_dir.starts_with(rig) {
25 return Err(REFUSAL.to_owned());
26 }
27 Ok(())
28}
29
30#[cfg(test)]
31mod tests {
32 use super::*;
33 use std::path::PathBuf;
34
35 fn scratch(tag: &str) -> tempfile::TempDir {
36 let root = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("tmp/testscratch");
37 std::fs::create_dir_all(&root).unwrap();
38 tempfile::Builder::new()
39 .prefix(&format!("rig-{tag}-"))
40 .tempdir_in(root)
41 .unwrap()
42 }
43
44 #[test]
45 fn a_missing_stamp_refuses_a_fixture_boot() {
46 let holder = scratch("missing");
47 assert_eq!(
48 guard_at(&holder.path().join("missing"), true, holder.path()),
49 Err(REFUSAL.to_owned())
50 );
51 }
52
53 #[test]
54 fn a_data_dir_outside_the_stamped_rig_is_refused() {
55 let holder = scratch("outside");
56 let rig = holder.path().join("rig");
57 std::fs::create_dir_all(&rig).unwrap();
58 let stamp = holder.path().join("stamp");
59 std::fs::write(&stamp, rig.to_string_lossy().as_bytes()).unwrap();
60 assert_eq!(
61 guard_at(&stamp, true, &holder.path().join("elsewhere")),
62 Err(REFUSAL.to_owned())
63 );
64 }
65
66 #[test]
67 fn a_data_dir_under_the_stamped_rig_passes() {
68 let holder = scratch("inside");
69 let rig = holder.path().join("rig");
70 let data = rig.join("data");
71 std::fs::create_dir_all(&data).unwrap();
72 let stamp = holder.path().join("stamp");
73 std::fs::write(&stamp, format!("{}\n", rig.display())).unwrap();
74 assert_eq!(guard_at(&stamp, true, &data), Ok(()));
75 }
76
77 #[test]
78 fn no_fixture_named_needs_no_stamp() {
79 let holder = scratch("no-fixture");
80 assert_eq!(
81 guard_at(&holder.path().join("missing"), false, holder.path()),
82 Ok(())
83 );
84 }
85}