mirror of
https://github.com/chatmail/core.git
synced 2026-05-22 16:26:31 +03:00
Resultify tools::delete_file()
This commit is contained in:
34
src/imex.rs
34
src/imex.rs
@@ -700,20 +700,16 @@ async fn export_self_keys(context: &Context, dir: &Path) -> Result<()> {
|
|||||||
for (id, public_key, private_key, is_default) in keys {
|
for (id, public_key, private_key, is_default) in keys {
|
||||||
let id = Some(id).filter(|_| is_default != 0);
|
let id = Some(id).filter(|_| is_default != 0);
|
||||||
if let Ok(key) = public_key {
|
if let Ok(key) = public_key {
|
||||||
if export_key_to_asc_file(context, dir, id, &key)
|
if let Err(err) = export_key_to_asc_file(context, dir, id, &key).await {
|
||||||
.await
|
error!(context, "Failed to export public key: {:#}.", err);
|
||||||
.is_err()
|
|
||||||
{
|
|
||||||
export_errors += 1;
|
export_errors += 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
export_errors += 1;
|
export_errors += 1;
|
||||||
}
|
}
|
||||||
if let Ok(key) = private_key {
|
if let Ok(key) = private_key {
|
||||||
if export_key_to_asc_file(context, dir, id, &key)
|
if let Err(err) = export_key_to_asc_file(context, dir, id, &key).await {
|
||||||
.await
|
error!(context, "Failed to export private key: {:#}.", err);
|
||||||
.is_err()
|
|
||||||
{
|
|
||||||
export_errors += 1;
|
export_errors += 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -733,7 +729,7 @@ async fn export_key_to_asc_file<T>(
|
|||||||
dir: &Path,
|
dir: &Path,
|
||||||
id: Option<i64>,
|
id: Option<i64>,
|
||||||
key: &T,
|
key: &T,
|
||||||
) -> std::io::Result<()>
|
) -> Result<()>
|
||||||
where
|
where
|
||||||
T: DcKey + Any,
|
T: DcKey + Any,
|
||||||
{
|
{
|
||||||
@@ -755,16 +751,16 @@ where
|
|||||||
key.key_id(),
|
key.key_id(),
|
||||||
file_name.display()
|
file_name.display()
|
||||||
);
|
);
|
||||||
delete_file(context, &file_name).await;
|
|
||||||
|
// Delete the file if it already exists.
|
||||||
|
delete_file(context, &file_name).await.ok();
|
||||||
|
|
||||||
let content = key.to_asc(None).into_bytes();
|
let content = key.to_asc(None).into_bytes();
|
||||||
let res = write_file(context, &file_name, &content).await;
|
write_file(context, &file_name, &content)
|
||||||
if res.is_err() {
|
.await
|
||||||
error!(context, "Cannot write key to {}", file_name.display());
|
.with_context(|| format!("cannot write key to {}", file_name.display()))?;
|
||||||
} else {
|
context.emit_event(EventType::ImexFileWritten(file_name));
|
||||||
context.emit_event(EventType::ImexFileWritten(file_name));
|
Ok(())
|
||||||
}
|
|
||||||
res
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@@ -854,12 +850,12 @@ mod tests {
|
|||||||
let context = TestContext::new_alice().await;
|
let context = TestContext::new_alice().await;
|
||||||
let blobdir = context.ctx.get_blobdir();
|
let blobdir = context.ctx.get_blobdir();
|
||||||
if let Err(err) = imex(&context.ctx, ImexMode::ExportSelfKeys, blobdir, None).await {
|
if let Err(err) = imex(&context.ctx, ImexMode::ExportSelfKeys, blobdir, None).await {
|
||||||
panic!("got error on export: {:?}", err);
|
panic!("got error on export: {:#}", err);
|
||||||
}
|
}
|
||||||
|
|
||||||
let context2 = TestContext::new_alice().await;
|
let context2 = TestContext::new_alice().await;
|
||||||
if let Err(err) = imex(&context2.ctx, ImexMode::ImportSelfKeys, blobdir, None).await {
|
if let Err(err) = imex(&context2.ctx, ImexMode::ImportSelfKeys, blobdir, None).await {
|
||||||
panic!("got error on import: {:?}", err);
|
panic!("got error on import: {:#}", err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -798,7 +798,14 @@ pub async fn remove_unused_files(context: &Context) -> Result<()> {
|
|||||||
entry.file_name()
|
entry.file_name()
|
||||||
);
|
);
|
||||||
let path = entry.path();
|
let path = entry.path();
|
||||||
delete_file(context, path).await;
|
if let Err(err) = delete_file(context, &path).await {
|
||||||
|
error!(
|
||||||
|
context,
|
||||||
|
"Failed to delete unused file {}: {:#}.",
|
||||||
|
path.display(),
|
||||||
|
err
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
|
|||||||
70
src/tools.rs
70
src/tools.rs
@@ -11,7 +11,7 @@ use std::path::{Path, PathBuf};
|
|||||||
use std::str::from_utf8;
|
use std::str::from_utf8;
|
||||||
use std::time::{Duration, SystemTime};
|
use std::time::{Duration, SystemTime};
|
||||||
|
|
||||||
use anyhow::{bail, Result};
|
use anyhow::{bail, Context as _, Result};
|
||||||
use chrono::{Local, TimeZone};
|
use chrono::{Local, TimeZone};
|
||||||
use futures::{StreamExt, TryStreamExt};
|
use futures::{StreamExt, TryStreamExt};
|
||||||
use mailparse::dateparse;
|
use mailparse::dateparse;
|
||||||
@@ -369,49 +369,39 @@ pub(crate) async fn get_filebytes(context: &Context, path: impl AsRef<Path>) ->
|
|||||||
Ok(meta.len())
|
Ok(meta.len())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn delete_file(context: &Context, path: impl AsRef<Path>) -> bool {
|
pub(crate) async fn delete_file(context: &Context, path: impl AsRef<Path>) -> Result<()> {
|
||||||
let path_abs = get_abs_path(context, &path);
|
let path = path.as_ref();
|
||||||
|
let path_abs = get_abs_path(context, path);
|
||||||
if !path_abs.exists() {
|
if !path_abs.exists() {
|
||||||
return false;
|
bail!("path {} does not exist", path_abs.display());
|
||||||
}
|
}
|
||||||
if !path_abs.is_file() {
|
if !path_abs.is_file() {
|
||||||
warn!(
|
warn!(context, "refusing to delete non-file {}.", path.display());
|
||||||
context,
|
bail!("not a file: \"{}\"", path.display());
|
||||||
"refusing to delete non-file \"{}\".",
|
|
||||||
path.as_ref().display()
|
|
||||||
);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let dpath = format!("{}", path.as_ref().to_string_lossy());
|
let dpath = format!("{}", path.to_string_lossy());
|
||||||
match fs::remove_file(path_abs).await {
|
fs::remove_file(path_abs)
|
||||||
Ok(_) => {
|
.await
|
||||||
context.emit_event(EventType::DeletedBlobFile(dpath));
|
.with_context(|| format!("cannot delete {:?}", dpath))?;
|
||||||
true
|
context.emit_event(EventType::DeletedBlobFile(dpath));
|
||||||
}
|
Ok(())
|
||||||
Err(err) => {
|
|
||||||
warn!(context, "Cannot delete \"{}\": {}", dpath, err);
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn delete_files_in_dir(context: &Context, path: impl AsRef<Path>) {
|
pub async fn delete_files_in_dir(context: &Context, path: impl AsRef<Path>) -> Result<()> {
|
||||||
match tokio::fs::read_dir(path).await {
|
let read_dir = tokio::fs::read_dir(path)
|
||||||
Ok(read_dir) => {
|
.await
|
||||||
let mut read_dir = tokio_stream::wrappers::ReadDirStream::new(read_dir);
|
.context("could not read dir to delete")?;
|
||||||
while let Some(entry) = read_dir.next().await {
|
let mut read_dir = tokio_stream::wrappers::ReadDirStream::new(read_dir);
|
||||||
match entry {
|
while let Some(entry) = read_dir.next().await {
|
||||||
Ok(file) => {
|
match entry {
|
||||||
delete_file(context, file.file_name()).await;
|
Ok(file) => {
|
||||||
}
|
delete_file(context, file.file_name()).await?;
|
||||||
Err(e) => warn!(context, "Could not read file to delete: {}", e),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Err(e) => warn!(context, "Could not read file to delete: {}", e),
|
||||||
}
|
}
|
||||||
|
|
||||||
Err(e) => warn!(context, "Could not read dir to delete: {}", e),
|
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn create_folder(
|
pub(crate) async fn create_folder(
|
||||||
@@ -1047,7 +1037,9 @@ DKIM Results: Passed=true, Works=true, Allow_Keychange=true";
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
assert!(!delete_file(context, "$BLOBDIR/lkqwjelqkwlje").await);
|
assert!(delete_file(context, "$BLOBDIR/lkqwjelqkwlje")
|
||||||
|
.await
|
||||||
|
.is_err());
|
||||||
assert!(write_file(context, "$BLOBDIR/foobar", b"content")
|
assert!(write_file(context, "$BLOBDIR/foobar", b"content")
|
||||||
.await
|
.await
|
||||||
.is_ok());
|
.is_ok());
|
||||||
@@ -1063,17 +1055,19 @@ DKIM Results: Passed=true, Works=true, Allow_Keychange=true";
|
|||||||
|
|
||||||
assert!(file_exist!(context, &abs_path));
|
assert!(file_exist!(context, &abs_path));
|
||||||
|
|
||||||
assert!(delete_file(context, "$BLOBDIR/foobar").await);
|
assert!(delete_file(context, "$BLOBDIR/foobar").await.is_ok());
|
||||||
assert!(create_folder(context, "$BLOBDIR/foobar-folder")
|
assert!(create_folder(context, "$BLOBDIR/foobar-folder")
|
||||||
.await
|
.await
|
||||||
.is_ok());
|
.is_ok());
|
||||||
assert!(file_exist!(context, "$BLOBDIR/foobar-folder"));
|
assert!(file_exist!(context, "$BLOBDIR/foobar-folder"));
|
||||||
assert!(!delete_file(context, "$BLOBDIR/foobar-folder").await);
|
assert!(delete_file(context, "$BLOBDIR/foobar-folder")
|
||||||
|
.await
|
||||||
|
.is_err());
|
||||||
|
|
||||||
let fn0 = "$BLOBDIR/data.data";
|
let fn0 = "$BLOBDIR/data.data";
|
||||||
assert!(write_file(context, &fn0, b"content").await.is_ok());
|
assert!(write_file(context, &fn0, b"content").await.is_ok());
|
||||||
|
|
||||||
assert!(delete_file(context, &fn0).await);
|
assert!(delete_file(context, &fn0).await.is_ok());
|
||||||
assert!(!file_exist!(context, &fn0));
|
assert!(!file_exist!(context, &fn0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user