fix(resurrection): log failure instead of crashing in some edge cases (#2851)
* fix(resurrection): log failure instead of crashing in some edge cases * style(fmt): rustfmt
This commit is contained in:
parent
a6ab09cbb0
commit
404608e7e3
2 changed files with 147 additions and 84 deletions
|
|
@ -535,23 +535,43 @@ pub(crate) fn pty_thread_main(mut pty: Pty, layout: Box<Layout>) -> Result<()> {
|
||||||
PtyInstruction::DumpLayout(mut session_layout_metadata, client_id) => {
|
PtyInstruction::DumpLayout(mut session_layout_metadata, client_id) => {
|
||||||
let err_context = || format!("Failed to dump layout");
|
let err_context = || format!("Failed to dump layout");
|
||||||
pty.populate_session_layout_metadata(&mut session_layout_metadata);
|
pty.populate_session_layout_metadata(&mut session_layout_metadata);
|
||||||
let (kdl_layout, _pane_contents) =
|
match session_serialization::serialize_session_layout(
|
||||||
session_serialization::serialize_session_layout(session_layout_metadata.into());
|
session_layout_metadata.into(),
|
||||||
pty.bus
|
) {
|
||||||
.senders
|
Ok((kdl_layout, _pane_contents)) => {
|
||||||
.send_to_server(ServerInstruction::Log(vec![kdl_layout], client_id))
|
pty.bus
|
||||||
.with_context(err_context)
|
.senders
|
||||||
.non_fatal();
|
.send_to_server(ServerInstruction::Log(vec![kdl_layout], client_id))
|
||||||
|
.with_context(err_context)
|
||||||
|
.non_fatal();
|
||||||
|
},
|
||||||
|
Err(e) => {
|
||||||
|
pty.bus
|
||||||
|
.senders
|
||||||
|
.send_to_server(ServerInstruction::Log(vec![e.to_owned()], client_id))
|
||||||
|
.with_context(err_context)
|
||||||
|
.non_fatal();
|
||||||
|
},
|
||||||
|
}
|
||||||
},
|
},
|
||||||
PtyInstruction::LogLayoutToHd(mut session_layout_metadata) => {
|
PtyInstruction::LogLayoutToHd(mut session_layout_metadata) => {
|
||||||
let err_context = || format!("Failed to dump layout");
|
let err_context = || format!("Failed to dump layout");
|
||||||
pty.populate_session_layout_metadata(&mut session_layout_metadata);
|
pty.populate_session_layout_metadata(&mut session_layout_metadata);
|
||||||
let kdl_layout =
|
match session_serialization::serialize_session_layout(
|
||||||
session_serialization::serialize_session_layout(session_layout_metadata.into());
|
session_layout_metadata.into(),
|
||||||
pty.bus
|
) {
|
||||||
.senders
|
Ok(kdl_layout_and_pane_contents) => {
|
||||||
.send_to_background_jobs(BackgroundJob::ReportLayoutInfo(kdl_layout))
|
pty.bus
|
||||||
.with_context(err_context)?;
|
.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::Exit => break,
|
PtyInstruction::Exit => break,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -64,16 +64,18 @@ pub struct PaneLayoutManifest {
|
||||||
|
|
||||||
pub fn serialize_session_layout(
|
pub fn serialize_session_layout(
|
||||||
global_layout_manifest: GlobalLayoutManifest,
|
global_layout_manifest: GlobalLayoutManifest,
|
||||||
) -> (String, BTreeMap<String, String>) {
|
) -> Result<(String, BTreeMap<String, String>), &'static str> {
|
||||||
// BTreeMap is the pane contents and their file names
|
// BTreeMap is the pane contents and their file names
|
||||||
let mut kdl_string = String::from("layout {\n");
|
let mut kdl_string = String::from("layout {\n");
|
||||||
let mut pane_contents = BTreeMap::new();
|
let mut pane_contents = BTreeMap::new();
|
||||||
stringify_global_cwd(&global_layout_manifest.global_cwd, &mut kdl_string);
|
stringify_global_cwd(&global_layout_manifest.global_cwd, &mut kdl_string);
|
||||||
stringify_multiple_tabs(
|
if let Err(e) = stringify_multiple_tabs(
|
||||||
global_layout_manifest.tabs,
|
global_layout_manifest.tabs,
|
||||||
&mut pane_contents,
|
&mut pane_contents,
|
||||||
&mut kdl_string,
|
&mut kdl_string,
|
||||||
);
|
) {
|
||||||
|
return Err(e);
|
||||||
|
}
|
||||||
stringify_new_tab_template(
|
stringify_new_tab_template(
|
||||||
global_layout_manifest.default_layout.template,
|
global_layout_manifest.default_layout.template,
|
||||||
&mut pane_contents,
|
&mut pane_contents,
|
||||||
|
|
@ -90,7 +92,7 @@ pub fn serialize_session_layout(
|
||||||
&mut kdl_string,
|
&mut kdl_string,
|
||||||
);
|
);
|
||||||
kdl_string.push_str("}");
|
kdl_string.push_str("}");
|
||||||
(kdl_string, pane_contents)
|
Ok((kdl_string, pane_contents))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn stringify_tab(
|
fn stringify_tab(
|
||||||
|
|
@ -100,31 +102,38 @@ fn stringify_tab(
|
||||||
tiled_panes: &Vec<PaneLayoutManifest>,
|
tiled_panes: &Vec<PaneLayoutManifest>,
|
||||||
floating_panes: &Vec<PaneLayoutManifest>,
|
floating_panes: &Vec<PaneLayoutManifest>,
|
||||||
pane_contents: &mut BTreeMap<String, String>,
|
pane_contents: &mut BTreeMap<String, String>,
|
||||||
) -> String {
|
) -> Option<String> {
|
||||||
let mut kdl_string = String::new();
|
let mut kdl_string = String::new();
|
||||||
let tiled_panes_layout = get_tiled_panes_layout_from_panegeoms(tiled_panes, None);
|
// let tiled_panes_layout = get_tiled_panes_layout_from_panegeoms(tiled_panes, None);
|
||||||
let floating_panes_layout = get_floating_panes_layout_from_panegeoms(floating_panes);
|
match get_tiled_panes_layout_from_panegeoms(tiled_panes, None) {
|
||||||
let tiled_panes = if &tiled_panes_layout.children_split_direction != &SplitDirection::default()
|
Some(tiled_panes_layout) => {
|
||||||
{
|
let floating_panes_layout = get_floating_panes_layout_from_panegeoms(floating_panes);
|
||||||
vec![tiled_panes_layout]
|
let tiled_panes =
|
||||||
} else {
|
if &tiled_panes_layout.children_split_direction != &SplitDirection::default() {
|
||||||
tiled_panes_layout.children
|
vec![tiled_panes_layout]
|
||||||
};
|
} else {
|
||||||
let mut tab_attributes = vec![format!("name=\"{}\"", tab_name,)];
|
tiled_panes_layout.children
|
||||||
if is_focused {
|
};
|
||||||
tab_attributes.push(format!("focus=true"));
|
let mut tab_attributes = vec![format!("name=\"{}\"", tab_name,)];
|
||||||
|
if is_focused {
|
||||||
|
tab_attributes.push(format!("focus=true"));
|
||||||
|
}
|
||||||
|
if hide_floating_panes {
|
||||||
|
tab_attributes.push(format!("hide_floating_panes=true"));
|
||||||
|
}
|
||||||
|
kdl_string.push_str(&kdl_string_from_tab(
|
||||||
|
&tiled_panes,
|
||||||
|
&floating_panes_layout,
|
||||||
|
tab_attributes,
|
||||||
|
None,
|
||||||
|
pane_contents,
|
||||||
|
));
|
||||||
|
Some(kdl_string)
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
return None;
|
||||||
|
},
|
||||||
}
|
}
|
||||||
if hide_floating_panes {
|
|
||||||
tab_attributes.push(format!("hide_floating_panes=true"));
|
|
||||||
}
|
|
||||||
kdl_string.push_str(&kdl_string_from_tab(
|
|
||||||
&tiled_panes,
|
|
||||||
&floating_panes_layout,
|
|
||||||
tab_attributes,
|
|
||||||
None,
|
|
||||||
pane_contents,
|
|
||||||
));
|
|
||||||
kdl_string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Redundant with `geoms_to_kdl_tab`
|
/// Redundant with `geoms_to_kdl_tab`
|
||||||
|
|
@ -507,23 +516,29 @@ fn stringify_multiple_tabs(
|
||||||
tabs: Vec<(String, TabLayoutManifest)>,
|
tabs: Vec<(String, TabLayoutManifest)>,
|
||||||
pane_contents: &mut BTreeMap<String, String>,
|
pane_contents: &mut BTreeMap<String, String>,
|
||||||
kdl_string: &mut String,
|
kdl_string: &mut String,
|
||||||
) {
|
) -> Result<(), &'static str> {
|
||||||
for (tab_name, tab_layout_manifest) in tabs {
|
for (tab_name, tab_layout_manifest) in tabs {
|
||||||
let tiled_panes = tab_layout_manifest.tiled_panes;
|
let tiled_panes = tab_layout_manifest.tiled_panes;
|
||||||
let floating_panes = tab_layout_manifest.floating_panes;
|
let floating_panes = tab_layout_manifest.floating_panes;
|
||||||
let hide_floating_panes = tab_layout_manifest.hide_floating_panes;
|
let hide_floating_panes = tab_layout_manifest.hide_floating_panes;
|
||||||
kdl_string.push_str(&indent(
|
let stringified = stringify_tab(
|
||||||
&stringify_tab(
|
tab_name.clone(),
|
||||||
tab_name.clone(),
|
tab_layout_manifest.is_focused,
|
||||||
tab_layout_manifest.is_focused,
|
hide_floating_panes,
|
||||||
hide_floating_panes,
|
&tiled_panes,
|
||||||
&tiled_panes,
|
&floating_panes,
|
||||||
&floating_panes,
|
pane_contents,
|
||||||
pane_contents,
|
);
|
||||||
),
|
match stringified {
|
||||||
INDENT,
|
Some(stringified) => {
|
||||||
));
|
kdl_string.push_str(&indent(&stringified, INDENT));
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
return Err("Failed to stringify tab");
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn kdl_string_from_floating_pane(
|
fn kdl_string_from_floating_pane(
|
||||||
|
|
@ -592,10 +607,15 @@ fn tiled_pane_layout_from_manifest(
|
||||||
fn get_tiled_panes_layout_from_panegeoms(
|
fn get_tiled_panes_layout_from_panegeoms(
|
||||||
geoms: &Vec<PaneLayoutManifest>,
|
geoms: &Vec<PaneLayoutManifest>,
|
||||||
split_size: Option<SplitSize>,
|
split_size: Option<SplitSize>,
|
||||||
) -> TiledPaneLayout {
|
) -> Option<TiledPaneLayout> {
|
||||||
let (children_split_direction, splits) = match get_splits(&geoms) {
|
let (children_split_direction, splits) = match get_splits(&geoms) {
|
||||||
Some(x) => x,
|
Some(x) => x,
|
||||||
None => return tiled_pane_layout_from_manifest(geoms.iter().next(), split_size),
|
None => {
|
||||||
|
return Some(tiled_pane_layout_from_manifest(
|
||||||
|
geoms.iter().next(),
|
||||||
|
split_size,
|
||||||
|
))
|
||||||
|
},
|
||||||
};
|
};
|
||||||
let mut children = Vec::new();
|
let mut children = Vec::new();
|
||||||
let mut remaining_geoms = geoms.clone();
|
let mut remaining_geoms = geoms.clone();
|
||||||
|
|
@ -614,29 +634,38 @@ fn get_tiled_panes_layout_from_panegeoms(
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.partition(|g| g.geom.x + g.geom.cols.as_usize() <= v_max),
|
.partition(|g| g.geom.x + g.geom.cols.as_usize() <= v_max),
|
||||||
};
|
};
|
||||||
let constraint =
|
match get_domain_constraint(&subgeoms, &children_split_direction, (v_min, v_max)) {
|
||||||
get_domain_constraint(&subgeoms, &children_split_direction, (v_min, v_max));
|
Some(constraint) => {
|
||||||
new_geoms.push(subgeoms);
|
new_geoms.push(subgeoms);
|
||||||
new_constraints.push(constraint);
|
new_constraints.push(constraint);
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
return None;
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
let new_split_sizes = get_split_sizes(&new_constraints);
|
let new_split_sizes = get_split_sizes(&new_constraints);
|
||||||
for (subgeoms, subsplit_size) in new_geoms.iter().zip(new_split_sizes) {
|
for (subgeoms, subsplit_size) in new_geoms.iter().zip(new_split_sizes) {
|
||||||
children.push(get_tiled_panes_layout_from_panegeoms(
|
match get_tiled_panes_layout_from_panegeoms(&subgeoms, subsplit_size) {
|
||||||
&subgeoms,
|
Some(child) => {
|
||||||
subsplit_size,
|
children.push(child);
|
||||||
));
|
},
|
||||||
|
None => {
|
||||||
|
return None;
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
let children_are_stacked = children_split_direction == SplitDirection::Horizontal
|
let children_are_stacked = children_split_direction == SplitDirection::Horizontal
|
||||||
&& new_geoms
|
&& new_geoms
|
||||||
.iter()
|
.iter()
|
||||||
.all(|c| c.iter().all(|c| c.geom.is_stacked));
|
.all(|c| c.iter().all(|c| c.geom.is_stacked));
|
||||||
TiledPaneLayout {
|
Some(TiledPaneLayout {
|
||||||
children_split_direction,
|
children_split_direction,
|
||||||
split_size,
|
split_size,
|
||||||
children,
|
children,
|
||||||
children_are_stacked,
|
children_are_stacked,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_floating_panes_layout_from_panegeoms(
|
fn get_floating_panes_layout_from_panegeoms(
|
||||||
|
|
@ -789,7 +818,7 @@ fn get_domain_constraint(
|
||||||
geoms: &Vec<PaneLayoutManifest>,
|
geoms: &Vec<PaneLayoutManifest>,
|
||||||
split_direction: &SplitDirection,
|
split_direction: &SplitDirection,
|
||||||
(v_min, v_max): (usize, usize),
|
(v_min, v_max): (usize, usize),
|
||||||
) -> Constraint {
|
) -> Option<Constraint> {
|
||||||
match split_direction {
|
match split_direction {
|
||||||
SplitDirection::Horizontal => get_domain_row_constraint(&geoms, (v_min, v_max)),
|
SplitDirection::Horizontal => get_domain_row_constraint(&geoms, (v_min, v_max)),
|
||||||
SplitDirection::Vertical => get_domain_col_constraint(&geoms, (v_min, v_max)),
|
SplitDirection::Vertical => get_domain_col_constraint(&geoms, (v_min, v_max)),
|
||||||
|
|
@ -800,21 +829,28 @@ fn get_domain_constraint(
|
||||||
fn get_domain_col_constraint(
|
fn get_domain_col_constraint(
|
||||||
geoms: &Vec<PaneLayoutManifest>,
|
geoms: &Vec<PaneLayoutManifest>,
|
||||||
(x_min, x_max): (usize, usize),
|
(x_min, x_max): (usize, usize),
|
||||||
) -> Constraint {
|
) -> Option<Constraint> {
|
||||||
let mut percent = 0.0;
|
let mut percent = 0.0;
|
||||||
let mut x = x_min;
|
let mut x = x_min;
|
||||||
while x != x_max {
|
while x != x_max {
|
||||||
// we only look at one (ie the last) geom that has value `x` for `g.x`
|
// we only look at one (ie the last) geom that has value `x` for `g.x`
|
||||||
let geom = geoms.iter().filter(|g| g.geom.x == x).last().unwrap();
|
let geom = geoms.iter().filter(|g| g.geom.x == x).last();
|
||||||
if let Some(size) = geom.geom.cols.as_percent() {
|
match geom {
|
||||||
percent += size;
|
Some(geom) => {
|
||||||
|
if let Some(size) = geom.geom.cols.as_percent() {
|
||||||
|
percent += size;
|
||||||
|
}
|
||||||
|
x += geom.geom.cols.as_usize();
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
return None;
|
||||||
|
},
|
||||||
}
|
}
|
||||||
x += geom.geom.cols.as_usize();
|
|
||||||
}
|
}
|
||||||
if percent == 0.0 {
|
if percent == 0.0 {
|
||||||
Constraint::Fixed(x_max - x_min)
|
Some(Constraint::Fixed(x_max - x_min))
|
||||||
} else {
|
} else {
|
||||||
Constraint::Percent(percent)
|
Some(Constraint::Percent(percent))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -822,21 +858,28 @@ fn get_domain_col_constraint(
|
||||||
fn get_domain_row_constraint(
|
fn get_domain_row_constraint(
|
||||||
geoms: &Vec<PaneLayoutManifest>,
|
geoms: &Vec<PaneLayoutManifest>,
|
||||||
(y_min, y_max): (usize, usize),
|
(y_min, y_max): (usize, usize),
|
||||||
) -> Constraint {
|
) -> Option<Constraint> {
|
||||||
let mut percent = 0.0;
|
let mut percent = 0.0;
|
||||||
let mut y = y_min;
|
let mut y = y_min;
|
||||||
while y != y_max {
|
while y != y_max {
|
||||||
// we only look at one (ie the last) geom that has value `y` for `g.y`
|
// we only look at one (ie the last) geom that has value `y` for `g.y`
|
||||||
let geom = geoms.iter().filter(|g| g.geom.y == y).last().unwrap();
|
let geom = geoms.iter().filter(|g| g.geom.y == y).last();
|
||||||
if let Some(size) = geom.geom.rows.as_percent() {
|
match geom {
|
||||||
percent += size;
|
Some(geom) => {
|
||||||
|
if let Some(size) = geom.geom.rows.as_percent() {
|
||||||
|
percent += size;
|
||||||
|
}
|
||||||
|
y += geom.geom.rows.as_usize();
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
return None;
|
||||||
|
},
|
||||||
}
|
}
|
||||||
y += geom.geom.rows.as_usize();
|
|
||||||
}
|
}
|
||||||
if percent == 0.0 {
|
if percent == 0.0 {
|
||||||
Constraint::Fixed(y_max - y_min)
|
Some(Constraint::Fixed(y_max - y_min))
|
||||||
} else {
|
} else {
|
||||||
Constraint::Percent(percent)
|
Some(Constraint::Percent(percent))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -932,7 +975,7 @@ mod tests {
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
// let kdl = kdl_string_from_panegeoms(&geoms);
|
// let kdl = kdl_string_from_panegeoms(&geoms);
|
||||||
let kdl = serialize_session_layout(global_layout_manifest);
|
let kdl = serialize_session_layout(global_layout_manifest).unwrap();
|
||||||
expect![[r#"layout {
|
expect![[r#"layout {
|
||||||
tab name="Tab #1" {
|
tab name="Tab #1" {
|
||||||
pane size=1
|
pane size=1
|
||||||
|
|
@ -958,7 +1001,7 @@ mod tests {
|
||||||
tabs: vec![("Tab #1".to_owned(), tab_layout_manifest)],
|
tabs: vec![("Tab #1".to_owned(), tab_layout_manifest)],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
let kdl = serialize_session_layout(global_layout_manifest);
|
let kdl = serialize_session_layout(global_layout_manifest).unwrap();
|
||||||
expect![[r#"layout {
|
expect![[r#"layout {
|
||||||
tab name="Tab #1" {
|
tab name="Tab #1" {
|
||||||
pane
|
pane
|
||||||
|
|
@ -986,7 +1029,7 @@ mod tests {
|
||||||
tabs: vec![("Tab #1".to_owned(), tab_layout_manifest)],
|
tabs: vec![("Tab #1".to_owned(), tab_layout_manifest)],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
let kdl = serialize_session_layout(global_layout_manifest);
|
let kdl = serialize_session_layout(global_layout_manifest).unwrap();
|
||||||
expect![[r#"layout {
|
expect![[r#"layout {
|
||||||
tab name="Tab #1" {
|
tab name="Tab #1" {
|
||||||
pane size=10 split_direction="vertical" {
|
pane size=10 split_direction="vertical" {
|
||||||
|
|
@ -1022,7 +1065,7 @@ mod tests {
|
||||||
tabs: vec![("Tab #1".to_owned(), tab_layout_manifest)],
|
tabs: vec![("Tab #1".to_owned(), tab_layout_manifest)],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
let kdl = serialize_session_layout(global_layout_manifest);
|
let kdl = serialize_session_layout(global_layout_manifest).unwrap();
|
||||||
expect![[r#"layout {
|
expect![[r#"layout {
|
||||||
tab name="Tab #1" {
|
tab name="Tab #1" {
|
||||||
pane split_direction="vertical" {
|
pane split_direction="vertical" {
|
||||||
|
|
@ -1059,7 +1102,7 @@ mod tests {
|
||||||
tabs: vec![("Tab #1".to_owned(), tab_layout_manifest)],
|
tabs: vec![("Tab #1".to_owned(), tab_layout_manifest)],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
let kdl = serialize_session_layout(global_layout_manifest);
|
let kdl = serialize_session_layout(global_layout_manifest).unwrap();
|
||||||
expect![[r#"layout {
|
expect![[r#"layout {
|
||||||
tab name="Tab #1" {
|
tab name="Tab #1" {
|
||||||
pane size=5
|
pane size=5
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue