From 579a54ec459778481cdf0185259572f8e72d3f23 Mon Sep 17 00:00:00 2001 From: Aram Drevekenin Date: Thu, 18 Jul 2024 14:29:03 +0200 Subject: [PATCH] fix(serialization): do not serialize junk sessions (#3504) * fix(serialization): do not serialize junk sessions * style(fmt): rustfmt --- zellij-server/src/pty.rs | 30 ++++++------ zellij-server/src/session_layout_metadata.rs | 49 ++++++++++++++++++++ zellij-utils/src/input/layout.rs | 16 +++++++ 3 files changed, 81 insertions(+), 14 deletions(-) diff --git a/zellij-server/src/pty.rs b/zellij-server/src/pty.rs index f8bd61d2..2d91e3ac 100644 --- a/zellij-server/src/pty.rs +++ b/zellij-server/src/pty.rs @@ -664,20 +664,22 @@ pub(crate) fn pty_thread_main(mut pty: Pty, layout: Box) -> Result<()> { PtyInstruction::LogLayoutToHd(mut session_layout_metadata) => { let err_context = || format!("Failed to dump layout"); pty.populate_session_layout_metadata(&mut session_layout_metadata); - match session_serialization::serialize_session_layout( - session_layout_metadata.into(), - ) { - Ok(kdl_layout_and_pane_contents) => { - pty.bus - .senders - .send_to_background_jobs(BackgroundJob::ReportLayoutInfo( - kdl_layout_and_pane_contents, - )) - .with_context(err_context)?; - }, - Err(e) => { - log::error!("Failed to log layout to HD: {}", e); - }, + if session_layout_metadata.is_dirty() { + match session_serialization::serialize_session_layout( + session_layout_metadata.into(), + ) { + Ok(kdl_layout_and_pane_contents) => { + pty.bus + .senders + .send_to_background_jobs(BackgroundJob::ReportLayoutInfo( + kdl_layout_and_pane_contents, + )) + .with_context(err_context)?; + }, + Err(e) => { + log::error!("Failed to log layout to HD: {}", e); + }, + } } }, PtyInstruction::FillPluginCwd( diff --git a/zellij-server/src/session_layout_metadata.rs b/zellij-server/src/session_layout_metadata.rs index 0ca25804..706d75a1 100644 --- a/zellij-server/src/session_layout_metadata.rs +++ b/zellij-server/src/session_layout_metadata.rs @@ -81,6 +81,55 @@ impl SessionLayoutMetadata { ClientMetadata::render_many(clients_metadata, &self.default_editor) } + pub fn is_dirty(&self) -> bool { + // here we check to see if the serialized layout would be different than the base one, and + // thus is "dirty". A layout is considered dirty if one of the following is true: + // 1. The current number of panes is different than the number of panes in the base layout + // (meaning a pane was opened or closed) + // 2. One or more terminal panes are running a command that is not the default shell + let base_layout_pane_count = self.default_layout.pane_count(); + let current_pane_count = self.pane_count(); + if current_pane_count != base_layout_pane_count { + return true; + } + for tab in &self.tabs { + for tiled_pane in &tab.tiled_panes { + if let Some(Run::Command(run_command)) = tiled_pane.run.as_ref() { + if !Self::is_default_shell( + self.default_shell.as_ref(), + &run_command.command.display().to_string(), + &run_command.args, + ) { + return true; + } + } + } + for floating_pane in &tab.floating_panes { + if let Some(Run::Command(run_command)) = floating_pane.run.as_ref() { + if !Self::is_default_shell( + self.default_shell.as_ref(), + &run_command.command.display().to_string(), + &run_command.args, + ) { + return true; + } + } + } + } + false + } + fn pane_count(&self) -> usize { + let mut pane_count = 0; + for tab in &self.tabs { + for _tiled_pane in &tab.tiled_panes { + pane_count += 1; + } + for _floating_pane in &tab.floating_panes { + pane_count += 1; + } + } + pane_count + } fn is_default_shell( default_shell: Option<&PathBuf>, command_name: &String, diff --git a/zellij-utils/src/input/layout.rs b/zellij-utils/src/input/layout.rs index 7dc3bc63..77411a5d 100644 --- a/zellij-utils/src/input/layout.rs +++ b/zellij-utils/src/input/layout.rs @@ -1511,6 +1511,22 @@ impl Layout { } } } + pub fn pane_count(&self) -> usize { + let mut pane_count = 0; + if let Some((tiled_pane_layout, floating_panes)) = self.template.as_ref() { + pane_count += tiled_pane_layout.pane_count(); + for _ in floating_panes { + pane_count += 1; + } + } + for (_, tiled_pane_layout, floating_panes) in &self.tabs { + pane_count += tiled_pane_layout.pane_count(); + for _ in floating_panes { + pane_count += 1; + } + } + pane_count + } } fn split_space(