added `-X` for excluding sets of extensions. `-X` is to `-E` as `-x` is to `-e`.

This commit is contained in:
Lynne Megido 2021-04-28 16:16:32 +10:00
parent b3ce5d3d46
commit 22f1f280d7
Signed by: lynnesbian
GPG Key ID: F0A184B5213D9F90
3 changed files with 67 additions and 19 deletions

View File

@ -4,10 +4,11 @@ Dates are given in YYYY-MM-DD format.
## v0.2
### v0.2.14 (2021-xx-yy)
#### Features
- Added `-x`/`--exclude` flag for excluding file extensions (overrides `-e` or `-E`)
- Added `-x`/`--exclude` flag for excluding file extensions (overrides `-e` or `-E` - `-E images -x jpg` scans all image
files, except ".jpg" files)
- Added `-X`/`--exclude-set` flag for excluding sets of files (like `-E`)
#### Other
- Publish my fork of ['mime_guess'] as ['new_mime_guess'], allowing it to be used properly with
- Published my fork of ['mime_guess'] as ['new_mime_guess'], allowing it to be used properly with
[crates.io](https://crates.io)
### v0.2.13 (2021-04-26)
@ -152,5 +153,5 @@ Initial commit!
[`clap`]: https://crates.io/crates/clap
[`infer`]: https://crates.io/crates/infer
[`mime_guess`]: https://crates.io/crates/mime_guess
[`new_mime_guess`]: https://crates.io/crates/mime_guess
[`snailquote`]: https://crates.io/crates/snailquote
[`new_mime_guess`]: https://crates.io/crates/new_mime_guess
[`snailquote`]: https://crates.io/crates/snailquote

View File

@ -55,7 +55,9 @@ pub struct Parameters {
#[clap(short = 'x', long, use_delimiter = true, require_delimiter = true)]
pub exclude: Option<Vec<StringType>>,
// TODO: -X/--exclude-set - allows you to exclude all extensions in a set, e.g. "-X documents"
/// Exclude files using a preset list of extensions.
#[clap(short = 'X', long, arg_enum)]
pub exclude_set: Option<ExtensionSet>,
/// Don't skip hidden files and directories.
/// Even if this flag is not present, fif will still recurse into a hidden root directory - for example, `fif
@ -133,10 +135,26 @@ impl Parameters {
}
pub fn excluded_extensions(&self) -> Option<Vec<&str>> {
self
.exclude
.as_ref()
.map(|exclude| exclude.iter().map(|ext| ext.as_str()).collect())
// start with an empty vec
let mut excluded = vec![];
if let Some(exclude) = self.exclude.as_ref() {
// add extensions excluded by `-x`
excluded.append(&mut exclude.iter().map(|ext| ext.as_str()).collect());
}
if let Some(exclude_set) = &self.exclude_set {
// add extensions excluded by `-X`
excluded.append(&mut exclude_set.extensions());
}
if excluded.is_empty() {
// no extensions to exclude - return none
None
} else {
// excluded doesn't sound like a word anymore
// tongue twister: enter X-options' excellent extension exclusion
Some(excluded)
}
}
pub const fn get_scan_opts(&self) -> ScanOpts {

View File

@ -7,10 +7,13 @@ use crate::{extension_from_path, scan_directory, scan_from_walkdir};
use mime_guess::mime::{APPLICATION_OCTET_STREAM, APPLICATION_PDF, IMAGE_JPEG, IMAGE_PNG};
use mime_guess::Mime;
use crate::parameters::Parameters;
use clap::Clap;
use std::collections::HashMap;
use std::ffi::OsStr;
use std::path::Path;
use crate::parameters::ExtensionSet;
const JPEG_BYTES: &[u8] = b"\xFF\xD8\xFF";
const PNG_BYTES: &[u8] = b"\x89\x50\x4E\x47\x0D\x0A\x1A\x0A";
@ -167,8 +170,7 @@ fn simple_directory() {
#[test]
/// Ensure that command line argument parsing works correctly - flags are interpreted, booleans are set, and so on.
fn argument_parsing() {
use crate::parameters::{Parameters, ScanOpts};
use clap::Clap;
use crate::parameters::ScanOpts;
// pass `-f`, which enables following symlinks, and `-E images`, which scans files with image extensions
let args: Parameters = Parameters::parse_from(vec!["fif", "-f", "-E", "images"]);
@ -204,11 +206,8 @@ fn argument_parsing() {
}
#[test]
/// Ensure exclude overrides `-e` and `-E`.
/// Ensure the `exclude` flag (`-x`) overrides `-e` and `-E`.
fn exclude_overrides() {
use crate::parameters::Parameters;
use clap::Clap;
// pass `-E images`, which includes many image extensions, and `-x jpg,png`, which should remove "jpg" and "png" from
// the extensions list
let args: Parameters = Parameters::parse_from(vec!["fif", "-x", "jpg,png", "-E", "images"]);
@ -232,12 +231,42 @@ fn exclude_overrides() {
assert!(extensions.contains(&"jkl"));
}
#[test]
/// Ensure the `exclude_set` flag (`-X`) overrides `-e`.
fn exclude_set_overrides_includes() {
// pass `-e jpg,flac` and `-X images` -- which should produce the equivalent of `-e flag`
let args: Parameters = Parameters::parse_from(vec!["fif", "-e", "jpg,flac", "-X", "images"]);
let extensions = args.extensions();
assert!(extensions.is_some(), "Extensions should be set!");
let mut extensions = extensions.unwrap().into_iter();
assert_eq!(extensions.next(), Some("flac"), "Extensions should contain flac!");
assert_eq!(extensions.next(), None, "Too many extensions!");
}
#[test]
/// Ensure the `exclude_set` flag (`-X`) overrides `-E`.
fn exclude_set_overrides_include_set() {
// pass `-E media` and `-X images` -- which should produce the equivalent of `-E audio,videos`
let args: Parameters = Parameters::parse_from(vec!["fif", "-E", "media", "-X", "images"]);
let extensions = args.extensions();
assert!(extensions.is_some(), "Extensions should be set!");
let extensions = extensions.unwrap();
// ensure all of audio and video's extensions are here
for &ext in ExtensionSet::Audio.extensions().iter().chain(ExtensionSet::Videos.extensions().iter()) {
assert!(extensions.contains(&ext), "Extensions should contain {}!", ext)
}
// ensure all of images' extensions are excluded
for ext in ExtensionSet::Images.extensions() {
assert!(!extensions.contains(&ext), "Extensions should not contain {}!", ext)
}
}
#[test]
/// Ensure that badly formed command line arguments are rejected.
fn rejects_bad_args() {
use crate::parameters::Parameters;
use clap::Clap;
let tests = [
// Non-existent flags:
vec!["fif", "-abcdefghijklmnopqrstuvwxyz"],