Skip to main content

flowey_lib_common/
download_cargo_fuzz.rs

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