summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars Wirzenius <liw@liw.fi>2021-04-23 14:22:39 +0300
committerLars Wirzenius <liw@liw.fi>2021-04-23 14:22:39 +0300
commitca61af01ed867e695ceb19b6975354743d6ab14a (patch)
tree356438510099cb5e130c564e747baf8b3c7107de
parentcd270b969176a11d659ac8cbf81c15e7150b4b22 (diff)
downloadsummain-rs-ca61af01ed867e695ceb19b6975354743d6ab14a.tar.gz
compute checkksum in blocking thread
-rw-r--r--src/bin/summain.rs20
-rw-r--r--src/lib.rs34
2 files changed, 30 insertions, 24 deletions
diff --git a/src/bin/summain.rs b/src/bin/summain.rs
index 2eb4152..2ad110b 100644
--- a/src/bin/summain.rs
+++ b/src/bin/summain.rs
@@ -17,16 +17,22 @@ async fn async_main() -> anyhow::Result<()> {
opt.pathnames[..].sort();
let mut handles = vec![];
- for (i, filename) in opt.pathnames.iter().cloned().enumerate() {
- handles.push(tokio::spawn(async move { manifest(i, filename) }));
+ for filename in opt.pathnames.iter().cloned() {
+ handles.push(tokio::spawn(async move { manifest(filename) }));
}
- let mut manifests = vec![];
+ let mut sumhandles = vec![];
for h in handles {
- manifests.push(h.await?.await?);
+ let mut m: ManifestEntry = h.await?.await?;
+ let h = tokio::task::spawn_blocking(move || match m.compute_checksum() {
+ Err(e) => Err(e),
+ Ok(_) => Ok(m),
+ });
+ sumhandles.push(h)
}
- for m in manifests {
+ for h in sumhandles {
+ let m: ManifestEntry = h.await??;
print!("{}", serde_yaml::to_string(&m)?);
}
@@ -39,8 +45,8 @@ struct Opt {
pathnames: Vec<PathBuf>,
}
-async fn manifest(i: usize, path: PathBuf) -> anyhow::Result<ManifestEntry> {
- ManifestEntry::new(i, &path)
+async fn manifest(path: PathBuf) -> anyhow::Result<ManifestEntry> {
+ ManifestEntry::new(&path)
.await
.with_context(|| format!("{}", path.display()))
}
diff --git a/src/lib.rs b/src/lib.rs
index 6bcef0b..82f4123 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -43,7 +43,10 @@ const BUF_SIZE: usize = 1024 * 1024;
#[derive(Serialize, Debug)]
pub struct ManifestEntry {
#[serde(skip)]
- index: usize,
+ is_regular: bool,
+
+ #[serde(skip)]
+ filename: PathBuf,
path: String,
#[serde(with = "mode")]
@@ -63,34 +66,36 @@ impl ManifestEntry {
/// caller. This function doesn't query the system for it.
///
/// The structure can be serialized using serde.
- pub async fn new(i: usize, path: &Path) -> std::io::Result<Self> {
+ pub async fn new(path: &Path) -> std::io::Result<Self> {
let m = symlink_metadata(path)?;
- let hash = if m.is_file() {
- let path = path.to_path_buf();
- Some(file_checksum(path).await?)
- } else {
- None
- };
let target = if m.file_type().is_symlink() {
Some(read_link(path)?)
} else {
None
};
Ok(Self {
- index: i,
+ is_regular: m.is_file(),
+ filename: path.to_path_buf(),
path: path.to_string_lossy().into_owned(),
mode: m.st_mode(),
mtime: m.st_mtime(),
mtime_nsec: m.st_mtime_nsec(),
nlink: m.st_nlink(),
size: if m.is_dir() { None } else { Some(m.st_size()) },
- sha256: hash,
+ sha256: None,
target,
})
}
+
+ pub fn compute_checksum(&mut self) -> std::io::Result<()> {
+ if self.is_regular {
+ self.sha256 = Some(file_checksum(&self.filename)?);
+ }
+ Ok(())
+ }
}
-async fn file_checksum(path: PathBuf) -> std::io::Result<String> {
+fn file_checksum(path: &Path) -> std::io::Result<String> {
let mut hasher = Sha256::new();
let file = File::open(path)?;
@@ -101,17 +106,12 @@ async fn file_checksum(path: PathBuf) -> std::io::Result<String> {
if n == 0 {
break;
}
- hasher = tokio::task::spawn_blocking(move || update_checksum(hasher, &buf[..n])).await?;
+ hasher.update(&buf[..n]);
}
let hash = hasher.finalize();
Ok(format!("{:x}", hash))
}
-fn update_checksum(mut hasher: Sha256, data: &[u8]) -> Sha256 {
- hasher.update(data);
- hasher
-}
-
mod mode {
use serde::{self, Serializer};