From 720083068e8f661d53a8fcf6e87b9a9d3530d71f Mon Sep 17 00:00:00 2001 From: n-dusan Date: Mon, 16 Dec 2024 11:51:51 +0100 Subject: [PATCH] chore: lots of clippy lints Transition from rust-version 1.78 -> 1.83 introduced new clippy rules. - Use `expect` macro instead of `allow` for crate specific lints - Add a `reason` attribute instead of keeping inline comments with explanations - Use default `as _` for traits which are brought into scope but unused - Small improvements related to borrowing lints --- src/db/init.rs | 2 +- src/db/mod.rs | 5 +- src/db/models/publication/mod.rs | 2 +- src/db/models/publication_version/manager.rs | 2 +- src/db/models/publication_version/mod.rs | 2 +- src/history/changes.rs | 57 ++++++++++------ src/history/rdf/graph.rs | 24 ++++--- src/lib.rs | 71 ++++++++++++++------ src/server/api/routes.rs | 10 ++- src/server/api/serve/mod.rs | 7 +- src/server/api/state.rs | 10 ++- src/server/api/versions/mod.rs | 7 +- src/server/api/versions/response/messages.rs | 4 +- src/server/api/versions/response/mod.rs | 5 +- src/server/app.rs | 10 ++- src/server/errors.rs | 13 ++-- src/server/git.rs | 14 ++-- src/server/tracing.rs | 2 +- src/stelae/stele.rs | 4 +- src/stelae/types/repositories.rs | 10 ++- src/utils/archive.rs | 2 +- src/utils/cli.rs | 20 ++++-- src/utils/git.rs | 8 ++- src/utils/http.rs | 4 +- src/utils/md5.rs | 2 +- src/utils/paths.rs | 2 +- tests/common/mod.rs | 4 +- 27 files changed, 192 insertions(+), 111 deletions(-) diff --git a/src/db/init.rs b/src/db/init.rs index 11d2511..acac4d8 100644 --- a/src/db/init.rs +++ b/src/db/init.rs @@ -1,4 +1,4 @@ -use crate::db::{DatabaseConnection, DatabaseKind, Db}; +use crate::db::{DatabaseConnection, DatabaseKind, Db as _}; use std::env; use std::path::{Path, PathBuf}; /// Connects to a database and applies migrations. diff --git a/src/db/mod.rs b/src/db/mod.rs index 55d7e42..a6223ec 100644 --- a/src/db/mod.rs +++ b/src/db/mod.rs @@ -1,12 +1,11 @@ //! Database related module. -#![allow(clippy::unreachable)] use async_trait::async_trait; use sqlx::Transaction; -use std::str::FromStr; +use std::str::FromStr as _; use sqlx::any::{self, AnyPoolOptions}; use sqlx::AnyPool; -use sqlx::ConnectOptions; +use sqlx::ConnectOptions as _; use tracing::instrument; /// Database initialization. diff --git a/src/db/models/publication/mod.rs b/src/db/models/publication/mod.rs index 3fdfde5..3185c1c 100644 --- a/src/db/models/publication/mod.rs +++ b/src/db/models/publication/mod.rs @@ -1,7 +1,7 @@ use async_trait::async_trait; use chrono::NaiveDate; use serde::{Deserialize, Serialize}; -use sqlx::{any::AnyRow, FromRow, Row}; +use sqlx::{any::AnyRow, FromRow, Row as _}; pub mod manager; diff --git a/src/db/models/publication_version/manager.rs b/src/db/models/publication_version/manager.rs index 07648e5..45d5667 100644 --- a/src/db/models/publication_version/manager.rs +++ b/src/db/models/publication_version/manager.rs @@ -120,7 +120,7 @@ impl super::TxManager for DatabaseTransaction { } /// Recursively find all publication versions starting from a given publication ID. - + /// /// This is necessary because publication versions can be the same across publications. /// To make versions query simpler, we walk the publication hierarchy starting from /// `publication_name` looking for related publications. diff --git a/src/db/models/publication_version/mod.rs b/src/db/models/publication_version/mod.rs index 46b95da..c9c36a6 100644 --- a/src/db/models/publication_version/mod.rs +++ b/src/db/models/publication_version/mod.rs @@ -1,6 +1,6 @@ use async_trait::async_trait; use serde::{Deserialize, Serialize}; -use sqlx::{any::AnyRow, FromRow, Row}; +use sqlx::{any::AnyRow, FromRow, Row as _}; pub mod manager; diff --git a/src/history/changes.rs b/src/history/changes.rs index 55b12d5..a18ebe4 100644 --- a/src/history/changes.rs +++ b/src/history/changes.rs @@ -1,9 +1,11 @@ //! Module for inserting changes into the database -#![allow( - clippy::exit, +#![expect( clippy::shadow_reuse, + reason = "Bindings that shadow other bindings in the same scope are used to make the code a bit more legible in this module" +)] +#![expect( clippy::future_not_send, - clippy::string_add + reason = "We don't worry about git2-rs not implementing `Send` trait" )] use super::rdf::graph::Bag; use crate::db::models::changed_library_document::{self, ChangedLibraryDocument}; @@ -20,7 +22,7 @@ use crate::db::models::publication_version; use crate::db::models::status::Status; use crate::db::models::{document, document_element}; use crate::db::models::{stele, version}; -use crate::db::{DatabaseTransaction, Tx}; +use crate::db::{DatabaseTransaction, Tx as _}; use crate::history::rdf::graph::StelaeGraph; use crate::history::rdf::namespaces::{dcterms, oll}; use crate::server::errors::CliError; @@ -33,7 +35,7 @@ use crate::{ db::{self, DatabaseConnection}, stelae::archive::Archive, }; -use anyhow::Context; +use anyhow::Context as _; use chrono::DateTime; use git2::{TreeWalkMode, TreeWalkResult}; use sophia::api::ns::rdfs; @@ -184,7 +186,6 @@ async fn load_delta_for_stele( /// /// # Errors /// Errors if the delta cannot be loaded from the publications -#[allow(clippy::unwrap_used)] async fn load_delta_from_publications( tx: &mut DatabaseTransaction, rdf_repo: &Repo, @@ -266,7 +267,7 @@ async fn load_delta_from_publications( })?; let (last_valid_pub_name, last_valid_codified_date) = referenced_publication_information(&pub_graph); - let publication_hash = md5::compute(pub_name.clone() + stele); + let publication_hash = md5::compute(format!("{}{}", pub_name.clone(), stele)); let last_inserted_pub_id = if let Some(valid_pub_name) = last_valid_pub_name { let last_inserted_pub = publication::TxManager::find_by_name_and_stele(tx, &valid_pub_name, stele).await?; @@ -310,7 +311,7 @@ async fn load_delta_for_publication( insert_document_changes( tx, - &last_inserted_date, + last_inserted_date.as_ref(), pub_document_versions, pub_graph, &publication, @@ -319,7 +320,7 @@ async fn load_delta_for_publication( insert_library_changes( tx, - &last_inserted_date, + last_inserted_date.as_ref(), pub_collection_versions, pub_graph, &publication, @@ -336,7 +337,7 @@ async fn load_delta_for_publication( /// Insert document changes into the database async fn insert_document_changes( tx: &mut DatabaseTransaction, - last_inserted_date: &Option, + last_inserted_date: Option<&NaiveDate>, pub_document_versions: Vec<&SimpleTerm<'_>>, pub_graph: &StelaeGraph, publication: &Publication, @@ -354,8 +355,12 @@ async fn insert_document_changes( } } version::TxManager::create(tx, &codified_date).await?; - let pub_version_hash = - md5::compute(publication.name.clone() + &codified_date + &publication.stele); + let pub_version_hash = md5::compute(format!( + "{}{}{}", + publication.name.clone(), + &codified_date, + &publication.stele + )); publication_version::TxManager::create( tx, &pub_version_hash, @@ -396,9 +401,12 @@ async fn insert_document_changes( )?; for el_status in statuses { let status = Status::from_string(&el_status)?; - let document_change_hash = md5::compute( - pub_version_hash.clone() + &doc_mpath.clone() + &status.to_int().to_string(), - ); + let document_change_hash = md5::compute(format!( + "{}{}{}", + pub_version_hash.clone(), + &doc_mpath.clone(), + &status.to_int().to_string() + )); document_changes_bulk.push(DocumentChange::new( document_change_hash, status.to_int(), @@ -417,7 +425,7 @@ async fn insert_document_changes( /// Insert library changes into the database async fn insert_library_changes( tx: &mut DatabaseTransaction, - last_inserted_date: &Option, + last_inserted_date: Option<&NaiveDate>, pub_collection_versions: Vec<&SimpleTerm<'_>>, pub_graph: &StelaeGraph, publication: &Publication, @@ -449,8 +457,12 @@ async fn insert_library_changes( url.clone(), publication.stele.clone(), )); - let pub_version_hash = - md5::compute(publication.name.clone() + &codified_date + &publication.stele); + let pub_version_hash = md5::compute(format!( + "{}{}{}", + publication.name.clone(), + &codified_date, + &publication.stele + )); library_changes_bulk.push(LibraryChange::new( pub_version_hash.clone(), library_status.to_int(), @@ -473,9 +485,12 @@ async fn insert_library_changes( continue; }; let status = Status::from_string(&found_status)?; - let document_change_hash = md5::compute( - pub_version_hash.clone() + &doc_mpath.clone() + &status.to_int().to_string(), - ); + let document_change_hash = md5::compute(format!( + "{}{}{}", + pub_version_hash.clone(), + &doc_mpath.clone(), + &status.to_int().to_string() + )); changed_library_document_bulk.push(ChangedLibraryDocument::new( document_change_hash, library_mpath.clone(), diff --git a/src/history/rdf/graph.rs b/src/history/rdf/graph.rs index 6f9e53e..99888f3 100644 --- a/src/history/rdf/graph.rs +++ b/src/history/rdf/graph.rs @@ -1,11 +1,18 @@ -#![allow( +#![expect( clippy::module_name_repetitions, + reason = "Call our graph `StelaeGraph`, which repeats the name graph, but is used to differentiate between our wrapper and the underlying sophia graph." +)] +#![expect( clippy::min_ident_chars, - clippy::pattern_type_mismatch + reason = "Nomenclature for RDF is `s`, `p, `o` instead of `subject`, `predicate`, `object`" +)] +#![expect( + clippy::pattern_type_mismatch, + reason = "Bypass sophia internal & ref match on SimpleTerm" )] /// The helper methods for working with RDF in Stelae. -use anyhow::Context; -use sophia::api::graph::{GTripleSource, Graph}; +use anyhow::Context as _; +use sophia::api::graph::{GTripleSource, Graph as _}; use sophia::api::ns::NsTerm; use sophia::api::MownStr; use sophia::api::{prelude::*, term::SimpleTerm}; @@ -94,7 +101,7 @@ impl StelaeGraph { subject: Option<&'graph SimpleTerm>, predicate: Option>, object: Option>, - ) -> anyhow::Result { + ) -> anyhow::Result> { let triple = self.get_next_triples_matching(subject, predicate, object)?; let SimpleTerm::Iri(iri) = &triple.o() else { anyhow::bail!("Expected literal language, got - {:?}", triple.o()); @@ -111,7 +118,7 @@ impl StelaeGraph { subject: Option<&'graph SimpleTerm>, predicate: Option>, object: Option>, - ) -> anyhow::Result<[&'graph SimpleTerm<'_>; 3]> { + ) -> anyhow::Result<[&'graph SimpleTerm<'graph>; 3]> { let triple = self .triples_matching_inner(subject, predicate, object) .next() @@ -151,7 +158,7 @@ impl StelaeGraph { subject: Option<&'graph SimpleTerm>, predicate: Option>, object: Option>, - ) -> anyhow::Result> { + ) -> anyhow::Result>> { let triples_iter = self.triples_matching_inner(subject, predicate, object); let iris = triples_iter .into_iter() @@ -184,10 +191,9 @@ impl Bag<'_> { /// /// # Errors /// Errors if the items are not found. - #[allow(clippy::separated_literal_suffix)] pub fn items(&self) -> anyhow::Result> { let container = &self.uri; - let mut i = 1_u32; + let mut i: u32 = 1; let mut items = vec![]; loop { let el_uri = format!("http://www.w3.org/1999/02/22-rdf-syntax-ns#_{i}"); diff --git a/src/lib.rs b/src/lib.rs index 6f55544..4ff00c3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -50,44 +50,77 @@ // > If you enable a restriction lint for your crate it is recommended to also fix code that // > this lint triggers on. However, those lints are really strict by design and you might want // > to #[allow] them in some special cases, with a comment justifying that. -#![allow(clippy::blanket_clippy_restriction_lints)] +#![allow( + clippy::blanket_clippy_restriction_lints, + reason = "See above explanation." +)] #![warn(clippy::restriction)] // // // ========================================================================= // Individually blanket-allow single lints relevant to this whole crate // ========================================================================= +#![allow(clippy::implicit_return, reason = "This is idiomatic Rust")] #![allow( - // This is idiomatic Rust - clippy::implicit_return, - - // Multiple deps are currently pinning `hermit-abi` — December 2022 clippy::multiple_crate_versions, - - // We're not interested in becoming no-std compatible + reason = "Multiple deps are currently pinning `hermit-abi` — December 2022" +)] +#![allow( clippy::std_instead_of_alloc, + reason = "We're not interested in becoming no-std compatible" +)] +#![allow( clippy::std_instead_of_core, - - // TODO: But I think the mod.rs is more conventional — @tombh + reason = "Import items from std instead of core" +)] +#![allow( clippy::mod_module_files, - - // Although performance is of course important for this application, it is not currently - // such that it would benefit from explicit inline suggestions. Besides, not specifying - // `#[inline]` doesn't mean that a function won't be inlined. And if performance does start - // to become a problem, there are other avenues to explore before deciding on which functions - // would benefit from explicit inlining. + reason = "TODO: But I think the mod.rs is more conventional — @tombh" +)] +#![allow( clippy::missing_inline_in_public_items, - - // I think marking `#[non_exhaustive]` is more for structs/enums that are imported into other crates + reason = " + Although performance is of course important for this application, it is not currently + such that it would benefit from explicit inline suggestions. Besides, not specifying + `#[inline]` doesn't mean that a function won't be inlined. And if performance does start + to become a problem, there are other avenues to explore before deciding on which functions + would benefit from explicit inlining +" +)] +#![allow( clippy::exhaustive_structs, + reason = "I think marking `#[non_exhaustive]` is more for structs/enums that are imported into other crates" +)] +#![allow( clippy::exhaustive_enums, + reason = "I think marking `#[non_exhaustive]` is more for structs/enums that are imported into other crates" +)] +#![allow( clippy::question_mark_used, + reason = "We rely on propagating errors with question mark extensively" +)] +#![allow( clippy::semicolon_outside_block, - // We tend to break up long functions into smaller ones, so this lint is not useful + reason = "Opt in to have semicolon in the outside block across codebase" +)] +#![allow( clippy::single_call_fn, + reason = "We tend to break up long functions into smaller ones, so this lint is not useful" +)] +#![allow( clippy::arithmetic_side_effects, - // We'll allow unimplemented! in code, but disallow todo! + reason = "Our arithmetic is very simple for now, so no side effects are expected at the time of writing this" +)] +#![allow( clippy::unimplemented, + reason = "We'll allow unimplemented! in code, but disallow todo!" +)] +#![allow( + clippy::renamed_function_params, + reason = " + Sometimes collides with `min_ident_chars`, in cases where trait params consist of a single char. + So we disallow single chars, and allow renamed_function_params. +" )] pub mod db; diff --git a/src/server/api/routes.rs b/src/server/api/routes.rs index b32a92c..41ea8c9 100644 --- a/src/server/api/routes.rs +++ b/src/server/api/routes.rs @@ -1,5 +1,8 @@ //! A central place to register App routes. -#![allow(clippy::exit)] +#![expect( + clippy::exit, + reason = "We exit with 1 error code on any application errors" +)] use std::{process, sync::OnceLock}; use crate::server::api::state; @@ -215,7 +218,10 @@ fn initialize_dynamic_routes< /// * `state` - The application state /// # Errors /// Will error if unable to register routes (e.g. if git repository cannot be opened) -#[allow(clippy::iter_over_hash_type)] +#[expect( + clippy::iter_over_hash_type, + reason = "List of repositories that are registered as routes are always sorted, even with iterating over hash type" +)] fn register_routes(cfg: &mut web::ServiceConfig, state: &T) -> anyhow::Result<()> { for stele in state.archive().stelae.values() { if let Some(repositories) = stele.repositories.as_ref() { diff --git a/src/server/api/serve/mod.rs b/src/server/api/serve/mod.rs index c32b36b..1b4d699 100644 --- a/src/server/api/serve/mod.rs +++ b/src/server/api/serve/mod.rs @@ -1,5 +1,4 @@ //! API endpoint for serving current documents from Stele repositories. -#![allow(clippy::infinite_loop)] use actix_web::{web, HttpRequest, HttpResponse, Responder}; use crate::{ @@ -12,7 +11,10 @@ use super::state::{RepoData as RepoState, Shared as SharedState}; const HEAD_COMMIT: &str = "HEAD"; /// Serve current document -#[allow(clippy::future_not_send)] +#[expect( + clippy::future_not_send, + reason = "We don't worry about git2-rs not implementing `Send` trait" +)] pub async fn serve( req: HttpRequest, shared: web::Data, @@ -39,7 +41,6 @@ pub async fn serve( /// Find the latest blob for the given path from the given repo /// Latest blob is found by looking at the HEAD commit -#[allow(clippy::panic_in_result_fn, clippy::unreachable)] #[tracing::instrument(name = "Finding document", skip(repo, shared))] fn find_current_blob( repo: &RepoState, diff --git a/src/server/api/state.rs b/src/server/api/state.rs index dd819af..172be04 100644 --- a/src/server/api/state.rs +++ b/src/server/api/state.rs @@ -98,7 +98,10 @@ impl fmt::Debug for Shared { } } -#[allow(clippy::missing_trait_methods)] +#[expect( + clippy::missing_trait_methods, + reason = "Use implicit trait implementation" +)] impl Clone for RepoData { fn clone(&self) -> Self { Self { @@ -111,7 +114,10 @@ impl Clone for RepoData { } } -#[allow(clippy::missing_trait_methods)] +#[expect( + clippy::missing_trait_methods, + reason = "Use implicit trait implementation" +)] impl Clone for Shared { fn clone(&self) -> Self { Self { diff --git a/src/server/api/versions/mod.rs b/src/server/api/versions/mod.rs index a26f148..74ab352 100644 --- a/src/server/api/versions/mod.rs +++ b/src/server/api/versions/mod.rs @@ -1,5 +1,8 @@ //! Handlers for serving historical documents. -#![allow(clippy::future_not_send)] +#![expect( + clippy::future_not_send, + reason = "We don't worry about git2-rs not implementing `Send` trait" +)] use actix_web::{web, HttpRequest, HttpResponse, Responder}; use chrono::NaiveDate; use std::convert::Into; @@ -18,7 +21,7 @@ use crate::{ use self::response::messages; -use super::state::{App as AppState, Global as GlobalState}; +use super::state::{App as AppState, Global as _}; /// Name of the current publication. pub const CURRENT_PUBLICATION_NAME: &str = "Current"; diff --git a/src/server/api/versions/response/messages.rs b/src/server/api/versions/response/messages.rs index 9788c35..9f93e58 100644 --- a/src/server/api/versions/response/messages.rs +++ b/src/server/api/versions/response/messages.rs @@ -44,7 +44,7 @@ pub fn historical( current_version, found_version_date, versions, - compare_to_date, + compare_to_date.as_ref(), ) }); let comparison = compare_to_date.as_ref().and_then(|found_compare_to_date| { @@ -90,7 +90,7 @@ fn version_message( current_version: &str, version_date: &str, versions: &[Version], - compare_to_date: &Option, + compare_to_date: Option<&String>, ) -> Option { let is_current_version = { let current_date = diff --git a/src/server/api/versions/response/mod.rs b/src/server/api/versions/response/mod.rs index 1d58e72..f64faea 100644 --- a/src/server/api/versions/response/mod.rs +++ b/src/server/api/versions/response/mod.rs @@ -88,7 +88,10 @@ impl From for Version { impl Versions { /// Build and returns an HTTP versions response converted into json. - #[allow(clippy::too_many_arguments)] + #[expect( + clippy::too_many_arguments, + reason = "Basically a model mapper for returning a `Versions` instance, can get simplified in the future. Leave it with too many args for now." + )] #[must_use] pub fn build( active_publication_name: &str, diff --git a/src/server/app.rs b/src/server/app.rs index cbbbfbc..0acf600 100644 --- a/src/server/app.rs +++ b/src/server/app.rs @@ -1,9 +1,7 @@ //! Serve documents in a Stelae archive. -#![allow( +#![expect( clippy::exit, - clippy::unused_async, - clippy::infinite_loop, - clippy::module_name_repetitions + reason = "We exit with 1 error code on any application errors" )] use crate::db; use crate::server::api::state::App as AppState; @@ -58,7 +56,7 @@ pub async fn serve_archive( let state = AppState { archive, db }; HttpServer::new(move || { - init_app(&state).unwrap_or_else(|err| { + init(&state).unwrap_or_else(|err| { tracing::error!("Unable to initialize app."); tracing::error!("Error: {err:?}"); // NOTE: We should not need to exit code 1 here (or in any of the closures in `routes.rs`). @@ -84,7 +82,7 @@ pub async fn serve_archive( /// * `state` - The application state /// # Errors /// Will error if unable to initialize the application -pub fn init_app( +pub fn init( state: &T, ) -> anyhow::Result< App< diff --git a/src/server/errors.rs b/src/server/errors.rs index 0cbf697..8fd2d55 100644 --- a/src/server/errors.rs +++ b/src/server/errors.rs @@ -1,11 +1,10 @@ -#![allow( - // derive_more doesn't respect these lints +//! Stelae-specific errors + +#![expect( clippy::pattern_type_mismatch, - clippy::use_self + reason = "derive_more doesn't respect these lints" )] -//! Stelae-specific errors - use actix_web::{error, http::StatusCode, HttpResponse}; use derive_more::{Display, Error}; use std::io; @@ -37,7 +36,7 @@ pub enum CliError { impl From for CliError { fn from(_error: io::Error) -> Self { - CliError::GenericError + Self::GenericError } } @@ -49,7 +48,7 @@ pub enum StelaeError { GitError, } -#[allow(clippy::missing_trait_methods)] +#[expect(clippy::missing_trait_methods, reason = "Use implicit implementation")] impl error::ResponseError for StelaeError { fn error_response(&self) -> HttpResponse { HttpResponse::build(self.status_code()).body(self.to_string()) diff --git a/src/server/git.rs b/src/server/git.rs index b4369d0..992f835 100644 --- a/src/server/git.rs +++ b/src/server/git.rs @@ -1,14 +1,5 @@ //! Legacy git microserver. -#![allow( - // Unused asyncs are the norm in Actix route definition files - clippy::unused_async, - clippy::unreachable, - clippy::let_with_type_underscore, - // Clippy wrongly detects the `infinite_loop` lint on functions with tracing::instrument! - clippy::infinite_loop -)] - use actix_web::{get, route, web, App, HttpResponse, HttpServer, Responder}; use git2::{self, ErrorCode}; use std::path::PathBuf; @@ -65,7 +56,10 @@ async fn get_blob( } /// A centralised place to match potentially unsafe internal errors to safe user-facing error responses -#[allow(clippy::wildcard_enum_match_arm)] +#[expect( + clippy::wildcard_enum_match_arm, + reason = "Default to wildcard match in case of unexpected errors" +)] #[tracing::instrument(name = "Error with Git blob request", skip(error, namespace, name))] fn blob_error_response(error: &anyhow::Error, namespace: &str, name: &str) -> HttpResponse { tracing::error!("{error}",); diff --git a/src/server/tracing.rs b/src/server/tracing.rs index 66233d6..ab31ed4 100644 --- a/src/server/tracing.rs +++ b/src/server/tracing.rs @@ -5,7 +5,7 @@ use std::time::Instant; use actix_web::{ body::MessageBody, dev::{ServiceRequest, ServiceResponse}, - HttpMessage, + HttpMessage as _, }; use tracing_actix_web::{DefaultRootSpanBuilder, RootSpanBuilder}; diff --git a/src/stelae/stele.rs b/src/stelae/stele.rs index f6f0265..328e556 100644 --- a/src/stelae/stele.rs +++ b/src/stelae/stele.rs @@ -8,7 +8,7 @@ use crate::{ stelae::types::{dependencies::Dependencies, repositories::Repositories}, utils::git::Repo, }; -use anyhow::Context; +use anyhow::Context as _; use git2::Repository as GitRepository; use serde_derive::{Deserialize, Serialize}; use serde_json; @@ -32,7 +32,7 @@ impl Stele { /// Will error if unable to find or parse repositories file at `targets/repositories.json` /// # Panics /// Will panic if unable to determine the current root Stele. - #[allow(clippy::shadow_reuse)] + #[expect(clippy::shadow_reuse, reason = "Use same param as field name")] pub fn new( archive_path: &Path, name: Option, diff --git a/src/stelae/types/repositories.rs b/src/stelae/types/repositories.rs index c40ec84..bec8d3a 100644 --- a/src/stelae/types/repositories.rs +++ b/src/stelae/types/repositories.rs @@ -121,7 +121,10 @@ impl Repositories { /// /// This is needed for serving current documents because Actix routes are matched in the order they are added. #[must_use] - #[allow(clippy::iter_over_hash_type)] + #[expect( + clippy::iter_over_hash_type, + reason = "Returns sorted repositories, even with iterating over hash type" + )] pub fn get_sorted(&self) -> Vec<&Repository> { let mut result = Vec::new(); for repository in self.repositories.values() { @@ -199,7 +202,10 @@ impl Repositories { } } -#[allow(clippy::missing_trait_methods)] +#[expect( + clippy::missing_trait_methods, + reason = "Use serde default trait implementations" +)] impl<'de> Deserialize<'de> for Repositories { fn deserialize(deserializer: D) -> Result where diff --git a/src/utils/archive.rs b/src/utils/archive.rs index 653193f..8f2de98 100644 --- a/src/utils/archive.rs +++ b/src/utils/archive.rs @@ -1,7 +1,7 @@ //! The archive module contains structs for interacting with a Stele archive use super::paths::fix_unc_path; -use anyhow::Context; +use anyhow::Context as _; use std::path::{Path, PathBuf}; /// given a &Path `path`, return the path to the containing archive. diff --git a/src/utils/cli.rs b/src/utils/cli.rs index e1fae7a..1333d5f 100644 --- a/src/utils/cli.rs +++ b/src/utils/cli.rs @@ -1,7 +1,8 @@ //! Running the CLI - -// Allow exits because in this file we ideally handle all errors with known exit codes -#![allow(clippy::exit)] +#![expect( + clippy::exit, + reason = "Allow exits because in this file we ideally handle all errors with known exit codes" +)] use crate::history::changes; use crate::server::app::serve_archive; @@ -17,9 +18,11 @@ use tracing; use tracing::Level; use tracing_appender::rolling; use tracing_subscriber::fmt; -use tracing_subscriber::fmt::writer::MakeWriterExt; -use tracing_subscriber::Layer; -use tracing_subscriber::{filter::EnvFilter, layer::SubscriberExt, util::SubscriberInitExt}; +use tracing_subscriber::fmt::writer::MakeWriterExt as _; +use tracing_subscriber::Layer as _; +use tracing_subscriber::{ + filter::EnvFilter, layer::SubscriberExt as _, util::SubscriberInitExt as _, +}; /// Stelae is currently just a simple git server. /// run from the library directory or pass @@ -69,7 +72,10 @@ enum Subcommands { /// `debug` log file contains all logs, `error` log file contains only `warn` and `error` /// NOTE: once `https://github.com/tokio-rs/tracing/pull/2497` is merged, /// update `init_tracing` to rotate log files based on size. -#[allow(clippy::expect_used)] +#[expect( + clippy::expect_used, + reason = "Expect that console logging can be initialized" +)] fn init_tracing(archive_path: &Path) { let taf_dir = archive_path.join(PathBuf::from("./.taf")); diff --git a/src/utils/git.rs b/src/utils/git.rs index eb703fe..4f2efbb 100644 --- a/src/utils/git.rs +++ b/src/utils/git.rs @@ -1,7 +1,7 @@ //! The git module contains structs for interacting with git repositories //! in the Stelae Archive. use crate::utils::paths::clean_path; -use anyhow::Context; +use anyhow::Context as _; use git2::{Commit, Repository, Sort}; use std::{ fmt, @@ -37,7 +37,11 @@ impl fmt::Debug for Repo { } } -#[allow(clippy::missing_trait_methods, clippy::unwrap_used)] +#[expect( + clippy::missing_trait_methods, + clippy::unwrap_used, + reason = "Expect to have git repo on disk" +)] impl Clone for Repo { fn clone(&self) -> Self { Self { diff --git a/src/utils/http.rs b/src/utils/http.rs index 7e5e7fa..7a9fa14 100644 --- a/src/utils/http.rs +++ b/src/utils/http.rs @@ -5,7 +5,9 @@ use actix_web::http::header::ContentType; use std::path::Path; /// `get_contenttype` uses the file extension to return the `ContentType` -/// for the content at `path`. If there is no extension, we assume it is +/// for the content at `path`. +/// +/// If there is no extension, we assume it is /// html. If the extension cannot be converted to a str, then we return /// HTML. /// Some browsers will not render `application/rdf+xml`, but instead will diff --git a/src/utils/md5.rs b/src/utils/md5.rs index 5221183..535cbb6 100644 --- a/src/utils/md5.rs +++ b/src/utils/md5.rs @@ -1,5 +1,5 @@ //! Utility functions for `md5` hash computation. -use md5::{Digest, Md5}; +use md5::{Digest as _, Md5}; /// Compute the `md5` hash of a string. /// diff --git a/src/utils/paths.rs b/src/utils/paths.rs index 51b749c..64f2868 100644 --- a/src/utils/paths.rs +++ b/src/utils/paths.rs @@ -15,7 +15,7 @@ pub fn fix_unc_path(absolute_path: &Path) -> PathBuf { absolute_path.to_path_buf() } -#[allow(clippy::expect_used)] +#[expect(clippy::expect_used, reason = "Expect to compile regex")] #[must_use] /// Remove leading and trailing `/`s from the `path` string. pub fn clean_path(path: &str) -> String { diff --git a/tests/common/mod.rs b/tests/common/mod.rs index 64af1ff..34b113b 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -16,7 +16,7 @@ static INIT: Once = Once::new(); use actix_http::body::MessageBody; -use stelae::server::app::init_app; +use stelae::server::app; use stelae::stelae::archive::Archive; pub const BASIC_MODULE_NAME: &str = "basic"; @@ -51,7 +51,7 @@ pub async fn initialize_app( ) -> impl Service, Error = Error> { let archive = Archive::parse(archive_path.to_path_buf(), archive_path, false).unwrap(); let state = TestAppState { archive }; - let app = init_app(&state).unwrap(); + let app = app::init(&state).unwrap(); test::init_service(app).await }