flowey_lib_hvlite/
resolve_openvmm_test_initrd.rs1use crate::common::CommonArch;
12use flowey::node::prelude::*;
13use std::collections::BTreeMap;
14use std::collections::BTreeSet;
15
16flowey_config! {
17 pub struct Config {
19 pub version: Option<String>,
21 pub local_paths: BTreeMap<CommonArch, ConfigVar<PathBuf>>,
24 }
25}
26
27flowey_request! {
28 pub enum Request {
29 Get(CommonArch, WriteVar<PathBuf>),
31 }
32}
33
34new_flow_node_with_config!(struct Node);
35
36impl FlowNodeWithConfig for Node {
37 type Request = Request;
38 type Config = Config;
39
40 fn imports(ctx: &mut ImportCtx<'_>) {
41 ctx.import::<flowey_lib_common::install_dist_pkg::Node>();
42 ctx.import::<flowey_lib_common::download_gh_release::Node>();
43 }
44
45 fn emit(
46 config: Config,
47 requests: Vec<Self::Request>,
48 ctx: &mut NodeCtx<'_>,
49 ) -> anyhow::Result<()> {
50 let Config {
51 version,
52 local_paths,
53 } = config;
54 let mut deps: BTreeMap<CommonArch, Vec<WriteVar<PathBuf>>> = BTreeMap::new();
55
56 for req in requests {
57 match req {
58 Request::Get(arch, var) => {
59 deps.entry(arch).or_default().push(var);
60 }
61 }
62 }
63
64 if version.is_some() && !local_paths.is_empty() {
65 anyhow::bail!("Cannot specify both Version and LocalPath requests");
66 }
67
68 if version.is_none() && local_paths.is_empty() {
69 anyhow::bail!("Must specify a Version or LocalPath request");
70 }
71
72 if deps.is_empty() {
75 return Ok(());
76 }
77
78 if !local_paths.is_empty() {
79 ctx.emit_rust_step("use local openvmm-test-initrd", |ctx| {
80 let deps = deps.claim(ctx);
81 let local_paths: BTreeMap<_, _> = local_paths
82 .into_iter()
83 .map(|(key, var)| (key, var.claim(ctx)))
84 .collect();
85 move |rt| {
86 let resolved_paths: BTreeMap<CommonArch, PathBuf> = local_paths
87 .into_iter()
88 .map(|(key, var)| (key, rt.read(var)))
89 .collect();
90
91 for (arch, vars) in deps {
92 let base_dir = resolved_paths.get(&arch).ok_or_else(|| {
93 anyhow::anyhow!("No local path specified for {:?}", arch)
94 })?;
95 let path = base_dir.join("initrd");
96 rt.write_all(vars, &path)
97 }
98
99 Ok(())
100 }
101 });
102
103 return Ok(());
104 }
105
106 let needed_archives: BTreeSet<CommonArch> = deps.keys().copied().collect();
110
111 let mut archives = BTreeMap::new();
112 for arch in needed_archives {
113 let version = version.clone().expect("local requests handled above");
114 let arch_str = match arch {
115 CommonArch::X86_64 => "x86_64",
116 CommonArch::Aarch64 => "aarch64",
117 };
118 let archive = ctx.reqv(|v| flowey_lib_common::download_gh_release::Request {
119 repo_owner: "microsoft".into(),
120 repo_name: "openvmm-deps".into(),
121 needs_auth: false,
122 tag: version.clone(),
123 file_name: format!("openvmm-test-initrd.{arch_str}.{version}.tar.gz"),
124 path: v,
125 });
126 archives.insert(arch, archive);
127 }
128
129 let persistent_dir = ctx.persistent_dir();
130
131 ctx.emit_rust_step("unpack openvmm-test-initrd archives", |ctx| {
132 let persistent_dir = persistent_dir.claim(ctx);
133 let archives = archives.claim(ctx);
134 let deps = deps.claim(ctx);
135 let version = version.clone().expect("local requests handled above");
136 move |rt| {
137 let persistent_dir = persistent_dir.map(|d| rt.read(d));
138
139 let mut extract_dirs = BTreeMap::new();
140 for (arch, archive) in archives {
141 let file = rt.read(archive);
142 let dir = flowey_lib_common::_util::extract::extract_tar_gz_if_new(
143 rt,
144 persistent_dir.as_deref(),
145 &file,
146 &version,
147 )?;
148 extract_dirs.insert(arch, dir);
149 }
150
151 for (arch, vars) in deps {
152 let path = extract_dirs[&arch].join("initrd");
153 rt.write_all(vars, &path)
154 }
155
156 Ok(())
157 }
158 });
159
160 Ok(())
161 }
162}