Add global `Fs` instance (#15044)

Marshall Bowers created

This PR adds a global `Fs` instance to the app context.

This will make it easier to access the filesystem in some cases instead
of having to thread it around.

Release Notes:

- N/A

Change summary

crates/fs/Cargo.toml   |  2 +-
crates/fs/src/fs.rs    | 17 +++++++++++++++++
crates/zed/src/main.rs |  4 +++-
3 files changed, 21 insertions(+), 2 deletions(-)

Detailed changes

crates/fs/Cargo.toml 🔗

@@ -19,7 +19,7 @@ collections.workspace = true
 futures.workspace = true
 git.workspace = true
 git2.workspace = true
-gpui = { workspace = true, optional = true }
+gpui.workspace = true
 lazy_static.workspace = true
 libc.workspace = true
 parking_lot.workspace = true

crates/fs/src/fs.rs 🔗

@@ -12,6 +12,7 @@ use std::os::unix::fs::MetadataExt;
 use async_tar::Archive;
 use futures::{future::BoxFuture, AsyncRead, Stream, StreamExt};
 use git::repository::{GitRepository, RealGitRepository};
+use gpui::{AppContext, Global, ReadGlobal};
 use rope::Rope;
 use smol::io::AsyncWriteExt;
 use std::{
@@ -102,6 +103,22 @@ pub trait Fs: Send + Sync {
     }
 }
 
+struct GlobalFs(Arc<dyn Fs>);
+
+impl Global for GlobalFs {}
+
+impl dyn Fs {
+    /// Returns the global [`Fs`].
+    pub fn global(cx: &AppContext) -> Arc<Self> {
+        GlobalFs::global(cx).0.clone()
+    }
+
+    /// Sets the global [`Fs`].
+    pub fn set_global(fs: Arc<Self>, cx: &mut AppContext) {
+        cx.set_global(GlobalFs(fs));
+    }
+}
+
 #[derive(Copy, Clone, Default)]
 pub struct CreateOptions {
     pub overwrite: bool,

crates/zed/src/main.rs 🔗

@@ -14,7 +14,7 @@ use collab_ui::channel_view::ChannelView;
 use db::kvp::KEY_VALUE_STORE;
 use editor::Editor;
 use env_logger::Builder;
-use fs::RealFs;
+use fs::{Fs, RealFs};
 use futures::{future, StreamExt};
 use git::GitHostingProviderRegistry;
 use gpui::{
@@ -399,6 +399,8 @@ fn main() {
             AppCommitSha::set_global(AppCommitSha(build_sha.into()), cx);
         }
 
+        <dyn Fs>::set_global(fs.clone(), cx);
+
         GitHostingProviderRegistry::set_global(git_hosting_provider_registry, cx);
         git_hosting_providers::init(cx);