Skip to content

Commit

Permalink
feat: add mirror election for network experience
Browse files Browse the repository at this point in the history
  • Loading branch information
ArcticLampyrid committed Feb 21, 2024
1 parent 1bd18bb commit c0d378d
Show file tree
Hide file tree
Showing 8 changed files with 88 additions and 20 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{error::InstallError, gh_helper, path_env::add_to_path_env};
use crate::{error::InstallError, gh_helper, path_env::add_to_path_env, reqwest_unified_builder};
use std::{collections::HashSet, env, io::Seek, path::PathBuf};
use tempfile::tempfile;
use zip::ZipArchive;
Expand Down Expand Up @@ -70,17 +70,15 @@ pub fn install_arm_embedded_gcc_windows() -> Result<(), InstallError> {
return Ok(());
}

let client = reqwest::blocking::ClientBuilder::new()
.user_agent("arm-embedded-gcc-installer")
.build()?;
let client = reqwest_unified_builder::build_blocking()?;
let url_for_gcc_zip = gh_helper::get_latest_release_url_with_fallback(
&client,
"xpack-dev-tools",
"arm-none-eabi-gcc-xpack",
|assert_name| assert_name.ends_with("-win32-x64.zip"),
"https://github.com/xpack-dev-tools/arm-none-eabi-gcc-xpack/releases/download/v12.3.1-1.1/xpack-arm-none-eabi-gcc-12.3.1-1.1-win32-x64.zip",
);
let url_for_gcc_zip = format!("https://ghproxy.com/{}", url_for_gcc_zip);
let url_for_gcc_zip = gh_helper::elect_mirror(url_for_gcc_zip);

println!("Downloading {}", url_for_gcc_zip);
let mut response = client.get(url_for_gcc_zip).send()?;
Expand Down
7 changes: 3 additions & 4 deletions cli/src/cmake_install/cmake_install_windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use std::env;
use std::path::PathBuf;

use crate::path_env::add_to_path_env;
use crate::reqwest_unified_builder;
use crate::{error::InstallError, gh_helper};
use tempfile::tempdir;

Expand Down Expand Up @@ -49,9 +50,7 @@ pub fn install_cmake_windows() -> Result<(), InstallError> {
};
let cmake_installer_suffix = format!("-windows-{}.msi", cmake_arch_suffix);

let client = reqwest::blocking::ClientBuilder::new()
.user_agent("cmake-installer")
.build()?;
let client = reqwest_unified_builder::build_blocking()?;
let url_for_cmake_msi = gh_helper::get_latest_release_url_with_fallback(
&client,
"Kitware",
Expand All @@ -63,7 +62,7 @@ pub fn install_cmake_windows() -> Result<(), InstallError> {
)
.as_str(),
);
let url_for_cmake_msi = format!("https://ghproxy.com/{}", url_for_cmake_msi);
let url_for_cmake_msi = gh_helper::elect_mirror(url_for_cmake_msi);

println!("Downloading {}", url_for_cmake_msi);
let mut response = client.get(url_for_cmake_msi).send()?;
Expand Down
68 changes: 68 additions & 0 deletions cli/src/gh_helper/mirror_election.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
use std::time::Duration;

use crate::reqwest_unified_builder;

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum MirrorType {
Official,
GhProxy,
}
static MIRROR_TYPE: std::sync::OnceLock<MirrorType> = std::sync::OnceLock::new();

fn get_mirror_type() -> MirrorType {
let result = *MIRROR_TYPE.get_or_init(|| {
let client = reqwest_unified_builder::build_blocking();
if let Ok(client) = client {
{
// check location
// for non-China users, use official resources
let response = client
.get("https://www.cloudflare.com/cdn-cgi/trace")
.timeout(Duration::from_secs(10))
.send();
if let Ok(response) = response {
if response.status().is_success() {
if let Ok(body) = response.text() {
if !body.contains("loc=CN") {
return MirrorType::Official;
}
}
}
}
}
// for China users, there may be a challenge to download the official resources
{
// check if ghproxy is available
let response = client
.get("https://mirror.ghproxy.com/")
.timeout(Duration::from_secs(10))
.send();
if let Ok(response) = response {
if response.status().is_success() {
return MirrorType::GhProxy;
}
}
}
}
MirrorType::Official
});
if result != MirrorType::Official {
println!("Info: access GitHub via {:?}", result);
}
result
}

