mirror of
https://github.com/zed-industries/zed.git
synced 2024-12-29 06:33:52 +03:00
Merge pull request #1430 from zed-industries/xdg-compliance
Store config files under `~/.config/zed` and data files under `~/Library/Application Support/Zed`
This commit is contained in:
commit
a59813cec5
@ -1,5 +1,5 @@
|
||||
use anyhow::Result;
|
||||
use std::path::PathBuf;
|
||||
use std::path::Path;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub struct Db(DbStore);
|
||||
@ -16,8 +16,8 @@ enum DbStore {
|
||||
|
||||
impl Db {
|
||||
/// Open or create a database at the given file path.
|
||||
pub fn open(path: PathBuf) -> Result<Arc<Self>> {
|
||||
let db = rocksdb::DB::open_default(&path)?;
|
||||
pub fn open(path: &Path) -> Result<Arc<Self>> {
|
||||
let db = rocksdb::DB::open_default(path)?;
|
||||
Ok(Arc::new(Self(DbStore::Real(db))))
|
||||
}
|
||||
|
||||
@ -125,7 +125,7 @@ mod tests {
|
||||
fn test_db() {
|
||||
let dir = TempDir::new("db-test").unwrap();
|
||||
let fake_db = Db::open_fake();
|
||||
let real_db = Db::open(dir.path().join("test.db")).unwrap();
|
||||
let real_db = Db::open(&dir.path().join("test.db")).unwrap();
|
||||
|
||||
for db in [&real_db, &fake_db] {
|
||||
assert_eq!(
|
||||
@ -152,7 +152,7 @@ mod tests {
|
||||
|
||||
drop(real_db);
|
||||
|
||||
let real_db = Db::open(dir.path().join("test.db")).unwrap();
|
||||
let real_db = Db::open(&dir.path().join("test.db")).unwrap();
|
||||
assert_eq!(
|
||||
real_db.read(["key-1", "key-2", "key-3"]).unwrap(),
|
||||
&[Some("one".as_bytes().to_vec()), None, None,]
|
||||
|
@ -28,15 +28,7 @@ use project::{Fs, ProjectStore};
|
||||
use serde_json::json;
|
||||
use settings::{self, KeymapFileContent, Settings, SettingsFileContent};
|
||||
use smol::process::Command;
|
||||
use std::{
|
||||
env,
|
||||
ffi::OsStr,
|
||||
fs, panic,
|
||||
path::{Path, PathBuf},
|
||||
sync::Arc,
|
||||
thread,
|
||||
time::Duration,
|
||||
};
|
||||
use std::{env, ffi::OsStr, fs, panic, path::PathBuf, sync::Arc, thread, time::Duration};
|
||||
use terminal;
|
||||
use theme::ThemeRegistry;
|
||||
use util::{ResultExt, TryFutureExt};
|
||||
@ -50,21 +42,17 @@ use zed::{
|
||||
|
||||
fn main() {
|
||||
let http = http::client();
|
||||
let home_dir = dirs::home_dir().expect("could not find home dir");
|
||||
let db_dir_path = home_dir.join("Library/Application Support/Zed");
|
||||
let logs_dir_path = home_dir.join("Library/Logs/Zed");
|
||||
fs::create_dir_all(&db_dir_path).expect("could not create database path");
|
||||
fs::create_dir_all(&logs_dir_path).expect("could not create logs path");
|
||||
init_logger(&logs_dir_path);
|
||||
init_paths();
|
||||
init_logger();
|
||||
|
||||
log::info!("========== starting zed ==========");
|
||||
let mut app = gpui::App::new(Assets).unwrap();
|
||||
let app_version = ZED_APP_VERSION
|
||||
.or_else(|| app.platform().app_version().ok())
|
||||
.map_or("dev".to_string(), |v| v.to_string());
|
||||
init_panic_hook(logs_dir_path, app_version, http.clone(), app.background());
|
||||
init_panic_hook(app_version, http.clone(), app.background());
|
||||
let db = app.background().spawn(async move {
|
||||
project::Db::open(db_dir_path.join("zed.db"))
|
||||
project::Db::open(&*zed::paths::DB)
|
||||
.log_err()
|
||||
.unwrap_or(project::Db::null())
|
||||
});
|
||||
@ -100,7 +88,7 @@ fn main() {
|
||||
app.run(move |cx| {
|
||||
let client = client::Client::new(http.clone());
|
||||
let mut languages = LanguageRegistry::new(login_shell_env_loaded);
|
||||
languages.set_language_server_download_dir(zed::ROOT_PATH.clone());
|
||||
languages.set_language_server_download_dir(zed::paths::LANGUAGES_DIR.clone());
|
||||
let languages = Arc::new(languages);
|
||||
let init_languages = cx
|
||||
.background()
|
||||
@ -205,42 +193,57 @@ fn main() {
|
||||
});
|
||||
}
|
||||
|
||||
fn init_logger(logs_dir_path: &Path) {
|
||||
fn init_paths() {
|
||||
fs::create_dir_all(&*zed::paths::CONFIG_DIR).expect("could not create config path");
|
||||
fs::create_dir_all(&*zed::paths::LANGUAGES_DIR).expect("could not create languages path");
|
||||
fs::create_dir_all(&*zed::paths::DB_DIR).expect("could not create database path");
|
||||
fs::create_dir_all(&*zed::paths::LOGS_DIR).expect("could not create logs path");
|
||||
|
||||
// Copy setting files from legacy locations. TODO: remove this after a few releases.
|
||||
thread::spawn(|| {
|
||||
if fs::metadata(&*zed::paths::legacy::SETTINGS).is_ok()
|
||||
&& fs::metadata(&*zed::paths::SETTINGS).is_err()
|
||||
{
|
||||
fs::copy(&*zed::paths::legacy::SETTINGS, &*zed::paths::SETTINGS).log_err();
|
||||
}
|
||||
|
||||
if fs::metadata(&*zed::paths::legacy::KEYMAP).is_ok()
|
||||
&& fs::metadata(&*zed::paths::KEYMAP).is_err()
|
||||
{
|
||||
fs::copy(&*zed::paths::legacy::KEYMAP, &*zed::paths::KEYMAP).log_err();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn init_logger() {
|
||||
if stdout_is_a_pty() {
|
||||
env_logger::init();
|
||||
} else {
|
||||
let level = LevelFilter::Info;
|
||||
let log_file_path = logs_dir_path.join("Zed.log");
|
||||
|
||||
// Prevent log file from becoming too large.
|
||||
const MAX_LOG_BYTES: u64 = 1 * 1024 * 1024;
|
||||
if fs::metadata(&log_file_path).map_or(false, |metadata| metadata.len() > MAX_LOG_BYTES) {
|
||||
let _ = fs::rename(&log_file_path, logs_dir_path.join("Zed.log.old"));
|
||||
if fs::metadata(&*zed::paths::LOG).map_or(false, |metadata| metadata.len() > MAX_LOG_BYTES)
|
||||
{
|
||||
let _ = fs::rename(&*zed::paths::LOG, &*zed::paths::OLD_LOG);
|
||||
}
|
||||
|
||||
let log_file = OpenOptions::new()
|
||||
.create(true)
|
||||
.append(true)
|
||||
.open(log_file_path)
|
||||
.open(&*zed::paths::LOG)
|
||||
.expect("could not open logfile");
|
||||
simplelog::WriteLogger::init(level, simplelog::Config::default(), log_file)
|
||||
.expect("could not initialize logger");
|
||||
}
|
||||
}
|
||||
|
||||
fn init_panic_hook(
|
||||
logs_dir_path: PathBuf,
|
||||
app_version: String,
|
||||
http: Arc<dyn HttpClient>,
|
||||
background: Arc<Background>,
|
||||
) {
|
||||
fn init_panic_hook(app_version: String, http: Arc<dyn HttpClient>, background: Arc<Background>) {
|
||||
background
|
||||
.spawn({
|
||||
let logs_dir_path = logs_dir_path.clone();
|
||||
|
||||
async move {
|
||||
let panic_report_url = format!("{}/api/panic", &*client::ZED_SERVER_URL);
|
||||
let mut children = smol::fs::read_dir(&logs_dir_path).await?;
|
||||
let mut children = smol::fs::read_dir(&*zed::paths::LOGS_DIR).await?;
|
||||
while let Some(child) = children.next().await {
|
||||
let child = child?;
|
||||
let child_path = child.path();
|
||||
@ -330,7 +333,7 @@ fn init_panic_hook(
|
||||
|
||||
let panic_filename = chrono::Utc::now().format("%Y_%m_%d %H_%M_%S").to_string();
|
||||
fs::write(
|
||||
logs_dir_path.join(format!("zed-{}-{}.panic", app_version, panic_filename)),
|
||||
zed::paths::LOGS_DIR.join(format!("zed-{}-{}.panic", app_version, panic_filename)),
|
||||
&message,
|
||||
)
|
||||
.context("error writing panic to disk")
|
||||
@ -464,8 +467,8 @@ fn load_config_files(
|
||||
.clone()
|
||||
.spawn(async move {
|
||||
let settings_file =
|
||||
WatchedJsonFile::new(fs.clone(), &executor, zed::SETTINGS_PATH.clone()).await;
|
||||
let keymap_file = WatchedJsonFile::new(fs, &executor, zed::KEYMAP_PATH.clone()).await;
|
||||
WatchedJsonFile::new(fs.clone(), &executor, zed::paths::SETTINGS.clone()).await;
|
||||
let keymap_file = WatchedJsonFile::new(fs, &executor, zed::paths::KEYMAP.clone()).await;
|
||||
tx.send((settings_file, keymap_file)).ok()
|
||||
})
|
||||
.detach();
|
||||
|
24
crates/zed/src/paths.rs
Normal file
24
crates/zed/src/paths.rs
Normal file
@ -0,0 +1,24 @@
|
||||
use std::path::PathBuf;
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
static ref HOME: PathBuf = dirs::home_dir().expect("failed to determine home directory");
|
||||
pub static ref CONFIG_DIR: PathBuf = HOME.join(".config").join("zed");
|
||||
pub static ref LOGS_DIR: PathBuf = HOME.join("Library/Logs/Zed");
|
||||
pub static ref LANGUAGES_DIR: PathBuf = HOME.join("Library/Application Support/Zed/languages");
|
||||
pub static ref DB_DIR: PathBuf = HOME.join("Library/Application Support/Zed/db");
|
||||
pub static ref DB: PathBuf = DB_DIR.join("zed.db");
|
||||
pub static ref SETTINGS: PathBuf = CONFIG_DIR.join("settings.json");
|
||||
pub static ref KEYMAP: PathBuf = CONFIG_DIR.join("keymap.json");
|
||||
pub static ref LOG: PathBuf = LOGS_DIR.join("Zed.log");
|
||||
pub static ref OLD_LOG: PathBuf = LOGS_DIR.join("Zed.log.old");
|
||||
}
|
||||
|
||||
pub mod legacy {
|
||||
use std::path::PathBuf;
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
static ref CONFIG_DIR: PathBuf = super::HOME.join(".zed");
|
||||
pub static ref SETTINGS: PathBuf = CONFIG_DIR.join("settings.json");
|
||||
pub static ref KEYMAP: PathBuf = CONFIG_DIR.join("keymap.json");
|
||||
}
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
mod feedback;
|
||||
pub mod languages;
|
||||
pub mod menus;
|
||||
pub mod paths;
|
||||
pub mod settings_file;
|
||||
#[cfg(any(test, feature = "test-support"))]
|
||||
pub mod test;
|
||||
@ -22,7 +23,6 @@ use gpui::{
|
||||
AssetSource, AsyncAppContext, ViewContext,
|
||||
};
|
||||
use language::Rope;
|
||||
use lazy_static::lazy_static;
|
||||
pub use lsp;
|
||||
pub use project::{self, fs};
|
||||
use project_panel::ProjectPanel;
|
||||
@ -30,11 +30,7 @@ use search::{BufferSearchBar, ProjectSearchBar};
|
||||
use serde::Deserialize;
|
||||
use serde_json::to_string_pretty;
|
||||
use settings::{keymap_file_json_schema, settings_file_json_schema, Settings};
|
||||
use std::{
|
||||
path::{Path, PathBuf},
|
||||
str,
|
||||
sync::Arc,
|
||||
};
|
||||
use std::{env, path::Path, str, sync::Arc};
|
||||
use util::ResultExt;
|
||||
pub use workspace;
|
||||
use workspace::{sidebar::Side, AppState, Workspace};
|
||||
@ -66,16 +62,6 @@ actions!(
|
||||
|
||||
const MIN_FONT_SIZE: f32 = 6.0;
|
||||
|
||||
lazy_static! {
|
||||
pub static ref HOME_PATH: PathBuf =
|
||||
dirs::home_dir().expect("failed to determine home directory");
|
||||
pub static ref LOG_PATH: PathBuf = HOME_PATH.join("Library/Logs/Zed/Zed.log");
|
||||
pub static ref OLD_LOG_PATH: PathBuf = HOME_PATH.join("Library/Logs/Zed/Zed.log.old");
|
||||
pub static ref ROOT_PATH: PathBuf = HOME_PATH.join(".zed");
|
||||
pub static ref SETTINGS_PATH: PathBuf = ROOT_PATH.join("settings.json");
|
||||
pub static ref KEYMAP_PATH: PathBuf = ROOT_PATH.join("keymap.json");
|
||||
}
|
||||
|
||||
pub fn init(app_state: &Arc<AppState>, cx: &mut gpui::MutableAppContext) {
|
||||
cx.add_action(about);
|
||||
cx.add_global_action(quit);
|
||||
@ -112,7 +98,7 @@ pub fn init(app_state: &Arc<AppState>, cx: &mut gpui::MutableAppContext) {
|
||||
cx.add_action({
|
||||
let app_state = app_state.clone();
|
||||
move |_: &mut Workspace, _: &OpenSettings, cx: &mut ViewContext<Workspace>| {
|
||||
open_config_file(&SETTINGS_PATH, app_state.clone(), cx, || {
|
||||
open_config_file(&paths::SETTINGS, app_state.clone(), cx, || {
|
||||
str::from_utf8(
|
||||
Assets
|
||||
.load("settings/initial_user_settings.json")
|
||||
@ -133,7 +119,7 @@ pub fn init(app_state: &Arc<AppState>, cx: &mut gpui::MutableAppContext) {
|
||||
cx.add_action({
|
||||
let app_state = app_state.clone();
|
||||
move |_: &mut Workspace, _: &OpenKeymap, cx: &mut ViewContext<Workspace>| {
|
||||
open_config_file(&KEYMAP_PATH, app_state.clone(), cx, || Default::default());
|
||||
open_config_file(&paths::KEYMAP, app_state.clone(), cx, || Default::default());
|
||||
}
|
||||
});
|
||||
cx.add_action({
|
||||
@ -237,11 +223,11 @@ pub fn initialize_workspace(
|
||||
},
|
||||
"schemas": [
|
||||
{
|
||||
"fileMatch": [".zed/settings.json"],
|
||||
"fileMatch": [schema_file_match(&*paths::SETTINGS)],
|
||||
"schema": settings_file_json_schema(theme_names, language_names),
|
||||
},
|
||||
{
|
||||
"fileMatch": [".zed/keymap.json"],
|
||||
"fileMatch": [schema_file_match(&*paths::KEYMAP)],
|
||||
"schema": keymap_file_json_schema(&action_names),
|
||||
}
|
||||
]
|
||||
@ -399,7 +385,6 @@ fn open_config_file(
|
||||
cx.spawn(|workspace, mut cx| async move {
|
||||
let fs = &app_state.fs;
|
||||
if !fs.is_file(path).await {
|
||||
fs.create_dir(&ROOT_PATH).await?;
|
||||
fs.create_file(path, Default::default()).await?;
|
||||
fs.save(path, &default_content(), Default::default())
|
||||
.await?;
|
||||
@ -427,8 +412,8 @@ fn open_log_file(
|
||||
workspace.with_local_workspace(cx, app_state.clone(), |_, cx| {
|
||||
cx.spawn_weak(|workspace, mut cx| async move {
|
||||
let (old_log, new_log) = futures::join!(
|
||||
app_state.fs.load(&OLD_LOG_PATH),
|
||||
app_state.fs.load(&LOG_PATH)
|
||||
app_state.fs.load(&paths::OLD_LOG),
|
||||
app_state.fs.load(&paths::LOG)
|
||||
);
|
||||
|
||||
if let Some(workspace) = workspace.upgrade(&cx) {
|
||||
@ -495,6 +480,11 @@ fn open_bundled_config_file(
|
||||
});
|
||||
}
|
||||
|
||||
fn schema_file_match(path: &Path) -> &Path {
|
||||
path.strip_prefix(path.parent().unwrap().parent().unwrap())
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
Loading…
Reference in New Issue
Block a user