.ok_or_else(|| DbErr::Custom("Trash not found".into()))?;
let path = get_note_storage_path(&backend.db, note_id).await?;
- let result = note::Entity::update_many()
+ let mut update = note::Entity::update_many()
.filter(note::Column::NoteId.eq(note_id))
- .col_expr(Column::CollectionId, Expr::value(trash_id))
- .exec(&backend.db).await?;
+ .col_expr(Column::CollectionId, Expr::value(trash_id));
+
+ let mut old_path: Option<PathBuf> = None;
+ let mut new_path: Option<PathBuf> = None;
+ if let Some(path) = path {
+ let note_path = Path::new(&path);
+ let trash_path = get_collection_storage_path(&backend.db, trash_id)
+ .await?
+ .ok_or(DbErr::Custom("Trash local path not found".into()))?;
+ // Even though the nodename probably already has a random suffix, we just
+ // add another random suffix, to make sure the trash filename is unique.
+ // It does not need to look pretty in the trash folder
+ let note_name = note_path.file_name().unwrap_or(std::ffi::OsStr::new("")).to_str().unwrap_or("").to_string();
+ let trashed_nodename = randomize_nodename(note_name.as_str());
+ let trashed_path = PathBuf::from(trash_path).join(trashed_nodename.clone());
+ old_path = Some(note_path.to_path_buf());
+ new_path = Some(trashed_path.clone());
+ let rename_result = tokio::fs::rename(note_path, &trashed_path).await;
+ if let Err(e) = rename_result {
+ return Err(DbErr::Custom(format!("rename failed: {}", e)));
+ }
+ // update nodename in the database
+ update = update.col_expr(Column::Nodename, Expr::value(trashed_nodename));
+ }
+
+ let result = update.exec(&backend.db).await?;
if result.rows_affected == 1 {
- if let Some(path) = path {
- let note_path = Path::new(&path);
- let trash_path = get_collection_storage_path(&backend.db, trash_id)
- .await?
- .ok_or(DbErr::Custom("Trash local path not found".into()))?;
- // Even though the nodename probably already has a random suffix, we just
- // add another random suffix, to make sure the trash filename is unique.
- // It does not need to look pretty in the trash folder
- let note_name = note_path.file_name().unwrap_or(std::ffi::OsStr::new("")).to_str().unwrap_or("").to_string();
- let trashed_nodename = randomize_nodename(note_name.as_str());
- let trashed_path = PathBuf::from(trash_path).join(trashed_nodename);
- let rename_result = tokio::fs::rename(path, &trashed_path).await;
- if let Err(e) = rename_result {
- // TODO: revert db previous update
- return Err(DbErr::Custom(format!("rename failed: {}", e)));
- }
- }
-
let event = NoteMoved {
note_id,
from_collection_id,
Ok(())
} else {
- Err(DbErr::Custom("unexpected number of affected rows".into()))
+ // revert previous rename operation
+ let mut msg = "unexpected number of affected rows".to_string();
+ if let Some(old_path) = old_path && let Some(new_path) = new_path {
+ let result = tokio::fs::rename(new_path, old_path).await;
+ if let Err(e) = result {
+ msg.push_str("; moving file back from trash failed");
+ }
+ }
+ Err(DbErr::Custom(msg))
}
}.await;