Skip to content

Commit c0b3670

Browse files
committed
Structify data volume fingerprints.
1 parent 6a08d43 commit c0b3670

File tree

1 file changed

+81
-75
lines changed

1 file changed

+81
-75
lines changed

src/docker/remote.rs

Lines changed: 81 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -343,13 +343,13 @@ impl<'a, 'b, 'c> ContainerDataVolume<'a, 'b, 'c> {
343343
let parent = temp::dir()?;
344344
file::create_dir_all(&parent)?;
345345
let fingerprint = parent.join(self.container);
346-
let current = get_project_fingerprint(src, copy_cache)?;
346+
let current = Fingerprint::read_dir(src, copy_cache)?;
347347
// need to check if the container path exists, otherwise we might
348348
// have stale data: the persistent volume was deleted & recreated.
349349
if fingerprint.exists() && self.container_path_exists(dst, msg_info)? {
350-
let previous = parse_project_fingerprint(&fingerprint)?;
351-
let (changed, removed) = get_fingerprint_difference(&previous, &current);
352-
write_project_fingerprint(&fingerprint, &current)?;
350+
let previous = Fingerprint::read_file(&fingerprint)?;
351+
let (changed, removed) = previous.difference(&current);
352+
current.write_file(&fingerprint)?;
353353

354354
if !changed.is_empty() {
355355
self.copy_file_list(src, dst, &changed, msg_info)?;
@@ -358,7 +358,7 @@ impl<'a, 'b, 'c> ContainerDataVolume<'a, 'b, 'c> {
358358
self.remove_file_list(dst, &removed, msg_info)?;
359359
}
360360
} else {
361-
write_project_fingerprint(&fingerprint, &current)?;
361+
current.write_file(&fingerprint)?;
362362
copy_all(msg_info)?;
363363
}
364364
}
@@ -457,87 +457,93 @@ fn warn_symlinks(had_symlinks: bool, msg_info: &mut MessageInfo) -> Result<()> {
457457
}
458458
}
459459

460-
type FingerprintMap = BTreeMap<String, time::SystemTime>;
460+
#[derive(Debug)]
461+
struct Fingerprint {
462+
map: BTreeMap<String, time::SystemTime>,
463+
}
461464

