ignore_unknown_exts flag, slightly more testing

This commit is contained in:
Lynne Megido 2021-08-07 00:12:26 +10:00
parent b48b8d5a65
commit ddde6acdd6
Signed by: lynnesbian
GPG key ID: F0A184B5213D9F90
6 changed files with 31 additions and 14 deletions

View file

@ -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
View file

@ -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",
] ]

View file

@ -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<()> {

View file

@ -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)

View file

@ -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
} }
} }

View file

@ -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]
); );
} }