use std::{collections::HashMap, fs, io, path::PathBuf, sync::Arc};
use barber::{ProgressBar, ProgressRenderer};
use crate::{
database::{DatabaseEntry, DatabaseError, library_db, sled_clear},
library::track::{Track, TrackId},
};
pub fn relink_orphans(
check_tracks: &mut [Track],
progress_renderer: Arc<dyn ProgressRenderer>,
sources: &HashMap<TrackId, PathBuf>,
) -> Result<(), DatabaseError> {
let orphaned_tracks: Vec<&mut Track> = check_tracks
.iter_mut()
.filter(|t| !t.src_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.relative_library_path.display()
));
} else {
if let Some(lib_container) = track.lib_container()
&& let Err(err) = fs::remove_file(lib_container.path())
&& !matches!(err.kind(), io::ErrorKind::NotFound)
{
return Err(err.into());
}
sled_clear(&Track::tree(&library_db()), track.id().as_bytes())
.map_err(DatabaseError::Sled)?;
progress_bar.set_label(&format!(
"Failed to relink {}: No source found. Removing from library",
track.relative_library_path.display(),
));
}
progress_bar.increment();
}
progress_bar.flush();
Ok(())
}