From 55434859767cdedcd7468a8a13e70ca0cb84982a Mon Sep 17 00:00:00 2001 From: Breadway Date: Thu, 6 Aug 2026 08:51:07 +0800 Subject: [PATCH] Fix all cargo clippy warnings across the workspace Removes genuinely dead code (unused import, no-op cast, an unused PendingGrab accessor, and TmdbClient's TV-search methods now that TVDB fully covers that path), tightens len()>0 checks to is_empty(), swaps two fixed-size test vec!s for arrays, restructures a match to avoid an unnecessary unwrap_err, fixes doc-comment list indentation, and hoists a locked-connection call out of a match scrutinee. Struct fields/enum variants that are still meaningful but not read by current callers (TorrentInfo::save_path, GrabCycleStats::items_seen, X1337 fallback route, BacklogCandidate::path) get #[allow(dead_code)] rather than deletion, same for the two 8-argument functions (too_many_arguments). --- breadarr-tui/src/app.rs | 2 +- breadarrd/src/importer/mod.rs | 14 ++---- breadarrd/src/main.rs | 5 ++- breadarrd/src/metadata/mod.rs | 1 + breadarrd/src/metadata/tmdb.rs | 82 +--------------------------------- breadarrd/src/notify.rs | 1 - breadarrd/src/qbit/mod.rs | 3 ++ breadarrd/src/scheduler.rs | 25 ++++++----- breadarrd/src/transcode/mod.rs | 5 +++ 9 files changed, 32 insertions(+), 106 deletions(-) diff --git a/breadarr-tui/src/app.rs b/breadarr-tui/src/app.rs index 046bf33..823535a 100644 --- a/breadarr-tui/src/app.rs +++ b/breadarr-tui/src/app.rs @@ -598,7 +598,7 @@ impl App { return; }; let (media_item_id, season_number, monitored) = - (detail.id, episode.season_number as i64, episode.monitored); + (detail.id, episode.season_number, episode.monitored); let result = if monitored { self.client .unmonitor_season(media_item_id, season_number) diff --git a/breadarrd/src/importer/mod.rs b/breadarrd/src/importer/mod.rs index 24768e4..d2ceded 100644 --- a/breadarrd/src/importer/mod.rs +++ b/breadarrd/src/importer/mod.rs @@ -99,14 +99,6 @@ impl PendingGrab { PendingGrab::Movie { .. } | PendingGrab::SeasonPack { .. } => None, } } - - fn root_folder(&self) -> &str { - match self { - PendingGrab::Episode { root_folder, .. } - | PendingGrab::Movie { root_folder, .. } - | PendingGrab::SeasonPack { root_folder, .. } => root_folder, - } - } } /// Three separate queries (rather than one `LEFT JOIN episode`) because a @@ -1615,7 +1607,7 @@ impl StaleFile { /// later step (free-space check, the actual move) fails, so a failed /// import never leaves neither the old file nor the new one behind. fn restore(&self) { - if self.parked_at.as_os_str().len() > 0 { + if !self.parked_at.as_os_str().is_empty() { std::fs::rename(&self.parked_at, &self.restore_to).ok(); } } @@ -1909,7 +1901,7 @@ fn import_one( if let Some(row_id) = stale.row_id { conn.execute("DELETE FROM episode_file WHERE id = ?1", params![row_id])?; } - if stale.parked_at.as_os_str().len() > 0 { + if !stale.parked_at.as_os_str().is_empty() { std::fs::remove_file(&stale.parked_at).ok(); } } @@ -2309,7 +2301,7 @@ fn import_season_pack_file( if let Some(row_id) = stale.row_id { conn.execute("DELETE FROM episode_file WHERE id = ?1", params![row_id])?; } - if stale.parked_at.as_os_str().len() > 0 { + if !stale.parked_at.as_os_str().is_empty() { std::fs::remove_file(&stale.parked_at).ok(); } } diff --git a/breadarrd/src/main.rs b/breadarrd/src/main.rs index 2dc933c..5483aa9 100644 --- a/breadarrd/src/main.rs +++ b/breadarrd/src/main.rs @@ -633,10 +633,11 @@ async fn background_loop( // repaired (a rename or an in-place transcode) gets re-probed // immediately rather than waiting for its own turn a full // interval later. - match { + let probe_result = { let conn = conn.lock().await; importer::probe_library(&conn) - } { + }; + match probe_result { Ok(report) if report.probed > 0 || report.failed > 0 => { info!(?report, "media probe sweep complete"); } diff --git a/breadarrd/src/metadata/mod.rs b/breadarrd/src/metadata/mod.rs index 788a584..0765f52 100644 --- a/breadarrd/src/metadata/mod.rs +++ b/breadarrd/src/metadata/mod.rs @@ -41,6 +41,7 @@ pub struct EpisodeInfo { /// `MutexGuard` across an `.await` point — this convenience wrapper is only /// safe for callers with an owned, unshared `Connection` (e.g. the debug /// CLI commands). +#[allow(clippy::too_many_arguments)] pub async fn add_series( conn: &Connection, tvdb: &tvdb::TvdbClient, diff --git a/breadarrd/src/metadata/tmdb.rs b/breadarrd/src/metadata/tmdb.rs index f5bc496..43e2af6 100644 --- a/breadarrd/src/metadata/tmdb.rs +++ b/breadarrd/src/metadata/tmdb.rs @@ -1,7 +1,7 @@ use anyhow::{Context, Result}; use serde::Deserialize; -use super::{EpisodeInfo, MovieSearchResult, SeriesSearchResult}; +use super::MovieSearchResult; pub struct TmdbClient { bearer_token: String, @@ -22,44 +22,6 @@ impl TmdbClient { } } - pub async fn search_tv(&self, query: &str) -> Result> { - #[derive(Deserialize)] - struct SearchResponse { - results: Vec, - } - #[derive(Deserialize)] - struct TvItem { - id: u64, - name: String, - first_air_date: Option, - } - - let resp: SearchResponse = self - .client - .get("https://api.themoviedb.org/3/search/tv") - .bearer_auth(&self.bearer_token) - .query(&[("query", query)]) - .send() - .await - .context("tmdb tv search request failed")? - .error_for_status() - .context("tmdb tv search returned an error status")? - .json() - .await - .context("tmdb tv search response was not valid JSON")?; - - Ok(resp - .results - .into_iter() - .map(|item| SeriesSearchResult { - external_id: item.id.to_string(), - name: item.name, - year: year_from_date(item.first_air_date.as_deref()), - aliases: Vec::new(), - }) - .collect()) - } - pub async fn search_movie(&self, query: &str) -> Result> { #[derive(Deserialize)] struct SearchResponse { @@ -96,48 +58,6 @@ impl TmdbClient { }) .collect()) } - - pub async fn tv_season_episodes(&self, tv_id: u64, season: u32) -> Result> { - #[derive(Deserialize)] - struct SeasonResponse { - #[serde(default)] - episodes: Vec, - } - #[derive(Deserialize)] - struct EpisodeItem { - season_number: u32, - episode_number: u32, - name: Option, - air_date: Option, - } - - let resp: SeasonResponse = self - .client - .get(format!( - "https://api.themoviedb.org/3/tv/{tv_id}/season/{season}" - )) - .bearer_auth(&self.bearer_token) - .send() - .await - .context("tmdb season request failed")? - .error_for_status() - .context("tmdb season returned an error status")? - .json() - .await - .context("tmdb season response was not valid JSON")?; - - Ok(resp - .episodes - .into_iter() - .map(|e| EpisodeInfo { - season_number: e.season_number, - episode_number: e.episode_number, - absolute_number: None, - title: e.name, - air_date: e.air_date, - }) - .collect()) - } } fn year_from_date(date: Option<&str>) -> Option { diff --git a/breadarrd/src/notify.rs b/breadarrd/src/notify.rs index 470d0d7..a3c2b59 100644 --- a/breadarrd/src/notify.rs +++ b/breadarrd/src/notify.rs @@ -1,4 +1,3 @@ -use anyhow::Result; use serde::Serialize; #[derive(Serialize)] diff --git a/breadarrd/src/qbit/mod.rs b/breadarrd/src/qbit/mod.rs index 89ac2d9..ec9af4b 100644 --- a/breadarrd/src/qbit/mod.rs +++ b/breadarrd/src/qbit/mod.rs @@ -69,6 +69,9 @@ pub struct TorrentInfo { pub name: String, pub state: String, pub progress: f64, + // Not read internally today, but kept to mirror qBittorrent's actual API + // shape 1:1 — useful in `{:?}` debug logging and cheap to keep in sync. + #[allow(dead_code)] pub save_path: String, /// Full path to the torrent's content (file or directory root) — /// qBittorrent resolves this for us, so importers don't need to guess diff --git a/breadarrd/src/scheduler.rs b/breadarrd/src/scheduler.rs index 37deb68..9cd10a7 100644 --- a/breadarrd/src/scheduler.rs +++ b/breadarrd/src/scheduler.rs @@ -752,6 +752,10 @@ async fn grab_and_capture_hash( #[derive(Debug, Default)] pub struct GrabCycleStats { + // Only read via the derived `Debug` (the debug-grab-cycle CLI command + // prints the whole struct), which clippy's dead-code analysis doesn't + // credit as a read. + #[allow(dead_code)] pub items_seen: usize, pub new_items: usize, pub grabbed: usize, @@ -840,8 +844,8 @@ pub async fn run_grab_cycle( /// outright (TLS/connection error, not a slow response). Also /// Cloudflare-fronted, so even if connectivity is restored it carries the /// same risk profile 1337x does. -/// If revisiting either, re-verify connectivity first — this isn't a -/// permanent architectural decision, just what was true when checked. +/// If revisiting either, re-verify connectivity first — this isn't a +/// permanent architectural decision, just what was true when checked. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] enum SearchRoute { /// Primary general-content (movies + non-anime TV) route — a JSON API, @@ -851,6 +855,7 @@ enum SearchRoute { /// (not just "no relevant results") — the mirror-rotation/cooldown /// machinery already built for it is real resilience worth keeping, /// just no longer the first choice given TPB's better precision. + #[allow(dead_code)] X1337, NyaaSearch, } @@ -1658,17 +1663,17 @@ pub async fn execute_search_targets( // with, since dedup (`is_seen`/`mark_seen`) and grab records // are keyed by source id — attributing a 1337x-sourced guid to // TPB's source id would silently break dedup between the two. - let (fetch_result, result_source_id) = - if primary_result.is_err() && matches!(target.route, SearchRoute::Tpb) { + let (fetch_result, result_source_id) = match primary_result { + Err(e) if matches!(target.route, SearchRoute::Tpb) => { tracing::warn!( query = %target.query, - error = %primary_result.as_ref().unwrap_err(), + error = %e, "TPB search failed, falling back to 1337x" ); (scrape.fetch(Some(&target.query)).await, scrape_source_id) - } else { - (primary_result, primary_id) - }; + } + other => (other, primary_id), + }; match fetch_result { Ok(items) => { @@ -2821,7 +2826,7 @@ mod tests { seeders: Some(500), leechers: None, }; - let mut items = vec![episode.clone(), pack.clone()]; + let mut items = [episode.clone(), pack.clone()]; items.sort_by_key(release_sort_key); assert_eq!(items[0].guid, "pack"); assert_eq!(items[1].guid, "episode"); @@ -2845,7 +2850,7 @@ mod tests { seeders: Some(50), leechers: None, }; - let mut items = vec![low.clone(), high.clone()]; + let mut items = [low.clone(), high.clone()]; items.sort_by_key(release_sort_key); assert_eq!(items[0].guid, "high"); assert_eq!(items[1].guid, "low"); diff --git a/breadarrd/src/transcode/mod.rs b/breadarrd/src/transcode/mod.rs index a31c2b1..ad2df9b 100644 --- a/breadarrd/src/transcode/mod.rs +++ b/breadarrd/src/transcode/mod.rs @@ -337,6 +337,7 @@ enum EncodeOutcome { /// original on most of a real backfill — regardless of how well-tuned the /// rate control is, this is what makes "never keep a non-improvement" true /// unconditionally. +#[allow(clippy::too_many_arguments)] fn encode_and_verify( input: PathBuf, job_id: i64, @@ -726,6 +727,10 @@ pub fn find_oversized_av1_candidates(conn: &Connection, cfg: &TranscodeConfig) - pub struct BacklogCandidate { pub episode_file_id: i64, + // Not read by current callers (they only need episode_file_id to look up + // the row again), but cheap to carry along for future logging/debugging + // of which file a candidate refers to. + #[allow(dead_code)] pub path: String, pub size_bytes: i64, pub video_codec: Option,