flowey_lib_common/
check_needs_relaunch.rs1use flowey::node::prelude::*;
7
8new_simple_flow_node!(struct Node);
9
10#[derive(Serialize, Deserialize)]
11pub enum BinOrEnv {
12 Bin(String),
13 Env(String, String),
14}
15
16flowey_request! {
17 pub struct Params {
18 pub check: ReadVar<Option<BinOrEnv>>,
20 pub done: Vec<WriteVar<SideEffect>>,
21 }
22}
23
24impl SimpleFlowNode for Node {
25 type Request = Params;
26
27 fn imports(_dep: &mut ImportCtx<'_>) {
28 }
30
31 fn process_request(request: Self::Request, ctx: &mut NodeCtx<'_>) -> anyhow::Result<()> {
32 if !matches!(ctx.backend(), FlowBackend::Local) {
33 anyhow::bail!("only supported on the local backend at this time");
34 }
35
36 let Params { check, done } = request;
37
38 if done.is_empty() {
41 return Ok(());
42 }
43
44 let check_install = {
45 move |_: &mut RustRuntimeServices<'_>, bin: &String| {
46 if which::which(bin).is_err() {
47 anyhow::bail!(format!("did not find {} on $PATH", bin));
48 }
49
50 anyhow::Ok(())
51 }
52 };
53
54 let check_env = {
55 move |_: &mut RustRuntimeServices<'_>, env: &String, expected: &String| {
56 let sh = xshell::Shell::new()?;
57 let env = sh.var(env)?;
58
59 if !env.contains(expected) {
60 anyhow::bail!(format!("did not find '{}' in {}", expected, env));
61 }
62
63 anyhow::Ok(())
64 }
65 };
66
67 ctx.emit_rust_step("ensure binaries are available on path", move |ctx| {
68 done.claim(ctx);
69 let check = check.claim(ctx);
70
71 move |rt| {
72 let check = rt.read(check);
73 if check.is_none() {
74 return Ok(());
75 }
76
77 let check = check.unwrap();
78 if match check {
79 BinOrEnv::Bin(bin) => {
80 check_install(rt, &bin)
81 }
82 BinOrEnv::Env(env, expected) => {
83 check_env(rt, &env, &expected)
84 }
85 }.is_err() {
86 let args = std::env::args().collect::<Vec<_>>().join(" ");
87 anyhow::bail!("To ensure installed dependencies are available on your $PATH, please restart your shell, and re-run: `{args}`");
88 }
89 Ok(())
90 }
91 });
92
93 Ok(())
94 }
95}