use super::transport::StatInfo;
use crate::osutils::sha::{sha_file, sha_file_by_name};
use std::fs::File;
#[cfg(unix)]
use std::os::unix::fs::MetadataExt;
use std::path::Path;
pub trait SHA1Provider: Send + Sync {
fn sha1(&self, path: &Path) -> std::io::Result<String>;
fn stat_and_sha1(&self, path: &Path) -> std::io::Result<(StatInfo, String)>;
}
pub struct DefaultSHA1Provider;
impl DefaultSHA1Provider {
pub fn new() -> DefaultSHA1Provider {
DefaultSHA1Provider {}
}
}
impl Default for DefaultSHA1Provider {
fn default() -> Self {
Self::new()
}
}
impl SHA1Provider for DefaultSHA1Provider {
fn sha1(&self, path: &Path) -> std::io::Result<String> {
sha_file_by_name(path)
}
fn stat_and_sha1(&self, path: &Path) -> std::io::Result<(StatInfo, String)> {
let mut f = File::open(path)?;
let md = f.metadata()?;
let sha1 = sha_file(&mut f)?;
let stat = metadata_to_stat_info(&md);
Ok((stat, sha1))
}
}
fn metadata_to_stat_info(md: &std::fs::Metadata) -> StatInfo {
use std::time::UNIX_EPOCH;
let mtime = md
.modified()
.ok()
.and_then(|t| t.duration_since(UNIX_EPOCH).ok())
.map(|d| d.as_secs() as i64)
.unwrap_or(0);
#[cfg(unix)]
let (mode, size, dev, ino, ctime) = (md.mode(), md.size(), md.dev(), md.ino(), md.ctime());
#[cfg(not(unix))]
let (mode, size, dev, ino, ctime) = {
let ctime = md
.created()
.ok()
.and_then(|t| t.duration_since(UNIX_EPOCH).ok())
.map(|d| d.as_secs() as i64)
.unwrap_or(0);
(0u32, md.len(), 0u64, 0u64, ctime)
};
StatInfo {
mode,
size,
mtime,
ctime,
dev,
ino,
}
}