mirror of
https://github.com/asciinema/asciinema.git
synced 2025-12-15 19:28:00 +01:00
Fix reading of asciicasts v1 and v2 having null env values in header
This commit is contained in:
@@ -274,6 +274,11 @@ mod tests {
|
|||||||
assert_eq!(version, 1);
|
assert_eq!(version, 1);
|
||||||
assert_eq!((header.term_cols, header.term_rows), (100, 50));
|
assert_eq!((header.term_cols, header.term_rows), (100, 50));
|
||||||
|
|
||||||
|
let mut expected_env = HashMap::new();
|
||||||
|
expected_env.insert("SHELL".to_owned(), "/bin/bash".to_owned());
|
||||||
|
expected_env.insert("TERM".to_owned(), "xterm-256color".to_owned());
|
||||||
|
assert_eq!(header.env.unwrap(), expected_env);
|
||||||
|
|
||||||
assert_eq!(events[0].time, Duration::from_micros(1));
|
assert_eq!(events[0].time, Duration::from_micros(1));
|
||||||
assert!(matches!(events[0].data, EventData::Output(ref s) if s == "ż"));
|
assert!(matches!(events[0].data, EventData::Output(ref s) if s == "ż"));
|
||||||
|
|
||||||
@@ -284,6 +289,18 @@ mod tests {
|
|||||||
assert!(matches!(events[2].data, EventData::Output(ref s) if s == "\r\n"));
|
assert!(matches!(events[2].data, EventData::Output(ref s) if s == "\r\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn open_v1_with_nulls_in_header() {
|
||||||
|
let Asciicast {
|
||||||
|
version, header, ..
|
||||||
|
} = super::open_from_path("tests/casts/nulls-v1.json").unwrap();
|
||||||
|
assert_eq!(version, 1);
|
||||||
|
|
||||||
|
let mut expected_env = HashMap::new();
|
||||||
|
expected_env.insert("SHELL".to_owned(), "/bin/bash".to_owned());
|
||||||
|
assert_eq!(header.env.unwrap(), expected_env);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn open_v2_minimal() {
|
fn open_v2_minimal() {
|
||||||
let Asciicast {
|
let Asciicast {
|
||||||
@@ -319,6 +336,11 @@ mod tests {
|
|||||||
assert_eq!(theme.bg, RGB8::new(0xff, 0xff, 0xff));
|
assert_eq!(theme.bg, RGB8::new(0xff, 0xff, 0xff));
|
||||||
assert_eq!(theme.palette[0], RGB8::new(0x24, 0x1f, 0x31));
|
assert_eq!(theme.palette[0], RGB8::new(0x24, 0x1f, 0x31));
|
||||||
|
|
||||||
|
let mut expected_env = HashMap::new();
|
||||||
|
expected_env.insert("SHELL".to_owned(), "/bin/bash".to_owned());
|
||||||
|
expected_env.insert("TERM".to_owned(), "xterm-256color".to_owned());
|
||||||
|
assert_eq!(header.env.unwrap(), expected_env);
|
||||||
|
|
||||||
assert_eq!(events[0].time, Duration::from_micros(1));
|
assert_eq!(events[0].time, Duration::from_micros(1));
|
||||||
assert!(matches!(events[0].data, EventData::Output(ref s) if s == "ż"));
|
assert!(matches!(events[0].data, EventData::Output(ref s) if s == "ż"));
|
||||||
|
|
||||||
@@ -338,6 +360,18 @@ mod tests {
|
|||||||
assert!(matches!(events[4].data, EventData::Output(ref s) if s == "\r\n"));
|
assert!(matches!(events[4].data, EventData::Output(ref s) if s == "\r\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn open_v2_with_nulls_in_header() {
|
||||||
|
let Asciicast {
|
||||||
|
version, header, ..
|
||||||
|
} = super::open_from_path("tests/casts/nulls-v2.cast").unwrap();
|
||||||
|
assert_eq!(version, 2);
|
||||||
|
|
||||||
|
let mut expected_env = HashMap::new();
|
||||||
|
expected_env.insert("SHELL".to_owned(), "/bin/bash".to_owned());
|
||||||
|
assert_eq!(header.env.unwrap(), expected_env);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn open_v3_minimal() {
|
fn open_v3_minimal() {
|
||||||
let Asciicast {
|
let Asciicast {
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ struct V1 {
|
|||||||
height: u16,
|
height: u16,
|
||||||
command: Option<String>,
|
command: Option<String>,
|
||||||
title: Option<String>,
|
title: Option<String>,
|
||||||
env: Option<HashMap<String, String>>,
|
env: Option<HashMap<String, Option<String>>>,
|
||||||
stdout: Vec<V1OutputEvent>,
|
stdout: Vec<V1OutputEvent>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -35,8 +35,16 @@ pub fn load(json: String) -> Result<Asciicast<'static>> {
|
|||||||
let term_type = asciicast
|
let term_type = asciicast
|
||||||
.env
|
.env
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|env| env.get("TERM"))
|
.map(|env| env.get("TERM"))
|
||||||
.cloned();
|
.unwrap_or_default()
|
||||||
|
.cloned()
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
|
let env = asciicast.env.map(|env| {
|
||||||
|
env.into_iter()
|
||||||
|
.filter_map(|(k, v)| v.map(|v| (k, v)))
|
||||||
|
.collect()
|
||||||
|
});
|
||||||
|
|
||||||
let header = Header {
|
let header = Header {
|
||||||
term_cols: asciicast.width,
|
term_cols: asciicast.width,
|
||||||
@@ -48,7 +56,7 @@ pub fn load(json: String) -> Result<Asciicast<'static>> {
|
|||||||
idle_time_limit: None,
|
idle_time_limit: None,
|
||||||
command: asciicast.command.clone(),
|
command: asciicast.command.clone(),
|
||||||
title: asciicast.title.clone(),
|
title: asciicast.title.clone(),
|
||||||
env: asciicast.env.clone(),
|
env,
|
||||||
};
|
};
|
||||||
|
|
||||||
let events = Box::new(asciicast.stdout.into_iter().scan(
|
let events = Box::new(asciicast.stdout.into_iter().scan(
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ struct V2Header {
|
|||||||
idle_time_limit: Option<f64>,
|
idle_time_limit: Option<f64>,
|
||||||
command: Option<String>,
|
command: Option<String>,
|
||||||
title: Option<String>,
|
title: Option<String>,
|
||||||
env: Option<HashMap<String, String>>,
|
env: Option<HashMap<String, Option<String>>>,
|
||||||
theme: Option<V2Theme>,
|
theme: Option<V2Theme>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,9 +70,22 @@ pub fn open(header_line: &str) -> Result<Parser> {
|
|||||||
|
|
||||||
impl Parser {
|
impl Parser {
|
||||||
pub fn parse<'a, I: Iterator<Item = io::Result<String>> + 'a>(self, lines: I) -> Asciicast<'a> {
|
pub fn parse<'a, I: Iterator<Item = io::Result<String>> + 'a>(self, lines: I) -> Asciicast<'a> {
|
||||||
let term_type = self.0.env.as_ref().and_then(|env| env.get("TERM").cloned());
|
let term_type = self
|
||||||
|
.0
|
||||||
|
.env
|
||||||
|
.as_ref()
|
||||||
|
.map(|env| env.get("TERM").cloned())
|
||||||
|
.unwrap_or_default()
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
let term_theme = self.0.theme.as_ref().map(|t| t.into());
|
let term_theme = self.0.theme.as_ref().map(|t| t.into());
|
||||||
|
|
||||||
|
let env = self.0.env.map(|env| {
|
||||||
|
env.into_iter()
|
||||||
|
.filter_map(|(k, v)| v.map(|v| (k, v)))
|
||||||
|
.collect()
|
||||||
|
});
|
||||||
|
|
||||||
let header = Header {
|
let header = Header {
|
||||||
term_cols: self.0.width,
|
term_cols: self.0.width,
|
||||||
term_rows: self.0.height,
|
term_rows: self.0.height,
|
||||||
@@ -83,7 +96,7 @@ impl Parser {
|
|||||||
idle_time_limit: self.0.idle_time_limit,
|
idle_time_limit: self.0.idle_time_limit,
|
||||||
command: self.0.command.clone(),
|
command: self.0.command.clone(),
|
||||||
title: self.0.title.clone(),
|
title: self.0.title.clone(),
|
||||||
env: self.0.env.clone(),
|
env,
|
||||||
};
|
};
|
||||||
|
|
||||||
let events = Box::new(lines.filter_map(parse_line));
|
let events = Box::new(lines.filter_map(parse_line));
|
||||||
@@ -367,6 +380,11 @@ impl serde::Serialize for V2Palette {
|
|||||||
|
|
||||||
impl From<&Header> for V2Header {
|
impl From<&Header> for V2Header {
|
||||||
fn from(header: &Header) -> Self {
|
fn from(header: &Header) -> Self {
|
||||||
|
let env = header
|
||||||
|
.env
|
||||||
|
.clone()
|
||||||
|
.map(|env| env.into_iter().map(|(k, v)| (k, Some(v))).collect());
|
||||||
|
|
||||||
V2Header {
|
V2Header {
|
||||||
version: 2,
|
version: 2,
|
||||||
width: header.term_cols,
|
width: header.term_cols,
|
||||||
@@ -375,7 +393,7 @@ impl From<&Header> for V2Header {
|
|||||||
idle_time_limit: header.idle_time_limit,
|
idle_time_limit: header.idle_time_limit,
|
||||||
command: header.command.clone(),
|
command: header.command.clone(),
|
||||||
title: header.title.clone(),
|
title: header.title.clone(),
|
||||||
env: header.env.clone(),
|
env,
|
||||||
theme: header.term_theme.as_ref().map(|t| t.into()),
|
theme: header.term_theme.as_ref().map(|t| t.into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
15
tests/casts/nulls-v1.json
Normal file
15
tests/casts/nulls-v1.json
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"width": 100,
|
||||||
|
"height": 50,
|
||||||
|
"env": {
|
||||||
|
"SHELL": "/bin/bash",
|
||||||
|
"TERM": null
|
||||||
|
},
|
||||||
|
"stdout": [
|
||||||
|
[
|
||||||
|
1.230000,
|
||||||
|
"hello"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
2
tests/casts/nulls-v2.cast
Normal file
2
tests/casts/nulls-v2.cast
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
{"version":2,"width":100,"height":50,"env":{"TERM":null,"SHELL":"/bin/bash"}}
|
||||||
|
[1.23, "o", "hello"]
|
||||||
Reference in New Issue
Block a user