diff --git a/xtask/src/app.rs b/xtask/src/app.rs index b7e3113..24e8402 100644 --- a/xtask/src/app.rs +++ b/xtask/src/app.rs @@ -30,6 +30,13 @@ pub struct Patch { } impl Patch { + pub fn with_root(self, root: Option<&Path>) -> Patch { + Patch { + base: root_path(root, self.base), + diff: root_path(root, self.diff), + } + } + pub fn base(&self) -> &Path { self.base.as_ref() } @@ -60,11 +67,15 @@ pub struct App { blobs: Vec, } +fn root_path(root: Option<&Path>, p: PathBuf) -> PathBuf { + if let Some(root) = root { root.join(p) } else { p } +} + impl App { - pub fn try_from_str(data: &str) -> Result { + pub fn try_from_str(root: Option<&Path>, data: &str) -> Result { let app_raw: AppRaw = toml::from_str(data)?; - let app = if let Some(base) = &app_raw.base { - let base = try_from_file(base) + let app = if let Some(base) = app_raw.base { + let base = try_from_file(root, &root_path(root, base)) .context("Failed to parse base App config")?; App { cpu: app_raw.cpu.unwrap_or(base.cpu), @@ -75,7 +86,8 @@ impl App { app_raw.patch } else { base.patch - }, + } + .map(|p| p.with_root(root)), size: app_raw.size.unwrap_or(base.size), board: app_raw.board.unwrap_or(base.board), blobs: app_raw.blobs.unwrap_or(base.blobs), @@ -86,7 +98,7 @@ impl App { firmware_version: app_raw .firmware_version .ok_or_else(|| anyhow!("'firmware_version' missing"))?, - patch: app_raw.patch, + patch: app_raw.patch.map(|p| p.with_root(root)), size: app_raw.size.ok_or_else(|| anyhow!("'size' missing"))?, board: app_raw .board @@ -140,7 +152,7 @@ impl App { } } -pub fn try_from_file(app: &Path) -> Result { +pub fn try_from_file(root: Option<&Path>, app: &Path) -> Result { eprintln!("reading from {app:?}"); let data = fs::read(app)?; //eprintln!("data: {data:?}"); @@ -151,7 +163,7 @@ pub fn try_from_file(app: &Path) -> Result { return Err(e.into()); } }; - App::try_from_str(data) + App::try_from_str(root, data) } #[cfg(test)] @@ -170,7 +182,7 @@ mod tests { 'b', 'c', ]"#; - let maybe = App::try_from_str(data); + let maybe = App::try_from_str(None, data); assert!(maybe.is_ok()); let app = maybe.unwrap(); assert_eq!(app.cpu, Cpu::Turin); @@ -199,7 +211,7 @@ mod tests { 'b', 'c', ]"#; - assert!(App::try_from_str(base_data).is_ok()); + assert!(App::try_from_str(None, base_data).is_ok()); let mut base_app = NamedTempFile::new().unwrap(); writeln!(base_app, "{base_data}").unwrap(); base_app.flush().unwrap(); @@ -215,7 +227,7 @@ mod tests { "#, base_app.path().display() ); - let maybe = App::try_from_str(&data); + let maybe = App::try_from_str(None, &data); assert!(maybe.is_ok()); let app = maybe.unwrap(); assert_eq!(app.cpu, Cpu::Turin); @@ -232,4 +244,26 @@ mod tests { assert_eq!(patch.base, PathBuf::from("base.json5")); assert_eq!(patch.diff, PathBuf::from("diff.patch")); } + + #[test] + fn patch_root() { + let data = r#" + cpu = 'test' + board = 'test' + size = 16 + firmware_version = 'test' + blobs = [] + [patch] + base = '/base.json5' + diff = 'diff.patch' + "#; + let maybe = App::try_from_str(Some(&Path::new("/configs")), data); + assert!(maybe.is_ok()); + let app = maybe.unwrap(); + assert!(app.patch.is_some()); + let patch = app.patch.unwrap(); + // Base path was absolute so should remain unchanged + assert_eq!(patch.base, PathBuf::from("/base.json5")); + assert_eq!(patch.diff, PathBuf::from("/configs/diff.patch")); + } } diff --git a/xtask/src/main.rs b/xtask/src/main.rs index bf40485..557e137 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -68,6 +68,8 @@ enum Command { locked: Locked, #[clap(flatten)] verbose: Verbose, + #[clap(long)] + root: Option, }, /// Dumps an existing image, extracting its blobs /// and printing its config @@ -193,7 +195,9 @@ fn main() -> std::io::Result<()> { profile, locked, verbose, + root, } => run_gen( + root.as_deref(), app.as_path(), config.as_deref(), payload.as_path(), @@ -217,6 +221,7 @@ fn build(args: Build) { } fn run_gen + ?Sized>( + root: Option<&P>, app: &P, config: Option<&P>, payload: &P, @@ -224,7 +229,8 @@ fn run_gen + ?Sized>( image: &P, args: Build, ) { - let app = app::try_from_file(app.as_ref()).expect("Parsed app"); + let app = app::try_from_file(root.map(|r| r.as_ref()), app.as_ref()) + .expect("Parsed app"); let name = app.name(); let name = Path::new(&name); let run = args.cmd_str("run"); @@ -335,6 +341,7 @@ fn cargo() -> String { fn test_payload() { let image = "target/test.img"; run_gen( + None, "apps/test.toml", None, "target/testpl",