Fixes the bug that made us remove the sandbox. The bug in question was very dumb: - there is sophisticated machinery for detecting whether a user-granted writable path is swapped out for a symlink in the timing gap between approval and sandbox creation - there was no equivalent machinery to do the same for the (much larger) gap between a user *persisting an approval* (either for the current thread or permanently via settings) - The fix is essentially to store canonical (i.e. absolute and symlink-free at all depths) paths as the source of truth, but retain the raw path for display purposes - On WSL, there is extra care needed becasue of the bidirectional mounting (i.e. `/mnt/c/...` and `\\wsl.localhost\Ubuntu\...`). In particular, `/mnt/c/...` paths, since their inodes do not necessarily pin NTFS file references, weaken the sandbox guarantees, and so we need some extra UI to call this out and docs etc... This also does not remove the feature flag, but just toggles it to "enabled_for_all" --- Release Notes: - N/A or Added/Fixed/Improved ... --------- Co-authored-by: Richard Feldman <oss@rtfeldman.com> Co-authored-by: Jakub Konka <kubkon@jakubkonka.com> Co-authored-by: Danilo Leal <daniloleal09@gmail.com> Co-authored-by: zed-zippy[bot] <234243425+zed-zippy[bot]@users.noreply.github.com>
202 lines
5.9 KiB
Rust
202 lines
5.9 KiB
Rust
mod base_keymap_setting;
|
|
mod content_into_gpui;
|
|
mod editable_setting_control;
|
|
mod editorconfig_store;
|
|
mod granted_write_path;
|
|
mod keymap_file;
|
|
mod settings_file;
|
|
mod settings_store;
|
|
mod vscode_import;
|
|
|
|
pub use settings_macros::RegisterSetting;
|
|
|
|
pub mod settings_content {
|
|
pub use ::settings_content::*;
|
|
}
|
|
|
|
pub mod fallible_options {
|
|
pub use ::settings_content::{FallibleOption, parse_json};
|
|
}
|
|
|
|
#[doc(hidden)]
|
|
pub mod private {
|
|
pub use crate::settings_store::{RegisteredSetting, SettingValue};
|
|
pub use inventory;
|
|
}
|
|
|
|
use gpui::{App, Global};
|
|
|
|
use rust_embed::RustEmbed;
|
|
use std::env;
|
|
use std::{borrow::Cow, fmt, str};
|
|
use util::asset_str;
|
|
|
|
pub use ::settings_content::*;
|
|
pub use base_keymap_setting::*;
|
|
pub use content_into_gpui::IntoGpui;
|
|
pub use editable_setting_control::*;
|
|
pub use editorconfig_store::{
|
|
Editorconfig, EditorconfigEvent, EditorconfigProperties, EditorconfigStore,
|
|
};
|
|
pub use granted_write_path::GrantedWritePath;
|
|
pub use keymap_file::{
|
|
KeyBindingValidator, KeyBindingValidatorRegistration, KeybindSource, KeybindUpdateOperation,
|
|
KeybindUpdateTarget, KeymapFile, KeymapFileLoadResult,
|
|
};
|
|
pub use settings_file::*;
|
|
pub use settings_json::*;
|
|
pub use settings_store::{
|
|
DefaultSemanticTokenRules, InvalidSettingsError, LSP_SETTINGS_SCHEMA_URL_PREFIX,
|
|
LocalSettingsKind, LocalSettingsPath, MigrationStatus, Settings, SettingsFile,
|
|
SettingsJsonSchemaParams, SettingsKey, SettingsLocation, SettingsParseResult, SettingsStore,
|
|
};
|
|
|
|
pub use vscode_import::{VsCodeSettings, VsCodeSettingsSource};
|
|
|
|
pub use keymap_file::ActionSequence;
|
|
|
|
#[derive(Clone, Debug, PartialEq)]
|
|
pub struct ActiveSettingsProfileName(pub String);
|
|
|
|
impl Global for ActiveSettingsProfileName {}
|
|
|
|
pub trait UserSettingsContentExt {
|
|
fn for_profile(&self, cx: &App) -> Option<&SettingsProfile>;
|
|
fn for_release_channel(&self) -> Option<&SettingsContent>;
|
|
fn for_os(&self) -> Option<&SettingsContent>;
|
|
}
|
|
|
|
impl UserSettingsContentExt for UserSettingsContent {
|
|
fn for_profile(&self, cx: &App) -> Option<&SettingsProfile> {
|
|
let Some(active_profile) = cx.try_global::<ActiveSettingsProfileName>() else {
|
|
return None;
|
|
};
|
|
self.profiles.get(&active_profile.0)
|
|
}
|
|
|
|
fn for_release_channel(&self) -> Option<&SettingsContent> {
|
|
self.release_channel_overrides
|
|
.get_by_key(release_channel::RELEASE_CHANNEL.dev_name())
|
|
}
|
|
|
|
fn for_os(&self) -> Option<&SettingsContent> {
|
|
self.platform_overrides.get_by_key(env::consts::OS)
|
|
}
|
|
}
|
|
|
|
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash, PartialOrd, Ord, serde::Serialize)]
|
|
pub struct WorktreeId(usize);
|
|
|
|
impl From<WorktreeId> for usize {
|
|
fn from(value: WorktreeId) -> Self {
|
|
value.0
|
|
}
|
|
}
|
|
|
|
impl WorktreeId {
|
|
pub fn from_usize(handle_id: usize) -> Self {
|
|
Self(handle_id)
|
|
}
|
|
|
|
pub fn from_proto(id: u64) -> Self {
|
|
Self(id as usize)
|
|
}
|
|
|
|
pub fn to_proto(self) -> u64 {
|
|
self.0 as u64
|
|
}
|
|
|
|
pub fn to_usize(self) -> usize {
|
|
self.0
|
|
}
|
|
}
|
|
|
|
impl fmt::Display for WorktreeId {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
std::fmt::Display::fmt(&self.0, f)
|
|
}
|
|
}
|
|
|
|
#[derive(RustEmbed)]
|
|
#[folder = "../../assets"]
|
|
#[include = "settings/*"]
|
|
#[include = "keymaps/*"]
|
|
#[exclude = "*.DS_Store"]
|
|
pub struct SettingsAssets;
|
|
|
|
pub fn init(cx: &mut App) {
|
|
let settings = SettingsStore::new(cx, &default_settings());
|
|
cx.set_global(settings);
|
|
SettingsStore::observe_active_settings_profile_name(cx).detach();
|
|
}
|
|
|
|
pub fn default_settings() -> Cow<'static, str> {
|
|
asset_str::<SettingsAssets>("settings/default.json")
|
|
}
|
|
|
|
pub fn default_semantic_token_rules() -> Cow<'static, str> {
|
|
asset_str::<SettingsAssets>("settings/default_semantic_token_rules.json")
|
|
}
|
|
|
|
#[cfg(target_os = "macos")]
|
|
pub const DEFAULT_KEYMAP_PATH: &str = "keymaps/default-macos.json";
|
|
|
|
#[cfg(target_os = "windows")]
|
|
pub const DEFAULT_KEYMAP_PATH: &str = "keymaps/default-windows.json";
|
|
|
|
#[cfg(not(any(target_os = "macos", target_os = "windows")))]
|
|
pub const DEFAULT_KEYMAP_PATH: &str = "keymaps/default-linux.json";
|
|
|
|
pub fn default_keymap() -> Cow<'static, str> {
|
|
asset_str::<SettingsAssets>(DEFAULT_KEYMAP_PATH)
|
|
}
|
|
|
|
pub const VIM_KEYMAP_PATH: &str = "keymaps/vim.json";
|
|
|
|
pub fn vim_keymap() -> Cow<'static, str> {
|
|
asset_str::<SettingsAssets>(VIM_KEYMAP_PATH)
|
|
}
|
|
|
|
/// Specific keybinding overrides. Loaded after the base keymap so they win over
|
|
/// conflicting base-keymap (and default `Editor`) bindings for the same chords,
|
|
/// while still allowing user keymaps (loaded last) to override them. Shared
|
|
/// across features - prefer adding a context block here over creating another
|
|
/// override keymap file.
|
|
#[cfg(target_os = "macos")]
|
|
pub const SPECIFIC_OVERRIDES_KEYMAP_PATH: &str = "keymaps/specific-overrides-macos.json";
|
|
|
|
#[cfg(not(target_os = "macos"))]
|
|
pub const SPECIFIC_OVERRIDES_KEYMAP_PATH: &str = "keymaps/specific-overrides.json";
|
|
|
|
pub fn initial_user_settings_content() -> Cow<'static, str> {
|
|
asset_str::<SettingsAssets>("settings/initial_user_settings.json")
|
|
}
|
|
|
|
pub fn initial_server_settings_content() -> Cow<'static, str> {
|
|
asset_str::<SettingsAssets>("settings/initial_server_settings.json")
|
|
}
|
|
|
|
pub fn initial_project_settings_content() -> Cow<'static, str> {
|
|
asset_str::<SettingsAssets>("settings/initial_local_settings.json")
|
|
}
|
|
|
|
pub fn initial_keymap_content() -> Cow<'static, str> {
|
|
asset_str::<SettingsAssets>("keymaps/initial.json")
|
|
}
|
|
|
|
pub fn initial_tasks_content() -> Cow<'static, str> {
|
|
asset_str::<SettingsAssets>("settings/initial_tasks.json")
|
|
}
|
|
|
|
pub fn initial_worktree_setup_tasks_content() -> Cow<'static, str> {
|
|
asset_str::<SettingsAssets>("settings/initial_worktree_setup_tasks.json")
|
|
}
|
|
|
|
pub fn initial_debug_tasks_content() -> Cow<'static, str> {
|
|
asset_str::<SettingsAssets>("settings/initial_debug_tasks.json")
|
|
}
|
|
|
|
pub fn initial_local_debug_tasks_content() -> Cow<'static, str> {
|
|
asset_str::<SettingsAssets>("settings/initial_local_debug_tasks.json")
|
|
}
|