Skip to content

Commit dc862a2

Browse files
Johan-Liebert1cgwalters
authored andcommitted
parser/grub: Use String instead of &str
Returning a local reference to a `&str` is quite tricky with rust. Update `title` and `chainloader`, the two dynamic fields in the grub menuentry, to be `String` instead of `&str` Signed-off-by: Johan-Liebert1 <[email protected]>
1 parent 93a6d75 commit dc862a2

File tree

2 files changed

+48
-37
lines changed

2 files changed

+48
-37
lines changed

crates/lib/src/parsers/grub_menuconfig.rs

Lines changed: 47 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,11 @@ pub(crate) struct MenuentryBody<'a> {
1616
/// Kernel modules to load
1717
pub(crate) insmod: Vec<&'a str>,
1818
/// Chainloader path (optional)
19-
pub(crate) chainloader: Option<&'a str>,
19+
pub(crate) chainloader: String,
2020
/// Search command (optional)
21-
pub(crate) search: Option<&'a str>,
21+
pub(crate) search: &'a str,
22+
/// The version
23+
pub(crate) version: u8,
2224
/// Additional commands
2325
pub(crate) extra: Vec<(&'a str, &'a str)>,
2426
}
@@ -29,13 +31,8 @@ impl<'a> Display for MenuentryBody<'a> {
2931
writeln!(f, "insmod {}", insmod)?;
3032
}
3133

32-
if let Some(search) = self.search {
33-
writeln!(f, "search {}", search)?;
34-
}
35-
36-
if let Some(chainloader) = self.chainloader {
37-
writeln!(f, "chainloader {}", chainloader)?;
38-
}
34+
writeln!(f, "search {}", self.search)?;
35+
writeln!(f, "chainloader {}", self.chainloader)?;
3936

