Avoid unnecessary DB writes (#29417)
Part of https://github.com/zed-industries/zed/issues/16472 * Adds debug logging to everywhere near INSERT/UPDATEs in the DB So something like `env RUST_LOG=debug,wasmtime_cranelift=off,cranelift_codegen=off,vte=off cargo run` could be used to view these (current zlog seems to process the exclusions odd, so not sure this is the optimal RUST_LOG line) can be used to debug any further writes. * Removes excessive window stack serialization Previously, it serialized unconditionally every 100ms. Now, only if the stack had changed, which is now check every 500ms. * Removes excessive terminal serialization Previously, it serialized its `cwd` on every `ItemEvent::UpdateTab` which was caused by e.g. any character output. Now, only if the `cwd` has changed at the next event processing time. Release Notes: - Fixed more excessive DB writes
This commit is contained in:
parent
37fa437990
commit
f106dfca42
16 changed files with 224 additions and 168 deletions
3
Cargo.lock
generated
3
Cargo.lock
generated
|
@ -3158,6 +3158,7 @@ dependencies = [
|
||||||
"go_to_line",
|
"go_to_line",
|
||||||
"gpui",
|
"gpui",
|
||||||
"language",
|
"language",
|
||||||
|
"log",
|
||||||
"menu",
|
"menu",
|
||||||
"picker",
|
"picker",
|
||||||
"postage",
|
"postage",
|
||||||
|
@ -3208,6 +3209,7 @@ dependencies = [
|
||||||
"db",
|
"db",
|
||||||
"gpui",
|
"gpui",
|
||||||
"languages",
|
"languages",
|
||||||
|
"log",
|
||||||
"notifications",
|
"notifications",
|
||||||
"project",
|
"project",
|
||||||
"serde",
|
"serde",
|
||||||
|
@ -7100,6 +7102,7 @@ dependencies = [
|
||||||
"editor",
|
"editor",
|
||||||
"file_icons",
|
"file_icons",
|
||||||
"gpui",
|
"gpui",
|
||||||
|
"log",
|
||||||
"project",
|
"project",
|
||||||
"schemars",
|
"schemars",
|
||||||
"serde",
|
"serde",
|
||||||
|
|
|
@ -20,6 +20,7 @@ command_palette_hooks.workspace = true
|
||||||
db.workspace = true
|
db.workspace = true
|
||||||
fuzzy.workspace = true
|
fuzzy.workspace = true
|
||||||
gpui.workspace = true
|
gpui.workspace = true
|
||||||
|
log.workspace = true
|
||||||
picker.workspace = true
|
picker.workspace = true
|
||||||
postage.workspace = true
|
postage.workspace = true
|
||||||
serde.workspace = true
|
serde.workspace = true
|
||||||
|
|
|
@ -67,7 +67,12 @@ impl CommandPaletteDB {
|
||||||
command_name: impl Into<String>,
|
command_name: impl Into<String>,
|
||||||
user_query: impl Into<String>,
|
user_query: impl Into<String>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
self.write_command_invocation_internal(command_name.into(), user_query.into())
|
let command_name = command_name.into();
|
||||||
|
let user_query = user_query.into();
|
||||||
|
log::debug!(
|
||||||
|
"Writing command invocation: command_name={command_name}, user_query={user_query}"
|
||||||
|
);
|
||||||
|
self.write_command_invocation_internal(command_name, user_query)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ component.workspace = true
|
||||||
gpui.workspace = true
|
gpui.workspace = true
|
||||||
languages.workspace = true
|
languages.workspace = true
|
||||||
notifications.workspace = true
|
notifications.workspace = true
|
||||||
|
log.workspace = true
|
||||||
project.workspace = true
|
project.workspace = true
|
||||||
ui.workspace = true
|
ui.workspace = true
|
||||||
ui_input.workspace = true
|
ui_input.workspace = true
|
||||||
|
|
|
@ -23,6 +23,9 @@ impl ComponentPreviewDb {
|
||||||
workspace_id: WorkspaceId,
|
workspace_id: WorkspaceId,
|
||||||
active_page_id: String,
|
active_page_id: String,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
|
log::debug!(
|
||||||
|
"Saving active page: item_id={item_id:?}, workspace_id={workspace_id:?}, active_page_id={active_page_id}"
|
||||||
|
);
|
||||||
let query = "INSERT INTO component_previews(item_id, workspace_id, active_page_id)
|
let query = "INSERT INTO component_previews(item_id, workspace_id, active_page_id)
|
||||||
VALUES (?1, ?2, ?3)
|
VALUES (?1, ?2, ?3)
|
||||||
ON CONFLICT DO UPDATE SET
|
ON CONFLICT DO UPDATE SET
|
||||||
|
|
|
@ -18,8 +18,13 @@ impl KeyValueStore {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn write_kvp(&self, key: String, value: String) -> anyhow::Result<()> {
|
||||||
|
log::debug!("Writing key-value pair for key {key}");
|
||||||
|
self.write_kvp_inner(key, value).await
|
||||||
|
}
|
||||||
|
|
||||||
query! {
|
query! {
|
||||||
pub async fn write_kvp(key: String, value: String) -> Result<()> {
|
async fn write_kvp_inner(key: String, value: String) -> Result<()> {
|
||||||
INSERT OR REPLACE INTO kv_store(key, value) VALUES ((?), (?))
|
INSERT OR REPLACE INTO kv_store(key, value) VALUES ((?), (?))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -78,8 +83,13 @@ impl GlobalKeyValueStore {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn write_kvp(&self, key: String, value: String) -> anyhow::Result<()> {
|
||||||
|
log::debug!("Writing global key-value pair for key {key}");
|
||||||
|
self.write_kvp_inner(key, value).await
|
||||||
|
}
|
||||||
|
|
||||||
query! {
|
query! {
|
||||||
pub async fn write_kvp(key: String, value: String) -> Result<()> {
|
async fn write_kvp_inner(key: String, value: String) -> Result<()> {
|
||||||
INSERT OR REPLACE INTO kv_store(key, value) VALUES ((?), (?))
|
INSERT OR REPLACE INTO kv_store(key, value) VALUES ((?), (?))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1251,6 +1251,7 @@ impl SerializableItem for Editor {
|
||||||
language,
|
language,
|
||||||
mtime,
|
mtime,
|
||||||
};
|
};
|
||||||
|
log::debug!("Serializing editor {item_id:?} in workspace {workspace_id:?}");
|
||||||
DB.save_serialized_editor(item_id, workspace_id, editor)
|
DB.save_serialized_editor(item_id, workspace_id, editor)
|
||||||
.await
|
.await
|
||||||
.context("failed to save serialized editor")
|
.context("failed to save serialized editor")
|
||||||
|
|
|
@ -276,6 +276,7 @@ impl EditorDb {
|
||||||
workspace_id: WorkspaceId,
|
workspace_id: WorkspaceId,
|
||||||
selections: Vec<(usize, usize)>,
|
selections: Vec<(usize, usize)>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
|
log::debug!("Saving selections for editor {editor_id} in workspace {workspace_id:?}");
|
||||||
let mut first_selection;
|
let mut first_selection;
|
||||||
let mut last_selection = 0_usize;
|
let mut last_selection = 0_usize;
|
||||||
for (count, placeholders) in std::iter::once("(?1, ?2, ?, ?)")
|
for (count, placeholders) in std::iter::once("(?1, ?2, ?, ?)")
|
||||||
|
@ -327,6 +328,7 @@ VALUES {placeholders};
|
||||||
workspace_id: WorkspaceId,
|
workspace_id: WorkspaceId,
|
||||||
folds: Vec<(usize, usize)>,
|
folds: Vec<(usize, usize)>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
|
log::debug!("Saving folds for editor {editor_id} in workspace {workspace_id:?}");
|
||||||
let mut first_fold;
|
let mut first_fold;
|
||||||
let mut last_fold = 0_usize;
|
let mut last_fold = 0_usize;
|
||||||
for (count, placeholders) in std::iter::once("(?1, ?2, ?, ?)")
|
for (count, placeholders) in std::iter::once("(?1, ?2, ?, ?)")
|
||||||
|
|
|
@ -270,6 +270,9 @@ impl ScrollManager {
|
||||||
|
|
||||||
cx.foreground_executor()
|
cx.foreground_executor()
|
||||||
.spawn(async move {
|
.spawn(async move {
|
||||||
|
log::debug!(
|
||||||
|
"Saving scroll position for item {item_id:?} in workspace {workspace_id:?}"
|
||||||
|
);
|
||||||
DB.save_scroll_position(
|
DB.save_scroll_position(
|
||||||
item_id,
|
item_id,
|
||||||
workspace_id,
|
workspace_id,
|
||||||
|
|
|
@ -21,6 +21,7 @@ db.workspace = true
|
||||||
editor.workspace = true
|
editor.workspace = true
|
||||||
file_icons.workspace = true
|
file_icons.workspace = true
|
||||||
gpui.workspace = true
|
gpui.workspace = true
|
||||||
|
log.workspace = true
|
||||||
project.workspace = true
|
project.workspace = true
|
||||||
schemars.workspace = true
|
schemars.workspace = true
|
||||||
serde.workspace = true
|
serde.workspace = true
|
||||||
|
|
|
@ -261,6 +261,7 @@ impl SerializableItem for ImageView {
|
||||||
|
|
||||||
Some(cx.background_spawn({
|
Some(cx.background_spawn({
|
||||||
async move {
|
async move {
|
||||||
|
log::debug!("Saving image at path {image_path:?}");
|
||||||
IMAGE_VIEWER
|
IMAGE_VIEWER
|
||||||
.save_image_path(item_id, workspace_id, image_path)
|
.save_image_path(item_id, workspace_id, image_path)
|
||||||
.await
|
.await
|
||||||
|
@ -399,18 +400,6 @@ mod persistence {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ImageViewerDb {
|
impl ImageViewerDb {
|
||||||
query! {
|
|
||||||
pub async fn update_workspace_id(
|
|
||||||
new_id: WorkspaceId,
|
|
||||||
old_id: WorkspaceId,
|
|
||||||
item_id: ItemId
|
|
||||||
) -> Result<()> {
|
|
||||||
UPDATE image_viewers
|
|
||||||
SET workspace_id = ?
|
|
||||||
WHERE workspace_id = ? AND item_id = ?
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
query! {
|
query! {
|
||||||
pub async fn save_image_path(
|
pub async fn save_image_path(
|
||||||
item_id: ItemId,
|
item_id: ItemId,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use db::kvp::KEY_VALUE_STORE;
|
use db::kvp::KEY_VALUE_STORE;
|
||||||
use gpui::{AnyWindowHandle, AppContext as _, Context, Subscription, Task, WindowId};
|
use gpui::{App, AppContext as _, Context, Subscription, Task, WindowId};
|
||||||
use util::ResultExt;
|
use util::ResultExt;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@ impl Session {
|
||||||
|
|
||||||
pub struct AppSession {
|
pub struct AppSession {
|
||||||
session: Session,
|
session: Session,
|
||||||
_serialization_task: Option<Task<()>>,
|
_serialization_task: Task<()>,
|
||||||
_subscriptions: Vec<Subscription>,
|
_subscriptions: Vec<Subscription>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,17 +67,21 @@ impl AppSession {
|
||||||
pub fn new(session: Session, cx: &Context<Self>) -> Self {
|
pub fn new(session: Session, cx: &Context<Self>) -> Self {
|
||||||
let _subscriptions = vec![cx.on_app_quit(Self::app_will_quit)];
|
let _subscriptions = vec![cx.on_app_quit(Self::app_will_quit)];
|
||||||
|
|
||||||
let _serialization_task = Some(cx.spawn(async move |_, cx| {
|
let _serialization_task = cx.spawn(async move |_, cx| {
|
||||||
|
let mut current_window_stack = Vec::new();
|
||||||
loop {
|
loop {
|
||||||
if let Some(windows) = cx.update(|cx| cx.window_stack()).ok().flatten() {
|
if let Some(windows) = cx.update(|cx| window_stack(cx)).ok().flatten() {
|
||||||
store_window_stack(windows).await;
|
if windows != current_window_stack {
|
||||||
|
store_window_stack(&windows).await;
|
||||||
|
current_window_stack = windows;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cx.background_executor()
|
cx.background_executor()
|
||||||
.timer(Duration::from_millis(100))
|
.timer(Duration::from_millis(500))
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
}));
|
});
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
session,
|
session,
|
||||||
|
@ -87,8 +91,8 @@ impl AppSession {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn app_will_quit(&mut self, cx: &mut Context<Self>) -> Task<()> {
|
fn app_will_quit(&mut self, cx: &mut Context<Self>) -> Task<()> {
|
||||||
if let Some(windows) = cx.window_stack() {
|
if let Some(window_stack) = window_stack(cx) {
|
||||||
cx.background_spawn(store_window_stack(windows))
|
cx.background_spawn(async move { store_window_stack(&window_stack).await })
|
||||||
} else {
|
} else {
|
||||||
Task::ready(())
|
Task::ready(())
|
||||||
}
|
}
|
||||||
|
@ -107,13 +111,17 @@ impl AppSession {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn store_window_stack(windows: Vec<AnyWindowHandle>) {
|
fn window_stack(cx: &App) -> Option<Vec<u64>> {
|
||||||
let window_ids = windows
|
Some(
|
||||||
.into_iter()
|
cx.window_stack()?
|
||||||
.map(|window| window.window_id().as_u64())
|
.into_iter()
|
||||||
.collect::<Vec<_>>();
|
.map(|window| window.window_id().as_u64())
|
||||||
|
.collect(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
if let Ok(window_ids_json) = serde_json::to_string(&window_ids) {
|
async fn store_window_stack(windows: &[u64]) {
|
||||||
|
if let Ok(window_ids_json) = serde_json::to_string(windows) {
|
||||||
KEY_VALUE_STORE
|
KEY_VALUE_STORE
|
||||||
.write_kvp(SESSION_WINDOW_STACK_KEY.to_string(), window_ids_json)
|
.write_kvp(SESSION_WINDOW_STACK_KEY.to_string(), window_ids_json)
|
||||||
.await
|
.await
|
||||||
|
|
|
@ -429,6 +429,9 @@ impl TerminalDb {
|
||||||
workspace_id: WorkspaceId,
|
workspace_id: WorkspaceId,
|
||||||
working_directory: PathBuf,
|
working_directory: PathBuf,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
|
log::debug!(
|
||||||
|
"Saving working directory {working_directory:?} for item {item_id} in workspace {workspace_id:?}"
|
||||||
|
);
|
||||||
let query =
|
let query =
|
||||||
"INSERT INTO terminals(item_id, workspace_id, working_directory, working_directory_path)
|
"INSERT INTO terminals(item_id, workspace_id, working_directory, working_directory_path)
|
||||||
VALUES (?1, ?2, ?3, ?4)
|
VALUES (?1, ?2, ?3, ?4)
|
||||||
|
|
|
@ -112,6 +112,7 @@ pub struct TerminalView {
|
||||||
cursor_shape: CursorShape,
|
cursor_shape: CursorShape,
|
||||||
blink_state: bool,
|
blink_state: bool,
|
||||||
blinking_terminal_enabled: bool,
|
blinking_terminal_enabled: bool,
|
||||||
|
cwd_serialized: bool,
|
||||||
blinking_paused: bool,
|
blinking_paused: bool,
|
||||||
blink_epoch: usize,
|
blink_epoch: usize,
|
||||||
hover_target_tooltip: Option<String>,
|
hover_target_tooltip: Option<String>,
|
||||||
|
@ -207,6 +208,7 @@ impl TerminalView {
|
||||||
scroll_handle,
|
scroll_handle,
|
||||||
show_scrollbar: !Self::should_autohide_scrollbar(cx),
|
show_scrollbar: !Self::should_autohide_scrollbar(cx),
|
||||||
hide_scrollbar_task: None,
|
hide_scrollbar_task: None,
|
||||||
|
cwd_serialized: false,
|
||||||
_subscriptions: vec![
|
_subscriptions: vec![
|
||||||
focus_in,
|
focus_in,
|
||||||
focus_out,
|
focus_out,
|
||||||
|
@ -843,167 +845,176 @@ fn subscribe_for_terminal_events(
|
||||||
cx: &mut Context<TerminalView>,
|
cx: &mut Context<TerminalView>,
|
||||||
) -> Vec<Subscription> {
|
) -> Vec<Subscription> {
|
||||||
let terminal_subscription = cx.observe(terminal, |_, _, cx| cx.notify());
|
let terminal_subscription = cx.observe(terminal, |_, _, cx| cx.notify());
|
||||||
|
let mut previous_cwd = None;
|
||||||
let terminal_events_subscription = cx.subscribe_in(
|
let terminal_events_subscription = cx.subscribe_in(
|
||||||
terminal,
|
terminal,
|
||||||
window,
|
window,
|
||||||
move |terminal_view, _, event, window, cx| match event {
|
move |terminal_view, terminal, event, window, cx| {
|
||||||
Event::Wakeup => {
|
let current_cwd = terminal.read(cx).working_directory();
|
||||||
cx.notify();
|
if current_cwd != previous_cwd {
|
||||||
cx.emit(Event::Wakeup);
|
previous_cwd = current_cwd;
|
||||||
cx.emit(ItemEvent::UpdateTab);
|
terminal_view.cwd_serialized = false;
|
||||||
cx.emit(SearchEvent::MatchesInvalidated);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Event::Bell => {
|
match event {
|
||||||
terminal_view.has_bell = true;
|
Event::Wakeup => {
|
||||||
cx.emit(Event::Wakeup);
|
cx.notify();
|
||||||
}
|
cx.emit(Event::Wakeup);
|
||||||
|
cx.emit(ItemEvent::UpdateTab);
|
||||||
Event::BlinkChanged(blinking) => {
|
cx.emit(SearchEvent::MatchesInvalidated);
|
||||||
if matches!(
|
|
||||||
TerminalSettings::get_global(cx).blinking,
|
|
||||||
TerminalBlink::TerminalControlled
|
|
||||||
) {
|
|
||||||
terminal_view.blinking_terminal_enabled = *blinking;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Event::TitleChanged => {
|
Event::Bell => {
|
||||||
cx.emit(ItemEvent::UpdateTab);
|
terminal_view.has_bell = true;
|
||||||
}
|
cx.emit(Event::Wakeup);
|
||||||
|
}
|
||||||
|
|
||||||
Event::NewNavigationTarget(maybe_navigation_target) => {
|
Event::BlinkChanged(blinking) => {
|
||||||
match maybe_navigation_target.as_ref() {
|
if matches!(
|
||||||
None => {
|
TerminalSettings::get_global(cx).blinking,
|
||||||
terminal_view.hover_target_tooltip = None;
|
TerminalBlink::TerminalControlled
|
||||||
terminal_view.hover_tooltip_update = Task::ready(());
|
) {
|
||||||
}
|
terminal_view.blinking_terminal_enabled = *blinking;
|
||||||
Some(MaybeNavigationTarget::Url(url)) => {
|
|
||||||
terminal_view.hover_target_tooltip = Some(url.clone());
|
|
||||||
terminal_view.hover_tooltip_update = Task::ready(());
|
|
||||||
}
|
|
||||||
Some(MaybeNavigationTarget::PathLike(path_like_target)) => {
|
|
||||||
let valid_files_to_open_task = possible_open_target(
|
|
||||||
&workspace,
|
|
||||||
&path_like_target.terminal_dir,
|
|
||||||
&path_like_target.maybe_path,
|
|
||||||
cx,
|
|
||||||
);
|
|
||||||
|
|
||||||
terminal_view.hover_tooltip_update =
|
|
||||||
cx.spawn(async move |terminal_view, cx| {
|
|
||||||
let file_to_open = valid_files_to_open_task.await;
|
|
||||||
terminal_view
|
|
||||||
.update(cx, |terminal_view, _| match file_to_open {
|
|
||||||
Some(
|
|
||||||
OpenTarget::File(path, _)
|
|
||||||
| OpenTarget::Worktree(path, _),
|
|
||||||
) => {
|
|
||||||
terminal_view.hover_target_tooltip =
|
|
||||||
Some(path.to_string(|path| {
|
|
||||||
path.to_string_lossy().to_string()
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
terminal_view.hover_target_tooltip = None;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.ok();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cx.notify()
|
Event::TitleChanged => {
|
||||||
}
|
cx.emit(ItemEvent::UpdateTab);
|
||||||
|
}
|
||||||
|
|
||||||
Event::Open(maybe_navigation_target) => match maybe_navigation_target {
|
Event::NewNavigationTarget(maybe_navigation_target) => {
|
||||||
MaybeNavigationTarget::Url(url) => cx.open_url(url),
|
match maybe_navigation_target.as_ref() {
|
||||||
|
None => {
|
||||||
|
terminal_view.hover_target_tooltip = None;
|
||||||
|
terminal_view.hover_tooltip_update = Task::ready(());
|
||||||
|
}
|
||||||
|
Some(MaybeNavigationTarget::Url(url)) => {
|
||||||
|
terminal_view.hover_target_tooltip = Some(url.clone());
|
||||||
|
terminal_view.hover_tooltip_update = Task::ready(());
|
||||||
|
}
|
||||||
|
Some(MaybeNavigationTarget::PathLike(path_like_target)) => {
|
||||||
|
let valid_files_to_open_task = possible_open_target(
|
||||||
|
&workspace,
|
||||||
|
&path_like_target.terminal_dir,
|
||||||
|
&path_like_target.maybe_path,
|
||||||
|
cx,
|
||||||
|
);
|
||||||
|
|
||||||
MaybeNavigationTarget::PathLike(path_like_target) => {
|
terminal_view.hover_tooltip_update =
|
||||||
if terminal_view.hover_target_tooltip.is_none() {
|
cx.spawn(async move |terminal_view, cx| {
|
||||||
return;
|
let file_to_open = valid_files_to_open_task.await;
|
||||||
|
terminal_view
|
||||||
|
.update(cx, |terminal_view, _| match file_to_open {
|
||||||
|
Some(
|
||||||
|
OpenTarget::File(path, _)
|
||||||
|
| OpenTarget::Worktree(path, _),
|
||||||
|
) => {
|
||||||
|
terminal_view.hover_target_tooltip =
|
||||||
|
Some(path.to_string(|path| {
|
||||||
|
path.to_string_lossy().to_string()
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
terminal_view.hover_target_tooltip = None;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.ok();
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
let task_workspace = workspace.clone();
|
|
||||||
let path_like_target = path_like_target.clone();
|
cx.notify()
|
||||||
cx.spawn_in(window, async move |terminal_view, cx| {
|
}
|
||||||
let open_target = terminal_view
|
|
||||||
.update(cx, |_, cx| {
|
Event::Open(maybe_navigation_target) => match maybe_navigation_target {
|
||||||
possible_open_target(
|
MaybeNavigationTarget::Url(url) => cx.open_url(url),
|
||||||
&task_workspace,
|
|
||||||
&path_like_target.terminal_dir,
|
MaybeNavigationTarget::PathLike(path_like_target) => {
|
||||||
&path_like_target.maybe_path,
|
if terminal_view.hover_target_tooltip.is_none() {
|
||||||
cx,
|
return;
|
||||||
)
|
}
|
||||||
})?
|
let task_workspace = workspace.clone();
|
||||||
.await;
|
let path_like_target = path_like_target.clone();
|
||||||
if let Some(open_target) = open_target {
|
cx.spawn_in(window, async move |terminal_view, cx| {
|
||||||
let path_to_open = open_target.path();
|
let open_target = terminal_view
|
||||||
let opened_items = task_workspace
|
.update(cx, |_, cx| {
|
||||||
.update_in(cx, |workspace, window, cx| {
|
possible_open_target(
|
||||||
workspace.open_paths(
|
&task_workspace,
|
||||||
vec![path_to_open.path.clone()],
|
&path_like_target.terminal_dir,
|
||||||
OpenOptions {
|
&path_like_target.maybe_path,
|
||||||
visible: Some(OpenVisible::OnlyDirectories),
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
None,
|
|
||||||
window,
|
|
||||||
cx,
|
cx,
|
||||||
)
|
)
|
||||||
})
|
})?
|
||||||
.context("workspace update")?
|
|
||||||
.await;
|
.await;
|
||||||
if opened_items.len() != 1 {
|
if let Some(open_target) = open_target {
|
||||||
debug_panic!(
|
let path_to_open = open_target.path();
|
||||||
"Received {} items for one path {path_to_open:?}",
|
let opened_items = task_workspace
|
||||||
opened_items.len(),
|
.update_in(cx, |workspace, window, cx| {
|
||||||
);
|
workspace.open_paths(
|
||||||
}
|
vec![path_to_open.path.clone()],
|
||||||
|
OpenOptions {
|
||||||
|
visible: Some(OpenVisible::OnlyDirectories),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
None,
|
||||||
|
window,
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.context("workspace update")?
|
||||||
|
.await;
|
||||||
|
if opened_items.len() != 1 {
|
||||||
|
debug_panic!(
|
||||||
|
"Received {} items for one path {path_to_open:?}",
|
||||||
|
opened_items.len(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(opened_item) = opened_items.first() {
|
if let Some(opened_item) = opened_items.first() {
|
||||||
if open_target.is_file() {
|
if open_target.is_file() {
|
||||||
if let Some(Ok(opened_item)) = opened_item {
|
if let Some(Ok(opened_item)) = opened_item {
|
||||||
if let Some(row) = path_to_open.row {
|
if let Some(row) = path_to_open.row {
|
||||||
let col = path_to_open.column.unwrap_or(0);
|
let col = path_to_open.column.unwrap_or(0);
|
||||||
if let Some(active_editor) =
|
if let Some(active_editor) =
|
||||||
opened_item.downcast::<Editor>()
|
opened_item.downcast::<Editor>()
|
||||||
{
|
{
|
||||||
active_editor
|
active_editor
|
||||||
.downgrade()
|
.downgrade()
|
||||||
.update_in(cx, |editor, window, cx| {
|
.update_in(cx, |editor, window, cx| {
|
||||||
editor.go_to_singleton_buffer_point(
|
editor.go_to_singleton_buffer_point(
|
||||||
language::Point::new(
|
language::Point::new(
|
||||||
row.saturating_sub(1),
|
row.saturating_sub(1),
|
||||||
col.saturating_sub(1),
|
col.saturating_sub(1),
|
||||||
),
|
),
|
||||||
window,
|
window,
|
||||||
cx,
|
cx,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.log_err();
|
.log_err();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if open_target.is_dir() {
|
||||||
|
task_workspace.update(cx, |workspace, cx| {
|
||||||
|
workspace.project().update(cx, |_, cx| {
|
||||||
|
cx.emit(project::Event::ActivateProjectPanel);
|
||||||
|
})
|
||||||
|
})?;
|
||||||
}
|
}
|
||||||
} else if open_target.is_dir() {
|
|
||||||
task_workspace.update(cx, |workspace, cx| {
|
|
||||||
workspace.project().update(cx, |_, cx| {
|
|
||||||
cx.emit(project::Event::ActivateProjectPanel);
|
|
||||||
})
|
|
||||||
})?;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
anyhow::Ok(())
|
anyhow::Ok(())
|
||||||
})
|
})
|
||||||
.detach_and_log_err(cx)
|
.detach_and_log_err(cx)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Event::BreadcrumbsChanged => cx.emit(ItemEvent::UpdateBreadcrumbs),
|
||||||
|
Event::CloseTerminal => cx.emit(ItemEvent::CloseItem),
|
||||||
|
Event::SelectionsChanged => {
|
||||||
|
window.invalidate_character_coordinates();
|
||||||
|
cx.emit(SearchEvent::ActiveMatchChanged)
|
||||||
}
|
}
|
||||||
},
|
|
||||||
Event::BreadcrumbsChanged => cx.emit(ItemEvent::UpdateBreadcrumbs),
|
|
||||||
Event::CloseTerminal => cx.emit(ItemEvent::CloseItem),
|
|
||||||
Event::SelectionsChanged => {
|
|
||||||
window.invalidate_character_coordinates();
|
|
||||||
cx.emit(SearchEvent::ActiveMatchChanged)
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -1539,6 +1550,9 @@ impl Item for TerminalView {
|
||||||
) {
|
) {
|
||||||
if self.terminal().read(cx).task().is_none() {
|
if self.terminal().read(cx).task().is_none() {
|
||||||
if let Some((new_id, old_id)) = workspace.database_id().zip(self.workspace_id) {
|
if let Some((new_id, old_id)) = workspace.database_id().zip(self.workspace_id) {
|
||||||
|
log::debug!(
|
||||||
|
"Updating workspace id for the terminal, old: {old_id:?}, new: {new_id:?}",
|
||||||
|
);
|
||||||
cx.background_spawn(TERMINAL_DB.update_workspace_id(
|
cx.background_spawn(TERMINAL_DB.update_workspace_id(
|
||||||
new_id,
|
new_id,
|
||||||
old_id,
|
old_id,
|
||||||
|
@ -1587,6 +1601,7 @@ impl SerializableItem for TerminalView {
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some((cwd, workspace_id)) = terminal.working_directory().zip(self.workspace_id) {
|
if let Some((cwd, workspace_id)) = terminal.working_directory().zip(self.workspace_id) {
|
||||||
|
self.cwd_serialized = true;
|
||||||
Some(cx.background_spawn(async move {
|
Some(cx.background_spawn(async move {
|
||||||
TERMINAL_DB
|
TERMINAL_DB
|
||||||
.save_working_directory(item_id, workspace_id, cwd)
|
.save_working_directory(item_id, workspace_id, cwd)
|
||||||
|
@ -1597,8 +1612,8 @@ impl SerializableItem for TerminalView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn should_serialize(&self, event: &Self::Event) -> bool {
|
fn should_serialize(&self, _: &Self::Event) -> bool {
|
||||||
matches!(event, ItemEvent::UpdateTab)
|
!self.cwd_serialized
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deserialize(
|
fn deserialize(
|
||||||
|
|
|
@ -1644,6 +1644,7 @@ impl VimDb {
|
||||||
path: Arc<Path>,
|
path: Arc<Path>,
|
||||||
marks: HashMap<String, Vec<Point>>,
|
marks: HashMap<String, Vec<Point>>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
|
log::debug!("Setting path {path:?} for {} marks", marks.len());
|
||||||
let result = self
|
let result = self
|
||||||
.write(move |conn| {
|
.write(move |conn| {
|
||||||
let mut query = conn.exec_bound(sql!(
|
let mut query = conn.exec_bound(sql!(
|
||||||
|
@ -1694,6 +1695,7 @@ impl VimDb {
|
||||||
mark_name: String,
|
mark_name: String,
|
||||||
path: Arc<Path>,
|
path: Arc<Path>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
|
log::debug!("Setting global mark path {path:?} for {mark_name}");
|
||||||
self.write(move |conn| {
|
self.write(move |conn| {
|
||||||
conn.exec_bound(sql!(
|
conn.exec_bound(sql!(
|
||||||
INSERT OR REPLACE INTO vim_global_marks_paths
|
INSERT OR REPLACE INTO vim_global_marks_paths
|
||||||
|
|
|
@ -739,6 +739,7 @@ impl WorkspaceDb {
|
||||||
/// Saves a workspace using the worktree roots. Will garbage collect any workspaces
|
/// Saves a workspace using the worktree roots. Will garbage collect any workspaces
|
||||||
/// that used this workspace previously
|
/// that used this workspace previously
|
||||||
pub(crate) async fn save_workspace(&self, workspace: SerializedWorkspace) {
|
pub(crate) async fn save_workspace(&self, workspace: SerializedWorkspace) {
|
||||||
|
log::debug!("Saving workspace at location: {:?}", workspace.location);
|
||||||
self.write(move |conn| {
|
self.write(move |conn| {
|
||||||
conn.with_savepoint("update_worktrees", || {
|
conn.with_savepoint("update_worktrees", || {
|
||||||
// Clear out panes and pane_groups
|
// Clear out panes and pane_groups
|
||||||
|
@ -909,6 +910,7 @@ impl WorkspaceDb {
|
||||||
{
|
{
|
||||||
Ok(project)
|
Ok(project)
|
||||||
} else {
|
} else {
|
||||||
|
log::debug!("Inserting SSH project at host {host}");
|
||||||
self.insert_ssh_project(host, port, paths, user)
|
self.insert_ssh_project(host, port, paths, user)
|
||||||
.await?
|
.await?
|
||||||
.ok_or_else(|| anyhow!("failed to insert ssh project"))
|
.ok_or_else(|| anyhow!("failed to insert ssh project"))
|
||||||
|
@ -1209,6 +1211,9 @@ impl WorkspaceDb {
|
||||||
pane_group: &SerializedPaneGroup,
|
pane_group: &SerializedPaneGroup,
|
||||||
parent: Option<(GroupId, usize)>,
|
parent: Option<(GroupId, usize)>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
|
if parent.is_none() {
|
||||||
|
log::debug!("Saving a pane group for workspace {workspace_id:?}");
|
||||||
|
}
|
||||||
match pane_group {
|
match pane_group {
|
||||||
SerializedPaneGroup::Group {
|
SerializedPaneGroup::Group {
|
||||||
axis,
|
axis,
|
||||||
|
@ -1387,6 +1392,10 @@ impl WorkspaceDb {
|
||||||
relative_worktree_path: String,
|
relative_worktree_path: String,
|
||||||
toolchain: Toolchain,
|
toolchain: Toolchain,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
|
log::debug!(
|
||||||
|
"Setting toolchain for workspace, worktree: {worktree_id:?}, relative path: {relative_worktree_path:?}, toolchain: {}",
|
||||||
|
toolchain.name
|
||||||
|
);
|
||||||
self.write(move |conn| {
|
self.write(move |conn| {
|
||||||
let mut insert = conn
|
let mut insert = conn
|
||||||
.exec_bound(sql!(
|
.exec_bound(sql!(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue