- Move User-Agent to reqwest client initialization
- Improve desktop path detection
- Run pipelines in parallel
This commit is contained in:
Michael Pfaff 2022-06-10 17:21:04 -04:00
parent 1c798dbcae
commit 4ad392d83a
Signed by: michael
GPG Key ID: CF402C4A012AA9D4
4 changed files with 57 additions and 26 deletions

1
Cargo.lock generated
View File

@ -842,6 +842,7 @@ name = "school-computer-toolkit"
version = "0.1.0"
dependencies = [
"dirs",
"futures-util",
"miette",
"ramhorns",
"reqwest",

View File

@ -7,6 +7,7 @@ edition = "2021"
[dependencies]
dirs = "4"
futures-util = { version = "0.3.21", default-features = false, features = [ "alloc" ] }
miette = { version = "4.7", features = [ "fancy" ] }
ramhorns = "0.14"
reqwest = { version = "0.11.10", features = [ "json" ] }

View File

@ -6,9 +6,6 @@ use tokio::io::AsyncWriteExt;
use crate::Context;
const USER_AGENT_STR: &'static str =
"Mozilla/5.0 (Windows NT 10.0; rv:91.0) Gecko/20100101 Firefox/91.0";
/// A sequential pipeline of [`Step`]s.
#[derive(Debug, Clone)]
pub struct Pipeline<'a> {
@ -114,7 +111,6 @@ impl<'a> Step<'a> {
let mut resp = ctx
.reqwest
.get(url)
.header("User-Agent", USER_AGENT_STR)
.send()
.await
.into_diagnostic()
@ -344,7 +340,6 @@ async fn fetch_latest_release<'a, 'b>(
.wrap_err("Invalid GitHub repo for download step.")?;
let mut resp = reqwest
.get(url)
.header("User-Agent", USER_AGENT_STR)
.send()
.await
.into_diagnostic()

View File

@ -14,20 +14,26 @@ use install::{Pipeline, RemoteResource, ShortcutTarget, Step};
const SWTOOLS_PATH: &'static str = "C:\\SWTools";
const USER_AGENT_STR: &'static str =
"Mozilla/5.0 (Windows NT 10.0; rv:91.0) Gecko/20100101 Firefox/91.0";
pub fn swtools_path() -> &'static Path {
Path::new(SWTOOLS_PATH)
}
pub fn desktop_path() -> PathBuf {
let mut dir = dirs::home_dir()
.expect("Could not find your home directory.")
.join("Desktop");
if !dir.exists() {
dir = Path::new("H:\\Profile\\Desktop").to_owned();
}
dir
pub fn desktop_path_fallible() -> Option<PathBuf> {
dirs::desktop_dir()
.filter(|dir| dir.exists())
.or_else(|| Some(Path::new("H:\\Profile\\Desktop").to_owned()))
.filter(|dir| dir.exists())
.or_else(|| dirs::home_dir().map(|dir| dir.join("Desktop")))
}
pub fn desktop_path() -> PathBuf {
desktop_path_fallible().expect("Desktop directory should have been resolved by now.")
}
#[derive(Clone)]
pub struct Context {
pub reqwest: reqwest::Client,
}
@ -44,7 +50,7 @@ async fn main() -> Result<()> {
bail!("Could not find or access {}", SWTOOLS_PATH);
}
if !desktop_path().exists() {
if desktop_path_fallible().is_none() {
bail!("Could not find your desktop directory.");
}
@ -59,20 +65,20 @@ async fn main() -> Result<()> {
let psiphon_dir = swtools_path().join("psiphon");
let psiphon_bin = psiphon_dir.join("psiphon3.exe");
let utilities = [
let pipelines = [
Pipeline::new(
"Install Notepad++",
vec![
Step::DownloadFile {
file: nppp_zip.as_path().into(),
file: nppp_zip.clone().into(),
res: RemoteResource::GitHubArtifact {
repo: "notepad-plus-plus/notepad-plus-plus",
pattern: "npp.{{tag_name_strip_prefix}}.portable.x64.zip",
},
},
Step::ExtractFile {
file: nppp_zip.as_path().into(),
dest: nppp_dir.as_path().into(),
file: nppp_zip.clone().into(),
dest: nppp_dir.clone().into(),
},
Step::CreateShortcut {
target: ShortcutTarget::Executable {
@ -88,14 +94,14 @@ async fn main() -> Result<()> {
"Install Explorer++",
vec![
Step::DownloadFile {
file: epp_zip.as_path().into(),
file: epp_zip.clone().into(),
res: RemoteResource::Url(
"https://explorerplusplus.com/software/explorer++_1.3.5_x64.zip",
),
},
Step::ExtractFile {
file: epp_zip.as_path().into(),
dest: epp_dir.as_path().into(),
file: epp_zip.clone().into(),
dest: epp_dir.clone().into(),
},
Step::CreateShortcut {
target: ShortcutTarget::Executable {
@ -111,14 +117,14 @@ async fn main() -> Result<()> {
"Install Psiphon VPN",
vec![
Step::DownloadFile {
file: psiphon_bin.as_path().into(),
file: psiphon_bin.clone().into(),
res: RemoteResource::Url(
"https://s3.amazonaws.com/f58p-mqce-k1yj/psiphon3.exe",
),
},
Step::CreateShortcut {
target: ShortcutTarget::Executable {
file: psiphon_bin.as_path().into(),
file: psiphon_bin.clone().into(),
args: "",
},
file: desktop_path().join("Psiphon3.lnk").into(),
@ -166,14 +172,42 @@ async fn main() -> Result<()> {
let ctx = Context {
reqwest: reqwest::Client::builder()
.user_agent(USER_AGENT_STR)
.build()
.into_diagnostic()
.wrap_err("Could not initialize HTTP client.")?,
};
for utility in utilities {
utility.invoke(&ctx).await?;
let results = futures_util::future::join_all(
pipelines
.into_iter()
.map(|pipeline| tokio::spawn({
let ctx = ctx.clone();
async move {
pipeline.invoke(&ctx).await
}
})),
)
.await;
let results = results
.into_iter()
.map(|result| match result.into_diagnostic().wrap_err("Task error.") {
Ok(Ok(t)) => Ok(t),
Ok(Err(e)) => Err(e),
Err(e) => Err(e),
});
let mut had_error = false;
for result in results {
if let Err(e) = result {
had_error = true;
eprintln!("{e:?}");
}
}
Ok(())
if had_error {
Err(miette!("One or more errors in pipelines."))
} else {
Ok(())
}
}