Skip to content

Commit 65613b4

Browse files
committed
Fixed updater
1 parent 6674bb6 commit 65613b4

3 files changed

Lines changed: 108 additions & 107 deletions

File tree

src/commands.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ mod paste;
88
mod submit;
99
mod test;
1010
mod update;
11-
mod util;
11+
pub mod util;
1212

1313
use crate::io::{Io, PrintColor};
1414
use anyhow::Context;
@@ -75,11 +75,11 @@ pub fn handle(matches: &clap::ArgMatches, io: &mut dyn Io) -> anyhow::Result<()>
7575
Some(("logout", _)) => logout::logout(io, &mut client)?,
7676
Some(("fetchupdate", _)) => {
7777
#[cfg(target_os = "windows")]
78-
crate::updater::process_update();
78+
crate::updater::process_update()?;
7979
}
8080
Some(("cleartemp", _)) => {
8181
#[cfg(target_os = "windows")]
82-
crate::updater::cleartemp().unwrap();
82+
crate::updater::cleartemp()?;
8383
}
8484
Some(("elevateddownload", _)) => {
8585
download::elevated_download(io, &mut client)?;

src/main.rs

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -36,27 +36,30 @@ fn main() {
3636
&mut stdin,
3737
matches.is_present("testmode"),
3838
);
39+
if let Err(err) = run(&mut io, &matches) {
40+
let error_string = err
41+
.chain()
42+
.map(|e| e.to_string())
43+
.collect::<Vec<_>>()
44+
.join("\n caused by: ");
45+
if let Err(err) = io.println(&error_string, PrintColor::Failed) {
46+
println!("Failed to print error: {err}");
47+
}
48+
}
49+
}
3950

51+
fn run(io: &mut IoProduction, matches: &ArgMatches) -> anyhow::Result<()> {
4052
match matches.occurrences_of("no-update") {
4153
0 => {
4254
let os = std::env::consts::OS;
4355
if os == "windows" {
4456
#[cfg(target_os = "windows")]
45-
updater::check_for_update();
57+
updater::check_for_update()?;
4658
}
4759
}
4860
_ => println!("No Auto-Updates"),
4961
}
50-
if let Err(err) = commands::handle(&matches, &mut io) {
51-
let error_string = err
52-
.chain()
53-
.map(|e| e.to_string())
54-
.collect::<Vec<_>>()
55-
.join("\n caused by: ");
56-
if let Err(err) = io.println(&error_string, PrintColor::Failed) {
57-
println!("Failed to print error: {err}");
58-
}
59-
}
62+
commands::handle(matches, io)
6063
}
6164