4037
for (k, v) in &self.extra {
4138
writeln!(f, "{k} {v}")?;
@@ -49,17 +46,17 @@ impl<'a> From<Vec<(&'a str, &'a str)>> for MenuentryBody<'a> {
4946
fn from(vec: Vec<(&'a str, &'a str)>) -> Self {
5047
let mut entry = Self {
5148
insmod: vec![],
52-
chainloader: None,
53-
search: None,
49+
chainloader: "".into(),
50+
search: "",
51+
version: 0,
5452
extra: vec![],
5553
};
5654

5755
for (key, value) in vec {
5856
match key {
5957
"insmod" => entry.insmod.push(value),
60-
"chainloader" => entry.chainloader = Some(value),
61-
"search" => entry.search = Some(value),
62-
// Skip 'set' commands as they are typically variable assignments
58+
"chainloader" => entry.chainloader = value.into(),
59+
"search" => entry.search = value,
6360
"set" => {}
6461
_ => entry.extra.push((key, value)),
6562
}
@@ -74,7 +71,7 @@ impl<'a> From<Vec<(&'a str, &'a str)>> for MenuentryBody<'a> {
7471
#[allow(dead_code)]
7572
pub(crate) struct MenuEntry<'a> {
7673
/// Display title (supports escaped quotes)
77-
pub(crate) title: &'a str,
74+
pub(crate) title: String,
7875
/// Commands within the menuentry block
7976
pub(crate) body: MenuentryBody<'a>,
8077
}
@@ -87,6 +84,22 @@ impl<'a> Display for MenuEntry<'a> {
8784
}
8885
}
8986

87+
impl<'a> MenuEntry<'a> {
88+
#[allow(dead_code)]
89+
pub(crate) fn new(boot_label: &str, uki_id: &str) -> Self {
90+
Self {
91+
title: format!("{boot_label}: ({uki_id})"),
92+
body: MenuentryBody {
93+
insmod: vec!["fat", "chain"],
94+
chainloader: format!("/EFI/Linux/{uki_id}.efi"),
95+
search: "--no-floppy --set=root --fs-uuid \"${EFI_PART_UUID}\"",
96+
version: 0,
97+
extra: vec![],
98+
},
99+
}
100+
}
101+
}
102+
90103
/// Parser that takes content until balanced brackets, handling nested brackets and escapes.
91104
#[allow(dead_code)]
92105
pub fn take_until_balanced_allow_nested(
@@ -183,7 +196,7 @@ fn parse_menuentry(input: &str) -> IResult<&str, MenuEntry> {
183196
Ok((
184197
input,
185198
MenuEntry {
186-
title,
199+
title: title.to_string(),
187200
body: MenuentryBody::from(map),
188201
},
189202
))
@@ -278,20 +291,22 @@ mod test {
278291

279292
let expected = vec![
280293
MenuEntry {
281-
title: "Fedora 42: (Verity-42)",
294+
title: "Fedora 42: (Verity-42)".into(),
282295
body: MenuentryBody {
283296
insmod: vec!["fat", "chain"],
284-
search: Some("--no-floppy --set=root --fs-uuid \"${EFI_PART_UUID}\""),
285-
chainloader: Some("/EFI/Linux/7e11ac46e3e022053e7226a20104ac656bf72d1a84e3a398b7cce70e9df188b6.efi"),
297+
search: "--no-floppy --set=root --fs-uuid \"${EFI_PART_UUID}\"",
298+
chainloader: "/EFI/Linux/7e11ac46e3e022053e7226a20104ac656bf72d1a84e3a398b7cce70e9df188b6.efi".into(),
299+
version: 0,
286300
extra: vec![],
287301
},
288302
},
289303
MenuEntry {
290-
title: "Fedora 43: (Verity-43)",
304+
title: "Fedora 43: (Verity-43)".into(),
291305
body: MenuentryBody {
292306
insmod: vec!["fat", "chain"],
293-
search: Some("--no-floppy --set=root --fs-uuid \"${EFI_PART_UUID}\""),
294-
chainloader: Some("/EFI/Linux/uki.efi"),
307+
search: "--no-floppy --set=root --fs-uuid \"${EFI_PART_UUID}\"",
308+
chainloader: "/EFI/Linux/uki.efi".into(),
309+
version: 0,
295310
extra: vec![
296311
("extra_field1", "this is extra"),
297312
("extra_field2", "this is also extra")
@@ -318,7 +333,7 @@ mod test {
318333

319334
assert_eq!(result.len(), 1);
320335
assert_eq!(result[0].title, "Title with \\\"escaped quotes\\\" inside");
321-
assert_eq!(result[0].body.chainloader, Some("/EFI/Linux/test.efi"));
336+
assert_eq!(result[0].body.chainloader, "/EFI/Linux/test.efi");
322337
}
323338

324339
#[test]
@@ -367,8 +382,8 @@ mod test {
367382
assert_eq!(result.len(), 1);
368383
assert_eq!(result[0].title, "Minimal Entry");
369384
assert_eq!(result[0].body.insmod.len(), 0);
370-
assert_eq!(result[0].body.chainloader, None);
371-
assert_eq!(result[0].body.search, None);
385+
assert_eq!(result[0].body.chainloader, "");
386+
assert_eq!(result[0].body.search, "");
372387
assert_eq!(result[0].body.extra.len(), 0);
373388
}
374389

@@ -386,8 +401,8 @@ mod test {
386401

387402
assert_eq!(result.len(), 1);
388403
assert_eq!(result[0].body.insmod, vec!["fat", "chain", "ext2"]);
389-
assert_eq!(result[0].body.chainloader, None);
390-
assert_eq!(result[0].body.search, None);
404+
assert_eq!(result[0].body.chainloader, "");
405+
assert_eq!(result[0].body.search, "");
391406
}
392407

393408
#[test]
@@ -405,7 +420,7 @@ mod test {
405420

406421
assert_eq!(result.len(), 1);
407422
assert_eq!(result[0].body.insmod, vec!["fat"]);
408-
assert_eq!(result[0].body.chainloader, Some("/EFI/Linux/test.efi"));
423+
assert_eq!(result[0].body.chainloader, "/EFI/Linux/test.efi");
409424
// set commands should be ignored
410425
assert!(!result[0].body.extra.iter().any(|(k, _)| k == &"set"));
411426
}
@@ -427,7 +442,7 @@ mod test {
427442
assert_eq!(result.len(), 1);
428443
assert_eq!(result[0].title, "Nested Braces");
429444
assert_eq!(result[0].body.insmod, vec!["fat"]);
430-
assert_eq!(result[0].body.chainloader, Some("/EFI/Linux/test.efi"));
445+
assert_eq!(result[0].body.chainloader, "/EFI/Linux/test.efi");
431446
// The if/fi block should be captured as extra commands
432447
assert!(result[0].body.extra.iter().any(|(k, _)| k == &"if"));
433448
}
@@ -506,12 +521,9 @@ mod test {
506521

507522
assert_eq!(result.len(), 2);
508523
assert_eq!(result[0].title, "First Entry");
509-
assert_eq!(result[0].body.chainloader, Some("/EFI/Linux/first.efi"));
524+
assert_eq!(result[0].body.chainloader, "/EFI/Linux/first.efi");
510525
assert_eq!(result[1].title, "Second Entry");
511-
assert_eq!(result[1].body.chainloader, Some("/EFI/Linux/second.efi"));
512-
assert_eq!(
513-
result[1].body.search,
514-
Some("--set=root --fs-uuid \"some-uuid\"")
515-
);
526+
assert_eq!(result[1].body.chainloader, "/EFI/Linux/second.efi");
527+
assert_eq!(result[1].body.search, "--set=root --fs-uuid \"some-uuid\"");
516528
}
517529
}

crates/lib/src/status.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -514,8 +514,7 @@ pub(crate) async fn composefs_deployment_status() -> Result<Host> {
514514
.ok_or(anyhow::anyhow!("First boot entry not found"))?
515515
.body
516516
.chainloader
517-
.map(|v| v.contains(composefs_arg.as_ref()))
518-
.unwrap_or_default()
517+
.contains(composefs_arg.as_ref())
519518
}
520519
};
521520

0 commit comments

Comments
 (0)