Add xdg trash support (#12391)

Joshua Ferguson created

- Added support for xdg trash when deleting files on linux
- moved ashpd depency to toplevel to use it in both fs and gpui

If I need to add test, or change anything, please let me know. I tested
locally by creating and deleting a file and confirming it showed up in
my trashcan, but that probably a less than ideal method of confirming
correct behavior

Also, I could remove the delete directory function for linux, and change
the one configured for macos to compile for both macos and linux (they
are the same, the version of the function they are calling is
different).

Release Notes:

- N/A

Change summary

Cargo.lock             |  1 +
Cargo.toml             |  7 +++----
crates/fs/Cargo.toml   |  3 +++
crates/fs/src/fs.rs    | 20 ++++++++++++++++++++
crates/gpui/Cargo.toml | 14 +++++++++++---
5 files changed, 38 insertions(+), 7 deletions(-)

Detailed changes

Cargo.lock 🔗

@@ -4202,6 +4202,7 @@ name = "fs"
 version = "0.1.0"
 dependencies = [
  "anyhow",
+ "ashpd",
  "async-tar",
  "async-trait",
  "cocoa",

Cargo.toml 🔗

@@ -257,6 +257,7 @@ zed_actions = { path = "crates/zed_actions" }
 
 anyhow = "1.0.57"
 any_vec = "0.13"
+ashpd = "0.8.0"
 async-compression = { version = "0.4", features = ["gzip", "futures-io"] }
 async-fs = "1.6"
 async-recursion = "1.0.0"
@@ -286,9 +287,7 @@ futures-batch = "0.6.1"
 futures-lite = "1.13"
 git2 = { version = "0.18", default-features = false }
 globset = "0.4"
-heed = { version = "0.20.1", features = [
-    "read-txn-no-tls",
-] }
+heed = { version = "0.20.1", features = ["read-txn-no-tls"] }
 hex = "0.4.3"
 html5ever = "0.27.0"
 ignore = "0.4.22"
@@ -497,7 +496,7 @@ type_complexity = "allow"
 
 [workspace.lints.rust]
 unexpected_cfgs = { level = "warn", check-cfg = [
-    'cfg(gles)' # used in gpui
+    'cfg(gles)', # used in gpui
 ] }
 
 [workspace.metadata.cargo-machete]

crates/fs/Cargo.toml 🔗

@@ -46,6 +46,9 @@ notify = "6.1.1"
 [target.'cfg(target_os = "windows")'.dependencies]
 windows.workspace = true
 
+[target.'cfg(target_os = "linux")'.dependencies]
+ashpd.workspace = true
+
 [dev-dependencies]
 gpui = { workspace = true, features = ["test-support"] }
 

crates/fs/src/fs.rs 🔗

@@ -1,6 +1,11 @@
 use anyhow::{anyhow, Result};
 use git::GitHostingProviderRegistry;
 
+#[cfg(target_os = "linux")]
+use ashpd::desktop::trash;
+#[cfg(target_os = "linux")]
+use std::{fs::File, os::fd::AsFd};
+
 #[cfg(unix)]
 use std::os::unix::fs::MetadataExt;
 
@@ -10,6 +15,7 @@ use git::repository::{GitRepository, RealGitRepository};
 use git2::Repository as LibGitRepository;
 use parking_lot::Mutex;
 use rope::Rope;
+
 #[cfg(any(test, feature = "test-support"))]
 use smol::io::AsyncReadExt;
 use smol::io::AsyncWriteExt;
@@ -273,11 +279,25 @@ impl Fs for RealFs {
         Ok(())
     }
 
+    #[cfg(target_os = "linux")]
+    async fn trash_file(&self, path: &Path, _options: RemoveOptions) -> Result<()> {
+        let file = File::open(path)?;
+        match trash::trash_file(&file.as_fd()).await {
+            Ok(_) => Ok(()),
+            Err(err) => Err(anyhow::Error::new(err)),
+        }
+    }
+
     #[cfg(target_os = "macos")]
     async fn trash_dir(&self, path: &Path, options: RemoveOptions) -> Result<()> {
         self.trash_file(path, options).await
     }
 
+    #[cfg(target_os = "linux")]
+    async fn trash_dir(&self, path: &Path, options: RemoveOptions) -> Result<()> {
+        self.trash_file(path, options).await
+    }
+
     async fn open_sync(&self, path: &Path) -> Result<Box<dyn io::Read>> {
         Ok(Box::new(std::fs::File::open(path)?))
     }

crates/gpui/Cargo.toml 🔗

@@ -12,7 +12,12 @@ workspace = true
 
 [features]
 default = []
-test-support = ["backtrace", "collections/test-support", "util/test-support", "http/test-support"]
+test-support = [
+    "backtrace",
+    "collections/test-support",
+    "util/test-support",
+    "http/test-support",
+]
 runtime_shaders = []
 macos-blade = ["blade-graphics", "blade-macros", "blade-util", "bytemuck"]
 
@@ -104,7 +109,7 @@ copypasta = "0.10.1"
 
 [target.'cfg(target_os = "linux")'.dependencies]
 as-raw-xcb-connection = "1"
-ashpd = "0.8.0"
+ashpd.workspace = true
 calloop = "0.12.4"
 calloop-wayland-source = "0.2.0"
 wayland-backend = { version = "0.3.3", features = ["client_system"] }
@@ -128,7 +133,10 @@ x11rb = { version = "0.13.0", features = [
     "resource_manager",
 ] }
 xkbcommon = { version = "0.7", features = ["wayland", "x11"] }
-xim = { git = "https://github.com/npmania/xim-rs", rev = "27132caffc5b9bc9c432ca4afad184ab6e7c16af", features = ["x11rb-xcb", "x11rb-client"] }
+xim = { git = "https://github.com/npmania/xim-rs", rev = "27132caffc5b9bc9c432ca4afad184ab6e7c16af", features = [
+    "x11rb-xcb",
+    "x11rb-client",
+] }
 
 [target.'cfg(windows)'.dependencies]
 windows.workspace = true