Compare commits

..

5 commits

Author SHA1 Message Date
4d553587aa
fixed powershell output
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-20 19:00:56 +10:00
255665cae0
output is now sorted 0u0
sort order: files that couldn't be read, then files with no known mimetype, then files with no known extensions, then files with the wrong extension
2021-04-20 18:52:49 +10:00
b877d7d65e
xdg-mime no longer uses git version 0u0 2021-04-20 17:26:31 +10:00
dc2ac7b002
reformatting/reordering 2021-04-20 15:20:10 +10:00
83091c754d
removed duplicate Archives pattern in extension_set.rs 2021-04-14 19:17:41 +10:00
10 changed files with 73 additions and 39 deletions

View file

@ -2,12 +2,16 @@
Dates are given in YYYY-MM-DD format. Dates are given in YYYY-MM-DD format.
## v0.2 ## v0.2
### v0.2.12 (2021-???) ### v0.2.13 (2021-???)
- Added Apple iWork document formats to documents extension set - Added Apple iWork document formats to documents extension set
- Cleaned up and properly documented tests - Cleaned up and properly documented tests
- Renamed `Script` (in `formats.rs`) to `Shell`, in line with renaming in `paramaters.rs` - Renamed `Script` (in `formats.rs`) to `Shell`, in line with renaming in `parameters.rs`
- Added .rpa (renpy archive) support - Added .rpa (Ren'Py archive) support to infer backend
- Added system extension set - Added system extension set
- [`xdg-mime`] no longer uses git version
- Output is sorted: Files that couldn't be read, then files with no known mimetype, then files with no known extensions,
then files with the wrong extension
- Fixed some bad formatting in PowerShell output
### v0.2.12 (2021-04-14) ### v0.2.12 (2021-04-14)
#### Features #### Features

13
Cargo.lock generated
View file

@ -202,6 +202,7 @@ dependencies = [
"exitcode", "exitcode",
"fastrand", "fastrand",
"infer", "infer",
"itertools",
"log", "log",
"mime_guess", "mime_guess",
"once_cell", "once_cell",
@ -282,6 +283,15 @@ dependencies = [
"cfg-if", "cfg-if",
] ]
[[package]]
name = "itertools"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37d572918e350e82412fe766d24b15e6682fb2ed2bbe018280caa810397cb319"
dependencies = [
"either",
]
[[package]] [[package]]
name = "lazy_static" name = "lazy_static"
version = "1.4.0" version = "1.4.0"
@ -742,7 +752,8 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]] [[package]]
name = "xdg-mime" name = "xdg-mime"
version = "0.3.3" version = "0.3.3"
source = "git+https://github.com/ebassi/xdg-mime-rs?rev=de5a6dd#de5a6dd04b1a225894c51b5c6e5f5a22ffa46373" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87bf7b69bb50588d70a36e467be29d3df3e8c32580276d62eded9738c1a797aa"
dependencies = [ dependencies = [
"dirs-next", "dirs-next",
"glob", "glob",

View file

@ -33,16 +33,15 @@ infer = "0.4.0"
rayon = { version = "1.5.0", optional = true } rayon = { version = "1.5.0", optional = true }
exitcode = "1.1.2" exitcode = "1.1.2"
cfg-if = "1.0.0" cfg-if = "1.0.0"
itertools = "0.10.0"
[target.'cfg(unix)'.dependencies] [target.'cfg(unix)'.dependencies]
xdg-mime = "0.3.2" xdg-mime = "0.3.3"
[target.'cfg(not(all(target_endian = "big", target_pointer_width = "32")))'.dependencies] [target.'cfg(not(all(target_endian = "big", target_pointer_width = "32")))'.dependencies]
smartstring = "0.2.6" smartstring = "0.2.6"
[patch.crates-io] [patch.crates-io]
# use git version while waiting on a release incorporating https://github.com/ebassi/xdg-mime-rs/commit/de5a6dd
xdg-mime = { git = "https://github.com/ebassi/xdg-mime-rs", version = "0.3", rev = "de5a6dd" }
# forked version with many more mime types # forked version with many more mime types
mime_guess = { git = "https://github.com/Lynnesbian/mime_guess", version = "2.0.4" } mime_guess = { git = "https://github.com/Lynnesbian/mime_guess", version = "2.0.4" }
@ -70,6 +69,9 @@ lto = "thin"
[profile.test] [profile.test]
opt-level = 0 opt-level = 0
# optimise dependencies, even when producing debug builds # optimise dependencies, even when producing debug and test builds
[profile.dev.package."*"] [profile.dev.package."*"]
opt-level = 3 opt-level = 3
[profile.test.package."*"]
opt-level = 3

View file

@ -43,9 +43,10 @@ impl ExtensionSet {
// 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!["zip", "tar", "gz", "zst", "xz", "rar", "7z", "bz", "bz2", "tgz", "rpa"], Self::Archives => vec!["zip", "tar", "gz", "zst", "xz", "rar", "7z", "bz", "bz2", "tgz", "rpa"],
Self::System => vec!["com", "dll", "exe", "sys", "reg", "nt", "cpl", "msi", "efi", "bio", "rcv", "mbr", "sbf", "grub", "ko", "dylib", "pdb", "hdmp", "crash", Self::System => vec![
"com", "dll", "exe", "sys", "reg", "nt", "cpl", "msi", "efi", "bio", "rcv", "mbr", "sbf", "grub", "ko",
"dylib", "pdb", "hdmp", "crash",
], ],
Self::Archives => vec!["zip", "tar", "gz", "zst", "xz", "rar", "7z", "bz", "bz2", "tgz"],
} }
} }
} }

