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 sh = xshell::Shell::new()?;
165
166 let install_dir = rt.read(install_dir);
167
168 let nuget_exe_path = install_dir.join("nuget.exe");
169
170 if !nuget_exe_path.exists() {
172 let nuget_install_latest_url =
173 "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe";
174 xshell::cmd!(
175 sh,
176 "curl --fail -o {nuget_exe_path} {nuget_install_latest_url}"
177 )
178 .run()?;
179 }
180
181 let write_mono_shim = || {
182 let sh = xshell::Shell::new()?;
183 fs::write(
184 "./nuget-shim.sh",
185 format!("#!/bin/sh\nmono {}/nuget.exe \"$@\"", install_dir.display()),
186 )?;
187 xshell::cmd!(sh, "chmod +x ./nuget-shim.sh").run()?;
188 anyhow::Ok(sh.current_dir().join("nuget-shim.sh").absolute()?)
189 };
190
191 let nuget_exec_path = match rt.platform() {
192 FlowPlatform::Windows => nuget_exe_path,
193 FlowPlatform::Linux(_) if crate::_util::running_in_wsl(rt) => {
194 {
196 let windows_userprofile =
197 xshell::cmd!(sh, "cmd.exe /c echo %UserProfile%").read()?;
198
199 let windows_dot_nuget_path =
200 crate::_util::wslpath::win_to_linux(windows_userprofile)
201 .join(".nuget");
202
203 let linux_dot_nuget_path =
204 dirs::home_dir().unwrap_or_default().join(".nuget");
205
206 if windows_dot_nuget_path.exists()
209 && fs_err::symlink_metadata(&linux_dot_nuget_path).is_err()
210 {
211 xshell::cmd!(
212 sh,
213 "ln -s {windows_dot_nuget_path} {linux_dot_nuget_path}"
214 )
215 .run()?;
216 }
217 }
218
219 if force_mono_nuget_exe_wsl2 {
220 write_mono_shim()?
221 } else {
222 let windows_tempdir = crate::_util::wslpath::win_to_linux(
228 xshell::cmd!(sh, "cmd.exe /c echo %Temp%").read()?,
229 );
230 let flowey_nuget = windows_tempdir.join("flowey_nuget.exe");
231 if !flowey_nuget.exists() {
232 fs_err::copy(nuget_exe_path, &flowey_nuget)?;
233 }
234 xshell::cmd!(sh, "chmod +x {flowey_nuget}").run()?;
235 flowey_nuget
236 }
237 }
238 FlowPlatform::Linux(_) => write_mono_shim()?,
239 platform => anyhow::bail!("unsupported platform {platform}"),
240 };
241
242 rt.write_all(broadcast_nuget_tool_kind, &nuget_exec_path);
243
244 Ok(())
245 }
246 });
247
248 Ok(())
249 }
250}