|
1 | 1 | use std::{
|
2 |
| - ffi::OsStr, |
3 |
| - fs::File, |
4 |
| - io::{BufRead, BufReader, Read, Write}, |
5 |
| - marker::PhantomData, |
6 |
| - ops::{Deref, DerefMut}, |
7 |
| - os::unix::fs::PermissionsExt, |
8 |
| - process::Command, |
| 2 | + io::{BufRead, BufReader, Read}, |
9 | 3 | str,
|
10 |
| - sync::{LazyLock, Mutex}, |
11 | 4 | };
|
12 | 5 |
|
13 |
| -use jane_eyre::eyre::{self, Context}; |
14 |
| -use mktemp::Temp; |
15 |
| -use tracing::{debug, info, trace, warn}; |
16 |
| - |
17 |
| -/// Global instance of [Shell] for single-threaded situations. |
18 |
| -#[allow(unused)] |
19 |
| -pub static SHELL: LazyLock<Mutex<Shell>> = |
20 |
| - LazyLock::new(|| Mutex::new(Shell::new().expect("Failed to create Shell"))); |
21 |
| - |
22 |
| -/// Runs shell scripts by writing their contents to a temporary file. |
23 |
| -/// |
24 |
| -/// This lets us compile shell scripts into the program binary, which is useful for two reasons: |
25 |
| -/// - The program can be run from any working directory without breaking the shell scripts |
26 |
| -/// - You can edit shell scripts while they are running without interfering with their execution |
27 |
| -/// (usually the shell will read the next command from the same offset in the new file) |
28 |
| -#[allow(unused)] |
29 |
| -#[derive(Debug)] |
30 |
| -pub struct Shell(Temp); |
31 |
| -impl Shell { |
32 |
| - pub fn new() -> eyre::Result<Self> { |
33 |
| - let result = Temp::new_file().wrap_err("Failed to create temporary file")?; |
34 |
| - let mut permissions = std::fs::metadata(&result) |
35 |
| - .wrap_err("Failed to get metadata")? |
36 |
| - .permissions(); |
37 |
| - permissions.set_mode(permissions.mode() | 0b001001001); |
38 |
| - std::fs::set_permissions(&result, permissions).wrap_err("Failed to set permissions")?; |
39 |
| - |
40 |
| - Ok(Self(result)) |
41 |
| - } |
42 |
| - |
43 |
| - /// Get a handle that wraps a [Command] that can run the given code. |
44 |
| - /// |
45 |
| - /// Each instance can only run one script at a time, hence the `&mut self`. |
46 |
| - #[tracing::instrument(level = "error", skip_all)] |
47 |
| - pub fn run<S: AsRef<OsStr>>( |
48 |
| - &mut self, |
49 |
| - code: &str, |
50 |
| - args: impl IntoIterator<Item = S>, |
51 |
| - ) -> eyre::Result<ShellHandle> { |
52 |
| - let path = self.0.as_path(); |
53 |
| - let args = args |
54 |
| - .into_iter() |
55 |
| - .map(|arg| arg.as_ref().to_owned()) |
56 |
| - .collect::<Vec<_>>(); |
57 |
| - debug!(?path, ?args, "Running script"); |
58 |
| - let mut file = File::create(&self.0).wrap_err("Failed to create shell script")?; |
59 |
| - file.write_all(code.as_bytes()) |
60 |
| - .wrap_err("Failed to write shell script")?; |
61 |
| - |
62 |
| - let mut result = Command::new(&*self.0); |
63 |
| - result.args(args); |
64 |
| - |
65 |
| - Ok(ShellHandle(result, PhantomData)) |
66 |
| - } |
67 |
| -} |
68 |
| - |
69 |
| -#[derive(Debug)] |
70 |
| -pub struct ShellHandle<'shell>(Command, PhantomData<&'shell mut Shell>); |
71 |
| - |
72 |
| -impl Deref for ShellHandle<'_> { |
73 |
| - type Target = Command; |
74 |
| - |
75 |
| - fn deref(&self) -> &Self::Target { |
76 |
| - &self.0 |
77 |
| - } |
78 |
| -} |
79 |
| - |
80 |
| -impl DerefMut for ShellHandle<'_> { |
81 |
| - fn deref_mut(&mut self) -> &mut Self::Target { |
82 |
| - &mut self.0 |
83 |
| - } |
84 |
| -} |
| 6 | +use tracing::{info, trace, warn}; |
85 | 7 |
|
86 | 8 | macro_rules! impl_log_output_as {
|
87 | 9 | ($name:ident, $macro:ident) => {
|
|
0 commit comments