Compare commits

..

No commits in common. "090e4adafe3ae4bf6ec0dc1a9147a9e2e9cacaff" and "534101db8b1033371dbb35cdd6f1c242729d9acf" have entirely different histories.

14 changed files with 113 additions and 149 deletions

2
.gitignore vendored
View file

@ -8,4 +8,4 @@ fif_*
!clippy.sh !clippy.sh
cargo-timing*.html cargo-timing*.html
todo.txt todo.txt
/pkg/* /pkg/fif.spec

View file

@ -62,22 +62,18 @@ build-nightly:
test-stable: test-stable:
extends: .cargo-test extends: .cargo-test
needs: ["build-stable"]
test-msrv: test-msrv:
extends: test-stable extends: test-stable
image: "rust:1.43.0" image: "rust:1.43.0"
needs: ["build-msrv"]
test-nightly: test-nightly:
extends: test-stable extends: test-stable
image: "rustlang/rust:nightly" image: "rustlang/rust:nightly"
needs: ["build-nightly"]
# VERSION # VERSION
fif-version: fif-version:
stage: version stage: version
needs: ["build-stable"]
script: script:
cargo run -- -V cargo run -- -V

View file

@ -1,8 +1,8 @@
# Changelog # Changelog
Dates are given in YYYY-MM-DD format. Dates are given in YYYY-MM-DD format.
## v0.3 ## v0.2
### v0.3.0 (2021-04-28) ### v0.2.14 (2021-xx-yy)
#### Features #### Features
- Added `-x`/`--exclude` flag for excluding file extensions (overrides `-e` or `-E` - `-E images -x jpg` scans all image - Added `-x`/`--exclude` flag for excluding file extensions (overrides `-e` or `-E` - `-E images -x jpg` scans all image
files, except ".jpg" files) files, except ".jpg" files)
@ -12,19 +12,12 @@ Dates are given in YYYY-MM-DD format.
- `-e` and `-E` no longer conflict with each other, and can now be used together. For example, `-E images -e mp3` - `-e` and `-E` no longer conflict with each other, and can now be used together. For example, `-E images -e mp3`
will scan all images *and* all MP3 files will scan all images *and* all MP3 files
- It is now possible to specify multiple extension sets at once: `-E images,system` will scan all images and archives - It is now possible to specify multiple extension sets at once: `-E images,system` will scan all images and archives
- fif's output now includes the directory it was run from
- Added `-q`/`--quiet` flag for reducing output verbosity
#### Bugfixes
- Resolved some discrepancies between `application/xml` and `text/xml`
#### Other #### Other
- Published 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) [crates.io](https://crates.io)
- The `videos` extension set has been renamed to `video`, in line with `audio`. `fif --help` has actually mistakenly - The `videos` extension set has been renamed to `video`, in line with `audio`. `fif --help` has actually mistakenly
referred to the set as `video` since v0.2.12! 0uo referred to the set as `video` since v0.2.12! 0uo
- CI has been vastly improved
- Changed default verbosity to `info`
## v0.2
### v0.2.13 (2021-04-26) ### v0.2.13 (2021-04-26)
#### Features #### Features
- Added `-v`/`--verbose` flag for setting verbosity without using `RUST_LOG` - Added `-v`/`--verbose` flag for setting verbosity without using `RUST_LOG`

2
Cargo.lock generated
View file

@ -193,7 +193,7 @@ dependencies = [
[[package]] [[package]]
name = "fif" name = "fif"
version = "0.3.0" version = "0.2.13"
dependencies = [ dependencies = [
"cached", "cached",
"cfg-if", "cfg-if",

View file

@ -1,7 +1,7 @@
[package] [package]
name = "fif" name = "fif"
description = "A command-line tool for detecting and optionally correcting files with incorrect extensions." description = "A command-line tool for detecting and optionally correcting files with incorrect extensions."
version = "0.3.0" version = "0.2.13"
authors = ["Lynnesbian <lynne@bune.city>"] authors = ["Lynnesbian <lynne@bune.city>"]
edition = "2018" edition = "2018"
license = "GPL-3.0-or-later" license = "GPL-3.0-or-later"

View file

@ -1,10 +1,5 @@
<div align="center">fif</div> fif
=== ===
<div align="center">
![A screenshot demonstrating fif's ability to detect the correct file extensions for a few files.
](https://gitlab.com/Lynnesbian/fif/-/blob/master/doc/screenshot.png)
[![Version](https://img.shields.io/crates/v/fif.svg?logo=rust&style=flat-square) [![Version](https://img.shields.io/crates/v/fif.svg?logo=rust&style=flat-square)
](https://crates.io/crates/fif) ](https://crates.io/crates/fif)
[![Minimum Supported Rust Version](https://img.shields.io/badge/msrv-1.43.0-orange?logo=rust&style=flat-square) [![Minimum Supported Rust Version](https://img.shields.io/badge/msrv-1.43.0-orange?logo=rust&style=flat-square)
@ -18,8 +13,7 @@
[![Unsafe forbidden](https://img.shields.io/badge/unsafe-forbidden-success.svg?style=flat-square) [![Unsafe forbidden](https://img.shields.io/badge/unsafe-forbidden-success.svg?style=flat-square)
](https://github.com/rust-secure-code/safety-dance/) ](https://github.com/rust-secure-code/safety-dance/)
*A command-line tool for detecting and optionally correcting files with incorrect extensions.* A command-line tool for detecting and optionally correcting files with incorrect extensions.
</div>
fif recursively scans the given directory and outputs a shell script to fix the name of any files with incorrect fif recursively scans the given directory and outputs a shell script to fix the name of any files with incorrect
extensions. By default, fif will scan all non-hidden files in the given directory, and will ignore symlinks. extensions. By default, fif will scan all non-hidden files in the given directory, and will ignore symlinks.
@ -35,8 +29,8 @@ that it's not doing anything that will give you a headache before running it.
cargo install --locked fif cargo install --locked fif
``` ```
To update, simply re-run this command, or use a tool like [cargo-update To update, simply re-run this command, or use a tool like
](https://github.com/nabijaczleweli/cargo-update). [cargo-update](https://github.com/nabijaczleweli/cargo-update).
#### Other backends #### Other backends
`fif` supports using [`infer`](https://crates.io/crates/infer) or [`xdg-mime`](https://crates.io/crates/xdg-mime) as its `fif` supports using [`infer`](https://crates.io/crates/infer) or [`xdg-mime`](https://crates.io/crates/xdg-mime) as its
@ -106,35 +100,23 @@ fif -O powershell ~/Documents > output.ps1
``` ```
### Logging ### Logging
By default, fif will log any info, warnings, and errors encountered during execution. This can be changed with the `-v` By default, fif will log any warnings and/or errors encountered during execution. This can be changed with the `-v`
flag: flag:
```bash ```bash
# also log debug info # also log info
fif -v ~/Downloads fif -v ~/Downloads
# ...and trace info # ...and debug
fif -vv ~/Downloads fif -vv ~/Downloads
# ...and trace
fif -vvv ~/Downloads
``` ```
The verbosity of the logging can be
You can also reduce the level of logging with the `-q` flag: modified by the `RUST_LOG` to one of: `trace`, `debug`, `info`, `warn`, `error`.
```bash
# don't show info
fif -q ~/Downloads
# ...or warnings
fif -qq ~/Downloads
# ...or even errors!
fif -qqq ~/Downloads
```
The verbosity of the logging can also be modified by setting the environment variable `RUST_LOG` to `off`, `trace`,
`debug`, `info`, `warn`, or `error`. Values set by `RUST_LOG` override the `-v` and `-q` flags.
For example: For example:
```bash ```bash
# show all levels except trace
RUST_LOG=debug fif ~/Downloads RUST_LOG=debug fif ~/Downloads
# only show errors
RUST_LOG=error fif ~/Downloads
``` ```
The five logging levels are used as follows: The five logging levels are used as follows:

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

26
pkg/PKGBUILD Normal file
View file

@ -0,0 +1,26 @@
pkgname=fif
pkgver=0.2.11
pkgrel=1
pkgdesc="A command-line tool for detecting and optionally correcting files with incorrect extensions."
# tier 1 rust linux targets
arch=('x86_64' 'i686' 'aarch64')
url="https://git.bune.city/lynnesbian/fif"
license=('GPLv3+')
depends=('shared-mime-info')
source=("$pkgname-$pkgver.tar.gz::https://git.bune.city/lynnesbian/$pkgname/archive/v${pkgver}.tar.gz")
sha256sums=("fd2b3133fabf8ad1993c6d16a9bf1ad645b1eff8fd30a4a9227ef5a157f56183")
build() {
cd "$pkgname"
cargo build --release --locked
}
check() {
cd "$pkgname"
cargo build --release --locked
}
package() {
cd "$pkgname"
install -Dm 755 target/release/${pkgname} -t "${pkgdir}/usr/bin"
}

View file

@ -18,6 +18,6 @@ pub struct Findings<'a> {
impl<'a> Findings<'a> { impl<'a> Findings<'a> {
pub fn recommended_extension(&self) -> Option<String> { pub fn recommended_extension(&self) -> Option<String> {
mime_extension_lookup(self.mime.clone()).map(|extensions| extensions[0].clone()) mime_extension_lookup(self.mime.clone()).map(|extensions| extensions[0].to_owned())
} }
} }

View file

@ -41,14 +41,6 @@ macro_rules! writables {
} }
} }
#[macro_export]
/// Does the same thing as [writables], but adds a Newline to the end.
macro_rules! writablesln {
[$($args:tt),+] => {
&[$(writables!(@do $args),)* writables!(@do Newline)]
};
}
/// The current version of fif, as defined in Cargo.toml. /// The current version of fif, as defined in Cargo.toml.
const VERSION: Option<&'static str> = option_env!("CARGO_PKG_VERSION"); const VERSION: Option<&'static str> = option_env!("CARGO_PKG_VERSION");
@ -138,12 +130,12 @@ pub trait Format {
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<()>;
fn unreadable<W: Write>(&self, f: &mut W, path: &Path) -> io::Result<()>; fn unreadable<W: Write>(&self, f: &mut W, path: &Path) -> io::Result<()>;
fn unknown_type<W: Write>(&self, f: &mut W, path: &Path) -> io::Result<()>; fn unknown_type<W: Write>(&self, f: &mut W, path: &Path) -> io::Result<()>;
fn header<W: Write>(&self, f: &mut W, entries: &Entries) -> io::Result<()>; fn header<W: Write>(&self, entries: &Entries, f: &mut W) -> io::Result<()>;
fn footer<W: Write>(&self, f: &mut W, entries: &Entries) -> io::Result<()>; fn footer<W: Write>(&self, entries: &Entries, f: &mut W) -> io::Result<()>;
fn write_all<W: Write>(&self, f: &mut W, entries: &Entries) -> io::Result<()> { fn write_all<W: Write>(&self, entries: &Entries, f: &mut W) -> io::Result<()> {
// TODO: clean this up - it's kinda messy // TODO: clean this up - it's kinda messy
self.header(f, entries)?; self.header(entries, f)?;
// output will be generated in the order: // output will be generated in the order:
// - files that couldn't be read // - files that couldn't be read
@ -178,7 +170,7 @@ pub trait Format {
} }
} }
self.footer(f, entries) self.footer(entries, f)
} }
} }
@ -191,36 +183,38 @@ impl Format 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, writables!("mv -v -i -- ", from, Space, to, Newline))
} }
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<()> {
smart_write(f, writablesln!["echo No known extension for ", path]) smart_write(f, writables!["echo No known extension for ", path, Newline])
} }
fn unreadable<W: Write>(&self, f: &mut W, path: &Path) -> io::Result<()> { fn unreadable<W: Write>(&self, f: &mut W, path: &Path) -> io::Result<()> {
smart_write(f, writablesln!["# Failed to read", path]) smart_write(f, writables!["# Failed to read", path, Newline])
} }
fn unknown_type<W: Write>(&self, f: &mut W, path: &Path) -> io::Result<()> { fn unknown_type<W: Write>(&self, f: &mut W, path: &Path) -> io::Result<()> {
smart_write(f, writablesln!["# Failed to detect mime type for ", path]) smart_write(f, writables!["# Failed to detect mime type for ", path, Newline])
} }
fn header<W: Write>(&self, f: &mut W, _: &Entries) -> io::Result<()> { fn header<W: Write>(&self, _: &Entries, f: &mut W) -> io::Result<()> {
smart_write( smart_write(
f, f,
writablesln!["#!/usr/bin/env sh", Newline, "# ", (generated_by().as_str())], writables![
)?; "#!/usr/bin/env sh",
Newline,
if let Ok(working_directory) = std::env::current_dir() { "# ",
smart_write(f, writablesln!["# Run from ", (working_directory.as_path())])?; (generated_by().as_str()),
} Newline,
"set -e",
smart_write(f, writablesln![Newline, "set -e", Newline]) Newline
],
)
} }
fn footer<W: Write>(&self, f: &mut W, _: &Entries) -> io::Result<()> { fn footer<W: Write>(&self, _: &Entries, f: &mut W) -> io::Result<()> {
smart_write(f, writablesln![Newline, "echo 'Done.'"]) smart_write(f, writables![Newline, "echo 'Done.'", Newline])
} }
} }
@ -240,7 +234,13 @@ impl Format for PowerShell {
// there doesn't seem to be a way to rename the file, prompting only if the target already exists. // there doesn't seem to be a way to rename the file, prompting only if the target already exists.
smart_write( smart_write(
f, f,
writablesln!["Rename-Item -Path ", from, " -NewName ", (to.file_name().unwrap())], writables![
"Rename-Item -Path ",
from,
" -NewName ",
(to.file_name().unwrap()),
Newline
],
) )
} }
@ -266,23 +266,27 @@ impl Format for PowerShell {
} }
fn unknown_type<W: Write>(&self, f: &mut W, path: &Path) -> io::Result<()> { fn unknown_type<W: Write>(&self, f: &mut W, path: &Path) -> io::Result<()> {
smart_write(f, writablesln!["<# Failed to detect mime type for ", path, " #>"])
}
fn header<W: Write>(&self, f: &mut W, _: &Entries) -> io::Result<()> {
smart_write( smart_write(
f, f,
writablesln!["#!/usr/bin/env pwsh", Newline, "<# ", (generated_by().as_str()), " #>"], writables!["<# Failed to detect mime type for ", path, " #>", Newline],
)?; )
if let Ok(working_directory) = std::env::current_dir() {
smart_write(f, writablesln!["<# Run from ", (working_directory.as_path()), " #>"])?;
}
smart_write(f, writables![Newline])
} }
fn footer<W: Write>(&self, f: &mut W, _: &Entries) -> io::Result<()> { fn header<W: Write>(&self, _: &Entries, f: &mut W) -> io::Result<()> {
smart_write(f, writablesln![Newline, "Write-Output 'Done!'"]) smart_write(
f,
writables![
"#!/usr/bin/env pwsh",
Newline,
"<# ",
(generated_by().as_str()),
" #>",
Newline
],
)
}
fn footer<W: Write>(&self, _: &Entries, f: &mut W) -> io::Result<()> {
smart_write(f, writables![Newline, "Write-Output 'Done!'", Newline])
} }
} }

View file

@ -63,10 +63,10 @@ pub fn mime_type<T: MimeDb>(db: &T, path: &Path) -> io::Result<Option<Mime>> {
// TODO: avoid cloning mime if possible, although i don't really see how it would be - maybe instead of passing the mime // TODO: avoid cloning mime if possible, although i don't really see how it would be - maybe instead of passing the mime
// object, pass a hash of it? // object, pass a hash of it?
cached! { cached! {
MIMEXT; MIMEXT;
fn mime_extension_lookup(mime: Mime) -> Option<Vec<String>> = { fn mime_extension_lookup(mime: Mime) -> Option<Vec<String>> = {
// Returns a list of known extensions for this mime type, if any. // Returns a list of known extensions for this mime type, if any.
// ↑ this is supposed to be a doc comment, but the cached! macro doesn't support that... maybe i should switch to // ↑ this is supposed to be a doc comment, but the cached! macro doesn't support that... maybe i should switch to
// the derive macro // the derive macro

View file

@ -74,7 +74,6 @@ fn main() {
// .target(env_logger::Target::Stdout) // log to stdout rather than stderr // .target(env_logger::Target::Stdout) // log to stdout rather than stderr
.init(); .init();
trace!("Initialise mimetype database");
init_db(); init_db();
debug!("Iterating directory: {:?}", args.dirs); debug!("Iterating directory: {:?}", args.dirs);
@ -122,8 +121,6 @@ fn main() {
) )
.collect(); .collect();
trace!("Scanning complete");
for result in &results { for result in &results {
match result { match result {
Ok(r) => { Ok(r) => {
@ -146,8 +143,8 @@ fn main() {
let mut buffered_stdout = BufWriter::new(stdout()); let mut buffered_stdout = BufWriter::new(stdout());
let result = match args.output_format { let result = match args.output_format {
OutputFormat::Sh => Shell::new().write_all(&mut buffered_stdout, &results), OutputFormat::Sh => Shell::new().write_all(&results, &mut buffered_stdout),
OutputFormat::PowerShell => PowerShell::new().write_all(&mut buffered_stdout, &results), OutputFormat::PowerShell => PowerShell::new().write_all(&results, &mut buffered_stdout),
OutputFormat::Text => todo!(), OutputFormat::Text => todo!(),
}; };
@ -279,11 +276,13 @@ fn scan_from_walkdir(entries: &[DirEntry]) -> Vec<Result<Findings, ScanError>> {
if #[cfg(feature = "multi-threaded")] { if #[cfg(feature = "multi-threaded")] {
use rayon::prelude::*; use rayon::prelude::*;
// split the entries into chunks of 32, and iterate over each chunk of entries in a separate thread // rather than using a standard par_iter, split the entries into chunks of 32 first.
// this allows each spawned thread to handle 32 files before before closing, rather than creating a new thread for
// each file. this leads to a pretty substantial speedup that i'm pretty substantially happy about 0u0
entries entries
.par_chunks(32) .par_chunks(32) // split into chunks of 32
.flat_map(|chunk| { .flat_map(|chunk| {
chunk chunk // return Vec<...> instead of Chunk<Vec<...>>
.iter() // iter over the chunk, which is a slice of DirEntry structs .iter() // iter over the chunk, which is a slice of DirEntry structs
.map(|entry| scan_file(entry)) .map(|entry| scan_file(entry))
.collect::<Vec<_>>() .collect::<Vec<_>>()
@ -349,7 +348,7 @@ fn scan_directory(
} }
} }
/// Initialises [`MIMEDB`] with a value dependent on the current backend. /// Initialises [MIMEDB] with a value dependent on the current backend.
fn init_db() { fn init_db() {
cfg_if! { cfg_if! {
if #[cfg(any(all(unix, feature = "infer-backend"), all(not(unix), not(feature = "xdg-mime-backend"))))] { if #[cfg(any(all(unix, feature = "infer-backend"), all(not(unix), not(feature = "xdg-mime-backend"))))] {

View file

@ -17,7 +17,6 @@ cfg_if! {
#[derive(Clap, PartialEq, Debug)] #[derive(Clap, PartialEq, Debug)]
pub enum OutputFormat { pub enum OutputFormat {
/// A Bourne shell compatible script. /// A Bourne shell compatible script.
#[clap(alias = "shell", alias = "bash")]
Sh, Sh,
/// A PowerShell script. /// A PowerShell script.
#[clap(alias = "powershell")] #[clap(alias = "powershell")]
@ -48,23 +47,23 @@ pub struct Parameters {
/// Only examine files with these extensions. /// Only examine files with these extensions.
/// Multiple extensions can be specified by either using the flag multiple times (`-e jpg -e png -e gif`), or by /// Multiple extensions can be specified by either using the flag multiple times (`-e jpg -e png -e gif`), or by
/// separating them with commas (`-e jpg,png,gif`). /// separating them with commas (`-e jpg,png,gif`).
#[clap(short, long, use_delimiter = true, require_delimiter = true, value_name = "ext")] #[clap(short, long, use_delimiter = true, require_delimiter = true)]
pub exts: Option<Vec<StringType>>, pub exts: Option<Vec<StringType>>,
/// Use these preset lists of extensions as the search filter (comma-separated list). /// Use these preset lists of extensions as the search filter (comma-separated list).
/// `media` includes all extensions from the `audio`, `video`, and `images` sets, making `-E media` equivalent to /// `media` includes all extensions from the `audio`, `video`, and `images` sets, making `-E media` equivalent to
/// `-E audio,video,images`. /// `-E audio,video,images`.
#[clap(short = 'E', long, arg_enum, use_delimiter = true, require_delimiter = true, value_name = "set")] #[clap(short = 'E', long, arg_enum, use_delimiter = true, require_delimiter = true)]
pub ext_set: Vec<ExtensionSet>, pub ext_set: Vec<ExtensionSet>,
/// Don't scan files with these extensions. /// Don't scan files with these extensions.
/// This option takes precedence over extensions specified with `-e` or `-E`. /// This option takes precedence over extensions specified with `-e` or `-E`.
#[clap(short = 'x', long, use_delimiter = true, require_delimiter = true, value_name = "ext")] #[clap(short = 'x', long, use_delimiter = true, require_delimiter = true)]
pub exclude: Option<Vec<StringType>>, pub exclude: Option<Vec<StringType>>,
/// Exclude files using a preset list of extensions. /// Exclude files using a preset list of extensions.
/// This option takes precedence over extensions specified with `-e` or `-E`. /// This option takes precedence over extensions specified with `-e` or `-E`.
#[clap(short = 'X', long, arg_enum, use_delimiter = true, require_delimiter = true, value_name = "set")] #[clap(short = 'X', long, arg_enum, use_delimiter = true, require_delimiter = true)]
pub exclude_set: Vec<ExtensionSet>, pub exclude_set: Vec<ExtensionSet>,
/// Don't skip hidden files and directories. /// Don't skip hidden files and directories.
@ -81,22 +80,18 @@ pub struct Parameters {
/// Output format to use. /// Output format to use.
/// By default, fif will output a PowerShell script on Windows, and a Bourne Shell script on other platforms. /// By default, fif will output a PowerShell script on Windows, and a Bourne Shell script on other platforms.
#[clap(short, long, default_value = DEFAULT_FORMAT, arg_enum, value_name = "format")] #[clap(short, long, default_value = DEFAULT_FORMAT, arg_enum)]
pub output_format: OutputFormat, pub output_format: OutputFormat,
/// Follow symlinks. /// Follow symlinks.
#[clap(short, long)] #[clap(short, long)]
pub follow_symlinks: bool, pub follow_symlinks: bool,
/// Output verbosity. Each additional `-v` increases verbosity. /// Output verbosity. Defaults to only logging warnings and errors.
/// Can be overridden by RUST_LOG. /// Can be overridden by RUST_LOG.
#[clap(short, long, parse(from_occurrences), group = "verbosity")] #[clap(short, long, parse(from_occurrences))]
pub verbose: u8, pub verbose: u8,
/// Output quietness. Each additional `-q` decreases verbosity.
#[clap(short, long, parse(from_occurrences), group = "verbosity")]
pub quiet: u8,
/// The directory to process. /// The directory to process.
// TODO: right now this can only take a single directory - should this be improved? // TODO: right now this can only take a single directory - should this be improved?
#[clap(name = "DIR", default_value = ".", parse(from_os_str))] #[clap(name = "DIR", default_value = ".", parse(from_os_str))]
@ -186,17 +181,11 @@ impl Parameters {
#![allow(clippy::missing_const_for_fn)] #![allow(clippy::missing_const_for_fn)]
// match was not permitted inside const functions until 1.46 // match was not permitted inside const functions until 1.46
match self.quiet { match self.verbose {
0 => { 0 => "warn",
match self.verbose { 1 => "info",
0 => "info", // no verbosity flags specified 2 => "debug",
1 => "debug", // -v _ => "trace",
_ => "trace" // -vv...
}
},
1 => "warn", // -q
2 => "error", // -qq
_ => "off" // -qqq...
} }
} }
} }
@ -240,11 +229,7 @@ impl ExtensionSet {
"pdf", "doc", "docx", "ppt", "pptx", "xls", "xlsx", "csv", "tsv", "odt", "ods", "odp", "oda", "rtf", "ps", "pdf", "doc", "docx", "ppt", "pptx", "xls", "xlsx", "csv", "tsv", "odt", "ods", "odp", "oda", "rtf", "ps",
"pages", "key", "numbers", "pages", "key", "numbers",
], ],
Self::Text => [ Self::Text => [mime_guess::get_mime_extensions_str("text/*").unwrap(), &["js", "pl", "csh", "sh", "bash", "zsh", "fish", "bat", "php"]].concat(),
mime_guess::get_mime_extensions_str("text/*").unwrap(),
&["js", "pl", "csh", "sh", "bash", "zsh", "fish", "bat", "php"],
]
.concat(),
// many compressed file types follow the name scheme "application/x.+compressed.*" - maybe this can be used // many compressed file types follow the name scheme "application/x.+compressed.*" - maybe this can be used
// somehow to extract extensions for compressed files from mime_guess? // somehow to extract extensions for compressed files from mime_guess?
Self::Archives => vec![ Self::Archives => vec![

View file

@ -339,7 +339,7 @@ fn outputs_move_commands() {
let mut contents = std::string::String::new(); let mut contents = std::string::String::new();
Shell::new() Shell::new()
.write_all(&mut cursor, &entries) .write_all(&entries, &mut cursor)
.expect("Failed to write to cursor"); .expect("Failed to write to cursor");
cursor.set_position(0); cursor.set_position(0);
cursor cursor
@ -387,24 +387,3 @@ fn writables_is_correct() {
writables!["henlo", (Path::new("henlo")), Newline, Space] writables!["henlo", (Path::new("henlo")), Newline, Space]
) )
} }
#[test]
/// Test various combinations of verbosity flags.
fn verbosity() {
assert!(Parameters::try_parse_from(&["fif", "-q", "-v"]).is_err(), "Failed to reject usage of both -q and -v!");
let mut expected_results = HashMap::new();
expected_results.insert("-qqqqqqqq", "off");
expected_results.insert("-qqq", "off");
expected_results.insert("-qq", "error");
expected_results.insert("-q", "warn");
expected_results.insert("-s", "info");
expected_results.insert("-v", "debug");
expected_results.insert("-vv", "trace");
expected_results.insert("-vvv", "trace");
expected_results.insert("-vvvvvvvv", "trace");
for (flags, level) in expected_results {
assert_eq!(Parameters::parse_from(&["fif", flags]).default_verbosity(), level)
}
}