Work
- Move User-Agent to reqwest client initialization - Improve desktop path detection - Run pipelines in parallel
This commit is contained in:
parent
1c798dbcae
commit
4ad392d83a
|
@ -842,6 +842,7 @@ name = "school-computer-toolkit"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"dirs",
|
"dirs",
|
||||||
|
"futures-util",
|
||||||
"miette",
|
"miette",
|
||||||
"ramhorns",
|
"ramhorns",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
|
|
|
@ -7,6 +7,7 @@ edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
dirs = "4"
|
dirs = "4"
|
||||||
|
futures-util = { version = "0.3.21", default-features = false, features = [ "alloc" ] }
|
||||||
miette = { version = "4.7", features = [ "fancy" ] }
|
miette = { version = "4.7", features = [ "fancy" ] }
|
||||||
ramhorns = "0.14"
|
ramhorns = "0.14"
|
||||||
reqwest = { version = "0.11.10", features = [ "json" ] }
|
reqwest = { version = "0.11.10", features = [ "json" ] }
|
||||||
|
|
|
@ -6,9 +6,6 @@ use tokio::io::AsyncWriteExt;
|
||||||
|
|
||||||
use crate::Context;
|
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.
|
/// A sequential pipeline of [`Step`]s.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Pipeline<'a> {
|
pub struct Pipeline<'a> {
|
||||||
|
@ -114,7 +111,6 @@ impl<'a> Step<'a> {
|
||||||
let mut resp = ctx
|
let mut resp = ctx
|
||||||
.reqwest
|
.reqwest
|
||||||
.get(url)
|
.get(url)
|
||||||
.header("User-Agent", USER_AGENT_STR)
|
|
||||||
.send()
|
.send()
|
||||||
.await
|
.await
|
||||||
.into_diagnostic()
|
.into_diagnostic()
|
||||||
|
@ -344,7 +340,6 @@ async fn fetch_latest_release<'a, 'b>(
|
||||||
.wrap_err("Invalid GitHub repo for download step.")?;
|
.wrap_err("Invalid GitHub repo for download step.")?;
|
||||||
let mut resp = reqwest
|
let mut resp = reqwest
|
||||||
.get(url)
|
.get(url)
|
||||||
.header("User-Agent", USER_AGENT_STR)
|
|
||||||
.send()
|
.send()
|
||||||
.await
|
.await
|
||||||
.into_diagnostic()
|
.into_diagnostic()
|
||||||
|
|
76
src/main.rs
76
src/main.rs
|
@ -14,20 +14,26 @@ use install::{Pipeline, RemoteResource, ShortcutTarget, Step};
|
||||||
|
|
||||||
const SWTOOLS_PATH: &'static str = "C:\\SWTools";
|
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 {
|
pub fn swtools_path() -> &'static Path {
|
||||||
Path::new(SWTOOLS_PATH)
|
Path::new(SWTOOLS_PATH)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn desktop_path() -> PathBuf {
|
pub fn desktop_path_fallible() -> Option<PathBuf> {
|
||||||
let mut dir = dirs::home_dir()
|
dirs::desktop_dir()
|
||||||
.expect("Could not find your home directory.")
|
.filter(|dir| dir.exists())
|
||||||
.join("Desktop");
|
.or_else(|| Some(Path::new("H:\\Profile\\Desktop").to_owned()))
|
||||||
if !dir.exists() {
|
.filter(|dir| dir.exists())
|
||||||
dir = Path::new("H:\\Profile\\Desktop").to_owned();
|
.or_else(|| dirs::home_dir().map(|dir| dir.join("Desktop")))
|
||||||
}
|
|
||||||
dir
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn desktop_path() -> PathBuf {
|
||||||
|
desktop_path_fallible().expect("Desktop directory should have been resolved by now.")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct Context {
|
pub struct Context {
|
||||||
pub reqwest: reqwest::Client,
|
pub reqwest: reqwest::Client,
|
||||||
}
|
}
|
||||||
|
@ -44,7 +50,7 @@ async fn main() -> Result<()> {
|
||||||
bail!("Could not find or access {}", SWTOOLS_PATH);
|
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.");
|
bail!("Could not find your desktop directory.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,20 +65,20 @@ async fn main() -> Result<()> {
|
||||||
let psiphon_dir = swtools_path().join("psiphon");
|
let psiphon_dir = swtools_path().join("psiphon");
|
||||||
let psiphon_bin = psiphon_dir.join("psiphon3.exe");
|
let psiphon_bin = psiphon_dir.join("psiphon3.exe");
|
||||||
|
|
||||||
let utilities = [
|
let pipelines = [
|
||||||
Pipeline::new(
|
Pipeline::new(
|
||||||
"Install Notepad++",
|
"Install Notepad++",
|
||||||
vec![
|
vec![
|
||||||
Step::DownloadFile {
|
Step::DownloadFile {
|
||||||
file: nppp_zip.as_path().into(),
|
file: nppp_zip.clone().into(),
|
||||||
res: RemoteResource::GitHubArtifact {
|
res: RemoteResource::GitHubArtifact {
|
||||||
repo: "notepad-plus-plus/notepad-plus-plus",
|
repo: "notepad-plus-plus/notepad-plus-plus",
|
||||||
pattern: "npp.{{tag_name_strip_prefix}}.portable.x64.zip",
|
pattern: "npp.{{tag_name_strip_prefix}}.portable.x64.zip",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Step::ExtractFile {
|
Step::ExtractFile {
|
||||||
file: nppp_zip.as_path().into(),
|
file: nppp_zip.clone().into(),
|
||||||
dest: nppp_dir.as_path().into(),
|
dest: nppp_dir.clone().into(),
|
||||||
},
|
},
|
||||||
Step::CreateShortcut {
|
Step::CreateShortcut {
|
||||||
target: ShortcutTarget::Executable {
|
target: ShortcutTarget::Executable {
|
||||||
|
@ -88,14 +94,14 @@ async fn main() -> Result<()> {
|
||||||
"Install Explorer++",
|
"Install Explorer++",
|
||||||
vec![
|
vec![
|
||||||
Step::DownloadFile {
|
Step::DownloadFile {
|
||||||
file: epp_zip.as_path().into(),
|
file: epp_zip.clone().into(),
|
||||||
res: RemoteResource::Url(
|
res: RemoteResource::Url(
|
||||||
"https://explorerplusplus.com/software/explorer++_1.3.5_x64.zip",
|
"https://explorerplusplus.com/software/explorer++_1.3.5_x64.zip",
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
Step::ExtractFile {
|
Step::ExtractFile {
|
||||||
file: epp_zip.as_path().into(),
|
file: epp_zip.clone().into(),
|
||||||
dest: epp_dir.as_path().into(),
|
dest: epp_dir.clone().into(),
|
||||||
},
|
},
|
||||||
Step::CreateShortcut {
|
Step::CreateShortcut {
|
||||||
target: ShortcutTarget::Executable {
|
target: ShortcutTarget::Executable {
|
||||||
|
@ -111,14 +117,14 @@ async fn main() -> Result<()> {
|
||||||
"Install Psiphon VPN",
|
"Install Psiphon VPN",
|
||||||
vec![
|
vec![
|
||||||
Step::DownloadFile {
|
Step::DownloadFile {
|
||||||
file: psiphon_bin.as_path().into(),
|
file: psiphon_bin.clone().into(),
|
||||||
res: RemoteResource::Url(
|
res: RemoteResource::Url(
|
||||||
"https://s3.amazonaws.com/f58p-mqce-k1yj/psiphon3.exe",
|
"https://s3.amazonaws.com/f58p-mqce-k1yj/psiphon3.exe",
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
Step::CreateShortcut {
|
Step::CreateShortcut {
|
||||||
target: ShortcutTarget::Executable {
|
target: ShortcutTarget::Executable {
|
||||||
file: psiphon_bin.as_path().into(),
|
file: psiphon_bin.clone().into(),
|
||||||
args: "",
|
args: "",
|
||||||
},
|
},
|
||||||
file: desktop_path().join("Psiphon3.lnk").into(),
|
file: desktop_path().join("Psiphon3.lnk").into(),
|
||||||
|
@ -166,14 +172,42 @@ async fn main() -> Result<()> {
|
||||||
|
|
||||||
let ctx = Context {
|
let ctx = Context {
|
||||||
reqwest: reqwest::Client::builder()
|
reqwest: reqwest::Client::builder()
|
||||||
|
.user_agent(USER_AGENT_STR)
|
||||||
.build()
|
.build()
|
||||||
.into_diagnostic()
|
.into_diagnostic()
|
||||||
.wrap_err("Could not initialize HTTP client.")?,
|
.wrap_err("Could not initialize HTTP client.")?,
|
||||||
};
|
};
|
||||||
|
|
||||||
for utility in utilities {
|
let results = futures_util::future::join_all(
|
||||||
utility.invoke(&ctx).await?;
|
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(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue