From 7a2b191ac615cccefa8aa1ebcc62c6584cb9fb2a Mon Sep 17 00:00:00 2001 From: Ben Kunkle Date: Thu, 13 Nov 2025 12:17:07 -0500 Subject: [PATCH] remote project settings Co-Authored-By: Mikayla --- crates/language/src/buffer.rs | 5 ++++ crates/project/src/project.rs | 36 +++++++++++++++------------ crates/proto/proto/worktree.proto | 22 ++++++++++++++++ crates/settings_ui/src/settings_ui.rs | 23 ----------------- crates/worktree/src/worktree.rs | 1 + 5 files changed, 48 insertions(+), 39 deletions(-) diff --git a/crates/language/src/buffer.rs b/crates/language/src/buffer.rs index ea2405d04c32cba45963bc32747ee0b94292ffd9..8cfd7573a3e4849de9189a573d947d640b853cf1 100644 --- a/crates/language/src/buffer.rs +++ b/crates/language/src/buffer.rs @@ -385,6 +385,8 @@ pub enum DiskState { Present { mtime: MTime }, /// Deleted file that was previously present. Deleted, + /// File stored remotely. + Remote, } impl DiskState { @@ -394,6 +396,7 @@ impl DiskState { DiskState::New => None, DiskState::Present { mtime } => Some(mtime), DiskState::Deleted => None, + DiskState::Remote => None, } } @@ -402,6 +405,7 @@ impl DiskState { DiskState::New => false, DiskState::Present { .. } => true, DiskState::Deleted => false, + DiskState::Remote => true, } } } @@ -2073,6 +2077,7 @@ impl Buffer { None => true, }, DiskState::Deleted => false, + DiskState::Remote => false, } } diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index 3f325aba2b18efb4f36faef4e0a655f716a860bd..a4dd98a82bb5906b0b7b9005f61c4d010adefb88 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -5275,32 +5275,36 @@ impl Project { } pub fn update_local_settings_file( - &self, + &mut self, worktree_id: WorktreeId, rel_path: Arc, - cx: &mut App, + cx: &mut Context, update: impl 'static + Send + FnOnce(&mut settings::SettingsContent, &App), ) { - let Some(worktree) = self.worktree_for_id(worktree_id, cx) else { - // todo(settings_ui) error? - return; - }; - cx.spawn(async move |cx| { - let file = worktree - .update(cx, |worktree, cx| worktree.load_file(&rel_path, cx))? + let open_buffer_task = self.open_buffer( + ProjectPath { + worktree_id, + path: rel_path, + }, + cx, + ); + cx.spawn(async move |this, cx| { + let buffer = open_buffer_task .await .context("Failed to load settings file")?; + let buffer_text = buffer.read_with(cx, |buffer, _| buffer.text())?; let new_text = cx.read_global::(|store, cx| { - store.new_text_for_update(file.text, move |settings| update(settings, cx)) + store.new_text_for_update(buffer_text, move |settings| update(settings, cx)) })?; - worktree - .update(cx, |worktree, cx| { - let line_ending = text::LineEnding::detect(&new_text); - worktree.write_file(rel_path.clone(), new_text.into(), line_ending, cx) - })? + + buffer.update(cx, |buffer, cx| { + buffer.set_text(new_text, cx); + })?; + + this.update(cx, |this, cx| this.save_buffer(buffer, cx))? .await - .context("Failed to write settings file")?; + .context("Failed to save settings file")?; anyhow::Ok(()) }) diff --git a/crates/proto/proto/worktree.proto b/crates/proto/proto/worktree.proto index 9ab9e95438d220834351308ea83ffe9a18dec999..197037bb50437dfccb67506a58486264ea520aa1 100644 --- a/crates/proto/proto/worktree.proto +++ b/crates/proto/proto/worktree.proto @@ -158,3 +158,25 @@ message UpdateUserSettings { uint64 project_id = 1; string contents = 2; } + +message LoadProjectFile { + uint64 project_id = 1; + uint64 worktree_id = 2; + string rel_path = 3; +} + +message LoadProjectFileResponse { + message LoadProjectFileError { + string message = 1; + uint64 code = 2; + } + + message LoadProjectFileSuccess { + string contents = 1; + } + + oneof result { + LoadProjectFileError error = 1; + LoadProjectFileSuccess success = 2; + } +} diff --git a/crates/settings_ui/src/settings_ui.rs b/crates/settings_ui/src/settings_ui.rs index 6a561086f2d614eb8fc06c5be146b5e02dc05b3d..2a3f1865652b7c2b903ea0affbd81022e565cb3c 100644 --- a/crates/settings_ui/src/settings_ui.rs +++ b/crates/settings_ui/src/settings_ui.rs @@ -2116,29 +2116,6 @@ impl SettingsWindow { } } - // TODO: - // Reconsider this after preview launch - // fn file_location_str(&self) -> String { - // match &self.current_file { - // SettingsUiFile::User => "settings.json".to_string(), - // SettingsUiFile::Project((worktree_id, path)) => self - // .worktree_root_dirs - // .get(&worktree_id) - // .map(|directory_name| { - // let path_style = PathStyle::local(); - // let file_path = path.join(paths::local_settings_file_relative_path()); - // format!( - // "{}{}{}", - // directory_name, - // path_style.separator(), - // file_path.display(path_style) - // ) - // }) - // .expect("Current file should always be present in root dir map"), - // SettingsUiFile::Server(file) => file.to_string(), - // } - // } - fn render_search(&self, _window: &mut Window, cx: &mut App) -> Div { h_flex() .py_1() diff --git a/crates/worktree/src/worktree.rs b/crates/worktree/src/worktree.rs index 1e8c1648dca98b267146211a9b36fb78f743fb82..0b10168939efa83e054de454e245ea04319b3354 100644 --- a/crates/worktree/src/worktree.rs +++ b/crates/worktree/src/worktree.rs @@ -706,6 +706,7 @@ impl Worktree { match self { Worktree::Local(this) => this.load_file(path, cx), Worktree::Remote(_) => { + // This needs to respect the private files configuration Task::ready(Err(anyhow!("remote worktrees can't yet load files"))) } }