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