flowey_lib_common/
download_cargo_nextest.rs1use crate::cache::CacheHit;
7use flowey::node::prelude::*;
8use std::collections::BTreeMap;
9
10flowey_config! {
11 pub struct Config {
13 pub version: Option<String>,
15 }
16}
17
18flowey_request! {
19 pub enum Request {
20 Get(target_lexicon::Triple, WriteVar<PathBuf>),
25 }
26}
27
28new_flow_node_with_config!(struct Node);
29
30impl FlowNodeWithConfig for Node {
31 type Request = Request;
32 type Config = Config;
33
34 fn imports(ctx: &mut ImportCtx<'_>) {
35 ctx.import::<crate::cache::Node>();
36 }
37
38 fn emit(
39 config: Config,
40 requests: Vec<Self::Request>,
41 ctx: &mut NodeCtx<'_>,
42 ) -> anyhow::Result<()> {
43 let mut reqs: BTreeMap<String, Vec<WriteVar<PathBuf>>> = BTreeMap::new();
44
45 for req in requests {
46 match req {
47 Request::Get(target, path) => {
48 reqs.entry(target.to_string()).or_default().push(path)
49 }
50 }
51 }
52
53 let version = config
54 .version
55 .ok_or(anyhow::anyhow!("missing config: version"))?;
56 let reqs = reqs;
57
58 if reqs.is_empty() {
61 return Ok(());
62 }
63
64 let cache_dir = ctx.emit_rust_stepv("create cargo-nextest cache dir", |_| {
65 |_| Ok(std::env::current_dir()?.absolute()?)
66 });
67
68 for (target, paths) in reqs {
69 let (cache_key, cache_dir) = {
70 let version = version.clone();
71 let cache_key = format!("cargo-nextest-{version}-{target}");
72 let cache_dir = cache_dir.map(ctx, {
73 let k = cache_key.clone();
74 |p| p.join(k)
75 });
76 (ReadVar::from_static(cache_key), cache_dir)
77 };
78
79 let hitvar = ctx.reqv(|v| {
80 crate::cache::Request {
81 label: "cargo-nextest".into(),
82 dir: cache_dir.clone(),
83 key: cache_key,
84 restore_keys: None, hitvar: v,
86 }
87 });
88
89 let version = version.clone();
90 ctx.emit_rust_step("downloading cargo-nextest", |ctx| {
91 let paths = paths.claim(ctx);
92 let cache_dir = cache_dir.claim(ctx);
93 let hitvar = hitvar.claim(ctx);
94
95 move |rt| {
96 let cache_dir = rt.read(cache_dir);
97
98 let cargo_nextest_bin = if target.contains("windows") {
99 "cargo-nextest.exe"
100 } else {
101 "cargo-nextest"
102 };
103 let cached_bin_path = cache_dir.join(cargo_nextest_bin);
104
105 if !matches!(rt.read(hitvar), CacheHit::Hit) {
106 download_cargo_nextest(rt, version, target)?;
107
108 fs_err::create_dir_all(&cache_dir)?;
110 fs_err::rename(cargo_nextest_bin, &cached_bin_path)?;
111 }
112
113 let cached_bin_path = cached_bin_path.absolute()?;
114 log::info!("downloaded to {}", cached_bin_path.to_string_lossy());
115 assert!(cached_bin_path.exists());
116 for path in paths {
117 rt.write(path, &cached_bin_path);
118 }
119
120 Ok(())
121 }
122 });
123 }
124
125 Ok(())
126 }
127}
128
129fn download_cargo_nextest(
132 rt: &mut RustRuntimeServices<'_>,
133 version: String,
134 target: String,
135) -> anyhow::Result<()> {
136 let nextest_archive = "nextest.tar.gz";
137 flowey::shell_cmd!(
138 rt,
139 "curl --fail -L https://get.nexte.st/{version}/{target}.tar.gz -o {nextest_archive}"
140 )
141 .run()?;
142 flowey::shell_cmd!(rt, "tar -xf {nextest_archive}").run()?;
143
144 Ok(())
145}