Skip to content

Commit 01de331

Browse files
perf(upgrade): cache downloaded binaries in DENO_DIR (denoland#26108)
Co-authored-by: Divy Srivastava <dj.srivastava23@gmail.com>
1 parent 73fbd61 commit 01de331

File tree

8 files changed

+128
-117
lines changed

8 files changed

+128
-117
lines changed

cli/download_deno_binary.rs

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
2+
3+
use std::path::Path;
4+
use std::path::PathBuf;
5+
6+
use crate::http_util::HttpClient;
7+
use crate::http_util::HttpClientProvider;
8+
use crate::util::progress_bar::ProgressBar;
9+
use crate::util::progress_bar::ProgressBarStyle;
10+
use deno_core::anyhow::bail;
11+
use deno_core::error::AnyError;
12+
13+
use crate::cache::DenoDir;
14+
use crate::shared::ReleaseChannel;
15+
16+
#[derive(Clone, Copy, Debug)]
17+
pub enum BinaryKind {
18+
Deno,
19+
Denort,
20+
}
21+
22+
impl BinaryKind {
23+
pub fn name(&self) -> &str {
24+
match self {
25+
BinaryKind::Deno => "deno",
26+
BinaryKind::Denort => "denort",
27+
}
28+
}
29+
}
30+
31+
pub async fn download_deno_binary(
32+
http_client_provider: &HttpClientProvider,
33+
deno_dir: &DenoDir,
34+
binary_kind: BinaryKind,
35+
target: &str,
36+
version_or_git_hash: &str,
37+
release_channel: ReleaseChannel,
38+
) -> Result<PathBuf, AnyError> {
39+
let binary_name = archive_name(binary_kind, target);
40+
let binary_path_suffix = match release_channel {
41+
ReleaseChannel::Canary => {
42+
format!("canary/{}/{}", version_or_git_hash, binary_name,)
43+
}
44+
_ => {
45+
format!("release/v{}/{}", version_or_git_hash, binary_name)
46+
}
47+
};
48+
49+
let download_directory = deno_dir.dl_folder_path();
50+
let binary_path = download_directory.join(&binary_path_suffix);
51+
52+
if !binary_path.exists() {
53+
let http_client = http_client_provider.get_or_create()?;
54+
download_base_binary(
55+
&http_client,
56+
&download_directory,
57+
&binary_path_suffix,
58+
)
59+
.await?;
60+
}
61+
62+
Ok(binary_path)
63+
}
64+
65+
pub fn archive_name(binary_kind: BinaryKind, target: &str) -> String {
66+
format!("{}-{}.zip", binary_kind.name(), target)
67+
}
68+
69+
async fn download_base_binary(
70+
http_client: &HttpClient,
71+
output_directory: &Path,
72+
binary_path_suffix: &str,
73+
) -> Result<(), AnyError> {
74+
let download_url = format!("https://dl.deno.land/{binary_path_suffix}");
75+
let maybe_bytes = {
76+
let progress_bars = ProgressBar::new(ProgressBarStyle::DownloadBars);
77+
// provide an empty string here in order to prefer the downloading
78+
// text above which will stay alive after the progress bars are complete
79+
let progress = progress_bars.update("");
80+
http_client
81+
.download_with_progress_and_retries(
82+
download_url.parse()?,
83+
None,
84+
&progress,
85+
)
86+
.await?
87+
};
88+
let Some(bytes) = maybe_bytes else {
89+
bail!("Failed downloading {download_url}. The version you requested may not have been built for the current architecture.");
90+
};
91+
92+
std::fs::create_dir_all(output_directory)?;
93+
let output_path = output_directory.join(binary_path_suffix);
94+
std::fs::create_dir_all(output_path.parent().unwrap())?;
95+
tokio::fs::write(output_path, bytes).await?;
96+
Ok(())
97+
}

cli/main.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ mod args;
44
mod auth_tokens;
55
mod cache;
66
mod cdp;
7+
mod download_deno_binary;
78
mod emit;
89
mod errors;
910
mod factory;

cli/mainrt.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ mod standalone;
1010
mod args;
1111
mod auth_tokens;
1212
mod cache;
13+
mod download_deno_binary;
1314
mod emit;
1415
mod errors;
1516
mod file_fetcher;

cli/standalone/binary.rs

Lines changed: 15 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@ use crate::args::NpmInstallDepsProvider;
6363
use crate::args::PermissionFlags;
6464
use crate::args::UnstableConfig;
6565
use crate::cache::DenoDir;
66+
use crate::download_deno_binary::archive_name;
67+
use crate::download_deno_binary::download_deno_binary;
68+
use crate::download_deno_binary::BinaryKind;
6669
use crate::emit::Emitter;
6770
use crate::file_fetcher::FileFetcher;
6871
use crate::http_util::HttpClientProvider;
@@ -452,36 +455,24 @@ impl<'a> DenoCompileBinaryWriter<'a> {
452455
}
453456

454457
let target = compile_flags.resolve_target();
455-
let binary_name = format!("denort-{target}.zip");
456-
457-
let binary_path_suffix =
458-
match crate::version::DENO_VERSION_INFO.release_channel {
459-
ReleaseChannel::Canary => {
460-
format!(
461-
"canary/{}/{}",
462-
crate::version::DENO_VERSION_INFO.git_hash,
463-
binary_name
464-
)
465-
}
466-
_ => {
467-
format!("release/v{}/{}", env!("CARGO_PKG_VERSION"), binary_name)
468-
}
469-
};
470458

471-
let download_directory = self.deno_dir.dl_folder_path();
472-
let binary_path = download_directory.join(&binary_path_suffix);
459+
let archive_name = archive_name(BinaryKind::Denort, &target);
473460

474-
if !binary_path.exists() {
475-
self
476-
.download_base_binary(&download_directory, &binary_path_suffix)
477-
.await?;
478-
}
461+
let binary_path = download_deno_binary(
462+
self.http_client_provider,
463+
self.deno_dir,
464+
BinaryKind::Denort,
465+
&target,
466+
crate::version::DENO_VERSION_INFO.version_or_git_hash(),
467+
crate::version::DENO_VERSION_INFO.release_channel,
468+
)
469+
.await?;
479470

480471
let archive_data = std::fs::read(binary_path)?;
481472
let temp_dir = tempfile::TempDir::new()?;
482473
let base_binary_path = archive::unpack_into_dir(archive::UnpackArgs {
483-
exe_name: "denort",
484-
archive_name: &binary_name,
474+
exe_name: BinaryKind::Denort.name(),
475+
archive_name: &archive_name,
485476
archive_data: &archive_data,
486477
is_windows: target.contains("windows"),
487478
dest_path: temp_dir.path(),
@@ -491,41 +482,6 @@ impl<'a> DenoCompileBinaryWriter<'a> {
491482
Ok(base_binary)
492483
}
493484

494-
async fn download_base_binary(
495-
&self,
496-
output_directory: &Path,
497-
binary_path_suffix: &str,
498-
) -> Result<(), AnyError> {
499-
let download_url = format!("https://dl.deno.land/{binary_path_suffix}");
500-
let maybe_bytes = {
501-
let progress_bars = ProgressBar::new(ProgressBarStyle::DownloadBars);
502-
let progress = progress_bars.update(&download_url);
503-
504-
self
505-
.http_client_provider
506-
.get_or_create()?
507-
.download_with_progress_and_retries(
508-
download_url.parse()?,
509-
None,
510-
&progress,
511-
)
512-
.await?
513-
};
514-
let bytes = match maybe_bytes {
515-
Some(bytes) => bytes,
516-
None => {
517-
log::info!("Download could not be found, aborting");
518-
std::process::exit(1)
519-
}
520-
};
521-
522-
std::fs::create_dir_all(output_directory)?;
523-
let output_path = output_directory.join(binary_path_suffix);
524-
std::fs::create_dir_all(output_path.parent().unwrap())?;
525-
tokio::fs::write(output_path, bytes).await?;
526-
Ok(())
527-
}
528-
529485
/// This functions creates a standalone deno binary by appending a bundle
530486
/// and magic trailer to the currently executing binary.
531487
#[allow(clippy::too_many_arguments)]

cli/tools/upgrade.rs

Lines changed: 14 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,14 @@ use crate::args::Flags;
66
use crate::args::UpgradeFlags;
77
use crate::args::UPGRADE_USAGE;
88
use crate::colors;
9+
use crate::download_deno_binary::archive_name;
10+
use crate::download_deno_binary::download_deno_binary;
11+
use crate::download_deno_binary::BinaryKind;
912
use crate::factory::CliFactory;
1013
use crate::http_util::HttpClient;
1114
use crate::http_util::HttpClientProvider;
1215
use crate::shared::ReleaseChannel;
1316
use crate::util::archive;
14-
use crate::util::progress_bar::ProgressBar;
15-
use crate::util::progress_bar::ProgressBarStyle;
1617
use crate::version;
1718

1819
use async_trait::async_trait;
@@ -34,12 +35,8 @@ use std::process::Command;
3435
use std::sync::Arc;
3536
use std::time::Duration;
3637

37-
const RELEASE_URL: &str = "https://github.com/denoland/deno/releases";
38-
const CANARY_URL: &str = "https://dl.deno.land/canary";
39-
const DL_RELEASE_URL: &str = "https://dl.deno.land/release";
40-
41-
pub static ARCHIVE_NAME: Lazy<String> =
42-
Lazy::new(|| format!("deno-{}.zip", env!("TARGET")));
38+
static ARCHIVE_NAME: Lazy<String> =
39+
Lazy::new(|| archive_name(BinaryKind::Deno, env!("TARGET")));
4340

4441
// How often query server for new version. In hours.
4542
const UPGRADE_CHECK_INTERVAL: i64 = 24;
@@ -532,13 +529,17 @@ pub async fn upgrade(
532529
return Ok(());
533530
};
534531

535-
let download_url = get_download_url(
532+
let binary_path = download_deno_binary(
533+
http_client_provider,
534+
factory.deno_dir()?,
535+
BinaryKind::Deno,
536+
env!("TARGET"),
536537
&selected_version_to_upgrade.version_or_hash,
537538
requested_version.release_channel(),
538-
)?;
539-
log::info!("{}", colors::gray(format!("Downloading {}", &download_url)));
540-
let Some(archive_data) = download_package(&client, download_url).await?
541-
else {
539+
)
540+
.await?;
541+
542+
let Ok(archive_data) = tokio::fs::read(&binary_path).await else {
542543
log::error!("Download could not be found, aborting");
543544
std::process::exit(1)
544545
};
@@ -881,48 +882,6 @@ fn base_upgrade_url() -> Cow<'static, str> {
881882
}
882883
}
883884

884-
fn get_download_url(
885-
version: &str,
886-
release_channel: ReleaseChannel,
887-
) -> Result<Url, AnyError> {
888-
let download_url = match release_channel {
889-
ReleaseChannel::Stable => {
890-
format!("{}/download/v{}/{}", RELEASE_URL, version, *ARCHIVE_NAME)
891-
}
892-
ReleaseChannel::Rc => {
893-
format!("{}/v{}/{}", DL_RELEASE_URL, version, *ARCHIVE_NAME)
894-
}
895-
ReleaseChannel::Canary => {
896-
format!("{}/{}/{}", CANARY_URL, version, *ARCHIVE_NAME)
897-
}
898-
ReleaseChannel::Lts => {
899-
format!("{}/v{}/{}", DL_RELEASE_URL, version, *ARCHIVE_NAME)
900-
}
901-
};
902-
903-
Url::parse(&download_url).with_context(|| {
904-
format!(
905-
"Failed to parse URL to download new release: {}",
906-
download_url
907-
)
908-
})
909-
}
910-
911-
async fn download_package(
912-
client: &HttpClient,
913-
download_url: Url,
914-
) -> Result<Option<Vec<u8>>, AnyError> {
915-
let progress_bar = ProgressBar::new(ProgressBarStyle::DownloadBars);
916-
// provide an empty string here in order to prefer the downloading
917-
// text above which will stay alive after the progress bars are complete
918-
let progress = progress_bar.update("");
919-
let maybe_bytes = client
920-
.download_with_progress_and_retries(download_url.clone(), None, &progress)
921-
.await
922-
.with_context(|| format!("Failed downloading {download_url}. The version you requested may not have been built for the current architecture."))?;
923-
Ok(maybe_bytes)
924-
}
925-
926885
fn replace_exe(from: &Path, to: &Path) -> Result<(), std::io::Error> {
927886
if cfg!(windows) {
928887
// On windows you cannot replace the currently running executable.

tests/specs/upgrade/out/upgrade.out

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
Current Deno version: [WILDCARD]
2-
Downloading https://github.com/denoland/deno/releases/download/v1.43.2/deno-[WILDCARD].zip
32
Deno is upgrading to version 1.43.2
43

54
Upgraded successfully to Deno v1.43.2 (stable)

tests/specs/upgrade/space_in_tmp/upgrade.out

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
Current Deno version: [WILDCARD]
2-
Downloading https://github.com/denoland/deno/releases/download/v1.43.2/deno-[WILDCARD].zip
32
Deno is upgrading to version 1.43.2
43

54
Upgraded successfully to Deno v1.43.2 (stable)

tests/specs/upgrade/specific_stable/upgrade.out

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
Current Deno version: [WILDCARD]
2-
Downloading https://github.com/denoland/deno/releases/download/v1.43.2/deno-[WILDCARD].zip
32
Deno is upgrading to version 1.43.2
43

54
Upgraded successfully to Deno v1.43.2 (stable)

0 commit comments

Comments
 (0)