move multiple files at once
This commit is contained in:
@@ -302,19 +302,50 @@ impl FileSystem {
|
||||
}
|
||||
}
|
||||
|
||||
async fn mv(&self, path: &AbsoluteFilePath, target_path: &AbsoluteFilePath) -> io::Result<()> {
|
||||
let current_path = self.get_target_path(path);
|
||||
let target_path = self.get_target_path(target_path);
|
||||
async fn mv(
|
||||
&self,
|
||||
path: &AbsoluteFilePath,
|
||||
target_path: &AbsoluteFilePath,
|
||||
) -> io::Result<(AbsoluteFilePath, AbsoluteFilePath)> {
|
||||
let mut target_path = target_path.clone();
|
||||
|
||||
if !fs::try_exists(¤t_path).await? {
|
||||
let current_fs_path = self.get_target_path(path);
|
||||
let mut target_fs_path = self.get_target_path(&target_path);
|
||||
|
||||
if !fs::try_exists(¤t_fs_path).await? {
|
||||
return Err(io::ErrorKind::NotFound.into());
|
||||
}
|
||||
|
||||
if fs::try_exists(&target_path).await? {
|
||||
if !fs::try_exists(&target_fs_path).await? {
|
||||
return fs::rename(current_fs_path, target_fs_path)
|
||||
.await
|
||||
.map(|_| (path.clone(), target_path.clone()));
|
||||
}
|
||||
|
||||
let target_is_dir = fs::metadata(target_fs_path).await?.is_dir();
|
||||
|
||||
if !target_is_dir {
|
||||
return Err(io::ErrorKind::AlreadyExists.into());
|
||||
}
|
||||
|
||||
fs::rename(current_path, &target_path).await
|
||||
let name = {
|
||||
let current_path = path.as_str();
|
||||
if let Some(last_slash_index) = current_path.rfind("/")
|
||||
&& last_slash_index > 0
|
||||
{
|
||||
¤t_path[last_slash_index + 1..]
|
||||
} else {
|
||||
return Err(io::ErrorKind::AlreadyExists.into());
|
||||
}
|
||||
};
|
||||
|
||||
target_path =
|
||||
target_path.join(&RelativeFilePath::new(FilePath::new(name).unwrap()).unwrap());
|
||||
target_fs_path = self.get_target_path(&target_path);
|
||||
|
||||
fs::rename(current_fs_path, target_fs_path)
|
||||
.await
|
||||
.map(|_| (path.clone(), target_path.clone()))
|
||||
}
|
||||
|
||||
async fn touch(&self, path: &AbsoluteFilePath) -> io::Result<()> {
|
||||
@@ -431,29 +462,42 @@ impl FileSystemRepository for FileSystem {
|
||||
})
|
||||
}
|
||||
|
||||
let results: Vec<Result<AbsoluteFilePath, RmError>> = join_all(
|
||||
join_all(
|
||||
paths
|
||||
.into_iter()
|
||||
.map(|path| _rm(&self, path, force))
|
||||
.collect::<Vec<_>>(),
|
||||
)
|
||||
.await;
|
||||
|
||||
results
|
||||
.await
|
||||
}
|
||||
|
||||
async fn mv(&self, request: MvRequest) -> Result<(), MvError> {
|
||||
self.mv(request.path(), request.target_path())
|
||||
.await
|
||||
.map_err(|e| match e.kind() {
|
||||
std::io::ErrorKind::NotFound => MvError::NotFound,
|
||||
_ => anyhow!(
|
||||
"Failed to move {} to {}: {e:?}",
|
||||
request.path(),
|
||||
request.target_path()
|
||||
)
|
||||
.into(),
|
||||
async fn mv(
|
||||
&self,
|
||||
request: MvRequest,
|
||||
) -> Vec<Result<(AbsoluteFilePath, AbsoluteFilePath), MvError>> {
|
||||
async fn _mv(
|
||||
fs: &FileSystem,
|
||||
path: AbsoluteFilePath,
|
||||
target_path: &AbsoluteFilePath,
|
||||
) -> Result<(AbsoluteFilePath, AbsoluteFilePath), MvError> {
|
||||
fs.mv(&path, target_path).await.map_err(|e| match e.kind() {
|
||||
std::io::ErrorKind::NotFound => MvError::NotFound(path),
|
||||
_ => MvError::Unknown(
|
||||
anyhow!("Failed to move {} to {}: {e:?}", path, target_path).into(),
|
||||
),
|
||||
})
|
||||
}
|
||||
|
||||
let (path_list, target_path) = request.unpack();
|
||||
let paths = Vec::<AbsoluteFilePath>::from(path_list);
|
||||
|
||||
join_all(
|
||||
paths
|
||||
.into_iter()
|
||||
.map(|path| _mv(&self, path, &target_path))
|
||||
.collect::<Vec<_>>(),
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn touch(&self, request: TouchRequest) -> Result<(), TouchError> {
|
||||
|
||||
@@ -110,12 +110,28 @@ impl WarrenNotifier for NotifierDebugLogger {
|
||||
}
|
||||
|
||||
async fn warren_mv(&self, response: &WarrenMvResponse) {
|
||||
tracing::debug!(
|
||||
"[Notifier] Renamed file {} to {} in warren {}",
|
||||
response.old_path(),
|
||||
response.path(),
|
||||
response.warren().name(),
|
||||
);
|
||||
let span = tracing::debug_span!("warren_mv", "{}", response.warren().name()).entered();
|
||||
|
||||
let results = response.results();
|
||||
|
||||
for result in results {
|
||||
match result.as_ref() {
|
||||
Ok((old_path, new_path)) => {
|
||||
tracing::debug!("Moved file {old_path} to {new_path}")
|
||||
}
|
||||
Err(e) => match e {
|
||||
crate::domain::warren::models::file::MvError::NotFound(path) => {
|
||||
tracing::debug!("File not found: {path}")
|
||||
}
|
||||
crate::domain::warren::models::file::MvError::AlreadyExists(path) => {
|
||||
tracing::debug!("File already exists: {path}")
|
||||
}
|
||||
crate::domain::warren::models::file::MvError::Unknown(_) => (),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
span.exit();
|
||||
}
|
||||
|
||||
async fn warren_touch(&self, warren: &Warren, path: &AbsoluteFilePath) {
|
||||
@@ -418,10 +434,11 @@ impl AuthNotifier for NotifierDebugLogger {
|
||||
}
|
||||
|
||||
async fn auth_warren_mv(&self, user: &User, response: &WarrenMvResponse) {
|
||||
let results = response.results();
|
||||
let successes = results.iter().filter(|r| r.is_ok()).count();
|
||||
|
||||
tracing::debug!(
|
||||
"[Notifier] Renamed file {} to {} in warren {} for authenticated user {}",
|
||||
response.old_path(),
|
||||
response.path(),
|
||||
"[Notifier] Moved {successes} file(s) in warren {} for authenticated user {}",
|
||||
response.warren().name(),
|
||||
user.id(),
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user