fix(resurrection): do not parse resurrection layouts on startup (#4292)
* fix(resurrection): do not parse resurrection layouts on startup * proper error when file is corrupt * docs(changelog): add PR * fix attach command * style(fmt): rustfmt
This commit is contained in:
parent
403f0a07be
commit
4a68c6d90b
5 changed files with 64 additions and 50 deletions
|
|
@ -17,6 +17,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
|
||||||
* fix: don't serialize when only ui elements present and provide post command disovery hook (https://github.com/zellij-org/zellij/pull/4276)
|
* fix: don't serialize when only ui elements present and provide post command disovery hook (https://github.com/zellij-org/zellij/pull/4276)
|
||||||
* fix: use plugin `/host` folder as cwd when opening new panes (https://github.com/zellij-org/zellij/pull/4290)
|
* fix: use plugin `/host` folder as cwd when opening new panes (https://github.com/zellij-org/zellij/pull/4290)
|
||||||
* fix: better command detection when serializing layouts for resurrection (https://github.com/zellij-org/zellij/pull/4287)
|
* fix: better command detection when serializing layouts for resurrection (https://github.com/zellij-org/zellij/pull/4287)
|
||||||
|
* fix: slow startup on very large caches (https://github.com/zellij-org/zellij/pull/4292)
|
||||||
* fix: don't show popups in the welcome screen (https://github.com/zellij-org/zellij/pull/4294)
|
* fix: don't show popups in the welcome screen (https://github.com/zellij-org/zellij/pull/4294)
|
||||||
|
|
||||||
## [0.42.2] - 2025-04-15
|
## [0.42.2] - 2025-04-15
|
||||||
|
|
|
||||||
|
|
@ -90,7 +90,7 @@ pub(crate) fn delete_all_sessions(yes: bool, force: bool) {
|
||||||
} else {
|
} else {
|
||||||
resurrectable_sessions
|
resurrectable_sessions
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|(name, _, _)| !active_sessions.contains(name))
|
.filter(|(name, _)| !active_sessions.contains(name))
|
||||||
.cloned()
|
.cloned()
|
||||||
.collect()
|
.collect()
|
||||||
};
|
};
|
||||||
|
|
@ -699,7 +699,15 @@ pub(crate) fn start_client(opts: CliArgs) {
|
||||||
.and_then(|s| session_exists(&s).ok())
|
.and_then(|s| session_exists(&s).ok())
|
||||||
.unwrap_or(false);
|
.unwrap_or(false);
|
||||||
let resurrection_layout =
|
let resurrection_layout =
|
||||||
session_name.as_ref().and_then(|s| resurrection_layout(&s));
|
session_name
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|s| match resurrection_layout(&s) {
|
||||||
|
Ok(layout) => layout,
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!("{}", e);
|
||||||
|
process::exit(2);
|
||||||
|
},
|
||||||
|
});
|
||||||
if (create || should_create_detached)
|
if (create || should_create_detached)
|
||||||
&& !session_exists
|
&& !session_exists
|
||||||
&& resurrection_layout.is_none()
|
&& resurrection_layout.is_none()
|
||||||
|
|
|
||||||
|
|
@ -113,12 +113,15 @@ pub fn spawn_session_if_needed(
|
||||||
} else {
|
} else {
|
||||||
let force_run_commands = false;
|
let force_run_commands = false;
|
||||||
let resurrection_layout =
|
let resurrection_layout =
|
||||||
resurrection_layout(&session_name).map(|mut resurrection_layout| {
|
resurrection_layout(&session_name)
|
||||||
if force_run_commands {
|
.ok()
|
||||||
resurrection_layout.recursively_add_start_suspended(Some(false));
|
.flatten()
|
||||||
}
|
.map(|mut resurrection_layout| {
|
||||||
resurrection_layout
|
if force_run_commands {
|
||||||
});
|
resurrection_layout.recursively_add_start_suspended(Some(false));
|
||||||
|
}
|
||||||
|
resurrection_layout
|
||||||
|
});
|
||||||
|
|
||||||
match resurrection_layout {
|
match resurrection_layout {
|
||||||
Some(resurrection_layout) => spawn_new_session(
|
Some(resurrection_layout) => spawn_new_session(
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,8 @@ impl SessionManager for RealSessionManager {
|
||||||
session_name: &str,
|
session_name: &str,
|
||||||
) -> Option<zellij_utils::input::layout::Layout> {
|
) -> Option<zellij_utils::input::layout::Layout> {
|
||||||
zellij_utils::sessions::resurrection_layout(session_name)
|
zellij_utils::sessions::resurrection_layout(session_name)
|
||||||
|
.ok()
|
||||||
|
.flatten()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn spawn_session_if_needed(
|
fn spawn_session_if_needed(
|
||||||
|
|
|
||||||
|
|
@ -21,16 +21,17 @@ pub fn get_sessions() -> Result<Vec<(String, Duration)>, io::ErrorKind> {
|
||||||
Ok(files) => {
|
Ok(files) => {
|
||||||
let mut sessions = Vec::new();
|
let mut sessions = Vec::new();
|
||||||
files.for_each(|file| {
|
files.for_each(|file| {
|
||||||
let file = file.unwrap();
|
if let Ok(file) = file {
|
||||||
let file_name = file.file_name().into_string().unwrap();
|
let file_name = file.file_name().into_string().unwrap();
|
||||||
let ctime = std::fs::metadata(&file.path())
|
let ctime = std::fs::metadata(&file.path())
|
||||||
.ok()
|
.ok()
|
||||||
.and_then(|f| f.created().ok())
|
.and_then(|f| f.created().ok())
|
||||||
.and_then(|d| d.elapsed().ok())
|
.and_then(|d| d.elapsed().ok())
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
let duration = Duration::from_secs(ctime.as_secs());
|
let duration = Duration::from_secs(ctime.as_secs());
|
||||||
if file.file_type().unwrap().is_socket() && assert_socket(&file_name) {
|
if file.file_type().unwrap().is_socket() && assert_socket(&file_name) {
|
||||||
sessions.push((file_name, duration));
|
sessions.push((file_name, duration));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
Ok(sessions)
|
Ok(sessions)
|
||||||
|
|
@ -40,7 +41,7 @@ pub fn get_sessions() -> Result<Vec<(String, Duration)>, io::ErrorKind> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_resurrectable_sessions() -> Vec<(String, Duration, Layout)> {
|
pub fn get_resurrectable_sessions() -> Vec<(String, Duration)> {
|
||||||
match fs::read_dir(&*ZELLIJ_SESSION_INFO_CACHE_DIR) {
|
match fs::read_dir(&*ZELLIJ_SESSION_INFO_CACHE_DIR) {
|
||||||
Ok(files_in_session_info_folder) => {
|
Ok(files_in_session_info_folder) => {
|
||||||
let files_that_are_folders = files_in_session_info_folder
|
let files_that_are_folders = files_in_session_info_folder
|
||||||
|
|
@ -50,30 +51,12 @@ pub fn get_resurrectable_sessions() -> Vec<(String, Duration, Layout)> {
|
||||||
.filter_map(|folder_name| {
|
.filter_map(|folder_name| {
|
||||||
let layout_file_name =
|
let layout_file_name =
|
||||||
session_layout_cache_file_name(&folder_name.display().to_string());
|
session_layout_cache_file_name(&folder_name.display().to_string());
|
||||||
let raw_layout = match std::fs::read_to_string(&layout_file_name) {
|
|
||||||
Ok(raw_layout) => raw_layout,
|
|
||||||
Err(_e) => {
|
|
||||||
return None;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
let ctime = match std::fs::metadata(&layout_file_name)
|
let ctime = match std::fs::metadata(&layout_file_name)
|
||||||
.and_then(|metadata| metadata.created())
|
.and_then(|metadata| metadata.created())
|
||||||
{
|
{
|
||||||
Ok(created) => Some(created),
|
Ok(created) => Some(created),
|
||||||
Err(_e) => None,
|
Err(_e) => None,
|
||||||
};
|
};
|
||||||
let layout = match Layout::from_kdl(
|
|
||||||
&raw_layout,
|
|
||||||
Some(layout_file_name.display().to_string()),
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
) {
|
|
||||||
Ok(layout) => layout,
|
|
||||||
Err(e) => {
|
|
||||||
log::error!("Failed to parse resurrection layout file: {}", e);
|
|
||||||
return None;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
let elapsed_duration = ctime
|
let elapsed_duration = ctime
|
||||||
.map(|ctime| {
|
.map(|ctime| {
|
||||||
Duration::from_secs(ctime.elapsed().ok().unwrap_or_default().as_secs())
|
Duration::from_secs(ctime.elapsed().ok().unwrap_or_default().as_secs())
|
||||||
|
|
@ -82,7 +65,7 @@ pub fn get_resurrectable_sessions() -> Vec<(String, Duration, Layout)> {
|
||||||
let session_name = folder_name
|
let session_name = folder_name
|
||||||
.file_name()
|
.file_name()
|
||||||
.map(|f| std::path::PathBuf::from(f).display().to_string())?;
|
.map(|f| std::path::PathBuf::from(f).display().to_string())?;
|
||||||
Some((session_name, elapsed_duration, layout))
|
Some((session_name, elapsed_duration))
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
},
|
},
|
||||||
|
|
@ -291,7 +274,7 @@ pub fn list_sessions(no_formatting: bool, short: bool, reverse: bool) {
|
||||||
let resurrectable_sessions = get_resurrectable_sessions();
|
let resurrectable_sessions = get_resurrectable_sessions();
|
||||||
let mut all_sessions: HashMap<String, (Duration, bool)> = resurrectable_sessions
|
let mut all_sessions: HashMap<String, (Duration, bool)> = resurrectable_sessions
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(name, timestamp, _layout)| (name.clone(), (timestamp.clone(), true)))
|
.map(|(name, timestamp)| (name.clone(), (timestamp.clone(), true)))
|
||||||
.collect();
|
.collect();
|
||||||
for (session_name, duration) in running_sessions {
|
for (session_name, duration) in running_sessions {
|
||||||
all_sessions.insert(session_name.clone(), (duration, false));
|
all_sessions.insert(session_name.clone(), (duration, false));
|
||||||
|
|
@ -362,17 +345,34 @@ pub fn session_exists(name: &str) -> Result<bool, io::ErrorKind> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the session is resurrecable, the returned layout is the one to be used to resurrect it
|
// if the session is resurrecable, the returned layout is the one to be used to resurrect it
|
||||||
pub fn resurrection_layout(session_name_to_resurrect: &str) -> Option<Layout> {
|
pub fn resurrection_layout(session_name_to_resurrect: &str) -> Result<Option<Layout>, String> {
|
||||||
let resurrectable_sessions = get_resurrectable_sessions();
|
let layout_file_name = session_layout_cache_file_name(&session_name_to_resurrect);
|
||||||
resurrectable_sessions
|
let raw_layout = match std::fs::read_to_string(&layout_file_name) {
|
||||||
.iter()
|
Ok(raw_layout) => raw_layout,
|
||||||
.find_map(|(name, _timestamp, layout)| {
|
Err(_e) => {
|
||||||
if name == session_name_to_resurrect {
|
return Ok(None);
|
||||||
Some(layout.clone())
|
},
|
||||||
} else {
|
};
|
||||||
None
|
match Layout::from_kdl(
|
||||||
}
|
&raw_layout,
|
||||||
})
|
Some(layout_file_name.display().to_string()),
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
) {
|
||||||
|
Ok(layout) => Ok(Some(layout)),
|
||||||
|
Err(e) => {
|
||||||
|
log::error!(
|
||||||
|
"Failed to parse resurrection layout file {}: {}",
|
||||||
|
layout_file_name.display(),
|
||||||
|
e
|
||||||
|
);
|
||||||
|
return Err(format!(
|
||||||
|
"Failed to parse resurrection layout file {}: {}.",
|
||||||
|
layout_file_name.display(),
|
||||||
|
e
|
||||||
|
));
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn assert_session(name: &str) {
|
pub fn assert_session(name: &str) {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue