Skip to content

Commit

Permalink
Update TreeTracker to track filenames of non-latest versions
Browse files Browse the repository at this point in the history
  • Loading branch information
jwodder committed Jan 10, 2025
1 parent ec5bb4c commit 5b8abd3
Show file tree
Hide file tree
Showing 3 changed files with 473 additions and 165 deletions.
3 changes: 2 additions & 1 deletion src/syncer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,8 @@ impl Syncer {
}
InventoryEntry::Item(item) => {

Check warning on line 142 in src/syncer/mod.rs

View check run for this annotation

Codecov / codecov/patch

src/syncer/mod.rs#L142

Added line #L142 was not covered by tests
// TODO: Store a Cond for awaiting completion of item processing
for dir in tracker.add(&item.key, ())? {
// TODO: Old filenames:
for dir in tracker.add(&item.key, (), None)? {
// TODO: Spawn in JoinSet
let this2 = this.clone();
tokio::task::spawn_blocking(move || this2.cleanup_dir(dir));
Expand Down
72 changes: 48 additions & 24 deletions src/syncer/treetracker/inner.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::keypath::KeyPath;
use either::Either;
use std::cmp::Ordering;
use std::collections::HashMap;

#[derive(Clone, Debug, Eq, PartialEq)]
pub(super) struct PartialDirectory<T> {
Expand Down Expand Up @@ -43,20 +44,32 @@ impl<T> PartialDirectory<T> {
pub(super) enum Entry<T> {
File {
name: String,
//old_filenames: Vec<String>, // TODO
value: T,
value: Option<T>,
old_filenames: HashMap<String, T>,
},
Dir {
name: String,
},
}

impl<T> Entry<T> {
pub(super) fn file<S: Into<String>>(name: S, value: T) -> Entry<T> {
Entry::File {
name: name.into(),
//old_filenames: Vec::new(), // TODO
value,
pub(super) fn file<S: Into<String>>(
name: S,
value: T,
old_filename: Option<String>,
) -> Entry<T> {
if let Some(of) = old_filename {
Entry::File {
name: name.into(),
value: None,
old_filenames: HashMap::from([(of, value)]),
}
} else {
Entry::File {
name: name.into(),
value: Some(value),
old_filenames: HashMap::new(),
}
}
}

Expand All @@ -71,14 +84,6 @@ impl<T> Entry<T> {
}
}

pub(super) fn is_file(&self) -> bool {
matches!(self, Entry::File { .. })
}

pub(super) fn is_dir(&self) -> bool {
matches!(self, Entry::Dir { .. })
}

pub(super) fn cmp_name(&self) -> CmpName<'_> {
match self {
Entry::File { name, .. } => CmpName::File(name.as_ref()),
Expand Down Expand Up @@ -143,14 +148,16 @@ pub(super) struct KeyComponents<'a, T> {
i: usize,
path: &'a str,
value: Option<T>,
old_filename: Option<Option<String>>,
}

impl<'a, T> KeyComponents<'a, T> {
pub(super) fn new(key: &'a KeyPath, value: T) -> Self {
pub(super) fn new(key: &'a KeyPath, value: T, old_filename: Option<String>) -> Self {
KeyComponents {
i: 0,
path: key.as_ref(),
value: Some(value),
old_filename: Some(old_filename),
}
}
}
Expand All @@ -165,25 +172,25 @@ impl<'a, T> Iterator for KeyComponents<'a, T> {
self.path = &self.path[(i + 1)..];
Component::Dir(name)
}
None => Component::File(self.path, self.value.take()?),
None => Component::File(self.path, self.value.take()?, self.old_filename.take()?),
};
let i = self.i;
self.i += 1;
Some((i, c))
}
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[derive(Clone, Debug, Eq, PartialEq)]
pub(super) enum Component<'a, T> {
Dir(&'a str),
File(&'a str, T),
File(&'a str, T, Option<String>),
}

impl<'a, T> Component<'a, T> {
pub(super) fn cmp_name(&self) -> CmpName<'a> {
match self {
Component::Dir(name) => CmpName::Dir(name),
Component::File(name, _) => CmpName::File(name),
Component::File(name, _, _) => CmpName::File(name),
}
}
}
Expand Down Expand Up @@ -227,19 +234,36 @@ mod tests {
#[test]
fn plain() {
let key = "foo/bar/quux.txt".parse::<KeyPath>().unwrap();
let mut iter = KeyComponents::new(&key, 1);
let mut iter = KeyComponents::new(&key, 1, None);
assert_eq!(iter.next(), Some((0, Component::Dir("foo"))));
assert_eq!(iter.next(), Some((1, Component::Dir("bar"))));
assert_eq!(iter.next(), Some((2, Component::File("quux.txt", 1))));
assert_eq!(iter.next(), Some((2, Component::File("quux.txt", 1, None))));
assert_eq!(iter.next(), None);
assert_eq!(iter.next(), None);
}

#[test]
fn filename_only() {
let key = "quux.txt".parse::<KeyPath>().unwrap();
let mut iter = KeyComponents::new(&key, 1);
assert_eq!(iter.next(), Some((0, Component::File("quux.txt", 1))));
let mut iter = KeyComponents::new(&key, 1, None);
assert_eq!(iter.next(), Some((0, Component::File("quux.txt", 1, None))));
assert_eq!(iter.next(), None);
assert_eq!(iter.next(), None);
}

#[test]
fn with_old_filename() {
let key = "foo/bar/quux.txt".parse::<KeyPath>().unwrap();
let mut iter = KeyComponents::new(&key, 1, Some("quux.old.1.2".into()));
assert_eq!(iter.next(), Some((0, Component::Dir("foo"))));
assert_eq!(iter.next(), Some((1, Component::Dir("bar"))));
assert_eq!(
iter.next(),
Some((
2,
Component::File("quux.txt", 1, Some("quux.old.1.2".into()))
))
);
assert_eq!(iter.next(), None);
assert_eq!(iter.next(), None);
}
Expand Down
Loading

0 comments on commit 5b8abd3

Please sign in to comment.