Fix shutdown to close the repository instead of aborting completely
Signed-off-by: trivernis <trivernis@protonmail.com>pull/4/head
parent
f77a45e963
commit
810f9986af
@ -0,0 +1,35 @@
|
|||||||
|
use std::io::Result;
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
use tokio::fs::{File, OpenOptions};
|
||||||
|
|
||||||
|
/// A file that only exists while being owned.
|
||||||
|
/// Will automatically be deleted on Drop
|
||||||
|
pub struct DropFile {
|
||||||
|
path: PathBuf,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DropFile {
|
||||||
|
pub async fn new<P: AsRef<Path>>(path: P) -> Result<(File, Self)> {
|
||||||
|
let file = OpenOptions::new()
|
||||||
|
.write(true)
|
||||||
|
.read(true)
|
||||||
|
.create(true)
|
||||||
|
.open(path.as_ref())
|
||||||
|
.await?;
|
||||||
|
Ok((file, Self::from_path(path)))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_path<P: AsRef<Path>>(path: P) -> Self {
|
||||||
|
Self {
|
||||||
|
path: path.as_ref().to_path_buf(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for DropFile {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
if let Err(e) = std::fs::remove_file(&self.path) {
|
||||||
|
tracing::error!("failed to remove drop file '{}'", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,2 +1,3 @@
|
|||||||
|
pub mod drop_file;
|
||||||
pub mod file_hash_store;
|
pub mod file_hash_store;
|
||||||
pub mod thumbnail_store;
|
pub mod thumbnail_store;
|
||||||
|
@ -0,0 +1,114 @@
|
|||||||
|
use crate::namespaces::files::FileSortContext;
|
||||||
|
use compare::Compare;
|
||||||
|
use mediarepo_core::mediarepo_api::types::filtering::{SortDirection, SortKey};
|
||||||
|
use std::cmp::Ordering;
|
||||||
|
|
||||||
|
#[tracing::instrument(level = "trace", skip_all)]
|
||||||
|
pub fn compare_files(
|
||||||
|
ctx_a: &FileSortContext,
|
||||||
|
ctx_b: &FileSortContext,
|
||||||
|
expression: &Vec<SortKey>,
|
||||||
|
) -> Ordering {
|
||||||
|
let cmp_date = compare::natural();
|
||||||
|
let cmp_u64 = compare::natural();
|
||||||
|
let cmp_u32 = compare::natural();
|
||||||
|
|
||||||
|
for sort_key in expression {
|
||||||
|
let ordering = match sort_key {
|
||||||
|
SortKey::Namespace(namespace) => {
|
||||||
|
let list_a = ctx_a.namespaces.get(&namespace.name);
|
||||||
|
let list_b = ctx_b.namespaces.get(&namespace.name);
|
||||||
|
|
||||||
|
let cmp_result = if let (Some(list_a), Some(list_b)) = (list_a, list_b) {
|
||||||
|
compare_tag_lists(list_a, list_b)
|
||||||
|
} else if list_a.is_some() {
|
||||||
|
Ordering::Greater
|
||||||
|
} else if list_b.is_some() {
|
||||||
|
Ordering::Less
|
||||||
|
} else {
|
||||||
|
Ordering::Equal
|
||||||
|
};
|
||||||
|
adjust_for_dir(cmp_result, &namespace.direction)
|
||||||
|
}
|
||||||
|
SortKey::FileName(direction) => {
|
||||||
|
adjust_for_dir(compare_opts(&ctx_a.name, &ctx_b.name), direction)
|
||||||
|
}
|
||||||
|
SortKey::FileSize(direction) => {
|
||||||
|
adjust_for_dir(cmp_u64.compare(&ctx_a.size, &ctx_b.size), direction)
|
||||||
|
}
|
||||||
|
SortKey::FileImportedTime(direction) => adjust_for_dir(
|
||||||
|
cmp_date.compare(&ctx_a.import_time, &ctx_b.import_time),
|
||||||
|
direction,
|
||||||
|
),
|
||||||
|
SortKey::FileCreatedTime(direction) => adjust_for_dir(
|
||||||
|
cmp_date.compare(&ctx_a.create_time, &ctx_b.create_time),
|
||||||
|
direction,
|
||||||
|
),
|
||||||
|
SortKey::FileChangeTime(direction) => adjust_for_dir(
|
||||||
|
cmp_date.compare(&ctx_a.change_time, &ctx_b.change_time),
|
||||||
|
direction,
|
||||||
|
),
|
||||||
|
SortKey::FileType(direction) => {
|
||||||
|
adjust_for_dir(ctx_a.mime_type.cmp(&ctx_b.mime_type), direction)
|
||||||
|
}
|
||||||
|
SortKey::NumTags(direction) => adjust_for_dir(
|
||||||
|
cmp_u32.compare(&ctx_a.tag_count, &ctx_b.tag_count),
|
||||||
|
direction,
|
||||||
|
),
|
||||||
|
};
|
||||||
|
if !ordering.is_eq() {
|
||||||
|
return ordering;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ordering::Equal
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compare_opts<T: Ord + Sized>(opt_a: &Option<T>, opt_b: &Option<T>) -> Ordering {
|
||||||
|
let cmp = compare::natural();
|
||||||
|
if let (Some(a), Some(b)) = (opt_a, opt_b) {
|
||||||
|
cmp.compare(a, b)
|
||||||
|
} else if opt_a.is_some() {
|
||||||
|
Ordering::Greater
|
||||||
|
} else if opt_b.is_some() {
|
||||||
|
Ordering::Less
|
||||||
|
} else {
|
||||||
|
Ordering::Equal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compare_f32(a: f32, b: f32) -> Ordering {
|
||||||
|
if a > b {
|
||||||
|
Ordering::Greater
|
||||||
|
} else if b > a {
|
||||||
|
Ordering::Less
|
||||||
|
} else {
|
||||||
|
Ordering::Equal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn adjust_for_dir(ordering: Ordering, direction: &SortDirection) -> Ordering {
|
||||||
|
if *direction == SortDirection::Descending {
|
||||||
|
ordering.reverse()
|
||||||
|
} else {
|
||||||
|
ordering
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compare_tag_lists(list_a: &Vec<String>, list_b: &Vec<String>) -> Ordering {
|
||||||
|
let first_diff = list_a
|
||||||
|
.into_iter()
|
||||||
|
.zip(list_b.into_iter())
|
||||||
|
.find(|(a, b)| *a != *b);
|
||||||
|
if let Some(diff) = first_diff {
|
||||||
|
if let (Some(num_a), Some(num_b)) = (diff.0.parse::<f32>().ok(), diff.1.parse::<f32>().ok())
|
||||||
|
{
|
||||||
|
compare_f32(num_a, num_b)
|
||||||
|
} else {
|
||||||
|
let cmp = compare::natural();
|
||||||
|
cmp.compare(diff.0, diff.1)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Ordering::Equal
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue