added rustfmt.toml, ran rustfmt
This commit is contained in:
parent
31acd76c73
commit
b6d340d45c
7 changed files with 94 additions and 74 deletions
4
rusftmt.toml
Normal file
4
rusftmt.toml
Normal file
|
@ -0,0 +1,4 @@
|
|||
max_width = 120
|
||||
hard_tabs = true
|
||||
tab_spaces = 2
|
||||
newline_style = "Unix"
|
|
@ -1,8 +1,10 @@
|
|||
use std::path::PathBuf;
|
||||
use crate::inspectors::mime_extension_lookup;
|
||||
|
||||
use mime_guess::Mime;
|
||||
use smartstring::alias::String;
|
||||
|
||||
use crate::inspectors::mime_extension_lookup;
|
||||
|
||||
pub struct Findings {
|
||||
pub file: PathBuf, // TODO: replace with Path???? <'a> and all that
|
||||
pub valid: bool,
|
||||
|
@ -11,7 +13,6 @@ pub struct Findings {
|
|||
|
||||
impl Findings {
|
||||
pub fn recommended_extension(&self) -> Option<String> {
|
||||
mime_extension_lookup(self.mime.clone())
|
||||
.map(|extensions| extensions[0].to_owned())
|
||||
mime_extension_lookup(self.mime.clone()).map(|extensions| extensions[0].to_owned())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,13 +16,15 @@ type Entries = [Result<Findings, (ScanError, PathBuf)>];
|
|||
|
||||
fn write_pathbuf<W: Write>(f: &mut W, path: &PathBuf) -> io::Result<()> {
|
||||
match path.to_str() {
|
||||
Some(string) => { write!(f, "{}", escape(string)) }
|
||||
Some(string) => {
|
||||
write!(f, "{}", escape(string))
|
||||
}
|
||||
None => {
|
||||
write!(f, "'")?;
|
||||
#[cfg(unix)]
|
||||
f.write_all(&*path.as_os_str().as_bytes())?;
|
||||
f.write_all(&*path.as_os_str().as_bytes())?;
|
||||
#[cfg(windows)]
|
||||
f.write_all(&*path.as_os_str().encode_wide().collect())?; // TODO: TEST THIS
|
||||
f.write_all(&*path.as_os_str().encode_wide().collect())?; // TODO: TEST THIS
|
||||
write!(f, "'")
|
||||
}
|
||||
}
|
||||
|
@ -48,11 +50,7 @@ pub trait Format {
|
|||
if !finding.valid {
|
||||
// the file's extension is wrong - check for known extension
|
||||
if let Some(ext) = finding.recommended_extension() {
|
||||
self.rename(
|
||||
f,
|
||||
&finding.file,
|
||||
&finding.file.with_extension(ext.as_str()),
|
||||
)?
|
||||
self.rename(f, &finding.file, &finding.file.with_extension(ext.as_str()))?
|
||||
} else {
|
||||
self.no_known_extension(f, &finding.file)?
|
||||
}
|
||||
|
@ -64,7 +62,7 @@ pub trait Format {
|
|||
// failed to read the file
|
||||
ScanError::File => self.unreadable(f, &error.1)?,
|
||||
// file was read successfully, but we couldn't determine a mimetype
|
||||
ScanError::Mime => self.unknown_type(f, &error.1)?
|
||||
ScanError::Mime => self.unknown_type(f, &error.1)?,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -77,7 +75,9 @@ pub trait Format {
|
|||
pub struct Script {}
|
||||
|
||||
impl Format for Script {
|
||||
fn new() -> Self { Self {} }
|
||||
fn new() -> Self {
|
||||
Self {}
|
||||
}
|
||||
|
||||
fn rename<W: Write>(&self, f: &mut W, from: &PathBuf, to: &PathBuf) -> io::Result<()> {
|
||||
// TODO: surely there's a better way...
|
||||
|
@ -85,29 +85,33 @@ impl Format for Script {
|
|||
write_pathbuf(f, from)?;
|
||||
write!(f, " ")?;
|
||||
write_pathbuf(f, to)?;
|
||||
writeln!(f, )
|
||||
writeln!(f,)
|
||||
}
|
||||
|
||||
fn no_known_extension<W: Write>(&self, f: &mut W, path: &PathBuf) -> io::Result<()> {
|
||||
write!(f, "echo No known extension for ")?;
|
||||
write_pathbuf(f, path)?;
|
||||
writeln!(f, )
|
||||
writeln!(f,)
|
||||
}
|
||||
|
||||
fn unreadable<W: Write>(&self, f: &mut W, path: &PathBuf) -> io::Result<()> {
|
||||
write!(f, "# Failed to read ")?;
|
||||
write_pathbuf(f, path)?;
|
||||
writeln!(f, )
|
||||
writeln!(f,)
|
||||
}
|
||||
|
||||
fn unknown_type<W: Write>(&self, f: &mut W, path: &PathBuf) -> io::Result<()> {
|
||||
write!(f, "# Failed to detect mime type for ")?;
|
||||
write_pathbuf(f, path)?;
|
||||
writeln!(f, )
|
||||
writeln!(f,)
|
||||
}
|
||||
|
||||
fn header<W: Write>(&self, _: &Entries, f: &mut W) -> io::Result<()> {
|
||||
write!(f, "#!/usr/bin/env sh\n\nGenerated by fif {}.\n\n", VERSION.unwrap_or("???"))
|
||||
write!(
|
||||
f,
|
||||
"#!/usr/bin/env sh\n\nGenerated by fif {}.\n\n",
|
||||
VERSION.unwrap_or("???")
|
||||
)
|
||||
}
|
||||
|
||||
fn footer<W: Write>(&self, _: &Entries, f: &mut W) -> io::Result<()> {
|
||||
|
|
|
@ -21,7 +21,7 @@ use crate::mimedb::MimeDb;
|
|||
// at least 265 bytes to identify a tar file.
|
||||
const BUF_SIZE: usize = 512;
|
||||
|
||||
pub fn mime_type<T: MimeDb>(db: &T, path: &Path) -> io::Result<Option<Mime>, > {
|
||||
pub fn mime_type<T: MimeDb>(db: &T, path: &Path) -> io::Result<Option<Mime>> {
|
||||
// attempt to read up to the BUF_SIZE bytes of the file
|
||||
|
||||
let mut buffer = [0; 64];
|
||||
|
@ -30,8 +30,7 @@ pub fn mime_type<T: MimeDb>(db: &T, path: &Path) -> io::Result<Option<Mime>, > {
|
|||
// this lint can be ignored: it's okay if the file isn't long enough to fill the buffer, as we only care about the
|
||||
// first few bytes for the purpose of mime sniffing
|
||||
#[allow(clippy::unused_io_amount)]
|
||||
file.read(&mut buffer)?;
|
||||
|
||||
file.read(&mut buffer)?;
|
||||
|
||||
let r = db.get_type(&buffer);
|
||||
if r.is_some() {
|
||||
|
@ -61,4 +60,3 @@ cached! {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
72
src/main.rs
72
src/main.rs
|
@ -21,7 +21,7 @@ use clap::Clap;
|
|||
use log::{debug, info, trace, warn};
|
||||
use once_cell::sync::OnceCell;
|
||||
#[cfg(feature = "multi-threaded")]
|
||||
use rayon::prelude::*;
|
||||
use rayon::prelude::*;
|
||||
use smartstring::alias::String;
|
||||
use walkdir::{DirEntry, WalkDir};
|
||||
|
||||
|
@ -31,18 +31,18 @@ use crate::mimedb::MimeDb;
|
|||
use crate::parameters::OutputFormat;
|
||||
use crate::scanerror::ScanError;
|
||||
|
||||
mod parameters;
|
||||
mod inspectors;
|
||||
mod formats;
|
||||
mod scanerror;
|
||||
mod findings;
|
||||
mod formats;
|
||||
mod inspectors;
|
||||
mod mimedb;
|
||||
mod parameters;
|
||||
mod scanerror;
|
||||
|
||||
#[cfg(feature = "infer-backend")]
|
||||
static MIMEDB: OnceCell<mimedb::InferDb> = OnceCell::new();
|
||||
static MIMEDB: OnceCell<mimedb::InferDb> = OnceCell::new();
|
||||
|
||||
#[cfg(feature = "xdg-mime-backend")]
|
||||
static MIMEDB: OnceCell<mimedb::XdgDb> = OnceCell::new();
|
||||
static MIMEDB: OnceCell<mimedb::XdgDb> = OnceCell::new();
|
||||
|
||||
// TODO: test if this actually works on a windows machine
|
||||
#[cfg(windows)]
|
||||
|
@ -50,14 +50,17 @@ fn is_hidden(entry: &DirEntry) -> bool {
|
|||
use std::os::windows::prelude::*;
|
||||
std::fs::metadata(entry) // try to get metadata for file
|
||||
.map_or(
|
||||
false, // if getting metadata/attributes fails, assume it's not hidden
|
||||
false, // if getting metadata/attributes fails, assume it's not hidden
|
||||
|f| f.file_attributes() & 0x2 > 0, // flag for hidden - https://docs.microsoft.com/windows/win32/fileio/file-attribute-constants
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(not(windows))]
|
||||
fn is_hidden(entry: &DirEntry) -> bool {
|
||||
entry.file_name().to_str().map_or(false, |f| f.starts_with('.') && f != ".")
|
||||
entry
|
||||
.file_name()
|
||||
.to_str()
|
||||
.map_or(false, |f| f.starts_with('.') && f != ".")
|
||||
}
|
||||
|
||||
fn wanted_file(args: ¶meters::Parameters, entry: &DirEntry) -> bool {
|
||||
|
@ -73,7 +76,9 @@ fn wanted_file(args: ¶meters::Parameters, entry: &DirEntry) -> bool {
|
|||
|
||||
let ext = extension_from_path(entry.path());
|
||||
|
||||
if ext.is_none() { return false; } // don't scan files without extensions. TODO - this should be configurable
|
||||
if ext.is_none() {
|
||||
return false;
|
||||
} // don't scan files without extensions. TODO - this should be configurable
|
||||
|
||||
if let Some(extensions) = &args.extensions {
|
||||
// if the user has specified a list of extensions to check against, make sure this file ends in one of them.
|
||||
|
@ -117,7 +122,7 @@ fn scan_file(entry: &DirEntry) -> Result<Findings, (ScanError, PathBuf)> {
|
|||
// there is a known set of extensions for this mimetype, but the file has no extension
|
||||
Some(_) => false,
|
||||
// there is no known set of extensions for this mimetype -- assume it's correct
|
||||
None => true
|
||||
None => true,
|
||||
};
|
||||
|
||||
Ok(Findings {
|
||||
|
@ -128,25 +133,25 @@ fn scan_file(entry: &DirEntry) -> Result<Findings, (ScanError, PathBuf)> {
|
|||
}
|
||||
|
||||
fn scan_from_walkdir(entries: Vec<DirEntry>) -> Vec<Result<Findings, (ScanError, PathBuf)>> {
|
||||
#[cfg(feature = "multi-threaded")] {
|
||||
#[cfg(feature = "multi-threaded")]
|
||||
{
|
||||
// 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
|
||||
.par_chunks(32) // split into chunks of 32
|
||||
.flat_map(|chunk| chunk // return Vec<...> instead of Chunk<Vec<...>>
|
||||
.iter() // iter over the chunk, which is a slice of DirEntry structs
|
||||
.map(|entry| scan_file(entry))
|
||||
.collect::<Vec<_>>()
|
||||
)
|
||||
.flat_map(|chunk| {
|
||||
chunk // return Vec<...> instead of Chunk<Vec<...>>
|
||||
.iter() // iter over the chunk, which is a slice of DirEntry structs
|
||||
.map(|entry| scan_file(entry))
|
||||
.collect::<Vec<_>>()
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "multi-threaded"))] {
|
||||
entries
|
||||
.iter()
|
||||
.map(|entry: &DirEntry| scan_file(entry))
|
||||
.collect()
|
||||
#[cfg(not(feature = "multi-threaded"))]
|
||||
{
|
||||
entries.iter().map(|entry: &DirEntry| scan_file(entry)).collect()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -161,10 +166,16 @@ fn main() {
|
|||
.init();
|
||||
|
||||
#[cfg(feature = "infer-backend")]
|
||||
MIMEDB.set(mimedb::InferDb::init()).or(Err("Failed to initialise MIMEDB")).unwrap();
|
||||
MIMEDB
|
||||
.set(mimedb::InferDb::init())
|
||||
.or(Err("Failed to initialise MIMEDB"))
|
||||
.unwrap();
|
||||
|
||||
#[cfg(feature = "xdg-mime-backend")]
|
||||
MIMEDB.set(mimedb::XdgDb::init()).or(Err("Failed to initialise MIMEDB")).unwrap();
|
||||
MIMEDB
|
||||
.set(mimedb::XdgDb::init())
|
||||
.or(Err("Failed to initialise MIMEDB"))
|
||||
.unwrap();
|
||||
|
||||
debug!("Iterating directory: {:?}", args.dirs);
|
||||
|
||||
|
@ -183,21 +194,26 @@ fn main() {
|
|||
match result {
|
||||
Ok(r) => {
|
||||
if !r.valid {
|
||||
info!("{:?} should have file extension {}", r.file, r.recommended_extension().unwrap())
|
||||
info!(
|
||||
"{:?} should have file extension {}",
|
||||
r.file,
|
||||
r.recommended_extension().unwrap()
|
||||
)
|
||||
} else {
|
||||
trace!("{:?} is totally fine", r.file)
|
||||
}
|
||||
}
|
||||
Err(f) => warn!("{:#?}: Error 0uo - {}", f.1, f.0)
|
||||
Err(f) => warn!("{:#?}: Error 0uo - {}", f.1, f.0),
|
||||
}
|
||||
}
|
||||
|
||||
match args.output_format {
|
||||
OutputFormat::Script => {
|
||||
let s = Script::new();
|
||||
s.write_all(&results, &mut BufWriter::new(stdout().lock())).expect("failed to output");
|
||||
s.write_all(&results, &mut BufWriter::new(stdout().lock()))
|
||||
.expect("failed to output");
|
||||
}
|
||||
OutputFormat::Text => todo!()
|
||||
OutputFormat::Text => todo!(),
|
||||
}
|
||||
|
||||
debug!("Done");
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use mime_guess::Mime;
|
||||
#[cfg(feature = "infer-backend")]
|
||||
use std::str::FromStr;
|
||||
use std::str::FromStr;
|
||||
|
||||
use mime_guess::Mime;
|
||||
|
||||
pub trait MimeDb {
|
||||
fn init() -> Self;
|
||||
|
@ -9,7 +10,7 @@ pub trait MimeDb {
|
|||
|
||||
#[cfg(feature = "infer-backend")]
|
||||
pub struct InferDb {
|
||||
db: infer::Infer
|
||||
db: infer::Infer,
|
||||
}
|
||||
|
||||
#[cfg(feature = "infer-backend")]
|
||||
|
@ -17,11 +18,8 @@ impl MimeDb for InferDb {
|
|||
fn init() -> Self {
|
||||
let mut info = infer::Infer::new();
|
||||
// add a random file type just to make sure adding works and such
|
||||
info.add(
|
||||
"image/jpeg2000",
|
||||
".jp2",
|
||||
|buf| {
|
||||
buf.len() > 23
|
||||
info.add("image/jpeg2000", ".jp2", |buf| {
|
||||
buf.len() > 23
|
||||
&& buf[0] == 0x00
|
||||
&& buf[1] == 0x00
|
||||
&& buf[2] == 0x00
|
||||
|
@ -38,8 +36,7 @@ impl MimeDb for InferDb {
|
|||
&& buf[21] == 0x70
|
||||
&& buf[22] == 0x32
|
||||
&& buf[23] == 0x20
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
// unmut
|
||||
let info = info;
|
||||
|
@ -48,22 +45,20 @@ impl MimeDb for InferDb {
|
|||
}
|
||||
|
||||
fn get_type(&self, data: &[u8]) -> Option<Mime> {
|
||||
self.db
|
||||
.get(data)
|
||||
.map(|f| Mime::from_str(f.mime_type()).unwrap())
|
||||
self.db.get(data).map(|f| Mime::from_str(f.mime_type()).unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "xdg-mime-backend")]
|
||||
pub struct XdgDb {
|
||||
db: xdg_mime::SharedMimeInfo
|
||||
db: xdg_mime::SharedMimeInfo,
|
||||
}
|
||||
|
||||
#[cfg(feature = "xdg-mime-backend")]
|
||||
impl MimeDb for XdgDb {
|
||||
fn init() -> Self {
|
||||
Self {
|
||||
db: xdg_mime::SharedMimeInfo::new()
|
||||
db: xdg_mime::SharedMimeInfo::new(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,16 +2,18 @@ use std::fmt::{Display, Formatter, Result};
|
|||
|
||||
pub enum ScanError {
|
||||
File,
|
||||
Mime
|
||||
Mime,
|
||||
}
|
||||
|
||||
impl Display for ScanError {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
|
||||
write!(f, "{}",
|
||||
match self {
|
||||
Self::File => "Couldn't read file",
|
||||
Self::Mime => "Couldn't determine mime type"
|
||||
}
|
||||
write!(
|
||||
f,
|
||||
"{}",
|
||||
match self {
|
||||
Self::File => "Couldn't read file",
|
||||
Self::Mime => "Couldn't determine mime type",
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue