Ericson "Fogo" Soares 3f468d8950 [ENG-835] Duplicating an empty directory doesn't duplicate nested empty directories (#1213)
* Bunch of warnings

* Solving the issue

* sd_core_sync::New

* dumb

---------

Co-authored-by: Brendan Allan <brendonovich@outlook.com>
2023-08-13 18:34:46 +00:00

178 lines
4.9 KiB
Rust

use crate::{
location::{
file_path_helper::{file_path_with_object, IsolatedFilePathData},
LocationError,
},
prisma::{file_path, location, PrismaClient},
util::db::{maybe_missing, MissingFieldError},
};
use std::path::{Path, PathBuf};
use serde::{Deserialize, Serialize};
pub mod create;
pub mod delete;
pub mod erase;
pub mod copy;
pub mod cut;
// pub mod decrypt;
// pub mod encrypt;
pub mod error;
use error::FileSystemJobsError;
// pub const BYTES_EXT: &str = ".bytes";
#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)]
pub enum ObjectType {
File,
Directory,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct FileData {
pub file_path: file_path_with_object::Data,
pub full_path: PathBuf,
}
pub async fn get_location_path_from_location_id(
db: &PrismaClient,
location_id: file_path::id::Type,
) -> Result<PathBuf, FileSystemJobsError> {
let location = db
.location()
.find_unique(location::id::equals(location_id))
.exec()
.await?
.ok_or(FileSystemJobsError::Location(LocationError::IdNotFound(
location_id,
)))?;
Ok(maybe_missing(location.path, "location.path")?.into())
}
pub async fn get_many_files_datas(
db: &PrismaClient,
location_path: impl AsRef<Path>,
file_path_ids: &[file_path::id::Type],
) -> Result<Vec<FileData>, FileSystemJobsError> {
let location_path = location_path.as_ref();
db._batch(
file_path_ids
.iter()
.map(|file_path_id| {
db.file_path()
.find_unique(file_path::id::equals(*file_path_id))
.include(file_path_with_object::include())
})
// FIXME:(fogodev -> Brendonovich) this collect is a workaround to a weird higher ranker lifetime error on
// the _batch function, it should be removed once the error is fixed
.collect::<Vec<_>>(),
)
.await?
.into_iter()
.zip(file_path_ids.iter())
.map(|(maybe_file_path, file_path_id)| {
maybe_file_path
.ok_or(FileSystemJobsError::FilePathIdNotFound(*file_path_id))
.and_then(|path_data| {
Ok(FileData {
full_path: location_path.join(IsolatedFilePathData::try_from(&path_data)?),
file_path: path_data,
})
})
})
.collect::<Result<Vec<_>, _>>()
}
pub async fn get_file_data_from_isolated_file_path(
db: &PrismaClient,
location_path: impl AsRef<Path>,
iso_file_path: &IsolatedFilePathData<'_>,
) -> Result<FileData, FileSystemJobsError> {
let location_path = location_path.as_ref();
db.file_path()
.find_unique(iso_file_path.into())
.include(file_path_with_object::include())
.exec()
.await?
.ok_or_else(|| {
FileSystemJobsError::FilePathNotFound(
location_path.join(iso_file_path).into_boxed_path(),
)
})
.and_then(|path_data| {
Ok(FileData {
full_path: location_path.join(IsolatedFilePathData::try_from(&path_data)?),
file_path: path_data,
})
})
}
pub async fn fetch_source_and_target_location_paths(
db: &PrismaClient,
source_location_id: location::id::Type,
target_location_id: location::id::Type,
) -> Result<(PathBuf, PathBuf), FileSystemJobsError> {
match db
._batch((
db.location()
.find_unique(location::id::equals(source_location_id)),
db.location()
.find_unique(location::id::equals(target_location_id)),
))
.await?
{
(Some(source_location), Some(target_location)) => Ok((
maybe_missing(source_location.path.map(PathBuf::from), "location.path")?,
maybe_missing(target_location.path.map(PathBuf::from), "location.path")?,
)),
(None, _) => Err(LocationError::IdNotFound(source_location_id))?,
(_, None) => Err(LocationError::IdNotFound(target_location_id))?,
}
}
fn construct_target_filename(
source_file_data: &FileData,
target_file_name_suffix: &Option<String>,
) -> Result<String, MissingFieldError> {
// extension wizardry for cloning and such
// if no suffix has been selected, just use the file name
// if a suffix is provided and it's a directory, use the directory name + suffix
// if a suffix is provided and it's a file, use the (file name + suffix).extension
Ok(if let Some(ref suffix) = target_file_name_suffix {
if maybe_missing(source_file_data.file_path.is_dir, "file_path.is_dir")?
|| source_file_data.file_path.extension.is_none()
|| source_file_data.file_path.extension == Some(String::new())
{
format!(
"{}{suffix}",
maybe_missing(&source_file_data.file_path.name, "file_path.name")?
)
} else {
format!(
"{}{suffix}.{}",
maybe_missing(&source_file_data.file_path.name, "file_path.name")?,
maybe_missing(&source_file_data.file_path.extension, "file_path.extension")?,
)
}
} else if *maybe_missing(&source_file_data.file_path.is_dir, "file_path.is_dir")?
|| source_file_data.file_path.extension.is_none()
|| source_file_data.file_path.extension == Some(String::new())
{
maybe_missing(&source_file_data.file_path.name, "file_path.name")?.clone()
} else {
format!(
"{}.{}",
maybe_missing(&source_file_data.file_path.name, "file_path.name")?,
maybe_missing(&source_file_data.file_path.extension, "file_path.extension")?
)
})
}