ignore_unknown_exts flag, slightly more testing
This commit is contained in:
parent
b48b8d5a65
commit
ddde6acdd6
6 changed files with 31 additions and 14 deletions
|
@ -3,6 +3,10 @@ Dates are given in YYYY-MM-DD format.
|
||||||
|
|
||||||
## v0.3
|
## v0.3
|
||||||
### v0.3.4 (2021-mm-dd)
|
### v0.3.4 (2021-mm-dd)
|
||||||
|
#### Features
|
||||||
|
- Added `-I`/`--ignore-unknown-exts` flag for ignoring files with unknown extensions - for example, if fif doesn't know
|
||||||
|
what a ".fake" file is, setting this flag will prevent it from renaming "photo.fake" to "photo.jpg". This is useful
|
||||||
|
for avoiding the case where fif incorrectly mislabels an obscure format it isn't aware of as something else.
|
||||||
#### Other
|
#### Other
|
||||||
- Refactored `formats.rs`
|
- Refactored `formats.rs`
|
||||||
- More accurate dependency versions in `Cargo.toml` to ensure that the MSRV stays supported
|
- More accurate dependency versions in `Cargo.toml` to ensure that the MSRV stays supported
|
||||||
|
|
4
Cargo.lock
generated
4
Cargo.lock
generated
|
@ -544,9 +544,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "redox_syscall"
|
name = "redox_syscall"
|
||||||
version = "0.2.9"
|
version = "0.2.10"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5ab49abadf3f9e1c4bc499e8845e152ad87d2ad2d30371841171169e9d75feee"
|
checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
]
|
]
|
||||||
|
|
|
@ -33,10 +33,6 @@ macro_rules! writables {
|
||||||
$crate::formats::Writable::Newline
|
$crate::formats::Writable::Newline
|
||||||
};
|
};
|
||||||
|
|
||||||
(@do Space) => {
|
|
||||||
$crate::formats::Writable::Space
|
|
||||||
};
|
|
||||||
|
|
||||||
(@do $arg:expr) => {
|
(@do $arg:expr) => {
|
||||||
$arg.into()
|
$arg.into()
|
||||||
}
|
}
|
||||||
|
@ -57,7 +53,6 @@ type Entries<'a> = [Result<Findings, ScanError<'a>>];
|
||||||
pub enum Writable<'a> {
|
pub enum Writable<'a> {
|
||||||
String(&'a str),
|
String(&'a str),
|
||||||
Path(&'a Path),
|
Path(&'a Path),
|
||||||
Space,
|
|
||||||
Newline,
|
Newline,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,7 +75,6 @@ fn smart_write<W: Write>(f: &mut W, writeables: &[Writable]) -> io::Result<()> {
|
||||||
// ehhhh
|
// ehhhh
|
||||||
for writeable in writeables {
|
for writeable in writeables {
|
||||||
match writeable {
|
match writeable {
|
||||||
Writable::Space => write!(f, " ")?,
|
|
||||||
Writable::Newline => {
|
Writable::Newline => {
|
||||||
cfg_if! {
|
cfg_if! {
|
||||||
if #[cfg(windows)] {
|
if #[cfg(windows)] {
|
||||||
|
@ -189,7 +183,7 @@ impl Format for Shell {
|
||||||
|
|
||||||
impl FormatSteps for Shell {
|
impl FormatSteps for Shell {
|
||||||
fn rename<W: Write>(&self, f: &mut W, from: &Path, to: &Path) -> io::Result<()> {
|
fn rename<W: Write>(&self, f: &mut W, from: &Path, to: &Path) -> io::Result<()> {
|
||||||
smart_write(f, writablesln!("mv -v -i -- ", from, Space, to))
|
smart_write(f, writablesln!("mv -v -i -- ", from, "\t", to))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn no_known_extension<W: Write>(&self, f: &mut W, path: &Path) -> io::Result<()> {
|
fn no_known_extension<W: Write>(&self, f: &mut W, path: &Path) -> io::Result<()> {
|
||||||
|
|
|
@ -34,6 +34,7 @@ use crate::mime_db::MimeDb;
|
||||||
use crate::parameters::{OutputFormat, ScanOpts};
|
use crate::parameters::{OutputFormat, ScanOpts};
|
||||||
use crate::utils::{clap_long_version, os_name};
|
use crate::utils::{clap_long_version, os_name};
|
||||||
use std::collections::BTreeSet;
|
use std::collections::BTreeSet;
|
||||||
|
use mime_guess::from_ext;
|
||||||
|
|
||||||
mod findings;
|
mod findings;
|
||||||
mod formats;
|
mod formats;
|
||||||
|
@ -217,6 +218,13 @@ fn wanted_file(
|
||||||
let ext = ext.to_string_lossy().to_lowercase();
|
let ext = ext.to_string_lossy().to_lowercase();
|
||||||
let ext = ext.as_str();
|
let ext = ext.as_str();
|
||||||
|
|
||||||
|
if scan_opts.ignore_unknown_exts {
|
||||||
|
if from_ext(ext).is_empty() {
|
||||||
|
// unknown extension, skip.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(exts) = exts {
|
if let Some(exts) = exts {
|
||||||
// only scan if the file has one of the specified extensions.
|
// only scan if the file has one of the specified extensions.
|
||||||
exts.contains(&ext)
|
exts.contains(&ext)
|
||||||
|
|
|
@ -128,6 +128,11 @@ pub struct Parameters {
|
||||||
/// The directory to process.
|
/// The directory to process.
|
||||||
#[clap(name = "DIR", default_value = ".", parse(from_os_str))]
|
#[clap(name = "DIR", default_value = ".", parse(from_os_str))]
|
||||||
pub dir: PathBuf,
|
pub dir: PathBuf,
|
||||||
|
|
||||||
|
/// Don't rename files with extensions unknown to fif.
|
||||||
|
/// For example, with this option, fif will not rename "image.unknown" to "image.jpg"
|
||||||
|
#[clap(short = 'I', long)]
|
||||||
|
pub ignore_unknown_exts: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lowercase_exts(exts: &str) -> Result<(), String> {
|
fn lowercase_exts(exts: &str) -> Result<(), String> {
|
||||||
|
@ -147,6 +152,8 @@ pub struct ScanOpts {
|
||||||
pub extensionless: bool,
|
pub extensionless: bool,
|
||||||
/// Should symlinks be followed?
|
/// Should symlinks be followed?
|
||||||
pub follow_symlinks: bool,
|
pub follow_symlinks: bool,
|
||||||
|
/// Whether to rename files with unknown extensions.
|
||||||
|
pub ignore_unknown_exts: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parameters {
|
impl Parameters {
|
||||||
|
@ -214,6 +221,7 @@ impl Parameters {
|
||||||
hidden: self.scan_hidden,
|
hidden: self.scan_hidden,
|
||||||
extensionless: self.scan_extensionless,
|
extensionless: self.scan_extensionless,
|
||||||
follow_symlinks: self.follow_symlinks,
|
follow_symlinks: self.follow_symlinks,
|
||||||
|
ignore_unknown_exts: self.ignore_unknown_exts
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -100,6 +100,7 @@ fn simple_directory() {
|
||||||
files.insert("test.pdf", PDF_BYTES);
|
files.insert("test.pdf", PDF_BYTES);
|
||||||
files.insert("test.zip", ZIP_BYTES);
|
files.insert("test.zip", ZIP_BYTES);
|
||||||
files.insert("wrong.jpg", PNG_BYTES);
|
files.insert("wrong.jpg", PNG_BYTES);
|
||||||
|
files.insert("ignore.fake_ext", ZIP_BYTES);
|
||||||
|
|
||||||
let dir = tempdir().expect("Failed to create temporary directory.");
|
let dir = tempdir().expect("Failed to create temporary directory.");
|
||||||
set_current_dir(dir.path()).expect("Failed to change directory.");
|
set_current_dir(dir.path()).expect("Failed to change directory.");
|
||||||
|
@ -117,11 +118,13 @@ fn simple_directory() {
|
||||||
hidden: true,
|
hidden: true,
|
||||||
extensionless: false,
|
extensionless: false,
|
||||||
follow_symlinks: false,
|
follow_symlinks: false,
|
||||||
|
ignore_unknown_exts: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
let entries = scan_directory(dir.path(), None, None, &scan_opts).expect("Directory scan failed.");
|
let entries = scan_directory(dir.path(), None, None, &scan_opts).expect("Directory scan failed.");
|
||||||
|
|
||||||
assert_eq!(entries.len(), files.len());
|
// there should be one file missing: "ignore.fake_ext"
|
||||||
|
assert_eq!(entries.len(), files.len() - 1);
|
||||||
|
|
||||||
// initialise global mime DB - this is needed because `scan_from_walkdir` expects it to be present.
|
// initialise global mime DB - this is needed because `scan_from_walkdir` expects it to be present.
|
||||||
crate::init_db();
|
crate::init_db();
|
||||||
|
@ -209,6 +212,7 @@ fn argument_parsing() {
|
||||||
hidden: false,
|
hidden: false,
|
||||||
extensionless: false,
|
extensionless: false,
|
||||||
follow_symlinks: true,
|
follow_symlinks: true,
|
||||||
|
ignore_unknown_exts: false,
|
||||||
},
|
},
|
||||||
"ScanOpts are incorrect"
|
"ScanOpts are incorrect"
|
||||||
);
|
);
|
||||||
|
@ -329,7 +333,7 @@ fn identify_random_bytes() {
|
||||||
for (mime, count) in &results {
|
for (mime, count) in &results {
|
||||||
println!("{}:\t{} counts", mime, count);
|
println!("{}:\t{} counts", mime, count);
|
||||||
}
|
}
|
||||||
println!("No type found:\t{} counts", 500 - results.values().sum::<i32>());
|
println!("No type found:\t{} counts", results.values().len() as i32 - results.values().sum::<i32>());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -363,7 +367,7 @@ fn outputs_move_commands() {
|
||||||
|
|
||||||
// the output should contain a command like "mv -i misnamed_file.png misnamed_file.jpg"
|
// the output should contain a command like "mv -i misnamed_file.png misnamed_file.jpg"
|
||||||
assert!(
|
assert!(
|
||||||
contents.contains("misnamed_file.jpg"),
|
contents.contains("misnamed_file.jpg") && contents.contains("misnamed_file.png"),
|
||||||
"{} output doesn't contain move command!\n===\n{}",
|
"{} output doesn't contain move command!\n===\n{}",
|
||||||
format,
|
format,
|
||||||
contents
|
contents
|
||||||
|
@ -433,9 +437,8 @@ fn writables_is_correct() {
|
||||||
"henlo".into(),
|
"henlo".into(),
|
||||||
Path::new("henlo").into(),
|
Path::new("henlo").into(),
|
||||||
Writable::Newline,
|
Writable::Newline,
|
||||||
Writable::Space
|
|
||||||
],
|
],
|
||||||
writables!["henlo", (Path::new("henlo")), Newline, Space]
|
writables!["henlo", (Path::new("henlo")), Newline]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue