Skip to main content

flowey_lib_common/
install_cargo_hack.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Install a cached copy of `cargo-hack`.
5
6use flowey::node::prelude::*;
7
8flowey_config! {
9    /// Config for the install_cargo_hack node.
10    pub struct Config {
11        /// Version of `cargo hack` to install (e.g: "0.6.45")
12        pub version: Option<String>,
13    }
14}
15
16flowey_request! {
17    /// Install `cargo-hack` as a Cargo subcommand.
18    pub struct Request(pub WriteVar<SideEffect>);
19}
20
21new_flow_node_with_config!(struct Node);
22
23impl FlowNodeWithConfig for Node {
24    type Request = Request;
25    type Config = Config;
26
27    fn imports(ctx: &mut ImportCtx<'_>) {
28        ctx.import::<crate::cache::Node>();
29        ctx.import::<crate::cfg_persistent_dir_cargo_install::Node>();
30        ctx.import::<crate::install_rust::Node>();
31    }
32
33    fn emit(
34        config: Config,
35        requests: Vec<Self::Request>,
36        ctx: &mut NodeCtx<'_>,
37    ) -> anyhow::Result<()> {
38        let version = config
39            .version
40            .ok_or(anyhow::anyhow!("missing config: version"))?;
41        let done = requests
42            .into_iter()
43            .map(|request| request.0)
44            .collect::<Vec<_>>();
45
46        if done.is_empty() {
47            return Ok(());
48        }
49
50        let cargo_hack_bin = ctx.platform().binary("cargo-hack");
51
52        let cache_dir = ctx.emit_rust_stepv("create cargo-hack cache dir", |_| {
53            |_| Ok(std::env::current_dir()?.absolute()?)
54        });
55
56        let cache_key = ReadVar::from_static(format!(
57            "cargo-hack-{version}-{}-{}",
58            ctx.arch(),
59            ctx.platform()
60        ));
61        let hitvar = ctx.reqv(|v| crate::cache::Request {
62            label: "cargo-hack".into(),
63            dir: cache_dir.clone(),
64            key: cache_key,
65            restore_keys: None, // we want an exact hit
66            hitvar: v,
67        });
68
69        let cargo_install_persistent_dir =
70            ctx.reqv(crate::cfg_persistent_dir_cargo_install::Request);
71        let rust_toolchain = ctx.reqv(crate::install_rust::Request::GetRustupToolchain);
72        let cargo_home = ctx.reqv(crate::install_rust::Request::GetCargoHome);
73
74        ctx.emit_rust_step("installing cargo-hack", |ctx| {
75            done.claim(ctx);
76
77            let cache_dir = cache_dir.claim(ctx);
78            let hitvar = hitvar.claim(ctx);
79            let cargo_install_persistent_dir = cargo_install_persistent_dir.claim(ctx);
80            let rust_toolchain = rust_toolchain.claim(ctx);
81            let cargo_home = cargo_home.claim(ctx);
82
83            move |rt| {
84                let cache_dir = rt.read(cache_dir);
85                let hitvar = rt.read(hitvar);
86                let cargo_install_persistent_dir = rt.read(cargo_install_persistent_dir);
87                let rust_toolchain = rt.read(rust_toolchain);
88                let cargo_home = rt.read(cargo_home);
89
90                crate::_util::cargo_install::install_cached_cargo_binary(
91                    rt,
92                    cache_dir,
93                    hitvar,
94                    cargo_install_persistent_dir,
95                    rust_toolchain,
96                    cargo_home,
97                    "cargo-hack",
98                    &version,
99                    &cargo_hack_bin,
100                )
101            }
102        });
103
104        Ok(())
105    }
106}