1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
use crate::color;
use crate::downloader::{download_from_url, Downloadable};
use crate::errors::ProtoError;
use log::{debug, trace};
use sha2::{Digest, Sha256};
use std::fs::File;
use std::io;
use std::path::{Path, PathBuf};
#[async_trait::async_trait]
pub trait Verifiable<'tool>: Send + Sync + Downloadable<'tool> {
fn get_checksum_path(&self) -> Result<PathBuf, ProtoError>;
fn get_checksum_url(&self) -> Result<Option<String>, ProtoError>;
async fn download_checksum(
&self,
to_file: &Path,
from_url: Option<&str>,
) -> Result<bool, ProtoError> {
if to_file.exists() {
debug!(target: self.get_log_target(), "Checksum already downloaded, continuing");
return Ok(false);
}
let from_url = match from_url {
Some(url) => Some(url.to_owned()),
None => self.get_checksum_url()?,
};
let Some(from_url) = from_url else {
return Ok(true);
};
debug!(
target: self.get_log_target(),
"Attempting to download checksum from {}",
color::url(&from_url),
);
download_from_url(&from_url, &to_file).await?;
debug!(target: self.get_log_target(), "Successfully downloaded checksum");
Ok(true)
}
async fn verify_checksum(
&self,
checksum_file: &Path,
download_file: &Path,
) -> Result<bool, ProtoError>;
}
pub fn get_sha256_hash_of_file<P: AsRef<Path>>(path: P) -> Result<String, ProtoError> {
let path = path.as_ref();
let handle_error = |e: io::Error| ProtoError::Fs(path.to_path_buf(), e.to_string());
trace!(
target: "proto:verifier",
"Calculating SHA256 checksum for file {}",
color::path(path)
);
let mut file = File::open(path).map_err(handle_error)?;
let mut sha = Sha256::new();
io::copy(&mut file, &mut sha).map_err(handle_error)?;
let hash = format!("{:x}", sha.finalize());
trace!(
target: "proto:verifier",
"Calculated hash {}",
color::symbol(&hash)
);
Ok(hash)
}