flowey_lib_common/
download_nuget_exe.rs1use flowey::node::prelude::*;
7use std::fs;
8
9#[derive(Serialize, Deserialize)]
10pub enum NugetInstallPlatform {
11 Windows,
12 Linux,
13 MacOs,
14}
15
16flowey_request! {
17 pub enum Request {
18 NugetBin(WriteVar<PathBuf>),
19 NugetInstallPlatform(WriteVar<NugetInstallPlatform>),
20 LocalOnlyForceWsl2MonoNugetExe(bool),
26 }
27}
28
29new_flow_node!(struct Node);
30
31impl FlowNode for Node {
32 type Request = Request;
33
34 fn imports(ctx: &mut ImportCtx<'_>) {
35 ctx.import::<crate::ado_task_nuget_tool_installer::Node>();
36 ctx.import::<crate::install_dist_pkg::Node>();
37 }
38
39 fn emit(requests: Vec<Self::Request>, ctx: &mut NodeCtx<'_>) -> anyhow::Result<()> {
40 let mut broadcast_nuget_tool_kind = Vec::new();
41 let mut broadcast_nuget_config_platform = Vec::new();
42 let mut force_mono_nuget_exe_wsl2 = None;
43
44 for req in requests {
45 match req {
46 Request::LocalOnlyForceWsl2MonoNugetExe(v) => same_across_all_reqs(
47 "LocalOnlyForceWsl2MonoNugetExe",
48 &mut force_mono_nuget_exe_wsl2,
49 v,
50 )?,
51 Request::NugetBin(outvar) => broadcast_nuget_tool_kind.push(outvar),
52 Request::NugetInstallPlatform(outvar) => {
53 broadcast_nuget_config_platform.push(outvar)
54 }
55 };
56 }
57
58 let broadcast_nuget_tool_kind = broadcast_nuget_tool_kind;
59 let broadcast_nuget_config_platform = broadcast_nuget_config_platform;
60
61 let force_mono_nuget_exe_wsl2 = if matches!(ctx.backend(), FlowBackend::Local) {
62 force_mono_nuget_exe_wsl2.ok_or(anyhow::anyhow!(
63 "Missing essential request: LocalOnlyForceWsl2MonoNugetExe"
64 ))?
65 } else {
66 if force_mono_nuget_exe_wsl2.is_some() {
67 anyhow::bail!(
68 "can only use `LocalOnlyForceWsl2MonoNugetExe` when using the Local backend"
69 );
70 }
71 false
72 };
73
74 if !broadcast_nuget_config_platform.is_empty() {
77 ctx.emit_rust_step("report nuget install platform", |ctx| {
78 let broadcast_nuget_config_platform = broadcast_nuget_config_platform.claim(ctx);
79 move |rt| {
80 let nuget_config_platform = match rt.platform() {
81 FlowPlatform::Windows => NugetInstallPlatform::Windows,
82 FlowPlatform::Linux(_) if crate::_util::running_in_wsl(rt) => {
83 if force_mono_nuget_exe_wsl2 {
84 NugetInstallPlatform::Linux
85 } else {
86 NugetInstallPlatform::Windows
87 }
88 }
89 FlowPlatform::Linux(_) => NugetInstallPlatform::Linux,
90 FlowPlatform::MacOs => NugetInstallPlatform::MacOs,
91 platform => anyhow::bail!("unsupported platform {platform}"),
92 };
93
94 rt.write_all(broadcast_nuget_config_platform, &nuget_config_platform);
95
96 Ok(())
97 }
98 });
99 }
100
101 match ctx.backend() {
102 FlowBackend::Ado => Self::emit_ado(ctx, broadcast_nuget_tool_kind),
103 FlowBackend::Local => {
104 Self::emit_local(ctx, broadcast_nuget_tool_kind, force_mono_nuget_exe_wsl2)
105 }
106 FlowBackend::Github => {
107 anyhow::bail!("nuget installation not yet implemented for the Github backend")
108 }
109 }
110 }
111}
112
113impl Node {
114 fn emit_ado(
115 ctx: &mut NodeCtx<'_>,
116 broadcast_nuget_tool_kind: Vec<WriteVar<PathBuf>>,
117 ) -> anyhow::Result<()> {
118 let nuget_tool_installed = ctx.reqv(crate::ado_task_nuget_tool_installer::Request);
119
120 ctx.emit_rust_step("report nuget install", move |ctx| {
121 nuget_tool_installed.claim(ctx);
122 let broadcast_nuget_tool_kind = broadcast_nuget_tool_kind.claim(ctx);
123 move |rt| {
124 rt.write_all(
126 broadcast_nuget_tool_kind,
127 &which::which(rt.platform().binary("nuget"))?,
128 );
129
130 Ok(())
131 }
132 });
133
134 Ok(())
135 }
136
137 fn emit_local(
138 ctx: &mut NodeCtx<'_>,
139 broadcast_nuget_tool_kind: Vec<WriteVar<PathBuf>>,
140 force_mono_nuget_exe_wsl2: bool,
141 ) -> anyhow::Result<()> {
142 if broadcast_nuget_tool_kind.is_empty() {
143 return Ok(());
144 }
145
146 let install_dir = ctx
147 .persistent_dir()
148 .ok_or(anyhow::anyhow!("No persistent dir for nuget installation"))?;
149
150 ctx.emit_rust_step("Install nuget", |ctx| {
160 let install_dir = install_dir.clone().claim(ctx);
162 let broadcast_nuget_tool_kind = broadcast_nuget_tool_kind.claim(ctx);
163 move |rt| {
164 let install_dir = rt.read(install_dir);
165
166 let nuget_exe_path = install_dir.join("nuget.exe");
167
168 if !nuget_exe_path.exists() {
170 let nuget_install_latest_url =
171 "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe";
172 flowey::shell_cmd!(
173 rt,
174 "curl --fail -o {nuget_exe_path} {nuget_install_latest_url}"
175 )
176 .run()?;
177 }
178
179 let write_mono_shim = |rt: &mut RustRuntimeServices<'_>| {
180 fs::write(
181 "./nuget-shim.sh",
182 format!("#!/bin/sh\nmono {}/nuget.exe \"$@\"", install_dir.display()),
183 )?;
184 flowey::shell_cmd!(rt, "chmod +x ./nuget-shim.sh").run()?;
185 anyhow::Ok(rt.sh.current_dir().join("nuget-shim.sh").absolute()?)
186 };
187
188 let nuget_exec_path = match rt.platform() {
189 FlowPlatform::Windows => nuget_exe_path,
190 FlowPlatform::Linux(_) if crate::_util::running_in_wsl(rt) => {
191 {
193 let windows_userprofile =
194 flowey::shell_cmd!(rt, "cmd.exe /c echo %UserProfile%").read()?;
195
196 let windows_dot_nuget_path =
197 crate::_util::wslpath::win_to_linux(rt, windows_userprofile)
198 .join(".nuget");
199
200 let linux_dot_nuget_path =
201 dirs::home_dir().unwrap_or_default().join(".nuget");
202
203 if windows_dot_nuget_path.exists()
206 && fs_err::symlink_metadata(&linux_dot_nuget_path).is_err()
207 {
208 flowey::shell_cmd!(
209 rt,
210 "ln -s {windows_dot_nuget_path} {linux_dot_nuget_path}"
211 )
212 .run()?;
213 }
214 }
215
216 if force_mono_nuget_exe_wsl2 {
217 write_mono_shim(rt)?
218 } else {
219 let windows_tempdir = crate::_util::wslpath::win_to_linux(
225 rt,
226 flowey::shell_cmd!(rt, "cmd.exe /c echo %Temp%").read()?,
227 );
228 let flowey_nuget = windows_tempdir.join("flowey_nuget.exe");
229 if !flowey_nuget.exists() {
230 fs_err::copy(nuget_exe_path, &flowey_nuget)?;
231 }
232 flowey::shell_cmd!(rt, "chmod +x {flowey_nuget}").run()?;
233 flowey_nuget
234 }
235 }
236 FlowPlatform::Linux(_) => write_mono_shim(rt)?,
237 platform => anyhow::bail!("unsupported platform {platform}"),
238 };
239
240 rt.write_all(broadcast_nuget_tool_kind, &nuget_exec_path);
241
242 Ok(())
243 }
244 });
245
246 Ok(())
247 }
248}