pub fn elect_mirror(url: String) -> String {
let mirror_type = get_mirror_type();
if mirror_type == MirrorType::GhProxy {
if url.contains("://github.com/") && url.contains("/releases/download/") {
// release download url
return format!("https://mirror.ghproxy.com/{}", url);
}
if url.contains("://raw.githubusercontent.com/") {
// raw content url
return format!("https://mirror.ghproxy.com/{}", url);
}
}
url
}
2 changes: 2 additions & 0 deletions cli/src/gh_helper/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
use crate::error::InstallError;
mod mirror_election;
pub use mirror_election::elect_mirror;

pub fn get_latest_release_url<F>(
client: &reqwest::blocking::Client,
Expand Down
1 change: 1 addition & 0 deletions cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ mod gh_helper;
mod ninja_install;
mod openocd_install;
mod path_env;
mod reqwest_unified_builder;
mod simple_template;
use clap::{Parser, Subcommand};
use error::InstallError;
Expand Down
8 changes: 3 additions & 5 deletions cli/src/ninja_install/ninja_install_windows.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@
use std::env;

use crate::{error::InstallError, gh_helper, path_env::add_to_path_env};
use crate::{error::InstallError, gh_helper, path_env::add_to_path_env, reqwest_unified_builder};
use zip::ZipArchive;

pub fn install_ninja_windows() -> Result<(), InstallError> {
let client = reqwest::blocking::ClientBuilder::new()
.user_agent("ninja-installer")
.build()?;
let client = reqwest_unified_builder::build_blocking()?;
let url_for_ninja_win_zip = gh_helper::get_latest_release_url_with_fallback(
&client,
"ninja-build",
"ninja",
|assert_name| assert_name == "ninja-win.zip",
"https://github.com/ninja-build/ninja/releases/download/v1.11.1/ninja-win.zip",
);
let url_for_ninja_win_zip = format!("https://ghproxy.com/{}", url_for_ninja_win_zip);
let url_for_ninja_win_zip = gh_helper::elect_mirror(url_for_ninja_win_zip);

println!("Downloading {}", url_for_ninja_win_zip);
let response = client.get(url_for_ninja_win_zip).send()?;
Expand Down
9 changes: 3 additions & 6 deletions cli/src/openocd_install/openocd_install_windows.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
use crate::{error::InstallError, gh_helper, path_env::add_to_path_env};
use crate::{error::InstallError, gh_helper, path_env::add_to_path_env, reqwest_unified_builder};
use tar::Archive;

pub fn install_openocd_windows() -> Result<(), InstallError> {
let client = reqwest::blocking::ClientBuilder::new()
.user_agent("openocd-installer")
.build()
.map_err(InstallError::HttpFetchFailed)?;
let client = reqwest_unified_builder::build_blocking()?;
let url_for_openocd_win_tgz = gh_helper::get_latest_release_url_with_fallback(
&client,
"openocd-org",
Expand All @@ -14,7 +11,7 @@ pub fn install_openocd_windows() -> Result<(), InstallError> {
"https://github.com/openocd-org/openocd/releases/download/v0.12.0/openocd-v0.12.0-i686-w64-mingw32.tar.gz",
);

let url_for_openocd_win_tgz = format!("https://ghproxy.com/{}", url_for_openocd_win_tgz);
let url_for_openocd_win_tgz = gh_helper::elect_mirror(url_for_openocd_win_tgz);
println!("Downloading {}", url_for_openocd_win_tgz);
let response = client.get(url_for_openocd_win_tgz).send()?;
if !response.status().is_success() {
Expand Down
5 changes: 5 additions & 0 deletions cli/src/reqwest_unified_builder.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
pub fn build_blocking() -> Result<reqwest::blocking::Client, reqwest::Error> {
reqwest::blocking::ClientBuilder::new()
.user_agent("stm32tesseract")
.build()
}

0 comments on commit c0d378d

Please sign in to comment.