Skip to main content

selene_core/library/
clean.rs

1use std::sync::Arc;
2
3use barber::{ProgressBar, ProgressRenderer};
4use lunar_lib::database::{Database, DbHandle, TransactionError, db_transaction};
5use thiserror::Error;
6
7use crate::{
8    database::LibraryDb,
9    library::{hash_source_files, track::Track},
10};
11
12#[derive(Debug, Error)]
13pub enum OrphanRelinkError {
14    #[error("IoError: {0}")]
15    Io(#[from] std::io::Error),
16
17    #[error("Transaction Error: {0}")]
18    Transaction(#[from] TransactionError),
19}
20
21pub fn relink_orphans(
22    mut check_tracks: Vec<Track>,
23    progress_renderer: Arc<dyn ProgressRenderer>,
24) -> Result<(), OrphanRelinkError> {
25    if check_tracks.is_empty() {
26        return Ok(());
27    }
28
29    let sources = hash_source_files(progress_renderer.clone())?;
30
31    check_tracks.retain(|t| {
32        let expected_source = t.container().path();
33        !expected_source.exists() || sources.get(&t.id()).is_some_and(|t| t != expected_source)
34    });
35
36    let progress_bar = ProgressBar::new(0, check_tracks.len(), progress_renderer);
37    progress_bar.set_label("Relinking orphaned sources...");
38
39    let db = DbHandle::<LibraryDb>::open().unwrap();
40    for mut track in check_tracks {
41        if let Some(source) = sources.get(&track.id()) {
42            track.set_source_file(source.to_owned());
43
44            db_transaction(
45                |cas_tx| cas_tx.tx_upsert(track.clone()).map_err(Into::into),
46                db.clone(),
47                false,
48            )
49            .map_err(TransactionError::from)?;
50
51            progress_bar.set_label(&format!(
52                "Relinked {} to {}",
53                track.metadata.safe_title(),
54                source.display()
55            ));
56        } else {
57            db.db()
58                .remove(*track.id())
59                .map_err(TransactionError::Sled)?;
60
61            progress_bar.set_label(&format!(
62                "Failed to relink {}: No source found. Removing from library",
63                track.metadata.safe_title()
64            ));
65        }
66
67        progress_bar.increment();
68    }
69    progress_bar.flush();
70    Ok(())
71}