use anyhow::{Result, anyhow};
use tracing::{error, info};
use s3util_rs::Config;
use super::{CopyPhase, ExitStatus, run_copy_phase};
pub async fn run_mv(config: Config) -> Result<ExitStatus> {
let phase = run_copy_phase(config.clone()).await?;
apply_mv_decision_tree(config, phase).await
}
async fn apply_mv_decision_tree(config: Config, phase: CopyPhase) -> Result<ExitStatus> {
if phase.cancelled {
return Ok(ExitStatus::Cancelled);
}
let outcome = match phase.transfer_result {
Ok(o) => o,
Err(e) => {
error!(error = format!("{e:#}"), "copy failed; source not deleted.");
return Err(e);
}
};
if phase.has_warning && !config.no_fail_on_verify_error {
let msg =
"verification failed; source not deleted (use --no-fail-on-verify-error to override)";
error!("{msg}");
return Err(anyhow!(msg));
}
if phase.cancellation_token.is_cancelled() {
return Ok(ExitStatus::Cancelled);
}
let version_id = config.version_id.clone().or(outcome.source_version_id);
let version_id_for_log = version_id.clone().unwrap_or_default();
match phase
.source_storage
.delete_object(&phase.source_key, version_id)
.await
{
Ok(_) => {
info!(
key = %phase.source_key,
version_id = %version_id_for_log,
"Source delete completed."
);
Ok(ExitStatus::Success)
}
Err(e) => {
error!(error = format!("{e:#}"), "source delete failed.");
Err(e)
}
}
}