From f4a9cfaa19d9f088768f2f705f14a400ad701a8b Mon Sep 17 00:00:00 2001 From: simonsan <14062932+simonsan@users.noreply.github.com> Date: Sun, 28 May 2023 22:09:28 +0200 Subject: [PATCH] refactor: to filetime for platform-agnostic atime, ctime, mtime inspection --- Cargo.lock | 13 +++++++ Cargo.toml | 3 ++ TODO.md | 1 + crates/organize-rs_core/Cargo.toml | 1 + crates/organize-rs_core/src/filters/impl_.rs | 24 ++++++------ crates/organize-rs_core/src/filters/tests.rs | 35 ++++++++++++++---- .../{different_sizes => size_based}/1MiB | Bin .../{different_sizes => size_based}/300KiB | Bin .../{different_sizes => size_based}/empty.txt | 0 tests/fixtures/.gitkeep | 0 10 files changed, 56 insertions(+), 21 deletions(-) rename crates/organize-rs_core/tests/fixtures/filters/{different_sizes => size_based}/1MiB (100%) rename crates/organize-rs_core/tests/fixtures/filters/{different_sizes => size_based}/300KiB (100%) rename crates/organize-rs_core/tests/fixtures/filters/{different_sizes => size_based}/empty.txt (100%) delete mode 100644 tests/fixtures/.gitkeep diff --git a/Cargo.lock b/Cargo.lock index 2e277b5..a33c164 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -625,6 +625,18 @@ dependencies = [ "instant", ] +[[package]] +name = "filetime" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cbc844cecaee9d4443931972e1289c8ff485cb4cc2767cb03ca139ed6885153" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall 0.2.16", + "windows-sys 0.48.0", +] + [[package]] name = "fnv" version = "1.0.7" @@ -1165,6 +1177,7 @@ dependencies = [ "displaydoc", "duct", "expect-test", + "filetime", "indicatif", "infer", "itertools", diff --git a/Cargo.toml b/Cargo.toml index b54127f..92505fb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -64,6 +64,8 @@ open = "4.1.0" winnow = "0.4.6" byte-unit = "4.0.19" +# date related +filetime = "0.2.21" # infer file and MIME type by magic number infer = "0.13" @@ -159,6 +161,7 @@ dialoguer = { workspace = true } ron = { workspace = true } open = { workspace = true } + [dev-dependencies] abscissa_core = { workspace = true, features = ["testing"] } once_cell = { workspace = true } diff --git a/TODO.md b/TODO.md index fb60494..05cfd07 100644 --- a/TODO.md +++ b/TODO.md @@ -13,6 +13,7 @@ 1. implement Terminal UI - generate config interactively `generate config --interactive` + - + 1. implement scripting 1. build GUI diff --git a/crates/organize-rs_core/Cargo.toml b/crates/organize-rs_core/Cargo.toml index d6678fd..b471482 100644 --- a/crates/organize-rs_core/Cargo.toml +++ b/crates/organize-rs_core/Cargo.toml @@ -64,6 +64,7 @@ winnow = { workspace = true } byte-unit = { workspace = true } trash = { workspace = true } rayon = { workspace = true } +filetime = { workspace = true } [dev-dependencies] rustup-toolchain = "0.1.4" diff --git a/crates/organize-rs_core/src/filters/impl_.rs b/crates/organize-rs_core/src/filters/impl_.rs index cf8296c..880b01a 100644 --- a/crates/organize-rs_core/src/filters/impl_.rs +++ b/crates/organize-rs_core/src/filters/impl_.rs @@ -1,5 +1,6 @@ use chrono::{DateTime, Utc}; +use filetime::FileTime; use itertools::Itertools; use jwalk::{ClientState, DirEntry}; @@ -198,9 +199,8 @@ impl FilterKind { ) -> Box) -> bool + 'args> { Box::new(|entry| { entry.metadata().ok().map_or(false, |metadata| { - metadata.accessed().map_or(false, |sys_time| { - Self::matches_date(&sys_time, &range.clone()) - }) + let atime = FileTime::from_last_access_time(&metadata); + Self::matches_date(&atime, &range.clone()) }) }) } @@ -210,30 +210,28 @@ impl FilterKind { ) -> Box) -> bool + 'args> { Box::new(|entry| { entry.metadata().ok().map_or(false, |metadata| { - metadata.modified().map_or(false, |sys_time| { - Self::matches_date(&sys_time, &range.clone()) - }) + let mtime = FileTime::from_last_modification_time(&metadata); + Self::matches_date(&mtime, &range.clone()) }) }) } + fn filter_by_created<'a, 'args, C: ClientState>( &'a self, range: &'args PeriodRange, ) -> Box) -> bool + 'args> { Box::new(|entry| { entry.metadata().ok().map_or(false, |metadata| { - metadata.created().map_or(false, |sys_time| { - Self::matches_date(&sys_time, &range.clone()) - }) + FileTime::from_creation_time(&metadata) + .map_or(false, |ctime| Self::matches_date(&ctime, &range.clone())) }) }) } - fn matches_date(item_date: &std::time::SystemTime, range: &PeriodRange) -> bool { - let datetime_file: DateTime = chrono::DateTime::from(*item_date); - let now = chrono::offset::Utc::now(); + fn matches_date(item_date: &FileTime, range: &PeriodRange) -> bool { + let now = FileTime::now(); - let seconds_since_created = match u64::try_from((now - datetime_file).num_seconds()) { + let seconds_since_created = match u64::try_from(now.seconds() - item_date.seconds()) { Ok(it) => it, Err(err) => { eprintln!("subtraction of two datetimes can't be negative: {err}"); diff --git a/crates/organize-rs_core/src/filters/tests.rs b/crates/organize-rs_core/src/filters/tests.rs index f1b55a9..e0f37f5 100644 --- a/crates/organize-rs_core/src/filters/tests.rs +++ b/crates/organize-rs_core/src/filters/tests.rs @@ -71,10 +71,10 @@ fn empty_file() -> Vec { #[fixture] fn size() -> Vec { vec![ - get_fixtures_dir().join("different_sizes"), - get_fixtures_dir().join("different_sizes").join("1MiB"), - get_fixtures_dir().join("different_sizes").join("300KiB"), - get_fixtures_dir().join("different_sizes").join("empty.txt"), + get_fixtures_dir().join("size_based"), + get_fixtures_dir().join("size_based").join("1MiB"), + get_fixtures_dir().join("size_based").join("300KiB"), + get_fixtures_dir().join("size_based").join("empty.txt"), ] } @@ -133,9 +133,28 @@ fn get_fixture_entries(sub_dir: impl AsRef) -> Vec> { .collect_vec() } +#[rstest] +fn test_filter_file_date_7d_passes(mut size: Vec) { + let filter = FilterKind::Size { + range: SizeRange::from_str("..2mb").unwrap(), + }; + + let mut entries = get_fixture_entries("date_based"); + let paths = entries.iter().map(|f| f.path()).collect_vec(); + assert_eq!(entries.len(), size.len()); + assert_eq!(paths, size); + entries.retain(|f| (filter.get_filter()(f))); + let paths = entries.iter().map(|f| f.path()).collect_vec(); + + _ = size.remove(0); + + assert_eq!(entries.len(), size.len()); + assert_eq!(paths, size); +} + #[rstest] #[should_panic] -fn test_filter_mimetype_image_passes(mut mimetype: Vec) { +fn test_filter_mimetype_image_fails(mut mimetype: Vec) { let filter = FilterKind::Mimetype { mimetype: vec![String::from("image")], }; @@ -522,7 +541,7 @@ fn test_filter_file_size_2mb_passes(mut size: Vec) { range: SizeRange::from_str("..2mb").unwrap(), }; - let mut entries = get_fixture_entries("different_sizes"); + let mut entries = get_fixture_entries("size_based"); let paths = entries.iter().map(|f| f.path()).collect_vec(); assert_eq!(entries.len(), size.len()); assert_eq!(paths, size); @@ -541,7 +560,7 @@ fn test_filter_file_size_350_800_kib_passes(mut size: Vec) { range: SizeRange::from_str("350KiB..800kib").unwrap(), }; - let mut entries = get_fixture_entries("different_sizes"); + let mut entries = get_fixture_entries("size_based"); let paths = entries.iter().map(|f| f.path()).collect_vec(); assert_eq!(entries.len(), size.len()); assert_eq!(paths, size); @@ -559,7 +578,7 @@ fn test_filter_file_size_250kib_passes(mut size: Vec) { range: SizeRange::from_str("250KiB..").unwrap(), }; - let mut entries = get_fixture_entries("different_sizes"); + let mut entries = get_fixture_entries("size_based"); let paths = entries.iter().map(|f| f.path()).collect_vec(); assert_eq!(entries.len(), size.len()); assert_eq!(paths, size); diff --git a/crates/organize-rs_core/tests/fixtures/filters/different_sizes/1MiB b/crates/organize-rs_core/tests/fixtures/filters/size_based/1MiB similarity index 100% rename from crates/organize-rs_core/tests/fixtures/filters/different_sizes/1MiB rename to crates/organize-rs_core/tests/fixtures/filters/size_based/1MiB diff --git a/crates/organize-rs_core/tests/fixtures/filters/different_sizes/300KiB b/crates/organize-rs_core/tests/fixtures/filters/size_based/300KiB similarity index 100% rename from crates/organize-rs_core/tests/fixtures/filters/different_sizes/300KiB rename to crates/organize-rs_core/tests/fixtures/filters/size_based/300KiB diff --git a/crates/organize-rs_core/tests/fixtures/filters/different_sizes/empty.txt b/crates/organize-rs_core/tests/fixtures/filters/size_based/empty.txt similarity index 100% rename from crates/organize-rs_core/tests/fixtures/filters/different_sizes/empty.txt rename to crates/organize-rs_core/tests/fixtures/filters/size_based/empty.txt diff --git a/tests/fixtures/.gitkeep b/tests/fixtures/.gitkeep deleted file mode 100644 index e69de29..0000000