View file

@ -1,11 +1,12 @@
use std::path::Path; use std::path::Path;
use crate::string_type::String;
use mime_guess::Mime; use mime_guess::Mime;
use crate::inspectors::mime_extension_lookup; use crate::inspectors::mime_extension_lookup;
use crate::string_type::String;
/// Information about a scanned file. /// Information about a scanned file.
#[derive(Ord, PartialOrd, Eq, PartialEq)]
pub struct Findings<'a> { pub struct Findings<'a> {
/// The location of the scanned file. /// The location of the scanned file.
pub file: &'a Path, pub file: &'a Path,

View file

@ -1,5 +1,6 @@
//! The various formats that [fif](crate) can output to. //! The various formats that [fif](crate) can output to.
use std::ffi::OsStr;
use std::io::{self, Write}; use std::io::{self, Write};
#[cfg(unix)] #[cfg(unix)]
use std::os::unix::ffi::OsStrExt; use std::os::unix::ffi::OsStrExt;
@ -9,7 +10,7 @@ use snailquote::escape;
use crate::scan_error::ScanError; use crate::scan_error::ScanError;
use crate::{Findings, BACKEND}; use crate::{Findings, BACKEND};
use std::ffi::OsStr; use itertools::Itertools;
/// 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");
@ -83,25 +84,36 @@ pub trait Format {
// TODO: clean this up - it's kinda messy // TODO: clean this up - it's kinda messy
self.header(entries, f)?; self.header(entries, f)?;
for entry in entries { // output will be generated in the order:
match entry { // - files that couldn't be read
Ok(finding) => { // - files with no known mime type
if let Some(ext) = finding.recommended_extension() { // - files with no known extension
self.rename(f, finding.file, &finding.file.with_extension(ext.as_str()))? // - files with a known extension
} else { // files that already have a correct extension won't be represented in the output.
self.no_known_extension(f, finding.file)?
}
}
Err(error) => { // sort errors so unreadable files appear before files with unknown mimetypes - ScanError impls Ord such that
// something went wrong 0uo // ScanError::File > ScanError::Mime
match error { let errors = entries.iter().filter_map(|e| e.as_ref().err()).sorted();
// failed to read the file // sort files so that files with no known extension come before those with known extensions - None > Some("jpg")
ScanError::File(path) => self.unreadable(f, path)?, let findings = entries
// file was read successfully, but we couldn't determine a mimetype .iter()
ScanError::Mime(path) => self.unknown_type(f, path)?, .filter_map(|e| e.as_ref().ok())
} .sorted_by(|a, b| b.recommended_extension().cmp(&a.recommended_extension()).reverse());
}
for error in errors {
match error {
// failed to read the file
ScanError::File(path) => self.unreadable(f, path)?,
// file was read successfully, but we couldn't determine a mimetype
ScanError::Mime(path) => self.unknown_type(f, path)?,
}
}
for finding in findings {
if let Some(ext) = finding.recommended_extension() {
self.rename(f, finding.file, &finding.file.with_extension(ext.as_str()))?
} else {
self.no_known_extension(f, finding.file)?
} }
} }
@ -214,7 +226,7 @@ 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( smart_write(
f, f,
&["<# Failed to detect mime type for ".into(), path.into(), "#>".into()], &["<# Failed to detect mime type for ".into(), path.into(), "#>".into(), Writable::Newline],
) )
} }

