mirror of
https://github.com/sharkdp/fd
synced 2024-10-06 07:49:18 +00:00
Add support for --changed-before and --changed-with for modification time based search
This commit is contained in:
parent
8691ab4bed
commit
54c117d72f
35
Cargo.lock
generated
35
Cargo.lock
generated
|
@ -82,6 +82,9 @@ dependencies = [
|
||||||
"clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"ctrlc 3.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ctrlc 3.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
"diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"filetime 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"if_chain 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"ignore 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ignore 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -92,6 +95,16 @@ dependencies = [
|
||||||
"version_check 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"version_check 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "filetime"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fnv"
|
name = "fnv"
|
||||||
version = "1.0.6"
|
version = "1.0.6"
|
||||||
|
@ -123,6 +136,19 @@ dependencies = [
|
||||||
"regex 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"regex 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "humantime"
|
||||||
|
version = "1.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "if_chain"
|
||||||
|
version = "0.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ignore"
|
name = "ignore"
|
||||||
version = "0.4.3"
|
version = "0.4.3"
|
||||||
|
@ -198,6 +224,11 @@ dependencies = [
|
||||||
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quick-error"
|
||||||
|
version = "1.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rand"
|
name = "rand"
|
||||||
version = "0.4.3"
|
version = "0.4.3"
|
||||||
|
@ -387,10 +418,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
"checksum crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "24ce9782d4d5c53674646a6a4c1863a21a8fc0cb649b3c94dfc16e45071dea19"
|
"checksum crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "24ce9782d4d5c53674646a6a4c1863a21a8fc0cb649b3c94dfc16e45071dea19"
|
||||||
"checksum ctrlc 3.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "630391922b1b893692c6334369ff528dcc3a9d8061ccf4c803aa8f83cb13db5e"
|
"checksum ctrlc 3.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "630391922b1b893692c6334369ff528dcc3a9d8061ccf4c803aa8f83cb13db5e"
|
||||||
"checksum diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a"
|
"checksum diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a"
|
||||||
|
"checksum filetime 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "da4b9849e77b13195302c174324b5ba73eec9b236b24c221a61000daefb95c5f"
|
||||||
"checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3"
|
"checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3"
|
||||||
"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
|
"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
|
||||||
"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
|
"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
|
||||||
"checksum globset 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8e49edbcc9c7fc5beb8c0a54e7319ff8bed353a2b55e85811c6281188c2a6c84"
|
"checksum globset 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8e49edbcc9c7fc5beb8c0a54e7319ff8bed353a2b55e85811c6281188c2a6c84"
|
||||||
|
"checksum humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0484fda3e7007f2a4a0d9c3a703ca38c71c54c55602ce4660c419fd32e188c9e"
|
||||||
|
"checksum if_chain 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4bac95d9aa0624e7b78187d6fb8ab012b41d9f6f54b1bcb61e61c4845f8357ec"
|
||||||
"checksum ignore 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3e9faa7c84064f07b40da27044af629f578bc7994b650d3e458d0c29183c1d91"
|
"checksum ignore 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3e9faa7c84064f07b40da27044af629f578bc7994b650d3e458d0c29183c1d91"
|
||||||
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
|
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
|
||||||
"checksum lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca488b89a5657b0a2ecd45b95609b3e848cf1755da332a0da46e2b2b1cb371a7"
|
"checksum lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca488b89a5657b0a2ecd45b95609b3e848cf1755da332a0da46e2b2b1cb371a7"
|
||||||
|
@ -399,6 +433,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
"checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d"
|
"checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d"
|
||||||
"checksum nix 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d37e713a259ff641624b6cb20e3b12b2952313ba36b6823c0f16e6cfd9e5de17"
|
"checksum nix 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d37e713a259ff641624b6cb20e3b12b2952313ba36b6823c0f16e6cfd9e5de17"
|
||||||
"checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30"
|
"checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30"
|
||||||
|
"checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0"
|
||||||
"checksum rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8356f47b32624fef5b3301c1be97e5944ecdd595409cc5da11d05f211db6cfbd"
|
"checksum rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8356f47b32624fef5b3301c1be97e5944ecdd595409cc5da11d05f211db6cfbd"
|
||||||
"checksum redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "c214e91d3ecf43e9a4e41e578973adeb14b474f2bee858742d127af75a0112b1"
|
"checksum redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "c214e91d3ecf43e9a4e41e578973adeb14b474f2bee858742d127af75a0112b1"
|
||||||
"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
|
"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
|
||||||
|
|
|
@ -40,6 +40,8 @@ num_cpus = "1.8"
|
||||||
regex = "1.0.0"
|
regex = "1.0.0"
|
||||||
regex-syntax = "0.6"
|
regex-syntax = "0.6"
|
||||||
ctrlc = "3.1"
|
ctrlc = "3.1"
|
||||||
|
humantime = "1.1.1"
|
||||||
|
if_chain = "0.1.3"
|
||||||
|
|
||||||
[dependencies.clap]
|
[dependencies.clap]
|
||||||
version = "2.31.2"
|
version = "2.31.2"
|
||||||
|
@ -51,3 +53,4 @@ libc = "0.2"
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
diff = "0.1"
|
diff = "0.1"
|
||||||
tempdir = "0.3"
|
tempdir = "0.3"
|
||||||
|
filetime = "0.2.1"
|
||||||
|
|
22
src/app.rs
22
src/app.rs
|
@ -169,6 +169,18 @@ pub fn build_app() -> App<'static, 'static> {
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
.hidden(true),
|
.hidden(true),
|
||||||
)
|
)
|
||||||
|
.arg(
|
||||||
|
arg("changed-within")
|
||||||
|
.long("changed-within")
|
||||||
|
.takes_value(true)
|
||||||
|
.number_of_values(1),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
arg("changed-before")
|
||||||
|
.long("changed-before")
|
||||||
|
.takes_value(true)
|
||||||
|
.number_of_values(1),
|
||||||
|
)
|
||||||
.arg(arg("pattern"))
|
.arg(arg("pattern"))
|
||||||
.arg(arg("path").multiple(true))
|
.arg(arg("path").multiple(true))
|
||||||
}
|
}
|
||||||
|
@ -292,5 +304,15 @@ fn usage() -> HashMap<&'static str, Help> {
|
||||||
'mi': mebibytes\n \
|
'mi': mebibytes\n \
|
||||||
'gi': gibibytes\n \
|
'gi': gibibytes\n \
|
||||||
'ti': tebibytes");
|
'ti': tebibytes");
|
||||||
|
doc!(h, "changed-before"
|
||||||
|
, "Limit results based on modification time older than duration or date provided."
|
||||||
|
, "Limit results based on modification time older than duration provided:\n \
|
||||||
|
using a duration: <NUM>d <NUM>h <NUM>m <NUM>s (e.g. 10h, 1d, 35min...)\n \
|
||||||
|
or a date and time: YYYY-MM-DD HH:MM:SS");
|
||||||
|
doc!(h, "changed-within"
|
||||||
|
, "Limit results based on modification time within the duration provided or between date provided and now."
|
||||||
|
, "Limit results based on modification time within the duration provided:\n \
|
||||||
|
using a duration: <NUM>d <NUM>h <NUM>m <NUM>s (e.g. 10h, 1d, 35min...)\n \
|
||||||
|
or a date and time: YYYY-MM-DD HH:MM:SS");
|
||||||
h
|
h
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
use std::ffi::OsString;
|
use std::ffi::OsString;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::process;
|
use std::process;
|
||||||
use std::time;
|
use std::time::{self, SystemTime};
|
||||||
|
|
||||||
use exec::CommandTemplate;
|
use exec::CommandTemplate;
|
||||||
use lscolors::LsColors;
|
use lscolors::LsColors;
|
||||||
|
@ -100,6 +100,38 @@ impl SizeFilter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Filter based on time ranges
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
pub enum TimeFilter {
|
||||||
|
Before(SystemTime),
|
||||||
|
After(SystemTime),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TimeFilter {
|
||||||
|
fn from_str(s: &str) -> Option<SystemTime> {
|
||||||
|
use humantime;
|
||||||
|
humantime::parse_duration(s)
|
||||||
|
.map(|duration| SystemTime::now() - duration)
|
||||||
|
.or_else(|_| humantime::parse_rfc3339_weak(s))
|
||||||
|
.ok()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn before(s: &str) -> Option<TimeFilter> {
|
||||||
|
Some(TimeFilter::Before(TimeFilter::from_str(s)?))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn after(s: &str) -> Option<TimeFilter> {
|
||||||
|
Some(TimeFilter::After(TimeFilter::from_str(s)?))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_within(&self, t: &SystemTime) -> bool {
|
||||||
|
match self {
|
||||||
|
TimeFilter::Before(limit) => t <= limit,
|
||||||
|
TimeFilter::After(limit) => t >= limit,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Configuration options for *fd*.
|
/// Configuration options for *fd*.
|
||||||
pub struct FdOptions {
|
pub struct FdOptions {
|
||||||
/// Whether the search is case-sensitive or case-insensitive.
|
/// Whether the search is case-sensitive or case-insensitive.
|
||||||
|
@ -162,6 +194,9 @@ pub struct FdOptions {
|
||||||
|
|
||||||
/// The given constraints on the size of returned files
|
/// The given constraints on the size of returned files
|
||||||
pub size_constraints: Vec<SizeFilter>,
|
pub size_constraints: Vec<SizeFilter>,
|
||||||
|
|
||||||
|
/// Constraints on last modification time of files
|
||||||
|
pub modification_constraints: Vec<TimeFilter>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Print error message to stderr.
|
/// Print error message to stderr.
|
||||||
|
@ -468,4 +503,18 @@ mod tests {
|
||||||
let f = SizeFilter::from_string("+1K").unwrap();
|
let f = SizeFilter::from_string("+1K").unwrap();
|
||||||
assert!(f.is_within(1000));
|
assert!(f.is_within(1000));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn is_time_within() {
|
||||||
|
let now = SystemTime::now();
|
||||||
|
assert!(TimeFilter::after("1min").unwrap().is_within(&now));
|
||||||
|
assert!(!TimeFilter::before("1min").unwrap().is_within(&now));
|
||||||
|
|
||||||
|
let t1m_ago = SystemTime::now() - time::Duration::from_secs(60);
|
||||||
|
assert!(!TimeFilter::after("30sec").unwrap().is_within(&t1m_ago));
|
||||||
|
assert!(TimeFilter::after("2min").unwrap().is_within(&t1m_ago));
|
||||||
|
|
||||||
|
assert!(TimeFilter::before("30sec").unwrap().is_within(&t1m_ago));
|
||||||
|
assert!(!TimeFilter::before("2min").unwrap().is_within(&t1m_ago));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
22
src/main.rs
22
src/main.rs
|
@ -13,11 +13,14 @@ extern crate clap;
|
||||||
extern crate ignore;
|
extern crate ignore;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate lazy_static;
|
extern crate lazy_static;
|
||||||
|
extern crate humantime;
|
||||||
#[cfg(all(unix, not(target_os = "redox")))]
|
#[cfg(all(unix, not(target_os = "redox")))]
|
||||||
extern crate libc;
|
extern crate libc;
|
||||||
extern crate num_cpus;
|
extern crate num_cpus;
|
||||||
extern crate regex;
|
extern crate regex;
|
||||||
extern crate regex_syntax;
|
extern crate regex_syntax;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate if_chain;
|
||||||
|
|
||||||
mod app;
|
mod app;
|
||||||
mod exec;
|
mod exec;
|
||||||
|
@ -40,7 +43,7 @@ use regex::{RegexBuilder, RegexSetBuilder};
|
||||||
use exec::CommandTemplate;
|
use exec::CommandTemplate;
|
||||||
use internal::{
|
use internal::{
|
||||||
pattern_has_uppercase_char, print_error_and_exit, transform_args_with_exec, FdOptions,
|
pattern_has_uppercase_char, print_error_and_exit, transform_args_with_exec, FdOptions,
|
||||||
FileTypes, SizeFilter,
|
FileTypes, SizeFilter, TimeFilter,
|
||||||
};
|
};
|
||||||
use lscolors::LsColors;
|
use lscolors::LsColors;
|
||||||
|
|
||||||
|
@ -150,6 +153,22 @@ fn main() {
|
||||||
})
|
})
|
||||||
.unwrap_or_else(|| vec![]);
|
.unwrap_or_else(|| vec![]);
|
||||||
|
|
||||||
|
let mut modification_constraints: Vec<TimeFilter> = Vec::new();
|
||||||
|
if let Some(t) = matches.value_of("changed-within") {
|
||||||
|
if let Some(f) = TimeFilter::after(t) {
|
||||||
|
modification_constraints.push(f);
|
||||||
|
} else {
|
||||||
|
print_error_and_exit(&format!("Error: {} is not a valid time.", t));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(t) = matches.value_of("changed-before") {
|
||||||
|
if let Some(f) = TimeFilter::before(t) {
|
||||||
|
modification_constraints.push(f);
|
||||||
|
} else {
|
||||||
|
print_error_and_exit(&format!("Error: {} is not a valid time.", t));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let config = FdOptions {
|
let config = FdOptions {
|
||||||
case_sensitive,
|
case_sensitive,
|
||||||
search_full_path: matches.is_present("full-path"),
|
search_full_path: matches.is_present("full-path"),
|
||||||
|
@ -226,6 +245,7 @@ fn main() {
|
||||||
.map(|vs| vs.map(PathBuf::from).collect())
|
.map(|vs| vs.map(PathBuf::from).collect())
|
||||||
.unwrap_or_else(|| vec![]),
|
.unwrap_or_else(|| vec![]),
|
||||||
size_constraints: size_limits,
|
size_constraints: size_limits,
|
||||||
|
modification_constraints,
|
||||||
};
|
};
|
||||||
|
|
||||||
match RegexBuilder::new(&pattern_regex)
|
match RegexBuilder::new(&pattern_regex)
|
||||||
|
|
15
src/walk.rs
15
src/walk.rs
|
@ -289,6 +289,21 @@ pub fn scan(path_vec: &[PathBuf], pattern: Arc<Regex>, config: Arc<FdOptions>) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Filter out unwanted modification times
|
||||||
|
if !config.modification_constraints.is_empty() {
|
||||||
|
if_chain!{
|
||||||
|
if entry_path.is_file();
|
||||||
|
if let Ok(metadata) = entry_path.metadata();
|
||||||
|
if let Ok(modified) = metadata.modified();
|
||||||
|
if config.modification_constraints.iter().all(|tf| tf.is_within(&modified));
|
||||||
|
then {
|
||||||
|
// When all is good, we just continue with pattern match
|
||||||
|
} else {
|
||||||
|
return ignore::WalkState::Continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let search_str_o = if config.search_full_path {
|
let search_str_o = if config.search_full_path {
|
||||||
match fshelper::path_absolute_form(entry_path) {
|
match fshelper::path_absolute_form(entry_path) {
|
||||||
Ok(path_abs_buf) => Some(path_abs_buf.to_string_lossy().into_owned().into()),
|
Ok(path_abs_buf) => Some(path_abs_buf.to_string_lossy().into_owned().into()),
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
|
|
||||||
//! Integration tests for the CLI interface of fd.
|
//! Integration tests for the CLI interface of fd.
|
||||||
|
|
||||||
|
extern crate filetime;
|
||||||
|
extern crate humantime;
|
||||||
extern crate regex;
|
extern crate regex;
|
||||||
|
|
||||||
mod testenv;
|
mod testenv;
|
||||||
|
@ -16,6 +18,7 @@ use regex::escape;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
use std::time::{Duration, SystemTime};
|
||||||
use testenv::TestEnv;
|
use testenv::TestEnv;
|
||||||
|
|
||||||
static DEFAULT_DIRS: &'static [&'static str] = &["one/two/three", "one/two/three/directory_foo"];
|
static DEFAULT_DIRS: &'static [&'static str] = &["one/two/three", "one/two/three/directory_foo"];
|
||||||
|
@ -1110,3 +1113,65 @@ fn test_size() {
|
||||||
// Files with size equal 4 kibibytes.
|
// Files with size equal 4 kibibytes.
|
||||||
te.assert_output(&["", "--size", "+4ki", "--size", "-4ki"], "4_kibibytes.foo");
|
te.assert_output(&["", "--size", "+4ki", "--size", "-4ki"], "4_kibibytes.foo");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
fn create_file_with_modified<P: AsRef<Path>>(path: P, duration_in_secs: u64) {
|
||||||
|
let st = SystemTime::now() - Duration::from_secs(duration_in_secs);
|
||||||
|
let ft = filetime::FileTime::from_system_time(st);
|
||||||
|
fs::File::create(&path).expect("creation failed");
|
||||||
|
filetime::set_file_times(&path, ft, ft).expect("time modification failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_modified_relative() {
|
||||||
|
let te = TestEnv::new(&[], &[]);
|
||||||
|
create_file_with_modified(te.test_root().join("0_now"), 0);
|
||||||
|
create_file_with_modified(te.test_root().join("1_min"), 60);
|
||||||
|
create_file_with_modified(te.test_root().join("10_min"), 600);
|
||||||
|
create_file_with_modified(te.test_root().join("1_h"), 60 * 60);
|
||||||
|
create_file_with_modified(te.test_root().join("2_h"), 2 * 60 * 60);
|
||||||
|
create_file_with_modified(te.test_root().join("1_day"), 24 * 60 * 60);
|
||||||
|
|
||||||
|
te.assert_output(
|
||||||
|
&["", "--changed-within", "15min"],
|
||||||
|
"0_now
|
||||||
|
1_min
|
||||||
|
10_min",
|
||||||
|
);
|
||||||
|
|
||||||
|
te.assert_output(
|
||||||
|
&["", "--changed-before", "15min"],
|
||||||
|
"1_h
|
||||||
|
2_h
|
||||||
|
1_day",
|
||||||
|
);
|
||||||
|
|
||||||
|
te.assert_output(
|
||||||
|
&["min", "--changed-within", "12h"],
|
||||||
|
"1_min
|
||||||
|
10_min",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
fn change_file_modified<P: AsRef<Path>>(path: P, iso_date: &str) {
|
||||||
|
let st = humantime::parse_rfc3339(iso_date).expect("invalid date");
|
||||||
|
let ft = filetime::FileTime::from_system_time(st);
|
||||||
|
filetime::set_file_times(path, ft, ft).expect("time modification failde");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_modified_asolute() {
|
||||||
|
let te = TestEnv::new(&[], &["15mar2018", "30dec2017"]);
|
||||||
|
change_file_modified(te.test_root().join("15mar2018"), "2018-03-15T12:00:00Z");
|
||||||
|
change_file_modified(te.test_root().join("30dec2017"), "2017-12-30T23:59:00Z");
|
||||||
|
|
||||||
|
te.assert_output(
|
||||||
|
&["", "--changed-within", "2018-01-01 00:00:00"],
|
||||||
|
"15mar2018",
|
||||||
|
);
|
||||||
|
te.assert_output(
|
||||||
|
&["", "--changed-before", "2018-01-01 00:00:00"],
|
||||||
|
"30dec2017",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue