diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index d93c0fd..31c01ad 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -81,15 +81,8 @@ clippy: cleanup-stable: extends: .cargo-cleanup -# commented out because cargo-sweep no longer works on our MSRV -#cleanup-msrv: -# extends: cleanup-stable -# image: "rust:1.43.0" -# cache: -# key: msrv -# paths: -# - target -# - .cargo +# there's no point running cargo sweep on MSRV, since it's always at the same version (and therefore cargo sweep will +# never delete anything) cleanup-nightly: extends: cleanup-stable @@ -107,8 +100,7 @@ build-base-stable: build-base-msrv: extends: build-base-stable -# needs: ["cleanup-msrv"] - image: "rust:1.43.0" + image: "rust:1.48.0" cache: key: msrv paths: @@ -134,7 +126,7 @@ build-stable: build-msrv: extends: build-stable needs: ["build-base-msrv"] - image: "rust:1.43.0" + image: "rust:1.48.0" cache: key: msrv paths: @@ -159,7 +151,7 @@ test-stable: test-msrv: extends: test-stable - image: "rust:1.43.0" + image: "rust:1.48.0" needs: ["build-msrv"] cache: key: msrv diff --git a/CHANGELOG.md b/CHANGELOG.md index 4865f07..b3c9616 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - For a more thorough breakdown of how these flags work, see [the corresponding wiki page](https://gitlab.com/Lynnesbian/fif/-/wikis/Fix). ### Changed +- The Minimum Supported Rust Version (MSRV) is now **1.48.0**. - Capped help output (`-h`/`--help`) width at 120 characters max - Output is now sorted by filename - specifically, errors will appear first, followed by files that fif is unable to recommend an extension for, in order of filename, followed by files that fif knows how to rename, again in order diff --git a/Cargo.lock b/Cargo.lock index d7f35fa..51a33c2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -175,7 +175,6 @@ checksum = "de853764b47027c2e862a995c34978ffa63c1501f2e15f987ba11bd4f9bba193" name = "fif" version = "0.3.7" dependencies = [ - "bitflags", "cfg-if", "clap", "clap_derive", @@ -622,9 +621,9 @@ checksum = "533494a8f9b724d33625ab53c6c4800f7cc445895924a8ef649222dcb76e938b" [[package]] name = "smartstring" -version = "0.2.7" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29620fe111ceaba7a50fd806b5f44c1ef44a697a739f6677a4464c7ea8685997" +checksum = "31aa6a31c0c2b21327ce875f7e8952322acfcfd0c27569a6e18a647281352c9b" dependencies = [ "static_assertions", ] diff --git a/Cargo.toml b/Cargo.toml index e9547cb..5c2bfdc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,7 @@ version = "0.3.7" authors = ["Lynnesbian "] edition = "2018" license = "GPL-3.0-or-later" -rust-version = "1.43.0" # this can actually go as low as 1.41.0 after removing cached, but i'll leave it 1.43.0 +rust-version = "1.48.0" # this can actually go as low as 1.41.0 after removing cached, but i'll leave it 1.43.0 repository = "https://gitlab.com/Lynnesbian/fif" readme = "README.md" keywords = ["mime", "mimetype", "utilities", "tools"] @@ -35,7 +35,6 @@ cfg-if = "1.0.0" itertools = "0.10.0" serde = { version = "1.0", features = ["derive"], optional = true } serde_json = { version = "1.0", optional = true } -bitflags = "~1.2.1" # 1.3+ requires Rust >= 1.46 num_cpus = { version = "1.13.0", optional = true } maplit = "1.0.2" @@ -54,11 +53,8 @@ infer = { version = "0.5.0", optional = true } # needs to be too. otherwise, fif won't work on platforms like powerpc, even though this dependency is the only # blocker -- fif runs just fine on powerpc without smartstring. or at least, just fine under qemu user-mode powerpc ~u0 -# additionally, smartstring 0.2.8 requires rust >=1.46 (due to https://github.com/rust-lang/rust/issues/49146), and -# 0.2.3 doesn't impl Display on its SmartString type. -# so, we need at least 0.2.4 so we can println! strings, and at most 0.2.7 until we bump the MSRV to at least 1.46. -# see https://github.com/bodil/smartstring/blob/master/CHANGELOG.md -smartstring = "<= 0.2.7, >= 0.2.4" +# additionally, versions before 0.2.4 didn't impl Display, so we need at least that version for displaying Strings. +smartstring = ">= 0.2.4" [dependencies.clap] # beta.4 requires rust >= 1.54.0 (and beta.3 was yanked) @@ -90,4 +86,4 @@ opt-level = 3 opt-level = 3 [package.metadata] -msrv = "1.43.0" +msrv = "1.48.0" diff --git a/README.md b/README.md index 92e950f..90d1822 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ [![Version](https://img.shields.io/crates/v/fif.svg?logo=rust&style=flat-square) ](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.48.0-orange?logo=rust&style=flat-square) ](https://gitlab.com/Lynnesbian/fif/-/blob/master/README.md#version-policy) [![License](https://img.shields.io/crates/l/fif.svg?style=flat-square) ](https://gitlab.com/Lynnesbian/fif/-/blob/master/LICENSE) @@ -215,4 +215,4 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License -along with this program. If not, see . \ No newline at end of file +along with this program. If not, see . diff --git a/clippy.sh b/clippy.sh index b16d373..ceae48a 100755 --- a/clippy.sh +++ b/clippy.sh @@ -23,6 +23,7 @@ for backend in "${_backends[@]}"; do -W clippy::pedantic \ -W clippy::complexity \ -W clippy::cargo \ + -W clippy::style \ -W clippy::float_cmp_const \ -W clippy::lossy_float_literal \ -W clippy::multiple_inherent_impl \ @@ -32,8 +33,6 @@ for backend in "${_backends[@]}"; do -A clippy::shadow_unrelated \ -A clippy::option_if_let_else \ -A clippy::multiple-crate-versions \ - -A clippy::cast-possible-truncation \ - -A clippy::cast-possible-wrap \ -A clippy::must_use_candidate \ -A clippy::missing_panics_doc \ -A clippy::missing_errors_doc \ @@ -45,9 +44,7 @@ done # redundant_closure...: the alternative is often much more verbose # shadow_unrelated: sometimes things that seem unrelated are actually related ;) # option_if_let_else: the suggested code is usually harder to read than the original -# multiple_crate_versions: cached uses an old version of hashbrown :c -# cast_possible_truncation: only ever used where it would be totally fine -# cast_possible_wrap: ditto +# multiple_crate_versions: this doesn't actually trip right now, but it's not something i would want CI to fail over # must_use_candidate: useless # missing_panics_doc: the docs are just for me, fif isn't really intended to be used as a library, so this is unneeded # missing_errors_doc: ditto diff --git a/clippy.toml b/clippy.toml index 3332aa9..9be86aa 100644 --- a/clippy.toml +++ b/clippy.toml @@ -1,2 +1,3 @@ # avoid-breaking-exported-api = false # only available on nightly for now -cognitive-complexity-threshold = 15 \ No newline at end of file +cognitive-complexity-threshold = 15 +msrv = "1.48.0" diff --git a/src/files.rs b/src/files.rs index a47f8a7..514275d 100644 --- a/src/files.rs +++ b/src/files.rs @@ -249,9 +249,29 @@ pub fn mime_type(db: &T, path: &Path) -> io::Result> { let mut file = File::open(path)?; // read a small amount to start with - file.read(&mut buffer)?; - let r = db.get_type(&buffer).filter(|mime| + let mut read = io::Result::Ok(0); + + for _ in 0..3 { + // try to read the file up to 3 times, retrying if interrupted, bailing otherwise + file.seek(SeekFrom::Start(0))?; + read = file.read(&mut buffer); + match read { + Ok(_) => break, + Err(ref e) if e.kind() == io::ErrorKind::Interrupted => continue, + Err(_) => break, + } + } + + let read = read?; + let r = db.get_type(&buffer); + + if read < INITIAL_BUF_SIZE { + // the file is smaller than INITIAL_BUF_SIZE - there's no point reading it again + return Ok(r); + } + + let r = r.filter(|mime| // some mime types should be investigated further, reading up to BUF_SIZE even if they've been determined already // one such type is XML - there's many more specific types that can be determined by reading further (such as SVG) mime != &mime::TEXT_XML @@ -268,24 +288,17 @@ pub fn mime_type(db: &T, path: &Path) -> io::Result> { return Ok(r); } - // attempt to read up to the BUF_SIZE bytes of the file. - // we've already read the first 128 bytes into a buffer, but i can't see an obvious way to reuse them in a way that's - // faster than simply moving the seek position back to the start of the file and re-reading the whole BUF_SIZE bytes. - // for example, reading (BUF_SIZE - INITIAL_BUF_SIZE) bytes, then concatenating the original INITIAL_BUF_SIZE buffer - // with this new one would presumably be faster - but it's not. i think it's more expensive to create the iterator, - // collect the contents, etc. i'll have to look into this more. i don't at all doubt that there IS a way to do this - // efficiently, and i can think of a way in principle, but i'm not sure how to express it in a way that is both - // idiomatic/safe and fast. + // attempt to read up to BUF_SIZE bytes of the file. let mut buffer = [0; BUF_SIZE]; file.seek(SeekFrom::Start(0))?; file.read(&mut buffer)?; Ok(db.get_type(&buffer)) } -// Returns a list of known extensions for this mime type, if any. -// This function uses the [Mime]'s "essence" rather than the [Mime] itself - mime_guess::get_mime_extensions ignores -// the type suffix, treating "image/svg+xml" as "image/svg", and thus fails to find any extensions. Passing the -// essence_str (which includes the suffix) fixes this. +/// Returns a list of known extensions for this mime type, if any. +/// This function uses the [`Mime`]'s "essence" rather than the [`Mime`] itself - [`mime_guess::get_mime_extensions`] +/// ignores the type suffix, treating "image/svg+xml" as "image/svg", and thus fails to find any extensions. Passing the +/// essence_str (which includes the suffix) fixes this. pub fn mime_extension_lookup(essence: String) -> Option> { if let Ok(cache) = MIMEXT.read() { if let Some(exts) = cache.get(&essence) { diff --git a/src/main.rs b/src/main.rs index b58c666..889e57f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -40,7 +40,7 @@ fn main() { let mut builder = env_logger::Builder::new(); builder - .filter_level(args.default_verbosity()) // set default log level + .filter_level(args.get_verbosity()) // set default log level .parse_default_env() // set log level from RUST_LOG .parse_env("FIF_LOG") // set log level from FIF_LOG .format(|buf, r| { diff --git a/src/parameters.rs b/src/parameters.rs index 2ed0a5a..7a119ad 100644 --- a/src/parameters.rs +++ b/src/parameters.rs @@ -249,6 +249,7 @@ impl Parameters { } } + /// Populates a [`ScanOpts`] struct with values from [`self`]. pub const fn get_scan_opts(&self) -> ScanOpts { ScanOpts { hidden: self.scan_hidden, @@ -258,10 +259,8 @@ impl Parameters { } } - pub fn default_verbosity(&self) -> log::LevelFilter { - #![allow(clippy::missing_const_for_fn)] - // match was not permitted inside const functions until 1.46 - + /// Gets the verbosity set by the user via the `-v` and `-q` flags. + pub const fn get_verbosity(&self) -> log::LevelFilter { use log::LevelFilter; match self.quiet {