View file

@ -91,8 +91,6 @@ cached! {
} }
} }
match exts { match exts {
Some(exts) => { Some(exts) => {
let possible_exts: Vec<String> = exts.iter().map(|e| String::from(*e)).collect(); let possible_exts: Vec<String> = exts.iter().map(|e| String::from(*e)).collect();

View file

@ -17,11 +17,14 @@
#![forbid(unsafe_code)] #![forbid(unsafe_code)]
#![warn(trivial_casts, unused_lifetimes, unused_qualifications)] #![warn(trivial_casts, unused_lifetimes, unused_qualifications)]
use std::io::{stdout, BufWriter}; use std::ffi::OsStr;
use std::io::{stdout, BufWriter, Write};
use std::path::Path; use std::path::Path;
use std::process::exit;
use cfg_if::cfg_if; use cfg_if::cfg_if;
use clap::Clap; use clap::Clap;
use env_logger::Env;
use log::{debug, error, info, trace, warn}; use log::{debug, error, info, trace, warn};
use once_cell::sync::OnceCell; use once_cell::sync::OnceCell;
#[cfg(feature = "multi-threaded")] #[cfg(feature = "multi-threaded")]
@ -33,9 +36,6 @@ use crate::formats::{Format, PowerShell, Shell};
use crate::mime_db::MimeDb; use crate::mime_db::MimeDb;
use crate::parameters::{OutputFormat, ScanOpts}; use crate::parameters::{OutputFormat, ScanOpts};
use crate::scan_error::ScanError; use crate::scan_error::ScanError;
use env_logger::Env;
use std::ffi::OsStr;
use std::process::exit;
mod extension_set; mod extension_set;
mod findings; mod findings;
@ -143,6 +143,11 @@ fn main() {
exit(exitcode::IOERR); exit(exitcode::IOERR);
} }
if buffered_stdout.flush().is_err() {
error!("Failed to flush stdout.");
exit(exitcode::IOERR);
}
debug!("Done"); debug!("Done");
} }

View file

@ -1,7 +1,7 @@
use std::fmt::{Display, Formatter, Result}; use std::fmt::{Display, Formatter, Result};
use std::path::Path; use std::path::Path;
#[derive(Debug)] #[derive(Debug, PartialEq, PartialOrd, Ord, Eq)]
pub enum ScanError<'a> { pub enum ScanError<'a> {
/// Something went wrong while trying to read the given file. /// Something went wrong while trying to read the given file.
File(&'a Path), File(&'a Path),

View file

@ -192,7 +192,7 @@ fn argument_parsing() {
ScanOpts { ScanOpts {
hidden: false, hidden: false,
extensionless: false, extensionless: false,
follow_symlinks: true follow_symlinks: true,
}, },
"ScanOpts are incorrect" "ScanOpts are incorrect"
) )