Bump to 0.3.1 and format/clippy
This commit is contained in:
286
src/memories.rs
286
src/memories.rs
@@ -36,9 +36,8 @@ impl PathExcluder {
|
||||
let mut excluded_patterns = Vec::new();
|
||||
|
||||
for dir in raw_excluded {
|
||||
if dir.starts_with('/') {
|
||||
if let Some(rel) = dir.strip_prefix('/') {
|
||||
// Absolute under base
|
||||
let rel = &dir[1..];
|
||||
if !rel.is_empty() {
|
||||
excluded_dirs.push(base.join(rel));
|
||||
}
|
||||
@@ -64,7 +63,10 @@ impl PathExcluder {
|
||||
// Directory-based exclusions
|
||||
for excluded in &self.excluded_dirs {
|
||||
if path.starts_with(excluded) {
|
||||
debug!("PathExcluder: excluded by dir: {:?} (rule: {:?})", path, excluded);
|
||||
debug!(
|
||||
"PathExcluder: excluded by dir: {:?} (rule: {:?})",
|
||||
path, excluded
|
||||
);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -73,19 +75,14 @@ impl PathExcluder {
|
||||
// not substrings.
|
||||
if !self.excluded_patterns.is_empty() {
|
||||
for component in path.components() {
|
||||
if let Some(comp_str) = component.as_os_str().to_str() {
|
||||
if self
|
||||
.excluded_patterns
|
||||
.iter()
|
||||
.any(|pat| pat == comp_str)
|
||||
{
|
||||
if let Some(comp_str) = component.as_os_str().to_str()
|
||||
&& self.excluded_patterns.iter().any(|pat| pat == comp_str) {
|
||||
debug!(
|
||||
"PathExcluder: excluded by component pattern: {:?} (component: {:?}, patterns: {:?})",
|
||||
path, comp_str, self.excluded_patterns
|
||||
);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -255,20 +252,19 @@ fn extract_date_from_filename(filename: &str) -> Option<DateTime<FixedOffset>> {
|
||||
let timestamp_str = captures.get(1)?.as_str();
|
||||
|
||||
// Millisecond timestamp (13 digits)
|
||||
if timestamp_str.len() >= 13 {
|
||||
if let Some(date_time) = timestamp_str[0..13]
|
||||
if timestamp_str.len() >= 13
|
||||
&& let Some(date_time) = timestamp_str[0..13]
|
||||
.parse::<i64>()
|
||||
.ok()
|
||||
.and_then(|timestamp_millis| DateTime::from_timestamp_millis(timestamp_millis))
|
||||
.and_then(DateTime::from_timestamp_millis)
|
||||
.map(|naive_dt| naive_dt.fixed_offset())
|
||||
{
|
||||
return Some(date_time);
|
||||
}
|
||||
}
|
||||
|
||||
// Second timestamp (10 digits)
|
||||
if timestamp_str.len() >= 10 {
|
||||
if let Some(date_time) = timestamp_str[0..10]
|
||||
if timestamp_str.len() >= 10
|
||||
&& let Some(date_time) = timestamp_str[0..10]
|
||||
.parse::<i64>()
|
||||
.ok()
|
||||
.and_then(|timestamp_secs| DateTime::from_timestamp(timestamp_secs, 0))
|
||||
@@ -276,7 +272,6 @@ fn extract_date_from_filename(filename: &str) -> Option<DateTime<FixedOffset>> {
|
||||
{
|
||||
return Some(date_time);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
@@ -607,137 +602,140 @@ mod tests {
|
||||
assert_eq!(dt_modified.year(), today.year());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_path_excluder_absolute_under_base() {
|
||||
let tmp = tempdir().unwrap();
|
||||
let base = tmp.path();
|
||||
#[test]
|
||||
fn test_path_excluder_absolute_under_base() {
|
||||
let tmp = tempdir().unwrap();
|
||||
let base = tmp.path();
|
||||
|
||||
// Simulate structure:
|
||||
// base/photos/private/secret.jpg
|
||||
// base/photos/public/ok.jpg
|
||||
// base/screenshots/img.png
|
||||
let photos_private = base.join("photos/private");
|
||||
let photos_public = base.join("photos/public");
|
||||
let screenshots = base.join("screenshots");
|
||||
// Simulate structure:
|
||||
// base/photos/private/secret.jpg
|
||||
// base/photos/public/ok.jpg
|
||||
// base/screenshots/img.png
|
||||
let photos_private = base.join("photos/private");
|
||||
let photos_public = base.join("photos/public");
|
||||
let screenshots = base.join("screenshots");
|
||||
|
||||
fs::create_dir_all(&photos_private).unwrap();
|
||||
fs::create_dir_all(&photos_public).unwrap();
|
||||
fs::create_dir_all(&screenshots).unwrap();
|
||||
fs::create_dir_all(&photos_private).unwrap();
|
||||
fs::create_dir_all(&photos_public).unwrap();
|
||||
fs::create_dir_all(&screenshots).unwrap();
|
||||
|
||||
let secret = photos_private.join("secret.jpg");
|
||||
let ok = photos_public.join("ok.jpg");
|
||||
let shot = screenshots.join("img.png");
|
||||
let secret = photos_private.join("secret.jpg");
|
||||
let ok = photos_public.join("ok.jpg");
|
||||
let shot = screenshots.join("img.png");
|
||||
|
||||
File::create(&secret).unwrap();
|
||||
File::create(&ok).unwrap();
|
||||
File::create(&shot).unwrap();
|
||||
File::create(&secret).unwrap();
|
||||
File::create(&ok).unwrap();
|
||||
File::create(&shot).unwrap();
|
||||
|
||||
// Exclude "/photos/private" and "/screenshots" under base
|
||||
let excluded = vec![
|
||||
String::from("/photos/private"),
|
||||
String::from("/screenshots"),
|
||||
];
|
||||
let excluder = PathExcluder::new(base, &excluded);
|
||||
// Exclude "/photos/private" and "/screenshots" under base
|
||||
let excluded = vec![
|
||||
String::from("/photos/private"),
|
||||
String::from("/screenshots"),
|
||||
];
|
||||
let excluder = PathExcluder::new(base, &excluded);
|
||||
|
||||
assert!(excluder.is_excluded(&secret), "secret should be excluded");
|
||||
assert!(excluder.is_excluded(&shot), "screenshots should be excluded");
|
||||
assert!(
|
||||
!excluder.is_excluded(&ok),
|
||||
"public photo should NOT be excluded"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_path_excluder_pattern_anywhere_under_base() {
|
||||
let tmp = tempdir().unwrap();
|
||||
let base = tmp.path();
|
||||
|
||||
// Simulate:
|
||||
// base/a/tmp_file.jpg
|
||||
// base/b/normal.jpg
|
||||
// base/c/sometmpdir/file.jpg
|
||||
let a = base.join("a");
|
||||
let b = base.join("b");
|
||||
let c = base.join("c/tmp");
|
||||
|
||||
fs::create_dir_all(&a).unwrap();
|
||||
fs::create_dir_all(&b).unwrap();
|
||||
fs::create_dir_all(&c).unwrap();
|
||||
|
||||
let tmp_file = a.join("tmp_file.jpg");
|
||||
let normal = b.join("normal.jpg");
|
||||
let tmp_dir_file = c.join("file.jpg");
|
||||
|
||||
File::create(&tmp_file).unwrap();
|
||||
File::create(&normal).unwrap();
|
||||
File::create(&tmp_dir_file).unwrap();
|
||||
|
||||
// Exclude any path containing "tmp"
|
||||
let excluded = vec![String::from("tmp")];
|
||||
let excluder = PathExcluder::new(base, &excluded);
|
||||
|
||||
assert!(
|
||||
!excluder.is_excluded(&tmp_file),
|
||||
"file with 'tmp' in name should NOT be excluded"
|
||||
);
|
||||
assert!(
|
||||
excluder.is_excluded(&tmp_dir_file),
|
||||
"file in directory with 'tmp' in path should be excluded"
|
||||
);
|
||||
assert!(
|
||||
!excluder.is_excluded(&normal),
|
||||
"file without 'tmp' in its path should NOT be excluded"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_path_excluder_mixed_absolute_and_pattern() {
|
||||
let tmp = tempdir().unwrap();
|
||||
let base = tmp.path();
|
||||
|
||||
// Simulate:
|
||||
// base/photos/private/secret_tmp.jpg -> excluded by absolute dir rule
|
||||
// base/photos/private/secret.jpg -> excluded by absolute dir rule
|
||||
// base/photos/tmp/public.jpg -> excluded by pattern "tmp" (dir name)
|
||||
// base/photos/public/tmp_public.jpg -> NOT excluded (file name contains "tmp" but not equal)
|
||||
// base/other/keep.jpg -> NOT excluded
|
||||
let photos_private = base.join("photos/private");
|
||||
let photos_tmp = base.join("photos/tmp");
|
||||
let photos_public = base.join("photos/public");
|
||||
let other = base.join("other");
|
||||
|
||||
fs::create_dir_all(&photos_private).unwrap();
|
||||
fs::create_dir_all(&photos_tmp).unwrap();
|
||||
fs::create_dir_all(&photos_public).unwrap();
|
||||
fs::create_dir_all(&other).unwrap();
|
||||
|
||||
let secret_tmp = photos_private.join("secret_tmp.jpg");
|
||||
let secret = photos_private.join("secret.jpg");
|
||||
let tmp_dir_file = photos_tmp.join("public.jpg");
|
||||
let tmp_in_name = photos_public.join("tmp_public.jpg");
|
||||
let keep = other.join("keep.jpg");
|
||||
|
||||
File::create(&secret_tmp).unwrap();
|
||||
File::create(&secret).unwrap();
|
||||
File::create(&tmp_dir_file).unwrap();
|
||||
File::create(&tmp_in_name).unwrap();
|
||||
File::create(&keep).unwrap();
|
||||
|
||||
// Mixed: exclude "/photos/private" (dir) and any component equal to "tmp"
|
||||
let excluded = vec![String::from("/photos/private"), String::from("tmp")];
|
||||
let excluder = PathExcluder::new(base, &excluded);
|
||||
|
||||
// Entire private tree is excluded by dir rule
|
||||
assert!(excluder.is_excluded(&secret_tmp));
|
||||
assert!(excluder.is_excluded(&secret));
|
||||
|
||||
// Dir 'tmp' under photos excluded by pattern
|
||||
assert!(excluder.is_excluded(&tmp_dir_file));
|
||||
|
||||
// File name containing 'tmp' but not equal should NOT be excluded
|
||||
assert!(!excluder.is_excluded(&tmp_in_name));
|
||||
|
||||
// keep.jpg doesn't match any rule
|
||||
assert!(!excluder.is_excluded(&keep));
|
||||
}
|
||||
assert!(excluder.is_excluded(&secret), "secret should be excluded");
|
||||
assert!(
|
||||
excluder.is_excluded(&shot),
|
||||
"screenshots should be excluded"
|
||||
);
|
||||
assert!(
|
||||
!excluder.is_excluded(&ok),
|
||||
"public photo should NOT be excluded"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_path_excluder_pattern_anywhere_under_base() {
|
||||
let tmp = tempdir().unwrap();
|
||||
let base = tmp.path();
|
||||
|
||||
// Simulate:
|
||||
// base/a/tmp_file.jpg
|
||||
// base/b/normal.jpg
|
||||
// base/c/sometmpdir/file.jpg
|
||||
let a = base.join("a");
|
||||
let b = base.join("b");
|
||||
let c = base.join("c/tmp");
|
||||
|
||||
fs::create_dir_all(&a).unwrap();
|
||||
fs::create_dir_all(&b).unwrap();
|
||||
fs::create_dir_all(&c).unwrap();
|
||||
|
||||
let tmp_file = a.join("tmp_file.jpg");
|
||||
let normal = b.join("normal.jpg");
|
||||
let tmp_dir_file = c.join("file.jpg");
|
||||
|
||||
File::create(&tmp_file).unwrap();
|
||||
File::create(&normal).unwrap();
|
||||
File::create(&tmp_dir_file).unwrap();
|
||||
|
||||
// Exclude any path containing "tmp"
|
||||
let excluded = vec![String::from("tmp")];
|
||||
let excluder = PathExcluder::new(base, &excluded);
|
||||
|
||||
assert!(
|
||||
!excluder.is_excluded(&tmp_file),
|
||||
"file with 'tmp' in name should NOT be excluded"
|
||||
);
|
||||
assert!(
|
||||
excluder.is_excluded(&tmp_dir_file),
|
||||
"file in directory with 'tmp' in path should be excluded"
|
||||
);
|
||||
assert!(
|
||||
!excluder.is_excluded(&normal),
|
||||
"file without 'tmp' in its path should NOT be excluded"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_path_excluder_mixed_absolute_and_pattern() {
|
||||
let tmp = tempdir().unwrap();
|
||||
let base = tmp.path();
|
||||
|
||||
// Simulate:
|
||||
// base/photos/private/secret_tmp.jpg -> excluded by absolute dir rule
|
||||
// base/photos/private/secret.jpg -> excluded by absolute dir rule
|
||||
// base/photos/tmp/public.jpg -> excluded by pattern "tmp" (dir name)
|
||||
// base/photos/public/tmp_public.jpg -> NOT excluded (file name contains "tmp" but not equal)
|
||||
// base/other/keep.jpg -> NOT excluded
|
||||
let photos_private = base.join("photos/private");
|
||||
let photos_tmp = base.join("photos/tmp");
|
||||
let photos_public = base.join("photos/public");
|
||||
let other = base.join("other");
|
||||
|
||||
fs::create_dir_all(&photos_private).unwrap();
|
||||
fs::create_dir_all(&photos_tmp).unwrap();
|
||||
fs::create_dir_all(&photos_public).unwrap();
|
||||
fs::create_dir_all(&other).unwrap();
|
||||
|
||||
let secret_tmp = photos_private.join("secret_tmp.jpg");
|
||||
let secret = photos_private.join("secret.jpg");
|
||||
let tmp_dir_file = photos_tmp.join("public.jpg");
|
||||
let tmp_in_name = photos_public.join("tmp_public.jpg");
|
||||
let keep = other.join("keep.jpg");
|
||||
|
||||
File::create(&secret_tmp).unwrap();
|
||||
File::create(&secret).unwrap();
|
||||
File::create(&tmp_dir_file).unwrap();
|
||||
File::create(&tmp_in_name).unwrap();
|
||||
File::create(&keep).unwrap();
|
||||
|
||||
// Mixed: exclude "/photos/private" (dir) and any component equal to "tmp"
|
||||
let excluded = vec![String::from("/photos/private"), String::from("tmp")];
|
||||
let excluder = PathExcluder::new(base, &excluded);
|
||||
|
||||
// Entire private tree is excluded by dir rule
|
||||
assert!(excluder.is_excluded(&secret_tmp));
|
||||
assert!(excluder.is_excluded(&secret));
|
||||
|
||||
// Dir 'tmp' under photos excluded by pattern
|
||||
assert!(excluder.is_excluded(&tmp_dir_file));
|
||||
|
||||
// File name containing 'tmp' but not equal should NOT be excluded
|
||||
assert!(!excluder.is_excluded(&tmp_in_name));
|
||||
|
||||
// keep.jpg doesn't match any rule
|
||||
assert!(!excluder.is_excluded(&keep));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user