flowey_lib_common/
download_cargo_fuzz.rs1use crate::cache::CacheHit;
7use flowey::node::prelude::*;
8
9flowey_config! {
10 pub struct Config {
12 pub version: Option<String>,
14 }
15}
16
17flowey_request! {
18 pub enum Request {
19 InstallWithCargo(WriteVar<SideEffect>),
21 }
22}
23
24new_flow_node_with_config!(struct Node);
25
26impl FlowNodeWithConfig for Node {
27 type Request = Request;
28 type Config = Config;
29
30 fn imports(ctx: &mut ImportCtx<'_>) {
31 ctx.import::<crate::cache::Node>();
32 ctx.import::<crate::cfg_persistent_dir_cargo_install::Node>();
33 ctx.import::<crate::install_rust::Node>();
34 }
35
36 fn emit(
37 config: Config,
38 requests: Vec<Self::Request>,
39 ctx: &mut NodeCtx<'_>,
40 ) -> anyhow::Result<()> {
41 let mut install_with_cargo = Vec::new();
42
43 for req in requests {
44 match req {
45 Request::InstallWithCargo(v) => install_with_cargo.push(v),
46 }
47 }
48
49 let version = config
50 .version
51 .ok_or(anyhow::anyhow!("missing config: version"))?;
52 let install_with_cargo = install_with_cargo;
53
54 if install_with_cargo.is_empty() {
57 return Ok(());
58 }
59
60 let cargo_fuzz_bin = ctx.platform().binary("cargo-fuzz");
61
62 let cache_dir = ctx.emit_rust_stepv("create cargo-fuzz cache dir", |_| {
63 |_| Ok(std::env::current_dir()?.absolute()?)
64 });
65
66 let cache_key = ReadVar::from_static(format!("cargo-fuzz-{version}"));
67 let hitvar = ctx.reqv(|v| {
68 crate::cache::Request {
69 label: "cargo-fuzz".into(),
70 dir: cache_dir.clone(),
71 key: cache_key,
72 restore_keys: None, hitvar: v,
74 }
75 });
76
77 let cargo_install_persistent_dir =
78 ctx.reqv(crate::cfg_persistent_dir_cargo_install::Request);
79 let rust_toolchain = ctx.reqv(crate::install_rust::Request::GetRustupToolchain);
80 let cargo_home = ctx.reqv(crate::install_rust::Request::GetCargoHome);
81
82 ctx.emit_rust_step("installing cargo-fuzz", |ctx| {
83 install_with_cargo.claim(ctx);
84
85 let cache_dir = cache_dir.claim(ctx);
86 let hitvar = hitvar.claim(ctx);
87 let cargo_install_persistent_dir = cargo_install_persistent_dir.claim(ctx);
88 let rust_toolchain = rust_toolchain.claim(ctx);
89 let cargo_home = cargo_home.claim(ctx);
90
91 move |rt| {
92 let cache_dir = rt.read(cache_dir);
93
94 let cached_bin_path = cache_dir.join(&cargo_fuzz_bin);
95 let cached = if matches!(rt.read(hitvar), CacheHit::Hit) {
96 assert!(cached_bin_path.exists());
97 Some(cached_bin_path.clone())
98 } else {
99 None
100 };
101
102 let path_to_cargo_fuzz = if let Some(cached) = cached {
103 cached
104 } else {
105 let root = rt.read(cargo_install_persistent_dir).unwrap_or("./".into());
106
107 let rust_toolchain = rt.read(rust_toolchain);
108 let run = |offline| {
109 let rust_toolchain = rust_toolchain.as_ref().map(|s| format!("+{s}"));
110
111 flowey::shell_cmd!(
112 rt,
113 "cargo {rust_toolchain...}
114 install
115 --locked
116 {offline...}
117 --root {root}
118 --target-dir {root}
119 --version {version}
120 cargo-fuzz
121 "
122 )
123 .run()
124 };
125
126 if run(Some("--offline")).is_err() {
128 run(None)?;
130 }
131
132 let out_bin = root.absolute()?.join("bin").join(&cargo_fuzz_bin);
133
134 fs_err::rename(out_bin, &cached_bin_path)?;
136 cached_bin_path.absolute()?
137 };
138
139 fs_err::copy(
142 &path_to_cargo_fuzz,
143 rt.read(cargo_home).join("bin").join(&cargo_fuzz_bin),
144 )?;
145
146 Ok(())
147 }
148 });
149
150 Ok(())
151 }
152}