Extract paths out of `util` (#13182)

Marshall Bowers created

This PR extracts the definition of the various Zed paths out of `util`
and into a new `paths` crate.

`util` is for generic utils, while these paths are Zed-specific. For
instance, `gpui` depends on `util`, and it shouldn't have knowledge of
these paths, since they are only used by Zed.

Release Notes:

- N/A

Change summary

Cargo.lock                                                      | 37 
Cargo.toml                                                      |  5 
crates/assistant/Cargo.toml                                     |  1 
crates/assistant/src/assistant.rs                               |  2 
crates/assistant/src/assistant_panel.rs                         |  3 
crates/assistant/src/context_store.rs                           |  3 
crates/assistant/src/prompt_library.rs                          |  3 
crates/cli/Cargo.toml                                           |  1 
crates/cli/src/main.rs                                          |  1 
crates/client/Cargo.toml                                        |  1 
crates/client/src/client.rs                                     |  2 
crates/client/src/telemetry.rs                                  |  2 
crates/copilot/Cargo.toml                                       |  1 
crates/copilot/src/copilot.rs                                   |  2 
crates/db/Cargo.toml                                            |  1 
crates/db/src/db.rs                                             |  2 
crates/extension/Cargo.toml                                     |  1 
crates/extension/src/extension_store.rs                         |  3 
crates/fs/Cargo.toml                                            | 24 
crates/fs/src/fs.rs                                             |  2 
crates/inline_completion_button/Cargo.toml                      |  1 
crates/inline_completion_button/src/inline_completion_button.rs |  2 
crates/languages/Cargo.toml                                     |  1 
crates/languages/src/json.rs                                    |  2 
crates/node_runtime/Cargo.toml                                  |  1 
crates/node_runtime/src/node_runtime.rs                         |  2 
crates/paths/Cargo.toml                                         | 17 
crates/paths/LICENSE-GPL                                        |  1 
crates/paths/src/paths.rs                                       | 92 +++
crates/prettier/Cargo.toml                                      |  1 
crates/prettier/src/prettier.rs                                 |  3 
crates/project/Cargo.toml                                       |  1 
crates/project/src/prettier_support.rs                          |  3 
crates/project/src/project.rs                                   | 10 
crates/rustdoc/Cargo.toml                                       |  1 
crates/rustdoc/src/store.rs                                     |  2 
crates/settings/Cargo.toml                                      |  1 
crates/settings/src/settings_file.rs                            |  2 
crates/supermaven_api/Cargo.toml                                |  2 
crates/supermaven_api/src/supermaven_api.rs                     |  2 
crates/terminal/Cargo.toml                                      |  2 
crates/terminal_view/Cargo.toml                                 |  2 
crates/util/Cargo.toml                                          |  2 
crates/util/src/paths.rs                                        | 84 --
crates/zed/Cargo.toml                                           |  1 
crates/zed/src/main.rs                                          | 14 
crates/zed/src/reliability.rs                                   |  2 
crates/zed/src/zed.rs                                           |  7 
crates/zed/src/zed/open_listener.rs                             |  1 
49 files changed, 208 insertions(+), 151 deletions(-)

Detailed changes

Cargo.lock 🔗

@@ -387,6 +387,7 @@ dependencies = [
  "open_ai",
  "ordered-float 2.10.0",
  "parking_lot",
+ "paths",
  "picker",
  "project",
  "rand 0.8.5",
@@ -2210,6 +2211,7 @@ dependencies = [
  "fork",
  "ipc-channel",
  "once_cell",
+ "paths",
  "plist",
  "release_channel",
  "serde",
@@ -2280,6 +2282,7 @@ dependencies = [
  "log",
  "once_cell",
  "parking_lot",
+ "paths",
  "postage",
  "rand 0.8.5",
  "release_channel",
@@ -2669,6 +2672,7 @@ dependencies = [
  "menu",
  "node_runtime",
  "parking_lot",
+ "paths",
  "project",
  "rpc",
  "serde",
@@ -3223,6 +3227,7 @@ dependencies = [
  "indoc",
  "lazy_static",
  "log",
+ "paths",
  "release_channel",
  "smol",
  "sqlez",
@@ -3393,15 +3398,6 @@ dependencies = [
  "subtle",
 ]
 
-[[package]]
-name = "dirs"
-version = "3.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "30baa043103c9d0c2a57cf537cc2f35623889dc0d405e6c3cccfadbc81c71309"
-dependencies = [
- "dirs-sys 0.3.7",
-]
-
 [[package]]
 name = "dirs"
 version = "4.0.0"
@@ -3856,6 +3852,7 @@ dependencies = [
  "lsp",
  "node_runtime",
  "parking_lot",
+ "paths",
  "project",
  "release_channel",
  "schemars",
@@ -4312,6 +4309,7 @@ dependencies = [
  "notify",
  "objc",
  "parking_lot",
+ "paths",
  "rope",
  "serde",
  "serde_json",
@@ -5445,6 +5443,7 @@ dependencies = [
  "indoc",
  "language",
  "lsp",
+ "paths",
  "project",
  "serde_json",
  "settings",
@@ -5898,6 +5897,7 @@ dependencies = [
  "log",
  "lsp",
  "node_runtime",
+ "paths",
  "project",
  "regex",
  "rope",
@@ -6667,6 +6667,7 @@ dependencies = [
  "futures 0.3.28",
  "http 0.1.0",
  "log",
+ "paths",
  "semver",
  "serde",
  "serde_json",
@@ -7402,6 +7403,15 @@ dependencies = [
  "rustc_version",
 ]
 
+[[package]]
+name = "paths"
+version = "0.1.0"
+dependencies = [
+ "dirs 4.0.0",
+ "lazy_static",
+ "util",
+]
+
 [[package]]
 name = "pbkdf2"
 version = "0.8.0"
@@ -7797,6 +7807,7 @@ dependencies = [
  "lsp",
  "node_runtime",
  "parking_lot",
+ "paths",
  "serde",
  "serde_json",
  "util",
@@ -7929,6 +7940,7 @@ dependencies = [
  "node_runtime",
  "parking_lot",
  "pathdiff",
+ "paths",
  "postage",
  "prettier",
  "pretty_assertions",
@@ -8871,6 +8883,7 @@ dependencies = [
  "indexmap 1.9.3",
  "indoc",
  "parking_lot",
+ "paths",
  "pretty_assertions",
  "serde",
  "strum",
@@ -9431,6 +9444,7 @@ dependencies = [
  "gpui",
  "indoc",
  "lazy_static",
+ "paths",
  "pretty_assertions",
  "release_channel",
  "rust-embed",
@@ -10266,10 +10280,10 @@ dependencies = [
  "anyhow",
  "futures 0.3.28",
  "http 0.1.0",
+ "paths",
  "serde",
  "serde_json",
  "smol",
- "util",
 ]
 
 [[package]]
@@ -11709,7 +11723,7 @@ dependencies = [
  "anyhow",
  "async-fs 1.6.0",
  "collections",
- "dirs 3.0.2",
+ "dirs 4.0.0",
  "futures 0.3.28",
  "futures-lite 1.13.0",
  "git2",
@@ -13480,6 +13494,7 @@ dependencies = [
  "outline",
  "outline_panel",
  "parking_lot",
+ "paths",
  "profiling",
  "project",
  "project_panel",

Cargo.toml 🔗

@@ -65,6 +65,7 @@ members = [
     "crates/open_ai",
     "crates/outline",
     "crates/outline_panel",
+    "crates/paths",
     "crates/picker",
     "crates/prettier",
     "crates/project",
@@ -215,6 +216,7 @@ ollama = { path = "crates/ollama" }
 open_ai = { path = "crates/open_ai" }
 outline = { path = "crates/outline" }
 outline_panel = { path = "crates/outline_panel" }
+paths = { path = "crates/paths" }
 picker = { path = "crates/picker" }
 plugin = { path = "crates/plugin" }
 plugin_macros = { path = "crates/plugin_macros" }
@@ -288,10 +290,10 @@ clap = { version = "4.4", features = ["derive"] }
 clickhouse = { version = "0.11.6" }
 cocoa = "0.25"
 ctor = "0.2.6"
-signal-hook = "0.3.17"
 core-foundation = { version = "0.9.3" }
 core-foundation-sys = "0.8.6"
 derive_more = "0.99.17"
+dirs = "4.0"
 emojis = "0.6.1"
 env_logger = "0.9"
 exec = "0.3.1"
@@ -354,6 +356,7 @@ serde_repr = "0.1"
 sha2 = "0.10"
 shellexpand = "2.1.0"
 shlex = "1.3.0"
+signal-hook = "0.3.17"
 similar = "1.3"
 smallvec = { version = "1.6", features = ["union"] }
 smol = "1.2"

crates/assistant/Cargo.toml 🔗

@@ -39,6 +39,7 @@ ollama = { workspace = true, features = ["schemars"] }
 open_ai = { workspace = true, features = ["schemars"] }
 ordered-float.workspace = true
 parking_lot.workspace = true
+paths.workspace = true
 project.workspace = true
 regex.workspace = true
 rope.workspace = true

crates/assistant/src/assistant.rs 🔗

@@ -21,6 +21,7 @@ pub(crate) use context_store::*;
 use gpui::{actions, AppContext, Global, SharedString, UpdateGlobal};
 pub(crate) use inline_assistant::*;
 pub(crate) use model_selector::*;
+use paths::EMBEDDINGS_DIR;
 use rustdoc::RustdocStore;
 use semantic_index::{CloudEmbeddingProvider, SemanticIndex};
 use serde::{Deserialize, Serialize};
@@ -34,7 +35,6 @@ use std::{
     sync::Arc,
 };
 pub(crate) use streaming_diff::*;
-use util::paths::EMBEDDINGS_DIR;
 
 actions!(
     assistant,

crates/assistant/src/assistant_panel.rs 🔗

@@ -40,6 +40,7 @@ use language::{
     LspAdapterDelegate, OffsetRangeExt as _, Point, ToOffset as _,
 };
 use multi_buffer::MultiBufferRow;
+use paths::CONTEXTS_DIR;
 use picker::{Picker, PickerDelegate};
 use project::{Project, ProjectLspAdapterDelegate, ProjectTransaction};
 use rustdoc::{CrateName, RustdocStore};
@@ -59,7 +60,7 @@ use ui::{
     prelude::*, ButtonLike, ContextMenu, Disclosure, ElevationIndex, KeyBinding, ListItem,
     ListItemSpacing, PopoverMenu, PopoverMenuHandle, Tab, TabBar, Tooltip,
 };
-use util::{paths::CONTEXTS_DIR, post_inc, ResultExt, TryFutureExt};
+use util::{post_inc, ResultExt, TryFutureExt};
 use uuid::Uuid;
 use workspace::NewFile;
 use workspace::{

crates/assistant/src/context_store.rs 🔗

@@ -5,11 +5,12 @@ use fs::Fs;
 use futures::StreamExt;
 use fuzzy::StringMatchCandidate;
 use gpui::{AppContext, Model, ModelContext, Task};
+use paths::CONTEXTS_DIR;
 use regex::Regex;
 use serde::{Deserialize, Serialize};
 use std::{cmp::Reverse, ffi::OsStr, path::PathBuf, sync::Arc, time::Duration};
 use ui::Context;
-use util::{paths::CONTEXTS_DIR, ResultExt, TryFutureExt};
+use util::{ResultExt, TryFutureExt};
 
 #[derive(Serialize, Deserialize)]
 pub struct SavedMessage {

crates/assistant/src/prompt_library.rs 🔗

@@ -20,6 +20,7 @@ use gpui::{
 use heed::{types::SerdeBincode, Database, RoTxn};
 use language::{language_settings::SoftWrap, Buffer, LanguageRegistry};
 use parking_lot::RwLock;
+use paths::PROMPTS_DIR;
 use picker::{Picker, PickerDelegate};
 use rope::Rope;
 use serde::{Deserialize, Serialize};
@@ -36,7 +37,7 @@ use ui::{
     div, prelude::*, IconButtonShape, ListItem, ListItemSpacing, ParentElement, Render,
     SharedString, Styled, TitleBar, Tooltip, ViewContext, VisualContext,
 };
-use util::{paths::PROMPTS_DIR, ResultExt, TryFutureExt};
+use util::{ResultExt, TryFutureExt};
 use uuid::Uuid;
 use workspace::Workspace;
 

crates/cli/Cargo.toml 🔗

@@ -21,6 +21,7 @@ anyhow.workspace = true
 clap.workspace = true
 ipc-channel = "0.18"
 once_cell.workspace = true
+paths.workspace = true
 release_channel.workspace = true
 serde.workspace = true
 util.workspace = true

crates/cli/src/main.rs 🔗

@@ -172,7 +172,6 @@ mod linux {
     use cli::FORCE_CLI_MODE_ENV_VAR_NAME;
     use fork::Fork;
     use once_cell::sync::Lazy;
-    use util::paths;
 
     use crate::{Detect, InstalledApp};
 

crates/client/Cargo.toml 🔗

@@ -31,6 +31,7 @@ http.workspace = true
 lazy_static.workspace = true
 log.workspace = true
 once_cell.workspace = true
+paths.workspace = true
 parking_lot.workspace = true
 postage.workspace = true
 rand.workspace = true

crates/client/src/client.rs 🔗

@@ -509,7 +509,7 @@ impl Client {
         let credentials_provider: Arc<dyn CredentialsProvider + Send + Sync + 'static> =
             if use_zed_development_auth {
                 Arc::new(DevelopmentCredentialsProvider {
-                    path: util::paths::CONFIG_DIR.join("development_auth"),
+                    path: paths::CONFIG_DIR.join("development_auth"),
                 })
             } else {
                 Arc::new(KeychainCredentialsProvider)

crates/client/src/telemetry.rs 🔗

@@ -223,7 +223,7 @@ impl Telemetry {
                 let state = state.clone();
                 async move {
                     if let Some(tempfile) =
-                        NamedTempFile::new_in(util::paths::CONFIG_DIR.as_path()).log_err()
+                        NamedTempFile::new_in(paths::CONFIG_DIR.as_path()).log_err()
                     {
                         state.lock().log_file = Some(tempfile);
                     }

crates/copilot/Cargo.toml 🔗

@@ -38,6 +38,7 @@ lsp.workspace = true
 menu.workspace = true
 node_runtime.workspace = true
 parking_lot.workspace = true
+paths.workspace = true
 project.workspace = true
 serde.workspace = true
 settings.workspace = true

crates/copilot/src/copilot.rs 🔗

@@ -33,7 +33,7 @@ use std::{
     path::{Path, PathBuf},
     sync::Arc,
 };
-use util::{fs::remove_matching, maybe, paths, ResultExt};
+use util::{fs::remove_matching, maybe, ResultExt};
 
 pub use copilot_completion_provider::CopilotCompletionProvider;
 pub use sign_in::CopilotCodeVerification;

crates/db/Cargo.toml 🔗

@@ -21,6 +21,7 @@ gpui.workspace = true
 indoc.workspace = true
 lazy_static.workspace = true
 log.workspace = true
+paths.workspace = true
 release_channel.workspace = true
 smol.workspace = true
 sqlez.workspace = true

crates/db/src/db.rs 🔗

@@ -7,10 +7,10 @@ use anyhow::Context;
 use gpui::AppContext;
 pub use indoc::indoc;
 pub use lazy_static;
+pub use paths::DB_DIR;
 pub use smol;
 pub use sqlez;
 pub use sqlez_macros;
-pub use util::paths::DB_DIR;
 
 use release_channel::ReleaseChannel;
 pub use release_channel::RELEASE_CHANNEL;

crates/extension/Cargo.toml 🔗

@@ -33,6 +33,7 @@ language.workspace = true
 log.workspace = true
 lsp.workspace = true
 node_runtime.workspace = true
+paths.workspace = true
 project.workspace = true
 release_channel.workspace = true
 schemars.workspace = true

crates/extension/src/extension_store.rs 🔗

@@ -36,6 +36,7 @@ use language::{
     LanguageConfig, LanguageMatcher, LanguageQueries, LanguageRegistry, QUERY_FILENAME_PREFIXES,
 };
 use node_runtime::NodeRuntime;
+use paths::EXTENSIONS_DIR;
 use project::ContextProviderWithTasks;
 use release_channel::ReleaseChannel;
 use semantic_version::SemanticVersion;
@@ -51,7 +52,7 @@ use std::{
 };
 use theme::{ThemeRegistry, ThemeSettings};
 use url::Url;
-use util::{maybe, paths::EXTENSIONS_DIR, ResultExt};
+use util::{maybe, ResultExt};
 use wasm_host::{
     wit::{is_supported_wasm_api_version, wasm_api_version_range},
     WasmExtension, WasmHost,

crates/fs/Cargo.toml 🔗

@@ -12,34 +12,32 @@ workspace = true
 path = "src/fs.rs"
 
 [dependencies]
-collections.workspace = true
-rope.workspace = true
-text.workspace = true
-util.workspace = true
-
 anyhow.workspace = true
 async-tar.workspace = true
 async-trait.workspace = true
+collections.workspace = true
 futures.workspace = true
-tempfile.workspace = true
-lazy_static.workspace = true
-parking_lot.workspace = true
-smol.workspace = true
 git.workspace = true
 git2.workspace = true
+gpui = { workspace = true, optional = true }
+lazy_static.workspace = true
+libc.workspace = true
+parking_lot.workspace = true
+paths.workspace = true
+rope.workspace = true
 serde.workspace = true
 serde_json.workspace = true
-libc.workspace = true
+smol.workspace = true
+tempfile.workspace = true
+text.workspace = true
 time.workspace = true
-
-gpui = { workspace = true, optional = true }
+util.workspace = true
 
 [target.'cfg(target_os = "macos")'.dependencies]
 fsevent.workspace = true
 objc = "0.2"
 cocoa = "0.25"
 
-
 [target.'cfg(not(target_os = "macos"))'.dependencies]
 notify = "6.1.1"
 

crates/fs/src/fs.rs 🔗

@@ -23,7 +23,7 @@ use std::{
 };
 use tempfile::{NamedTempFile, TempDir};
 use text::LineEnding;
-use util::{paths, ResultExt};
+use util::ResultExt;
 
 #[cfg(any(test, feature = "test-support"))]
 use collections::{btree_map, BTreeMap};

crates/inline_completion_button/Cargo.toml 🔗

@@ -19,6 +19,7 @@ editor.workspace = true
 fs.workspace = true
 gpui.workspace = true
 language.workspace = true
+paths.workspace = true
 settings.workspace = true
 supermaven.workspace = true
 ui.workspace = true

crates/inline_completion_button/src/inline_completion_button.rs 🔗

@@ -15,7 +15,7 @@ use language::{
 use settings::{update_settings_file, Settings, SettingsStore};
 use std::{path::Path, sync::Arc};
 use supermaven::{AccountStatus, Supermaven};
-use util::{paths, ResultExt};
+use util::ResultExt;
 use workspace::{
     create_and_open_local_file,
     item::ItemHandle,

crates/languages/Cargo.toml 🔗

@@ -26,6 +26,7 @@ lazy_static.workspace = true
 log.workspace = true
 lsp.workspace = true
 node_runtime.workspace = true
+paths.workspace = true
 project.workspace = true
 regex.workspace = true
 rope.workspace = true

crates/languages/src/json.rs 🔗

@@ -19,7 +19,7 @@ use std::{
     sync::{Arc, OnceLock},
 };
 use task::{TaskTemplate, TaskTemplates, VariableName};
-use util::{maybe, paths, ResultExt};
+use util::{maybe, ResultExt};
 
 const SERVER_PATH: &str = "node_modules/vscode-json-languageserver/bin/vscode-json-languageserver";
 

crates/node_runtime/Cargo.toml 🔗

@@ -24,6 +24,7 @@ async_zip.workspace = true
 futures.workspace = true
 http.workspace = true
 log.workspace = true
+paths.workspace = true
 semver.workspace = true
 serde.workspace = true
 serde_json.workspace = true

crates/node_runtime/src/node_runtime.rs 🔗

@@ -138,7 +138,7 @@ impl RealNodeRuntime {
         };
 
         let folder_name = format!("node-{VERSION}-{os}-{arch}");
-        let node_containing_dir = util::paths::SUPPORT_DIR.join("node");
+        let node_containing_dir = paths::SUPPORT_DIR.join("node");
         let node_dir = node_containing_dir.join(folder_name);
         let node_binary = node_dir.join(NODE_PATH);
         let npm_file = node_dir.join(NPM_PATH);

crates/paths/Cargo.toml 🔗

@@ -0,0 +1,17 @@
+[package]
+name = "paths"
+version = "0.1.0"
+edition = "2021"
+publish = false
+license = "GPL-3.0-or-later"
+
+[lints]
+workspace = true
+
+[lib]
+path = "src/paths.rs"
+
+[dependencies]
+dirs.workspace = true
+lazy_static.workspace = true
+util.workspace = true

crates/paths/src/paths.rs 🔗

@@ -0,0 +1,92 @@
+//! Paths to locations used by Zed.
+
+use std::path::{Path, PathBuf};
+
+use util::paths::HOME;
+
+lazy_static::lazy_static! {
+    pub static ref CONFIG_DIR: PathBuf = if cfg!(target_os = "windows") {
+        dirs::config_dir()
+            .expect("failed to determine RoamingAppData directory")
+            .join("Zed")
+    } else if cfg!(target_os = "linux") {
+        if let Ok(flatpak_xdg_config) = std::env::var("FLATPAK_XDG_CONFIG_HOME") {
+           flatpak_xdg_config.into()
+        } else {
+            dirs::config_dir().expect("failed to determine XDG_CONFIG_HOME directory")
+        }.join("zed")
+    } else {
+        HOME.join(".config").join("zed")
+    };
+    pub static ref CONTEXTS_DIR: PathBuf = if cfg!(target_os = "macos") {
+        CONFIG_DIR.join("conversations")
+    } else {
+        SUPPORT_DIR.join("conversations")
+    };
+    pub static ref PROMPTS_DIR: PathBuf = if cfg!(target_os = "macos") {
+        CONFIG_DIR.join("prompts")
+    } else {
+        SUPPORT_DIR.join("prompts")
+    };
+    pub static ref EMBEDDINGS_DIR: PathBuf = if cfg!(target_os = "macos") {
+        CONFIG_DIR.join("embeddings")
+    } else {
+        SUPPORT_DIR.join("embeddings")
+    };
+    pub static ref THEMES_DIR: PathBuf = CONFIG_DIR.join("themes");
+
+    pub static ref SUPPORT_DIR: PathBuf = if cfg!(target_os = "macos") {
+        HOME.join("Library/Application Support/Zed")
+    } else if cfg!(target_os = "linux") {
+        if let Ok(flatpak_xdg_data) = std::env::var("FLATPAK_XDG_DATA_HOME") {
+            flatpak_xdg_data.into()
+        } else {
+            dirs::data_local_dir().expect("failed to determine XDG_DATA_HOME directory")
+        }.join("zed")
+    } else if cfg!(target_os = "windows") {
+        dirs::data_local_dir()
+            .expect("failed to determine LocalAppData directory")
+            .join("Zed")
+    } else {
+        CONFIG_DIR.clone()
+    };
+    pub static ref LOGS_DIR: PathBuf = if cfg!(target_os = "macos") {
+        HOME.join("Library/Logs/Zed")
+    } else {
+        SUPPORT_DIR.join("logs")
+    };
+    pub static ref EXTENSIONS_DIR: PathBuf = SUPPORT_DIR.join("extensions");
+    pub static ref LANGUAGES_DIR: PathBuf = SUPPORT_DIR.join("languages");
+    pub static ref COPILOT_DIR: PathBuf = SUPPORT_DIR.join("copilot");
+    pub static ref SUPERMAVEN_DIR: PathBuf = SUPPORT_DIR.join("supermaven");
+    pub static ref DEFAULT_PRETTIER_DIR: PathBuf = SUPPORT_DIR.join("prettier");
+    pub static ref DB_DIR: PathBuf = SUPPORT_DIR.join("db");
+    pub static ref CRASHES_DIR: Option<PathBuf> = cfg!(target_os = "macos")
+        .then_some(HOME.join("Library/Logs/DiagnosticReports"));
+    pub static ref CRASHES_RETIRED_DIR: Option<PathBuf> = CRASHES_DIR
+        .as_ref()
+        .map(|dir| dir.join("Retired"));
+
+    pub static ref SETTINGS: PathBuf = CONFIG_DIR.join("settings.json");
+    pub static ref KEYMAP: PathBuf = CONFIG_DIR.join("keymap.json");
+    pub static ref TASKS: PathBuf = CONFIG_DIR.join("tasks.json");
+    pub static ref LAST_USERNAME: PathBuf = CONFIG_DIR.join("last-username.txt");
+    pub static ref LOG: PathBuf = LOGS_DIR.join("Zed.log");
+    pub static ref OLD_LOG: PathBuf = LOGS_DIR.join("Zed.log.old");
+    pub static ref LOCAL_SETTINGS_RELATIVE_PATH: &'static Path = Path::new(".zed/settings.json");
+    pub static ref LOCAL_TASKS_RELATIVE_PATH: &'static Path = Path::new(".zed/tasks.json");
+    pub static ref LOCAL_VSCODE_TASKS_RELATIVE_PATH: &'static Path = Path::new(".vscode/tasks.json");
+    pub static ref TEMP_DIR: PathBuf = if cfg!(target_os = "windows") {
+        dirs::cache_dir()
+            .expect("failed to determine LocalAppData directory")
+            .join("Zed")
+    } else if cfg!(target_os = "linux") {
+        if let Ok(flatpak_xdg_cache) = std::env::var("FLATPAK_XDG_CACHE_HOME") {
+            flatpak_xdg_cache.into()
+        } else {
+            dirs::cache_dir().expect("failed to determine XDG_CACHE_HOME directory")
+        }.join("zed")
+    } else {
+        HOME.join(".cache").join("zed")
+    };
+}

crates/prettier/Cargo.toml 🔗

@@ -25,6 +25,7 @@ log.workspace = true
 lsp.workspace = true
 node_runtime.workspace = true
 parking_lot.workspace = true
+paths.workspace = true
 serde.workspace = true
 serde_json.workspace = true
 util.workspace = true

crates/prettier/src/prettier.rs 🔗

@@ -5,13 +5,14 @@ use gpui::{AsyncAppContext, Model};
 use language::{language_settings::language_settings, Buffer, Diff};
 use lsp::{LanguageServer, LanguageServerId};
 use node_runtime::NodeRuntime;
+use paths::DEFAULT_PRETTIER_DIR;
 use serde::{Deserialize, Serialize};
 use std::{
     ops::ControlFlow,
     path::{Path, PathBuf},
     sync::Arc,
 };
-use util::paths::{PathMatcher, DEFAULT_PRETTIER_DIR};
+use util::paths::PathMatcher;
 
 #[derive(Clone)]
 pub enum Prettier {

crates/project/Cargo.toml 🔗

@@ -45,6 +45,7 @@ lsp.workspace = true
 node_runtime.workspace = true
 parking_lot.workspace = true
 pathdiff.workspace = true
+paths.workspace = true
 postage.workspace = true
 prettier.workspace = true
 worktree.workspace = true

crates/project/src/prettier_support.rs 🔗

@@ -18,8 +18,9 @@ use language::{
 };
 use lsp::{LanguageServer, LanguageServerId};
 use node_runtime::NodeRuntime;
+use paths::DEFAULT_PRETTIER_DIR;
 use prettier::Prettier;
-use util::{paths::DEFAULT_PRETTIER_DIR, ResultExt, TryFutureExt};
+use util::{ResultExt, TryFutureExt};
 
 use crate::{
     Event, File, FormatOperation, PathChange, Project, ProjectEntryId, Worktree, WorktreeId,

crates/project/src/project.rs 🔗

@@ -66,6 +66,9 @@ use lsp::{
 use lsp_command::*;
 use node_runtime::NodeRuntime;
 use parking_lot::{Mutex, RwLock};
+use paths::{
+    LOCAL_SETTINGS_RELATIVE_PATH, LOCAL_TASKS_RELATIVE_PATH, LOCAL_VSCODE_TASKS_RELATIVE_PATH,
+};
 use postage::watch;
 use prettier_support::{DefaultPrettier, PrettierInstance};
 use project_settings::{LspSettings, ProjectSettings};
@@ -107,11 +110,8 @@ use terminals::Terminals;
 use text::{Anchor, BufferId, LineEnding};
 use unicase::UniCase;
 use util::{
-    debug_panic, defer, maybe, merge_json_value_into, parse_env_output,
-    paths::{
-        LOCAL_SETTINGS_RELATIVE_PATH, LOCAL_TASKS_RELATIVE_PATH, LOCAL_VSCODE_TASKS_RELATIVE_PATH,
-    },
-    post_inc, NumericPrefixWithSuffix, ResultExt, TryFutureExt as _,
+    debug_panic, defer, maybe, merge_json_value_into, parse_env_output, post_inc,
+    NumericPrefixWithSuffix, ResultExt, TryFutureExt as _,
 };
 use worktree::{CreatedEntry, RemoteWorktreeClient, Snapshot, Traversal};
 

crates/rustdoc/Cargo.toml 🔗

@@ -25,6 +25,7 @@ html_to_markdown.workspace = true
 http.workspace = true
 indexmap.workspace = true
 parking_lot.workspace = true
+paths.workspace = true
 serde.workspace = true
 strum.workspace = true
 util.workspace = true

crates/rustdoc/src/store.rs 🔗

@@ -12,8 +12,8 @@ use gpui::{AppContext, BackgroundExecutor, Global, ReadGlobal, Task, UpdateGloba
 use heed::types::SerdeBincode;
 use heed::Database;
 use parking_lot::RwLock;
+use paths::SUPPORT_DIR;
 use serde::{Deserialize, Serialize};
-use util::paths::SUPPORT_DIR;
 use util::ResultExt;
 
 use crate::indexer::{RustdocIndexer, RustdocProvider};

crates/settings/Cargo.toml 🔗

@@ -22,6 +22,7 @@ fs.workspace = true
 futures.workspace = true
 gpui.workspace = true
 lazy_static.workspace = true
+paths.workspace = true
 release_channel.workspace = true
 rust-embed.workspace = true
 schemars.workspace = true

crates/settings/src/settings_file.rs 🔗

@@ -4,7 +4,7 @@ use fs::Fs;
 use futures::{channel::mpsc, StreamExt};
 use gpui::{AppContext, BackgroundExecutor, UpdateGlobal};
 use std::{io::ErrorKind, path::PathBuf, sync::Arc, time::Duration};
-use util::{paths, ResultExt};
+use util::ResultExt;
 
 pub const EMPTY_THEME_NAME: &str = "empty-theme";
 

crates/supermaven_api/Cargo.toml 🔗

@@ -16,7 +16,7 @@ doctest = false
 anyhow.workspace = true
 futures.workspace = true
 http.workspace = true
+paths.workspace = true
 serde.workspace = true
 serde_json.workspace = true
 smol.workspace = true
-util.workspace = true

crates/supermaven_api/src/supermaven_api.rs 🔗

@@ -2,12 +2,12 @@ use anyhow::{anyhow, Context, Result};
 use futures::io::BufReader;
 use futures::{AsyncReadExt, Future};
 use http::{AsyncBody, HttpClient, Request as HttpRequest};
+use paths::SUPERMAVEN_DIR;
 use serde::{Deserialize, Serialize};
 use smol::fs::{self, File};
 use smol::stream::StreamExt;
 use std::path::{Path, PathBuf};
 use std::sync::Arc;
-use util::paths::SUPERMAVEN_DIR;
 
 #[derive(Serialize)]
 pub struct GetExternalUserRequest {

crates/terminal/Cargo.toml 🔗

@@ -17,7 +17,7 @@ doctest = false
 alacritty_terminal = { git = "https://github.com/alacritty/alacritty", rev = "cacdb5bb3b72bad2c729227537979d95af75978f" }
 anyhow.workspace = true
 collections.workspace = true
-dirs = "4.0.0"
+dirs.workspace = true
 futures.workspace = true
 gpui.workspace = true
 libc.workspace = true

crates/terminal_view/Cargo.toml 🔗

@@ -16,7 +16,7 @@ doctest = false
 anyhow.workspace = true
 db.workspace = true
 collections.workspace = true
-dirs = "4.0.0"
+dirs.workspace = true
 editor.workspace = true
 futures.workspace = true
 gpui.workspace = true

crates/util/Cargo.toml 🔗

@@ -18,7 +18,7 @@ test-support = ["tempfile", "git2"]
 [dependencies]
 anyhow.workspace = true
 collections.workspace = true
-dirs = "3.0"
+dirs.workspace = true
 futures.workspace = true
 git2 = { workspace = true, optional = true }
 globset.workspace = true

crates/util/src/paths.rs 🔗

@@ -8,90 +8,6 @@ use serde::{Deserialize, Serialize};
 
 lazy_static::lazy_static! {
     pub static ref HOME: PathBuf = dirs::home_dir().expect("failed to determine home directory");
-    pub static ref CONFIG_DIR: PathBuf = if cfg!(target_os = "windows") {
-        dirs::config_dir()
-            .expect("failed to determine RoamingAppData directory")
-            .join("Zed")
-    } else if cfg!(target_os = "linux") {
-        if let Ok(flatpak_xdg_config) = std::env::var("FLATPAK_XDG_CONFIG_HOME") {
-           flatpak_xdg_config.into()
-        } else {
-            dirs::config_dir().expect("failed to determine XDG_CONFIG_HOME directory")
-        }.join("zed")
-    } else {
-        HOME.join(".config").join("zed")
-    };
-    pub static ref CONTEXTS_DIR: PathBuf = if cfg!(target_os = "macos") {
-        CONFIG_DIR.join("conversations")
-    } else {
-        SUPPORT_DIR.join("conversations")
-    };
-    pub static ref PROMPTS_DIR: PathBuf = if cfg!(target_os = "macos") {
-        CONFIG_DIR.join("prompts")
-    } else {
-        SUPPORT_DIR.join("prompts")
-    };
-    pub static ref EMBEDDINGS_DIR: PathBuf = if cfg!(target_os = "macos") {
-        CONFIG_DIR.join("embeddings")
-    } else {
-        SUPPORT_DIR.join("embeddings")
-    };
-    pub static ref THEMES_DIR: PathBuf = CONFIG_DIR.join("themes");
-
-    pub static ref SUPPORT_DIR: PathBuf = if cfg!(target_os = "macos") {
-        HOME.join("Library/Application Support/Zed")
-    } else if cfg!(target_os = "linux") {
-        if let Ok(flatpak_xdg_data) = std::env::var("FLATPAK_XDG_DATA_HOME") {
-            flatpak_xdg_data.into()
-        } else {
-            dirs::data_local_dir().expect("failed to determine XDG_DATA_HOME directory")
-        }.join("zed")
-    } else if cfg!(target_os = "windows") {
-        dirs::data_local_dir()
-            .expect("failed to determine LocalAppData directory")
-            .join("Zed")
-    } else {
-        CONFIG_DIR.clone()
-    };
-    pub static ref LOGS_DIR: PathBuf = if cfg!(target_os = "macos") {
-        HOME.join("Library/Logs/Zed")
-    } else {
-        SUPPORT_DIR.join("logs")
-    };
-    pub static ref EXTENSIONS_DIR: PathBuf = SUPPORT_DIR.join("extensions");
-    pub static ref LANGUAGES_DIR: PathBuf = SUPPORT_DIR.join("languages");
-    pub static ref COPILOT_DIR: PathBuf = SUPPORT_DIR.join("copilot");
-    pub static ref SUPERMAVEN_DIR: PathBuf = SUPPORT_DIR.join("supermaven");
-    pub static ref DEFAULT_PRETTIER_DIR: PathBuf = SUPPORT_DIR.join("prettier");
-    pub static ref DB_DIR: PathBuf = SUPPORT_DIR.join("db");
-    pub static ref CRASHES_DIR: Option<PathBuf> = cfg!(target_os = "macos")
-        .then_some(HOME.join("Library/Logs/DiagnosticReports"));
-    pub static ref CRASHES_RETIRED_DIR: Option<PathBuf> = CRASHES_DIR
-        .as_ref()
-        .map(|dir| dir.join("Retired"));
-
-    pub static ref SETTINGS: PathBuf = CONFIG_DIR.join("settings.json");
-    pub static ref KEYMAP: PathBuf = CONFIG_DIR.join("keymap.json");
-    pub static ref TASKS: PathBuf = CONFIG_DIR.join("tasks.json");
-    pub static ref LAST_USERNAME: PathBuf = CONFIG_DIR.join("last-username.txt");
-    pub static ref LOG: PathBuf = LOGS_DIR.join("Zed.log");
-    pub static ref OLD_LOG: PathBuf = LOGS_DIR.join("Zed.log.old");
-    pub static ref LOCAL_SETTINGS_RELATIVE_PATH: &'static Path = Path::new(".zed/settings.json");
-    pub static ref LOCAL_TASKS_RELATIVE_PATH: &'static Path = Path::new(".zed/tasks.json");
-    pub static ref LOCAL_VSCODE_TASKS_RELATIVE_PATH: &'static Path = Path::new(".vscode/tasks.json");
-    pub static ref TEMP_DIR: PathBuf = if cfg!(target_os = "windows") {
-        dirs::cache_dir()
-            .expect("failed to determine LocalAppData directory")
-            .join("Zed")
-    } else if cfg!(target_os = "linux") {
-        if let Ok(flatpak_xdg_cache) = std::env::var("FLATPAK_XDG_CACHE_HOME") {
-            flatpak_xdg_cache.into()
-        } else {
-            dirs::cache_dir().expect("failed to determine XDG_CACHE_HOME directory")
-        }.join("zed")
-    } else {
-        HOME.join(".cache").join("zed")
-    };
 }
 
 pub trait PathExt {

crates/zed/Cargo.toml 🔗

@@ -70,6 +70,7 @@ notifications.workspace = true
 outline.workspace = true
 outline_panel.workspace = true
 parking_lot.workspace = true
+paths.workspace = true
 profiling.workspace = true
 project.workspace = true
 project_panel.workspace = true

crates/zed/src/main.rs 🔗

@@ -40,7 +40,7 @@ use std::{
     sync::Arc,
 };
 use theme::{ActiveTheme, SystemAppearance, ThemeRegistry, ThemeSettings};
-use util::{maybe, parse_env_output, paths, with_clone, ResultExt, TryFutureExt};
+use util::{maybe, parse_env_output, with_clone, ResultExt, TryFutureExt};
 use uuid::Uuid;
 use welcome::{show_welcome_view, BaseKeymap, FIRST_OPEN};
 use workspace::{AppState, WorkspaceSettings, WorkspaceStore};
@@ -668,12 +668,12 @@ async fn restore_or_create_workspace(
 
 fn init_paths() -> anyhow::Result<()> {
     for path in [
-        &*util::paths::CONFIG_DIR,
-        &*util::paths::EXTENSIONS_DIR,
-        &*util::paths::LANGUAGES_DIR,
-        &*util::paths::DB_DIR,
-        &*util::paths::LOGS_DIR,
-        &*util::paths::TEMP_DIR,
+        &*paths::CONFIG_DIR,
+        &*paths::EXTENSIONS_DIR,
+        &*paths::LANGUAGES_DIR,
+        &*paths::DB_DIR,
+        &*paths::LOGS_DIR,
+        &*paths::TEMP_DIR,
     ]
     .iter()
     {

crates/zed/src/reliability.rs 🔗

@@ -22,7 +22,7 @@ use std::{io::Write, panic, sync::atomic::AtomicU32, thread};
 use telemetry_events::LocationData;
 use telemetry_events::Panic;
 use telemetry_events::PanicRequest;
-use util::{paths, ResultExt};
+use util::ResultExt;
 
 use crate::stdout_is_a_pty;
 static PANIC_COUNT: AtomicU32 = AtomicU32::new(0);

crates/zed/src/zed.rs 🔗

@@ -36,12 +36,9 @@ use task::static_source::{StaticSource, TrackedFile};
 use theme::ActiveTheme;
 use workspace::notifications::NotificationId;
 
+use paths::{LOCAL_SETTINGS_RELATIVE_PATH, LOCAL_TASKS_RELATIVE_PATH};
 use terminal_view::terminal_panel::{self, TerminalPanel};
-use util::{
-    asset_str,
-    paths::{self, LOCAL_SETTINGS_RELATIVE_PATH, LOCAL_TASKS_RELATIVE_PATH},
-    ResultExt,
-};
+use util::{asset_str, ResultExt};
 use uuid::Uuid;
 use vim::VimModeSetting;
 use welcome::BaseKeymap;

crates/zed/src/zed/open_listener.rs 🔗

@@ -113,7 +113,6 @@ impl OpenListener {
 pub fn listen_for_cli_connections(opener: OpenListener) -> Result<()> {
     use release_channel::RELEASE_CHANNEL_NAME;
     use std::os::unix::net::UnixDatagram;
-    use util::paths;
 
     let sock_path = paths::SUPPORT_DIR.join(format!("zed-{}.sock", *RELEASE_CHANNEL_NAME));
     // remove the socket if the process listening on it has died