Added merge
All checks were successful
Publish Metadata Agent Image / build-and-push-image (push) Successful in 1m7s
Publish Web Player Image / build-and-push-image (push) Successful in 1m11s
Publish Server Image / build-and-push-image (push) Successful in 2m14s

This commit is contained in:
2026-03-19 00:55:49 +00:00
parent 4a272f373d
commit e1782a6e3b
13 changed files with 949 additions and 23 deletions

View File

@@ -1,18 +1,27 @@
use std::path::{Path, PathBuf};
pub enum MoveOutcome {
/// File was moved/renamed to destination.
Moved(PathBuf),
/// Destination already existed; inbox duplicate was removed.
Merged(PathBuf),
}
/// Move a file from inbox to the permanent storage directory.
///
/// Creates the directory structure: `storage_dir/artist/album/filename`
/// Returns the full path of the moved file.
///
/// If `rename` fails (cross-device), falls back to copy + remove.
/// If the destination already exists the inbox copy is removed and
/// `MoveOutcome::Merged` is returned instead of an error.
pub async fn move_to_storage(
storage_dir: &Path,
artist: &str,
album: &str,
filename: &str,
source: &Path,
) -> anyhow::Result<PathBuf> {
) -> anyhow::Result<MoveOutcome> {
let artist_dir = sanitize_dir_name(artist);
let album_dir = sanitize_dir_name(album);
@@ -21,9 +30,13 @@ pub async fn move_to_storage(
let dest = dest_dir.join(filename);
// Avoid overwriting existing files
// File already at destination — remove the inbox duplicate
if dest.exists() {
anyhow::bail!("Destination already exists: {:?}", dest);
if source.exists() {
tokio::fs::remove_file(source).await?;
tracing::info!(from = ?source, to = ?dest, "merged duplicate into existing storage file");
}
return Ok(MoveOutcome::Merged(dest));
}
// Try atomic rename first (same filesystem)
@@ -37,7 +50,7 @@ pub async fn move_to_storage(
}
tracing::info!(from = ?source, to = ?dest, "moved file to storage");
Ok(dest)
Ok(MoveOutcome::Moved(dest))
}
/// Remove characters that are unsafe for directory names.