462-
fn parse_project_fingerprint(path: &Path) -> Result<FingerprintMap> {
463-
let file = fs::OpenOptions::new().read(true).open(path)?;
464-
let reader = io::BufReader::new(file);
465-
let mut result = BTreeMap::new();
466-
for line in reader.lines() {
467-
let line = line?;
468-
let (timestamp, relpath) = line
469-
.split_once('\t')
470-
.ok_or_else(|| eyre::eyre!("unable to parse fingerprint line '{line}'"))?;
471-
let modified = time_from_millis(timestamp.parse::<u64>()?);
472-
result.insert(relpath.to_owned(), modified);
465+
impl Fingerprint {
466+
fn new() -> Self {
467+
Self {
468+
map: BTreeMap::new(),
469+
}
473470
}
474471

475-
Ok(result)
476-
}
472+
fn read_file(path: &Path) -> Result<Self> {
473+
let file = fs::OpenOptions::new().read(true).open(path)?;
474+
let reader = io::BufReader::new(file);
475+
let mut map = BTreeMap::new();
476+
for line in reader.lines() {
477+
let line = line?;
478+
let (timestamp, relpath) = line
479+
.split_once('\t')
480+
.ok_or_else(|| eyre::eyre!("unable to parse fingerprint line '{line}'"))?;
481+
let modified = time_from_millis(timestamp.parse::<u64>()?);
482+
map.insert(relpath.to_owned(), modified);
483+
}
477484

478-
fn write_project_fingerprint(path: &Path, fingerprint: &FingerprintMap) -> Result<()> {
479-
let mut file = fs::OpenOptions::new()
480-
.write(true)
481-
.truncate(true)
482-
.create(true)
483-
.open(path)?;
484-
for (relpath, modified) in fingerprint {
485-
let timestamp = time_to_millis(modified)?;
486-
writeln!(file, "{timestamp}\t{relpath}")?;
485+
Ok(Self { map })
487486
}
488487

489-
Ok(())
490-
}
491-
492-
fn read_dir_fingerprint(
493-
home: &Path,
494-
path: &Path,
495-
map: &mut FingerprintMap,
496-
copy_cache: bool,
497-
) -> Result<()> {
498-
for entry in fs::read_dir(path)? {
499-
let file = entry?;
500-
let file_type = file.file_type()?;
501-
// only parse known files types: 0 or 1 of these tests can pass.
502-
if file_type.is_dir() {
503-
if copy_cache || !is_cachedir(&file) {
504-
read_dir_fingerprint(home, &path.join(file.file_name()), map, copy_cache)?;
505-
}
506-
} else if file_type.is_file() || file_type.is_symlink() {
507-
// we're mounting to the same location, so this should fine
508-
// we need to round the modified date to millis.
509-
let modified = file.metadata()?.modified()?;
510-
let rounded = time_from_millis(time_to_millis(&modified)?);
511-
let relpath = file.path().strip_prefix(home)?.as_posix_relative()?;
512-
map.insert(relpath, rounded);
488+
fn write_file(&self, path: &Path) -> Result<()> {
489+
let mut file = fs::OpenOptions::new()
490+
.write(true)
491+
.truncate(true)
492+
.create(true)
493+
.open(path)?;
494+
for (relpath, modified) in &self.map {
495+
let timestamp = time_to_millis(modified)?;
496+
writeln!(file, "{timestamp}\t{relpath}")?;
513497
}
498+
499+
Ok(())
514500
}
515501

516-
Ok(())
517-
}
502+
fn _read_dir(&mut self, home: &Path, path: &Path, copy_cache: bool) -> Result<()> {
503+
for entry in fs::read_dir(path)? {
504+
let file = entry?;
505+
let file_type = file.file_type()?;
506+
// only parse known files types: 0 or 1 of these tests can pass.
507+
if file_type.is_dir() {
508+
if copy_cache || !is_cachedir(&file) {
509+
self._read_dir(home, &path.join(file.file_name()), copy_cache)?;
510+
}
511+
} else if file_type.is_file() || file_type.is_symlink() {
512+
// we're mounting to the same location, so this should fine
513+
// we need to round the modified date to millis.
514+
let modified = file.metadata()?.modified()?;
515+
let rounded = time_from_millis(time_to_millis(&modified)?);
516+
let relpath = file.path().strip_prefix(home)?.as_posix_relative()?;
517+
self.map.insert(relpath, rounded);
518+
}
519+
}
518520

519-
fn get_project_fingerprint(home: &Path, copy_cache: bool) -> Result<FingerprintMap> {
520-
let mut result = BTreeMap::new();
521-
read_dir_fingerprint(home, home, &mut result, copy_cache)?;
522-
Ok(result)
523-
}
521+
Ok(())
522+
}
524523

525-
fn get_fingerprint_difference<'a, 'b>(
526-
previous: &'a FingerprintMap,
527-
current: &'b FingerprintMap,
528-
) -> (Vec<&'b str>, Vec<&'a str>) {
529-
// this can be added or updated
530-
let changed: Vec<&str> = current
531-
.iter()
532-
.filter(|(k, v1)| previous.get(*k).map_or(true, |v2| v1 != &v2))
533-
.map(|(k, _)| k.as_str())
534-
.collect();
535-
let removed: Vec<&str> = previous
536-
.iter()
537-
.filter(|(k, _)| !current.contains_key(*k))
538-
.map(|(k, _)| k.as_str())
539-
.collect();
540-
(changed, removed)
524+
fn read_dir(home: &Path, copy_cache: bool) -> Result<Fingerprint> {
525+
let mut result = Fingerprint::new();
526+
result._read_dir(home, home, copy_cache)?;
527+
Ok(result)
528+
}
529+
530+
// gets difference between previous and current
531+
fn difference<'a, 'b>(&'a self, current: &'b Fingerprint) -> (Vec<&'b str>, Vec<&'a str>) {
532+
// this can be added or updated
533+
let changed: Vec<&str> = current
534+
.map
535+
.iter()
536+
.filter(|(k, v1)| self.map.get(*k).map_or(true, |v2| v1 != &v2))
537+
.map(|(k, _)| k.as_str())
538+
.collect();
539+
let removed: Vec<&str> = self
540+
.map
541+
.iter()
542+
.filter(|(k, _)| !current.map.contains_key(*k))
543+
.map(|(k, _)| k.as_str())
544+
.collect();
545+
(changed, removed)
546+
}
541547
}
542548

543549
impl QualifiedToolchain {

0 commit comments

Comments
 (0)