Use download_and_extract in fetchers

to improve efficiency by avoiding disk io (except for `PkgFmt::Zip`
and `PkgFmt::Bin`) and run the compresser in parallel to the downloader.

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>
This commit is contained in:
Jiahao XU 2022-06-09 14:46:00 +10:00
parent b6bfd40c3a
commit c9b0d45a24
No known key found for this signature in database
GPG key ID: 591C0B03040416D6
4 changed files with 19 additions and 24 deletions

View file

@ -17,8 +17,8 @@ pub trait Fetcher: Send + Sync {
where where
Self: Sized; Self: Sized;
/// Fetch a package /// Fetch a package and extract
async fn fetch(&self, dst: &Path) -> Result<(), BinstallError>; async fn fetch_and_extract(&self, dst: &Path) -> Result<(), BinstallError>;
/// Check if a package is available for download /// Check if a package is available for download
async fn check(&self) -> Result<bool, BinstallError>; async fn check(&self) -> Result<bool, BinstallError>;

View file

@ -7,7 +7,7 @@ use serde::Serialize;
use url::Url; use url::Url;
use super::Data; use super::Data;
use crate::{download, remote_exists, BinstallError, PkgFmt, Template}; use crate::{download_and_extract, remote_exists, BinstallError, PkgFmt, Template};
pub struct GhCrateMeta { pub struct GhCrateMeta {
data: Data, data: Data,
@ -40,10 +40,10 @@ impl super::Fetcher for GhCrateMeta {
remote_exists(url, Method::HEAD).await remote_exists(url, Method::HEAD).await
} }
async fn fetch(&self, dst: &Path) -> Result<(), BinstallError> { async fn fetch_and_extract(&self, dst: &Path) -> Result<(), BinstallError> {
let url = self.url()?; let url = self.url()?;
info!("Downloading package from: '{url}'"); info!("Downloading package from: '{url}'");
download(url.as_str(), dst).await download_and_extract::<_, 0>(url, self.pkg_fmt(), dst, None).await
} }
fn pkg_fmt(&self) -> PkgFmt { fn pkg_fmt(&self) -> PkgFmt {

View file

@ -6,7 +6,7 @@ use reqwest::Method;
use url::Url; use url::Url;
use super::Data; use super::Data;
use crate::{download, remote_exists, BinstallError, PkgFmt}; use crate::{download_and_extract, remote_exists, BinstallError, PkgFmt};
const BASE_URL: &str = "https://github.com/alsuren/cargo-quickinstall/releases/download"; const BASE_URL: &str = "https://github.com/alsuren/cargo-quickinstall/releases/download";
const STATS_URL: &str = "https://warehouse-clerk-tmp.vercel.app/api/crate"; const STATS_URL: &str = "https://warehouse-clerk-tmp.vercel.app/api/crate";
@ -36,10 +36,10 @@ impl super::Fetcher for QuickInstall {
remote_exists(Url::parse(&url)?, Method::HEAD).await remote_exists(Url::parse(&url)?, Method::HEAD).await
} }
async fn fetch(&self, dst: &Path) -> Result<(), BinstallError> { async fn fetch_and_extract(&self, dst: &Path) -> Result<(), BinstallError> {
let url = self.package_url(); let url = self.package_url();
info!("Downloading package from: '{url}'"); info!("Downloading package from: '{url}'");
download(&url, &dst).await download_and_extract::<_, 0>(Url::parse(&url)?, self.pkg_fmt(), dst, None).await
} }
fn pkg_fmt(&self) -> PkgFmt { fn pkg_fmt(&self) -> PkgFmt {

View file

@ -361,11 +361,21 @@ async fn install_from_package(
meta.bin_dir = "{ bin }{ binary-ext }".to_string(); meta.bin_dir = "{ bin }{ binary-ext }".to_string();
} }
let bin_path = temp_dir.path().join(format!("bin-{}", opts.name));
debug!("Using temporary binary path: {}", bin_path.display());
// Download package // Download package
if opts.dry_run { if opts.dry_run {
info!("Dry run, not downloading package"); info!("Dry run, not downloading package");
} else { } else {
fetcher.fetch(&pkg_path).await?; fetcher.fetch_and_extract(&bin_path).await?;
if binaries.is_empty() {
error!("No binaries specified (or inferred from file system)");
return Err(miette!(
"No binaries specified (or inferred from file system)"
));
}
} }
#[cfg(incomplete)] #[cfg(incomplete)]
@ -392,21 +402,6 @@ async fn install_from_package(
} }
} }
let bin_path = temp_dir.path().join(format!("bin-{}", opts.name));
debug!("Using temporary binary path: {}", bin_path.display());
if !opts.dry_run {
// Extract files
extract(&pkg_path, fetcher.pkg_fmt(), &bin_path)?;
if binaries.is_empty() {
error!("No binaries specified (or inferred from file system)");
return Err(miette!(
"No binaries specified (or inferred from file system)"
));
}
}
// List files to be installed // List files to be installed
// based on those found via Cargo.toml // based on those found via Cargo.toml
let bin_data = bins::Data { let bin_data = bins::Data {