diff --git a/src/config/settings.rs b/src/config/settings.rs index fedf3da65c..63c4f2625a 100644 --- a/src/config/settings.rs +++ b/src/config/settings.rs @@ -176,7 +176,9 @@ impl Settings { settings.yes = true; } if settings.all_compile { - settings.node.compile = Some(true); + if settings.node.compile.is_none() { + settings.node.compile = Some(true); + } if settings.python.compile.is_none() { settings.python.compile = Some(true); } diff --git a/src/plugins/core/node.rs b/src/plugins/core/node.rs index b08175b6c7..d72ef4cc39 100644 --- a/src/plugins/core/node.rs +++ b/src/plugins/core/node.rs @@ -27,6 +27,11 @@ pub struct NodePlugin { ba: Arc, } +enum FetchOutcome { + Downloaded, + NotFound, +} + impl NodePlugin { pub fn new() -> Self { Self { @@ -34,54 +39,15 @@ impl NodePlugin { } } - async fn install_precompiled( + async fn fetch_binary( &self, ctx: &InstallContext, tv: &mut ToolVersion, opts: &BuildOpts, - ) -> Result<()> { - let settings = Settings::get(); - match self - .fetch_tarball( - ctx, - tv, - &ctx.pr, - &opts.binary_tarball_url, - &opts.binary_tarball_path, - &opts.version, - ) - .await - { - Err(e) - if settings.node.compile != Some(false) - && matches!(http::error_code(&e), Some(404)) => - { - debug!("precompiled node not found"); - return self.install_compiled(ctx, tv, opts).await; - } - e => e, - }?; - let tarball_name = &opts.binary_tarball_name; - ctx.pr.set_message(format!("extract {tarball_name}")); - file::remove_all(&opts.install_path)?; - file::untar( - &opts.binary_tarball_path, - &opts.install_path, - &TarOptions { - format: TarFormat::TarGz, - strip_components: 1, - pr: Some(&ctx.pr), - }, - )?; - Ok(()) - } + extract: impl FnOnce() -> Result<()>, + ) -> Result { + debug!("{:?}: we will fetch a precompiled version", self); - async fn install_windows( - &self, - ctx: &InstallContext, - tv: &mut ToolVersion, - opts: &BuildOpts, - ) -> Result<()> { match self .fetch_tarball( ctx, @@ -93,13 +59,30 @@ impl NodePlugin { ) .await { + Ok(()) => { + debug!("{:?}: successfully downloaded node archive", self); + } Err(e) if matches!(http::error_code(&e), Some(404)) => { - bail!("precompiled node not found {e}"); + debug!("{:?}: precompiled node archive not found {e}", self); + return Ok(FetchOutcome::NotFound); } - e => e, - }?; + Err(e) => return Err(e), + }; + let tarball_name = &opts.binary_tarball_name; ctx.pr.set_message(format!("extract {tarball_name}")); + debug!("{:?}: extracting precompiled node", self); + + if let Err(e) = extract() { + debug!("{:?}: extraction failed: {e}", self); + return Err(e); + } + + debug!("{:?}: precompiled node extraction was successful", self); + Ok(FetchOutcome::Downloaded) + } + + fn extract_zip(&self, opts: &BuildOpts, _ctx: &InstallContext) -> Result<()> { let tmp_extract_path = tempdir_in(opts.install_path.parent().unwrap())?; file::unzip( &opts.binary_tarball_path, @@ -114,12 +97,60 @@ impl NodePlugin { Ok(()) } - async fn install_compiled( + async fn install_precompiled( + &self, + ctx: &InstallContext, + tv: &mut ToolVersion, + opts: &BuildOpts, + ) -> Result<()> { + match self + .fetch_binary(ctx, tv, opts, || { + file::untar( + &opts.binary_tarball_path, + &opts.install_path, + &TarOptions { + format: TarFormat::TarGz, + strip_components: 1, + pr: Some(&ctx.pr), + }, + )?; + Ok(()) + }) + .await? + { + FetchOutcome::Downloaded => Ok(()), + FetchOutcome::NotFound => { + if Settings::get().node.compile != Some(false) { + self.install_compiling(ctx, tv, opts).await + } else { + bail!("precompiled node archive not found and compilation is disabled") + } + } + } + } + + async fn install_windows( + &self, + ctx: &InstallContext, + tv: &mut ToolVersion, + opts: &BuildOpts, + ) -> Result<()> { + match self + .fetch_binary(ctx, tv, opts, || self.extract_zip(opts, ctx)) + .await? + { + FetchOutcome::Downloaded => Ok(()), + FetchOutcome::NotFound => bail!("precompiled node archive not found (404)"), + } + } + + async fn install_compiling( &self, ctx: &InstallContext, tv: &mut ToolVersion, opts: &BuildOpts, ) -> Result<()> { + debug!("{:?}: we will fetch the source and compile", self); let tarball_name = &opts.source_tarball_name; self.fetch_tarball( ctx, @@ -454,10 +485,11 @@ impl Backend for NodePlugin { if cfg!(windows) { self.install_windows(ctx, &mut tv, &opts).await?; } else if settings.node.compile == Some(true) { - self.install_compiled(ctx, &mut tv, &opts).await?; + self.install_compiling(ctx, &mut tv, &opts).await?; } else { self.install_precompiled(ctx, &mut tv, &opts).await?; } + debug!("{:?}: checking installation is working as expected", self); self.test_node(&ctx.config, &tv, &ctx.pr).await?; if !cfg!(windows) { self.install_npm_shim(&tv)?;