use std::{collections::HashMap, fs, io, path::PathBuf, sync::Arc};
use barber::{ProgressBar, ProgressRenderer};
use lunar_lib::database::{Database, DatabaseEntry, DatabaseError};
use crate::{
database::LibraryDb,
errors::OrphanRelinkError,
library::track::{Track, TrackId},
};
pub fn relink_orphans(
check_tracks: &mut [Track],
progress_renderer: Arc<dyn ProgressRenderer>,
sources: &HashMap<TrackId, PathBuf>,
) -> Result<(), OrphanRelinkError> {
let orphaned_tracks: Vec<&mut Track> = check_tracks
.iter_mut()
.filter(|t| !t.container().path().exists())
.collect();
if orphaned_tracks.is_empty() {
return Ok(());
}
let progress_bar = ProgressBar::new(0, orphaned_tracks.len(), progress_renderer);
progress_bar.set_label("Relinking orphaned sources...");
for track in orphaned_tracks {
if let Some(source) = sources.get(&track.id()) {
track.set_source_file(source.to_owned());
track.db_upsert()?;
progress_bar.set_label(&format!(
"Succesfully relinked {}",
track.metadata.safe_title()
));
} else {
if let Err(err) = fs::remove_file(track.container().path())
&& !matches!(err.kind(), io::ErrorKind::NotFound)
{
return Err(err.into());
}
let db = LibraryDb::open()?;
db.remove(*track.id()).map_err(DatabaseError::Sled)?;
progress_bar.set_label(&format!(
"Failed to relink {}: No source found. Removing from library",
track.metadata.safe_title()
));
}
progress_bar.increment();
}
progress_bar.flush();
Ok(())
}