Skip to main content

bash_interop/
scratch.rs

1//! Scratch material for tests built on the rig: a directory of bash scripts,
2//! the command line that runs one, an answer that sources a file, and
3//! [`accounts`] — shells built by hand where none need run.
4//!
5//! Deliberately public: a crate driving its own rigs writes the same tests
6//! this one does.
7
8pub mod accounts;
9
10use std::ffi::OsString;
11use std::fs;
12use std::path::{Path, PathBuf};
13
14use crate::failure::{Doing, Failure};
15use crate::rig::Answer;
16
17/// A directory of bash scripts, removed when this is dropped — so it must be
18/// held for as long as the run that reads it.
19pub struct Scripts(tempfile::TempDir);
20
21impl Scripts {
22    /// A fresh directory holding each `(name, body)`. A `name` with a `/`
23    /// gets its directories made.
24    pub fn of(files: &[(&str, &str)]) -> Self {
25        let dir = tempfile::tempdir().expect("a scratch directory");
26        for (name, body) in files {
27            let file = dir.path().join(name);
28            if let Some(parent) = file.parent() {
29                fs::create_dir_all(parent).expect(name);
30            }
31            fs::write(file, body).expect(name);
32        }
33        Self(dir)
34    }
35
36    pub fn dir(&self) -> &Path {
37        self.0.path()
38    }
39
40    /// Where `name` is, written or not yet.
41    pub fn at(&self, name: &str) -> PathBuf {
42        self.dir().join(name)
43    }
44}
45
46/// `bash <script>` — the command line, program included, since a run starts
47/// whatever its argv names.
48pub fn bash(script: PathBuf) -> Vec<OsString> {
49    vec!["bash".into(), script.into()]
50}
51
52/// Write bash of your own and answer with a command to source it.
53pub fn sourcing(path: &Path, body: &str) -> Result<Answer, Failure> {
54    fs::write(path, body).doing(|| format!("writing {}", path.display()))?;
55
56    Ok(Answer::of(
57        "source",
58        [path.to_string_lossy()],
59    ))
60}