6265
fn generate_completions(matches: &ArgMatches) {

src/updater.rs

Lines changed: 91 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::commands::util::get_path;
2+
use anyhow::Context;
23
use indicatif::{ProgressBar, ProgressStyle};
34
use reqwest::{header, Url};
45
use std::cmp::min;
@@ -22,19 +23,21 @@ pub const DELAY: u128 = 1440 * 60 * 1000;
2223
/// Will run in privileged stage if needed on Windows!
2324
///
2425
25-
pub fn check_for_update() {
26-
if is_it_time_yet() {
27-
generate_time_stamp();
28-
checktemp();
29-
let new_ver = get_latest_version();
26+
pub fn check_for_update() -> anyhow::Result<()> {
27+
if is_it_time_yet()? {
28+
generate_time_stamp()?;
29+
checktemp()?;
30+
let new_ver = get_latest_version()?;
3031
println!("Checking for updates...");
3132
if compare_versions(new_ver) {
32-
process_update();
33+
process_update()?;
3334
}
3435
}
36+
Ok(())
3537
}
36-
fn checktemp() {
37-
let mut tmp_filepath = env::current_exe().unwrap();
38+
39+
fn checktemp() -> anyhow::Result<()> {
40+
let mut tmp_filepath = env::current_exe()?;
3841
tmp_filepath.pop();
3942
let tmp_filepath = Path::new(&tmp_filepath).join("tmp");
4043
let tmp_filepath = tmp_filepath.join("tmc.exe");
@@ -51,33 +54,37 @@ fn checktemp() {
5154
}
5255
}
5356
}
57+
Ok(())
5458
}
59+
5560
pub fn cleartemp() -> Result<(), std::io::Error> {
5661
println!("Cleaning temp...");
57-
let mut tmp_filepath = env::current_exe().unwrap();
62+
let mut tmp_filepath = env::current_exe()?;
5863
tmp_filepath.pop();
5964
let tmp_filepath = Path::new(&tmp_filepath).join("tmp");
6065
let tmp_filepath = tmp_filepath.join("tmc.exe");
6166
fs::remove_file(&tmp_filepath)?;
6267
println!("Temp cleared!");
6368
Ok(())
6469
}
65-
pub fn process_update() {
66-
let new_ver = get_latest_version();
70+
71+
pub fn process_update() -> anyhow::Result<()> {
72+
let new_ver = get_latest_version()?;
6773
match stash_old_executable() {
68-
Err(e) => match e.kind() {
69-
std::io::ErrorKind::PermissionDenied => {
74+
Err(e) => match e.downcast_ref::<std::io::Error>().map(|e| e.kind()) {
75+
Some(std::io::ErrorKind::PermissionDenied) => {
7076
println!("Permission Denied! Restarting with administrator privileges...");
7177
elevate("fetchupdate".to_string());
72-
return;
78+
return Ok(());
7379
}
7480
_ => {
7581
println!("{:#?}", e);
7682
}
7783
},
78-
_ => update(new_ver).unwrap(),
84+
_ => update(new_ver)?,
7985
}
80-
println!("Update completed succesfully!")
86+
println!("Update completed succesfully!");
87+
Ok(())
8188
}
8289
fn elevate(command: String) {
8390
Command::new("powershell")
@@ -92,33 +99,32 @@ fn elevate(command: String) {
9299
.spawn()
93100
.expect("launch failure");
94101
}
95-
fn is_it_time_yet() -> bool {
96-
let config = TmcConfig::load(PLUGIN, get_path().as_path()).unwrap();
102+
fn is_it_time_yet() -> anyhow::Result<bool> {
103+
let config = TmcConfig::load(PLUGIN, get_path()?.as_path())?;
97104

98-
let last_check = match config.get("update-last-checked") {
99-
ConfigValue::Value(Some(s)) => toml::Value::as_str(&s).unwrap().to_string(),
105+
let value = config.get("update-last-checked");
106+
let last_check = match &value {
107+
ConfigValue::Value(Some(s)) => s.as_str().context("invalid value")?,
100108
_ => {
101-
return true;
109+
return Ok(true);
102110
}
103111
};
104112

105113
let last_check = match last_check.parse::<u128>() {
106114
Ok(time) => time,
107-
_ => return true,
115+
_ => return Ok(true),
108116
};
109117
let now = SystemTime::now();
110118
let now = now
111119
.duration_since(UNIX_EPOCH)
112120
.expect("Time went backwards")
113121
.as_millis();
114-
if now - last_check as u128 > DELAY {
115-
return true;
116-
}
117-
false
122+
let update = now - last_check as u128 > DELAY;
123+
Ok(update)
118124
}
119125

120-
fn generate_time_stamp() {
121-
let mut config = TmcConfig::load(PLUGIN, get_path().as_path()).unwrap();
126+
fn generate_time_stamp() -> anyhow::Result<()> {
127+
let mut config = TmcConfig::load(PLUGIN, get_path()?.as_path())?;
122128
let now = SystemTime::now();
123129
let since_the_epoch = now
124130
.duration_since(UNIX_EPOCH)
@@ -131,12 +137,13 @@ fn generate_time_stamp() {
131137
) {
132138
println!("timestamp could not be changed");
133139
}
134-
if let Err(_err) = config.save(get_path().as_path()) {
140+
if let Err(_err) = config.save(get_path()?.as_path()) {
135141
println!("Problem saving timestamp");
136142
}
143+
Ok(())
137144
}
138145

139-
fn get_latest_version() -> String {
146+
fn get_latest_version() -> anyhow::Result<String> {
140147
let url = GITHUB_URL;
141148
let mut headers = header::HeaderMap::new();
142149
headers.insert(
@@ -146,21 +153,20 @@ fn get_latest_version() -> String {
146153
let resp = reqwest::blocking::Client::new()
147154
.get(url)
148155
.headers(headers)
149-
.send()
150-
.unwrap();
156+
.send()?;
151157
if !resp.status().is_success() {
152-
panic!(
158+
anyhow::bail!(
153159
"Version lookup failed with status: {:?} - for: {:?}",
154160
resp.status(),
155161
&url
156162
);
157163
}
158-
let tags = resp.json::<serde_json::Value>().unwrap();
159-
let tags = tags.as_array().unwrap();
164+
let tags = resp.json::<serde_json::Value>()?;
165+
let tags = tags.as_array().context("tags were not an array")?;
160166

161167
let latest = tags[0]["name"].to_string();
162-
163-
latest[1..latest.len() - 1].to_string()
168+
let latest = latest[1..latest.len() - 1].to_string();
169+
Ok(latest)
164170
}
165171

166172
fn compare_versions(version: String) -> bool {
@@ -188,23 +194,18 @@ fn compare_versions(version: String) -> bool {
188194
false
189195
}
190196

191-
fn update(version: String) -> Result<(), std::io::Error> {
197+
fn update(version: String) -> anyhow::Result<()> {
192198
use io::BufRead;
193199
let resp = reqwest::blocking::Client::new()
194-
.get(generate_download_url(version))
195-
.send()
196-
.unwrap();
200+
.get(generate_download_url(version)?)
201+
.send()?;
197202
let size = resp
198203
.headers()
199204
.get(reqwest::header::CONTENT_LENGTH)
200-
.map(|val| {
201-
val.to_str()
202-
.map(|s| s.parse::<u64>().unwrap_or(0))
203-
.unwrap_or(0)
204-
})
205+
.and_then(|val| val.to_str().ok().and_then(|s| s.parse::<u64>().ok()))
205206
.unwrap_or(0);
206207
if !resp.status().is_success() {
207-
panic!("Download request failed with status: {:?}", resp.status());
208+
anyhow::bail!("Download request failed with status: {:?}", resp.status());
208209
}
209210
let filepath = env::current_exe()?;
210211
let mut dest = fs::File::create(&filepath)?;
@@ -232,64 +233,61 @@ fn update(version: String) -> Result<(), std::io::Error> {
232233
Ok(())
233234
}
234235

235-
fn stash_old_executable() -> Result<(), std::io::Error> {
236-
let filepath = env::current_exe().unwrap();
236+
fn stash_old_executable() -> anyhow::Result<()> {
237+
let filepath = env::current_exe()?;
237238

238-
let mut tmp_filepath = env::current_exe().unwrap();
239+
let mut tmp_filepath = filepath.clone();
239240
tmp_filepath.pop();
240-
let tmp_filepath = Path::new(&tmp_filepath).join("tmp");
241-
fs::create_dir_all(&tmp_filepath)?;
242-
let tmp_filepath = tmp_filepath.join("tmc.exe");
243-
244-
if tmp_filepath.exists() {
245-
fs::remove_file(&tmp_filepath)?;
246-
}
247-
248-
fs::rename(&filepath, &tmp_filepath)?;
241+
let tmp_dir = tmp_filepath.join("tmp");
242+
fs::create_dir_all(&tmp_dir)?;
243+
let tmp_tmc = tmp_dir.join("tmc.exe");
244+
fs::rename(&filepath, &tmp_tmc)?;
249245
Ok(())
250246
}
251247

252-
fn generate_download_url(version: String) -> Url {
248+
fn generate_download_url(version: String) -> anyhow::Result<Url> {
253249
let arch = env::consts::ARCH;
254-
let mut target = String::new();
255-
match arch {
256-
"x86_64" => target.push_str("x86_64-pc-windows-msvc-"),
257-
"i686" => target.push_str("i686-pc-windows-msvc-"),
258-
_ => println!("Wow! {}", arch),
259-
}
260-
let mut download_url = String::from("https://download.mooc.fi/tmc-cli-rust/tmc-cli-rust-");
261-
download_url.push_str(&target);
262-
download_url.push_str(&version);
263-
download_url.push_str(".exe");
264-
Url::parse(&download_url).unwrap()
250+
let target = match arch {
251+
"x86_64" => "x86_64-pc-windows-msvc",
252+
"i686" => "i686-pc-windows-msvc-",
253+
unexpected => anyhow::bail!("Unexpected arch {unexpected}"),
254+
};
255+
let download_url =
256+
format!("https://download.mooc.fi/tmc-cli-rust/tmc-cli-rust-{target}-{version}.exe");
257+
let url = Url::parse(&download_url)?;
258+
Ok(url)
265259
}
266260

267-
#[test]
268-
fn compare_versions_test() {
269-
let oldest = String::from("v0.0.1");
270-
let the_future = String::from("v999.999.999");
271-
assert_eq!(compare_versions(oldest), false);
272-
assert_eq!(compare_versions(the_future), true);
273-
assert_eq!(
274-
compare_versions(env!("CARGO_PKG_VERSION").to_string()),
275-
false
276-
);
277-
}
261+
#[cfg(test)]
262+
mod test {
263+
use super::*;
278264

279-
#[test]
280-
#[cfg(windows)]
281-
fn generate_download_url_test() {
282-
let oldest = String::from("v0.0.1");
283-
let arch = env::consts::ARCH;
284-
match arch {
285-
"x86_64" => assert_eq!(
286-
generate_download_url(oldest).to_string(),
265+
#[test]
266+
fn compare_versions_test() {
267+
let oldest = String::from("v0.0.1");
268+
let the_future = String::from("v999.999.999");
269+
assert_eq!(compare_versions(oldest), false);
270+
assert_eq!(compare_versions(the_future), true);
271+
assert_eq!(
272+
compare_versions(env!("CARGO_PKG_VERSION").to_string()),
273+
false
274+
);
275+
}
276+
277+
#[test]
278+
fn generate_download_url_test() {
279+
let oldest = String::from("v0.0.1");
280+
let arch = env::consts::ARCH;
281+
match arch {
282+
"x86_64" => assert_eq!(
283+
generate_download_url(oldest).unwrap().to_string(),
287284
"https://download.mooc.fi/tmc-cli-rust/tmc-cli-rust-x86_64-pc-windows-msvc-v0.0.1.exe"
288285
),
289-
"i686" => assert_eq!(
290-
generate_download_url(oldest).to_string(),
286+
"i686" => assert_eq!(
287+
generate_download_url(oldest).unwrap().to_string(),
291288
"https://download.mooc.fi/tmc-cli-rust/tmc-cli-rust-i686-pc-windows-msvc-v0.0.1.exe"
292289
),
293-
_ => println!("Wow! {}", arch),
290+
_ => println!("Wow! {}", arch),
291+
}
294292
}
295293
}

0 commit comments

Comments
 (0)