merge: clear the clippy backlog and unify lock helpers (D1-warnings, D3)

51 clippy warnings -> 0, with 8 justified #[allow]s (IPC arity, specta wire
types, and the 9 test-only await-holding-lock sites). 27 raw lock calls moved to
the poison-tolerant helpers - all of them test code; production was already
clean.

Caught a non-neutral clippy --fix: removing the redundant 'use hostname;' in
credentials.rs orphaned its #[cfg(target_os = "linux")] onto SERVICE_NAME,
which would have cfg'd the constant out of every non-Linux build. Compiles clean
on Linux, so only Windows/macOS CI would have caught it.
This commit is contained in:
2026-08-16 23:06:33 +02:00
27 changed files with 173 additions and 109 deletions
+22 -22
View File
@@ -990,7 +990,7 @@ struct JellyfinMediaSource {
}
impl JellyfinItem {
fn to_media_item(self, server_id: String) -> MediaItem {
fn into_media_item(self, server_id: String) -> MediaItem {
// Extract image tags before consuming self
let primary_tag = self.image_tags.as_ref().and_then(|tags| tags.primary());
let backdrop_tags = self.backdrop_image_tags;
@@ -1129,7 +1129,7 @@ impl MediaRepository for OnlineRepository {
items: response
.items
.into_iter()
.map(|item| item.to_media_item(self.user_id.clone()))
.map(|item| item.into_media_item(self.user_id.clone()))
.collect(),
total_record_count: response.total_record_count,
})
@@ -1150,7 +1150,7 @@ impl MediaRepository for OnlineRepository {
let endpoint = format!("/Users/{}/Items/{}?Fields=BackdropImageTags,ParentBackdropImageTags,People,MediaStreams,MediaSources,PremiereDate,UserData", self.user_id, item_id);
let item: JellyfinItem = self.get_json(&endpoint).await?;
let media_item = item.to_media_item(self.user_id.clone());
let media_item = item.into_media_item(self.user_id.clone());
Ok(media_item)
}
@@ -1165,7 +1165,7 @@ impl MediaRepository for OnlineRepository {
let items: Vec<JellyfinItem> = self.get_json(&endpoint).await?;
Ok(items
.into_iter()
.map(|item| item.to_media_item(self.user_id.clone()))
.map(|item| item.into_media_item(self.user_id.clone()))
.collect())
}
@@ -1196,7 +1196,7 @@ impl MediaRepository for OnlineRepository {
Ok(response
.items
.into_iter()
.map(|item| item.to_media_item(self.user_id.clone()))
.map(|item| item.into_media_item(self.user_id.clone()))
.collect())
}
@@ -1215,7 +1215,7 @@ impl MediaRepository for OnlineRepository {
Ok(response
.items
.into_iter()
.map(|item| item.to_media_item(self.user_id.clone()))
.map(|item| item.into_media_item(self.user_id.clone()))
.collect())
}
@@ -1235,7 +1235,7 @@ impl MediaRepository for OnlineRepository {
let items: Vec<MediaItem> = response
.items
.into_iter()
.map(|item| item.to_media_item(self.user_id.clone()))
.map(|item| item.into_media_item(self.user_id.clone()))
.collect();
debug!("[get_recently_played_audio] Fetched {} items", items.len());
@@ -1258,7 +1258,7 @@ impl MediaRepository for OnlineRepository {
"[get_recently_played_audio] Grouping item '{}' into album '{}'",
item.name, key
);
album_map.entry(key).or_insert_with(Vec::new).push(item);
album_map.entry(key).or_default().push(item);
} else {
debug!(
"[get_recently_played_audio] No album_id or album_name for item: '{}'",
@@ -1373,7 +1373,7 @@ impl MediaRepository for OnlineRepository {
Ok(response
.items
.into_iter()
.map(|item| item.to_media_item(self.user_id.clone()))
.map(|item| item.into_media_item(self.user_id.clone()))
.collect())
}
@@ -1393,7 +1393,7 @@ impl MediaRepository for OnlineRepository {
Ok(response
.items
.into_iter()
.map(|item| item.to_media_item(self.user_id.clone()))
.map(|item| item.into_media_item(self.user_id.clone()))
.collect())
}
@@ -1503,7 +1503,7 @@ impl MediaRepository for OnlineRepository {
items: response
.items
.into_iter()
.map(|item| item.to_media_item(self.user_id.clone()))
.map(|item| item.into_media_item(self.user_id.clone()))
.collect(),
total_record_count: response.total_record_count,
})
@@ -1881,7 +1881,7 @@ impl MediaRepository for OnlineRepository {
Ok(response
.items
.into_iter()
.map(|item| item.to_media_item(self.server_url.clone()))
.map(|item| item.into_media_item(self.server_url.clone()))
.collect())
}
@@ -1894,7 +1894,7 @@ impl MediaRepository for OnlineRepository {
let items = response
.items
.into_iter()
.map(|item| item.to_media_item(self.server_url.clone()))
.map(|item| item.into_media_item(self.server_url.clone()))
.collect();
Ok(SearchResult {
items,
@@ -2231,7 +2231,7 @@ impl MediaRepository for OnlineRepository {
items: response
.items
.into_iter()
.map(|item| item.to_media_item(self.user_id.clone()))
.map(|item| item.into_media_item(self.user_id.clone()))
.collect(),
total_record_count: response.total_record_count,
})
@@ -2374,7 +2374,7 @@ impl MediaRepository for OnlineRepository {
async fn get_person(&self, person_id: &str) -> Result<MediaItem, RepoError> {
let endpoint = format!("/Users/{}/Items/{}", self.user_id, person_id);
let item: JellyfinItem = self.get_json(&endpoint).await?;
Ok(item.to_media_item(self.user_id.clone()))
Ok(item.into_media_item(self.user_id.clone()))
}
/// A person's filmography — every item they are credited on.
@@ -2407,7 +2407,7 @@ impl MediaRepository for OnlineRepository {
items: response
.items
.into_iter()
.map(|item| item.to_media_item(self.user_id.clone()))
.map(|item| item.into_media_item(self.user_id.clone()))
.collect(),
total_record_count: response.total_record_count,
})
@@ -2431,7 +2431,7 @@ impl MediaRepository for OnlineRepository {
items: response
.items
.into_iter()
.map(|item| item.to_media_item(self.user_id.clone()))
.map(|item| item.into_media_item(self.user_id.clone()))
.collect(),
total_record_count: response.total_record_count,
})
@@ -2519,7 +2519,7 @@ impl MediaRepository for OnlineRepository {
.into_iter()
.map(|pi| PlaylistEntry {
playlist_item_id: pi.playlist_item_id,
item: pi.item.to_media_item(self.user_id.clone()),
item: pi.item.into_media_item(self.user_id.clone()),
})
.collect())
}
@@ -3017,7 +3017,7 @@ mod tests {
}))
.expect("fixture must deserialize");
let streams = item.to_media_item("server-1".to_string()).media_streams;
let streams = item.into_media_item("server-1".to_string()).media_streams;
let streams = streams.expect("the item carries streams");
let deliverable = |index: i32| {
streams
@@ -3612,7 +3612,7 @@ mod tests {
}"#;
let item: JellyfinItem = serde_json::from_str(json).expect("item should deserialize");
let media = item.to_media_item("server1".to_string());
let media = item.into_media_item("server1".to_string());
let user_data = media.user_data.expect("user data should be mapped");
assert_eq!(user_data.is_favorite, Some(true));
@@ -3632,7 +3632,7 @@ mod tests {
let json = r#"{"Id": "x", "Name": "No User Data", "Type": "Movie"}"#;
let item: JellyfinItem = serde_json::from_str(json).expect("item should deserialize");
let media = item.to_media_item("server1".to_string());
let media = item.into_media_item("server1".to_string());
assert!(media.user_data.is_none());
}
@@ -3676,7 +3676,7 @@ mod tests {
}"#;
let jellyfin_item: JellyfinItem = serde_json::from_str(json).expect("Failed to parse");
let media_item = jellyfin_item.to_media_item("test-server-id".to_string());
let media_item = jellyfin_item.into_media_item("test-server-id".to_string());
assert_eq!(media_item.id, "album456");
assert_eq!(media_item.name, "Love and Theft");