Make Delete All Recordings more robust against missing recordings

For some reason, some QMDL files are missing on my device. In this
situation Delete All Recordings should not fail on the first missing
file.
This commit is contained in:
Markus Unterwaditzer
2025-05-16 21:33:48 +02:00
committed by Will Greenberg
parent 3fa583f671
commit 90e2bddbbb

View File

@@ -1,7 +1,9 @@
use std::io::{self, ErrorKind};
use std::path::{Path, PathBuf};
use chrono::{DateTime, Local}; use chrono::{DateTime, Local};
use rayhunter::util::RuntimeMetadata; use rayhunter::util::RuntimeMetadata;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::path::{Path, PathBuf};
use thiserror::Error; use thiserror::Error;
use tokio::{ use tokio::{
fs::{self, try_exists, File, OpenOptions}, fs::{self, try_exists, File, OpenOptions},
@@ -289,10 +291,10 @@ impl RecordingStore {
self.write_manifest().await?; self.write_manifest().await?;
let qmdl_filepath = entry_to_delete.get_qmdl_filepath(&self.path); let qmdl_filepath = entry_to_delete.get_qmdl_filepath(&self.path);
let analysis_filepath = entry_to_delete.get_analysis_filepath(&self.path); let analysis_filepath = entry_to_delete.get_analysis_filepath(&self.path);
tokio::fs::remove_file(qmdl_filepath) remove_file_if_exists(&qmdl_filepath)
.await .await
.map_err(RecordingStoreError::DeleteFileError)?; .map_err(RecordingStoreError::DeleteFileError)?;
tokio::fs::remove_file(analysis_filepath) remove_file_if_exists(&analysis_filepath)
.await .await
.map_err(RecordingStoreError::DeleteFileError)?; .map_err(RecordingStoreError::DeleteFileError)?;
Ok(entry_to_delete) Ok(entry_to_delete)
@@ -303,22 +305,41 @@ impl RecordingStore {
self.close_current_entry().await?; self.close_current_entry().await?;
} }
let mut keep = Vec::new();
for entry in &self.manifest.entries { for entry in &self.manifest.entries {
let qmdl_filepath = entry.get_qmdl_filepath(&self.path); let qmdl_filepath = entry.get_qmdl_filepath(&self.path);
let analysis_filepath = entry.get_analysis_filepath(&self.path); let analysis_filepath = entry.get_analysis_filepath(&self.path);
tokio::fs::remove_file(qmdl_filepath)
.await if let Err(e) = remove_file_if_exists(&qmdl_filepath).await {
.map_err(RecordingStoreError::DeleteFileError)?; log::warn!("failed to remove {qmdl_filepath:?}: {e:?}");
tokio::fs::remove_file(analysis_filepath) keep.push(true);
.await continue;
.map_err(RecordingStoreError::DeleteFileError)?;
} }
self.manifest.entries.drain(..);
if let Err(e) = remove_file_if_exists(&analysis_filepath).await {
log::warn!("failed to remove {analysis_filepath:?}: {e:?}");
keep.push(true);
continue;
}
keep.push(false);
}
let mut keep_iter = keep.into_iter();
self.manifest.entries.retain(|_| keep_iter.next().unwrap());
self.write_manifest().await?; self.write_manifest().await?;
Ok(()) Ok(())
} }
} }
async fn remove_file_if_exists(path: &Path) -> Result<(), io::Error> {
match tokio::fs::remove_file(path).await {
Err(e) if e.kind() == ErrorKind::NotFound => Ok(()),
res => res,
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;