mod answering;
mod attaching;
mod failing;
mod malformed;
mod owning;
mod serving;
mod starting;
mod transparency;
mod transport;
use std::ffi::OsString;
use std::sync::Arc;
use bash_strings::emit_scalar;
use bash_interop::rig::{Attended, Driving, Failure, Layout, Message, Provision, Rig, Shell, Whole, heard};
use bash_interop::scratch::{Scripts, bash};
pub const ENTRY: &str = "main.bash";
pub fn join(at: &Layout) -> String {
let dir = emit_scalar(at.text());
format!(
r#"
BC_JOIN KEEP {dir}
"#
)
}
pub trait Joins {
fn joining(&self, at: &Layout) -> String;
}
pub fn provisioned<R: Joins>(rig: &R) -> impl Fn(&Layout) -> Result<Vec<(OsString, OsString)>, Failure> + '_ {
|at| {
Ok(vec![at.bash_env(
Provision::Joining(&rig.joining(at)),
)?])
}
}
pub fn deploy_session(at: &Layout) -> (OsString, OsString) {
(
OsString::from("DEPLOY_SESSION"),
OsString::from(at.text()),
)
}
pub struct Keeping;
impl Rig for Keeping {
type Reaction = Vec<Message>;
fn bash(&self, _at: &Layout) -> String {
String::new()
}
async fn joined(&self, _at: &Layout, _shell: Arc<Shell>) -> Result<Vec<Message>, Failure> {
Ok(Vec::new())
}
}
impl Driving for Keeping {}
pub type Ran = Whole<Vec<Message>>;
pub async fn running(files: &[(&str, &str)]) -> Ran {
let scripts = Scripts::of(files);
let ran = Keeping
.run(
&bash(scripts.at(ENTRY)),
provisioned(&Keeping),
)
.await
.unwrap_or_else(|error| panic!("{error}"));
ran.whole().unwrap_or_else(|error| panic!("{error}"))
}
pub async fn script(body: &str) -> Ran {
running(&[(ENTRY, body)]).await
}
pub fn lines<K: AsRef<[Message]>>(shells: &[Attended<K>]) -> Vec<&Message> {
heard(shells).into_iter().map(|said| said.message).collect()
}
pub fn behind<'a, K: AsRef<[Message]>>(shells: &'a [Attended<K>], lead: &str) -> Vec<&'a [String]> {
lines(shells)
.into_iter()
.filter_map(|message| message.behind(lead))
.collect()
}
pub fn beginning(messages: &[&[String]], word: &str) -> usize {
messages
.iter()
.filter(|words| words.first().is_some_and(|first| first == word))
.count()
}
pub fn gone(pid: i32) -> bool {
for _ in 0..100 {
if unsafe { libc::kill(pid, 0) } != 0 {
return true;
}
std::thread::sleep(std::time::Duration::from_millis(20));
}
false
}
pub fn report<K: AsRef<[Message]>>(shells: &[Attended<K>]) -> String {
let lines: Vec<String> = heard(shells)
.iter()
.map(|said| {
format!(
" pid {:>7} | {}",
said.shell.pid,
said.message.words.join(" ")
)
})
.collect();
format!("\ncapture:\n{}", lines.join("\n"))
}
impl Joins for Keeping {
fn joining(&self, at: &Layout) -> String {
join(at)
}
}