Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: smoother large file download&proxy #463

Merged
merged 10 commits into from
Dec 12, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]

### Added
- smoother large file download&proxy support (#463)

### Fixed
- When queriying GitHub for the list of releases, retrieve more items (#462)
Expand Down
40 changes: 40 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ rust-version = "1.74.1"

[dependencies]
async-trait = "0.1.83"
bytes = "1.8.0"
clap = { version = "4.5.21", features = ["derive", "env"] }
clap_complete = "4.5.38"
directories = "5.0.1"
Expand All @@ -24,7 +25,7 @@ guess_host_triple = "0.1.4"
log = "0.4.22"
miette = { version = "7.3.0", features = ["fancy"] }
regex = "1.11.1"
reqwest = { version = "0.12.9", features = ["blocking", "socks"] }
reqwest = { version = "0.12.9", features = ["blocking", "socks", "stream"] }
retry = "2.0.0"
serde_json = "1.0.133"
strum = { version = "0.26.3", features = ["derive"] }
Expand All @@ -33,6 +34,7 @@ tempfile = "3.14.0"
thiserror = "2.0.3"
tokio = { version = "1.41.1", features = ["full"] }
tokio-retry = "0.3.0"
tokio-stream = "0.1.17"
update-informer = "1.1.0"
xz2 = "0.1.7"
zip = "2.2.1"
Expand Down
54 changes: 52 additions & 2 deletions src/toolchain/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ use std::{
use tar::Archive;
use tokio::{fs::remove_dir_all, sync::mpsc};
use tokio_retry::{strategy::FixedInterval, Retry};
use tokio_stream::StreamExt;
use xz2::read::XzDecoder;
use zip::ZipArchive;

Expand All @@ -49,6 +50,27 @@ pub trait Installable {
fn name(&self) -> String;
}

/// Get https proxy from environment variables(if any)
///
/// sadly there is not standard on the environment variable name for the proxy, but it seems
/// that the most common are:
///
/// - https_proxy(or http_proxy for http)
/// - HTTPS_PROXY(or HTTP_PROXY for http)
/// - all_proxy
/// - ALL_PROXY
///
/// hence we will check for all of them
fn https_proxy() -> Option<String> {
for proxy in ["https_proxy", "HTTPS_PROXY", "all_proxy", "ALL_PROXY"] {
if let Ok(proxy_addr) = std::env::var(proxy) {
info!("Get Proxy from env var: {}={}", proxy, proxy_addr);
return Some(proxy_addr);
}
}
None
}

/// Downloads a file from a URL and uncompresses it, if necesary, to the output directory.
pub async fn download_file(
url: String,
Expand All @@ -70,8 +92,36 @@ pub async fn download_file(
.map_err(|_| Error::CreateDirectory(output_directory.to_string()))?;
}
info!("Downloading '{}'", &file_name);
let resp = reqwest::get(&url).await?;
let bytes = resp.bytes().await?;

let resp = {
let mut builder = reqwest::Client::builder();
if let Some(proxy) = https_proxy() {
builder = builder.proxy(reqwest::Proxy::https(&proxy).unwrap());
}
let client = builder.build()?;
client.get(&url).send().await?
};
let bytes = {
let len = resp.content_length();
let mut size_downloaded = 0;
let mut stream = resp.bytes_stream();
let mut bytes = bytes::BytesMut::new();
while let Some(chunk_result) = stream.next().await {
let chunk = chunk_result?;
size_downloaded += chunk.len();
if let Some(len) = len {
print!(
"\rDownloading {file_name} {}/{} bytes",
size_downloaded, len
);
} else {
print!("\rDownloaded {file_name} {} bytes", size_downloaded);
discord9 marked this conversation as resolved.
Show resolved Hide resolved
}

bytes.extend(&chunk);
}
bytes.freeze()
};
if uncompress {
let extension = Path::new(file_name).extension().unwrap().to_str().unwrap();
match extension {
Expand Down
9 changes: 7 additions & 2 deletions src/toolchain/rust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,16 @@ pub struct XtensaRust {
impl XtensaRust {
/// Get the latest version of Xtensa Rust toolchain.
pub async fn get_latest_version() -> Result<String> {
let json = github_query(XTENSA_RUST_LATEST_API_URL)?;
let json = tokio::task::spawn_blocking(|| github_query(XTENSA_RUST_LATEST_API_URL))
.await
.unwrap()?;
let mut version = json["tag_name"].to_string();

version.retain(|c| c != 'v' && c != '"');
Self::parse_version(&version)?;
let borrowed = version.clone();
tokio::task::spawn_blocking(move || Self::parse_version(&borrowed))
.await
.expect("Join blocking task error")?;
debug!("Latest Xtensa Rust version: {}", version);
Ok(version)
}
Expand Down
Loading