microsoft/openvmm
Publicmirrored fromhttps://github.com/microsoft/openvmmAvailable
flowey/flowey_lib_common/src/check_needs_relaunch.rs
95lines · modecode
| 1 | // Copyright (c) Microsoft Corporation. |
| 2 | // Licensed under the MIT License. |
| 3 | |
| 4 | //! Check if shell must be relaunched to refresh environment variables |
| 5 | |
| 6 | use flowey::node::prelude::*; |
| 7 | |
| 8 | new_simple_flow_node!(struct Node); |
| 9 | |
| 10 | #[derive(Serialize, Deserialize)] |
| 11 | pub enum BinOrEnv { |
| 12 | Bin(String), |
| 13 | Env(String, String), |
| 14 | } |
| 15 | |
| 16 | flowey_request! { |
| 17 | pub struct Params { |
| 18 | /// Ensure requested binary is available on path or environment variable contains expected value |
| 19 | pub check: ReadVar<Option<BinOrEnv>>, |
| 20 | pub done: Vec<WriteVar<SideEffect>>, |
| 21 | } |
| 22 | } |
| 23 | |
| 24 | impl SimpleFlowNode for Node { |
| 25 | type Request = Params; |
| 26 | |
| 27 | fn imports(_dep: &mut ImportCtx<'_>) { |
| 28 | // no deps |
| 29 | } |
| 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 | // -- end of req processing -- // |
| 39 | |
| 40 | 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 | } |
| 96 | |