diff --git a/bootspec/src/lib.rs b/bootspec/src/lib.rs index 25e9722..bd79500 100644 --- a/bootspec/src/lib.rs +++ b/bootspec/src/lib.rs @@ -12,17 +12,6 @@ pub struct SpecialisationName(pub String); /// A wrapper type describing the root directory of a NixOS system configuration. pub struct SystemConfigurationRoot(pub PathBuf); -#[derive(Debug, Default, Clone, Deserialize, Serialize, PartialEq, Eq)] -/// A wrapper type describing the path to the bootspec schema file. -pub struct BootSpecPath(pub PathBuf); - -#[derive(Debug, Default, Clone, Deserialize, Serialize, PartialEq, Eq)] -/// Provides the information necessary to consume a specialisation with or without a bootspec. -pub struct SpecialisationDescription { - /// The optional path to the specialisation's bootspec. - pub bootspec: BootSpecPath, -} - // !!! IMPORTANT: KEEP `BootJson`, `SCHEMA_VERSION`, and `JSON_FILENAME` IN SYNC !!! /// The current bootspec schema. pub type BootJson = v1::BootJsonV1; diff --git a/bootspec/src/v1.rs b/bootspec/src/v1.rs index 6394129..9edaebe 100644 --- a/bootspec/src/v1.rs +++ b/bootspec/src/v1.rs @@ -3,7 +3,7 @@ use std::path::PathBuf; use serde::{Deserialize, Serialize}; -use crate::{SpecialisationDescription, SpecialisationName, SystemConfigurationRoot}; +use crate::{SpecialisationName, SystemConfigurationRoot}; /// The V1 bootspec schema version. pub const SCHEMA_VERSION: u32 = 1; @@ -29,7 +29,7 @@ pub struct BootJsonV1 { /// Path to "append-initrd-secrets" script -- $toplevel/append-initrd-secrets pub initrd_secrets: Option, /// Mapping of specialisation names to their boot.json - pub specialisation: HashMap, + pub specialisation: HashMap, /// config.system.build.toplevel path pub toplevel: SystemConfigurationRoot, } diff --git a/synthesize/integration-test-cases/expected-synthesis/15.09-plain/boot.v1.json b/synthesize/integration-test-cases/expected-synthesis/15.09-plain.json similarity index 100% rename from synthesize/integration-test-cases/expected-synthesis/15.09-plain/boot.v1.json rename to synthesize/integration-test-cases/expected-synthesis/15.09-plain.json diff --git a/synthesize/integration-test-cases/expected-synthesis/16.03-plain/boot.v1.json b/synthesize/integration-test-cases/expected-synthesis/16.03-plain.json similarity index 100% rename from synthesize/integration-test-cases/expected-synthesis/16.03-plain/boot.v1.json rename to synthesize/integration-test-cases/expected-synthesis/16.03-plain.json diff --git a/synthesize/integration-test-cases/expected-synthesis/16.09-plain/boot.v1.json b/synthesize/integration-test-cases/expected-synthesis/16.09-plain.json similarity index 100% rename from synthesize/integration-test-cases/expected-synthesis/16.09-plain/boot.v1.json rename to synthesize/integration-test-cases/expected-synthesis/16.09-plain.json diff --git a/synthesize/integration-test-cases/expected-synthesis/17.03-plain/boot.v1.json b/synthesize/integration-test-cases/expected-synthesis/17.03-plain.json similarity index 100% rename from synthesize/integration-test-cases/expected-synthesis/17.03-plain/boot.v1.json rename to synthesize/integration-test-cases/expected-synthesis/17.03-plain.json diff --git a/synthesize/integration-test-cases/expected-synthesis/17.09-plain/boot.v1.json b/synthesize/integration-test-cases/expected-synthesis/17.09-plain.json similarity index 100% rename from synthesize/integration-test-cases/expected-synthesis/17.09-plain/boot.v1.json rename to synthesize/integration-test-cases/expected-synthesis/17.09-plain.json diff --git a/synthesize/integration-test-cases/expected-synthesis/18.03-plain/boot.v1.json b/synthesize/integration-test-cases/expected-synthesis/18.03-plain.json similarity index 100% rename from synthesize/integration-test-cases/expected-synthesis/18.03-plain/boot.v1.json rename to synthesize/integration-test-cases/expected-synthesis/18.03-plain.json diff --git a/synthesize/integration-test-cases/expected-synthesis/18.09-plain/boot.v1.json b/synthesize/integration-test-cases/expected-synthesis/18.09-plain.json similarity index 100% rename from synthesize/integration-test-cases/expected-synthesis/18.09-plain/boot.v1.json rename to synthesize/integration-test-cases/expected-synthesis/18.09-plain.json diff --git a/synthesize/integration-test-cases/expected-synthesis/19.03-plain/boot.v1.json b/synthesize/integration-test-cases/expected-synthesis/19.03-plain.json similarity index 100% rename from synthesize/integration-test-cases/expected-synthesis/19.03-plain/boot.v1.json rename to synthesize/integration-test-cases/expected-synthesis/19.03-plain.json diff --git a/synthesize/integration-test-cases/expected-synthesis/19.09-plain/boot.v1.json b/synthesize/integration-test-cases/expected-synthesis/19.09-plain.json similarity index 100% rename from synthesize/integration-test-cases/expected-synthesis/19.09-plain/boot.v1.json rename to synthesize/integration-test-cases/expected-synthesis/19.09-plain.json diff --git a/synthesize/integration-test-cases/expected-synthesis/20.03-plain/boot.v1.json b/synthesize/integration-test-cases/expected-synthesis/20.03-plain.json similarity index 100% rename from synthesize/integration-test-cases/expected-synthesis/20.03-plain/boot.v1.json rename to synthesize/integration-test-cases/expected-synthesis/20.03-plain.json diff --git a/synthesize/integration-test-cases/expected-synthesis/20.09-plain/boot.v1.json b/synthesize/integration-test-cases/expected-synthesis/20.09-plain.json similarity index 100% rename from synthesize/integration-test-cases/expected-synthesis/20.09-plain/boot.v1.json rename to synthesize/integration-test-cases/expected-synthesis/20.09-plain.json diff --git a/synthesize/integration-test-cases/expected-synthesis/21.05-plain/boot.v1.json b/synthesize/integration-test-cases/expected-synthesis/21.05-plain.json similarity index 100% rename from synthesize/integration-test-cases/expected-synthesis/21.05-plain/boot.v1.json rename to synthesize/integration-test-cases/expected-synthesis/21.05-plain.json diff --git a/synthesize/integration-test-cases/expected-synthesis/21.11-plain/boot.v1.json b/synthesize/integration-test-cases/expected-synthesis/21.11-plain.json similarity index 100% rename from synthesize/integration-test-cases/expected-synthesis/21.11-plain/boot.v1.json rename to synthesize/integration-test-cases/expected-synthesis/21.11-plain.json diff --git a/synthesize/integration-test-cases/expected-synthesis/21.11-specialisations.json b/synthesize/integration-test-cases/expected-synthesis/21.11-specialisations.json new file mode 100644 index 0000000..1f2acad --- /dev/null +++ b/synthesize/integration-test-cases/expected-synthesis/21.11-specialisations.json @@ -0,0 +1,29 @@ +{ + "schemaVersion": 1, + "label": "NixOS 21.11pre-git (Linux 5.10.81)", + "kernel": "/nix/store/hprwry55jwyd71ng7v7c2rhk3a3z1im8-linux-5.10.81/bzImage", + "kernelParams": [ + "loglevel=4", + "net.ifnames=0" + ], + "init": "/nix/store/kgkjwhscv52r2y1ha1y19lb9h4j3lfrc-nixos-system-nixos-21.11pre-git/init", + "initrd": "/nix/store/69bhfdfv77y0vclnlxqrd8pxjzbkz47w-initrd-linux-5.10.81/initrd", + "initrdSecrets": "/nix/store/kgkjwhscv52r2y1ha1y19lb9h4j3lfrc-nixos-system-nixos-21.11pre-git/append-initrd-secrets", + "specialisation": { + "example": { + "schemaVersion": 1, + "label": "NixOS 21.11pre-git (Linux 5.10.81)", + "kernel": "/nix/store/hprwry55jwyd71ng7v7c2rhk3a3z1im8-linux-5.10.81/bzImage", + "kernelParams": [ + "loglevel=4", + "net.ifnames=0" + ], + "init": "/nix/store/3w5kr91xq46638fd310q2sa9mjm6r6hn-nixos-system-nixos-21.11pre-git/init", + "initrd": "/nix/store/69bhfdfv77y0vclnlxqrd8pxjzbkz47w-initrd-linux-5.10.81/initrd", + "initrdSecrets": "/nix/store/3w5kr91xq46638fd310q2sa9mjm6r6hn-nixos-system-nixos-21.11pre-git/append-initrd-secrets", + "specialisation": {}, + "toplevel": "/nix/store/3w5kr91xq46638fd310q2sa9mjm6r6hn-nixos-system-nixos-21.11pre-git" + } + }, + "toplevel": "/nix/store/kgkjwhscv52r2y1ha1y19lb9h4j3lfrc-nixos-system-nixos-21.11pre-git" +} \ No newline at end of file diff --git a/synthesize/integration-test-cases/expected-synthesis/21.11-specialisations/boot.v1.json b/synthesize/integration-test-cases/expected-synthesis/21.11-specialisations/boot.v1.json deleted file mode 100644 index 22872bf..0000000 --- a/synthesize/integration-test-cases/expected-synthesis/21.11-specialisations/boot.v1.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schemaVersion": 1, - "label": "NixOS 21.11pre-git (Linux 5.10.81)", - "kernel": "/nix/store/hprwry55jwyd71ng7v7c2rhk3a3z1im8-linux-5.10.81/bzImage", - "kernelParams": [ - "loglevel=4", - "net.ifnames=0" - ], - "init": "/nix/store/kgkjwhscv52r2y1ha1y19lb9h4j3lfrc-nixos-system-nixos-21.11pre-git/init", - "initrd": "/nix/store/69bhfdfv77y0vclnlxqrd8pxjzbkz47w-initrd-linux-5.10.81/initrd", - "initrdSecrets": "/nix/store/kgkjwhscv52r2y1ha1y19lb9h4j3lfrc-nixos-system-nixos-21.11pre-git/append-initrd-secrets", - "specialisation": { - "example": { - "bootspec": "./generated-synthesis/21.11-specialisations/specialisation/example.json" - } - }, - "toplevel": "/nix/store/kgkjwhscv52r2y1ha1y19lb9h4j3lfrc-nixos-system-nixos-21.11pre-git" -} \ No newline at end of file diff --git a/synthesize/integration-test-cases/expected-synthesis/21.11-specialisations/specialisation/example.json b/synthesize/integration-test-cases/expected-synthesis/21.11-specialisations/specialisation/example.json deleted file mode 100644 index f0be414..0000000 --- a/synthesize/integration-test-cases/expected-synthesis/21.11-specialisations/specialisation/example.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "schemaVersion": 1, - "label": "NixOS 21.11pre-git (Linux 5.10.81)", - "kernel": "/nix/store/hprwry55jwyd71ng7v7c2rhk3a3z1im8-linux-5.10.81/bzImage", - "kernelParams": [ - "loglevel=4", - "net.ifnames=0" - ], - "init": "/nix/store/3w5kr91xq46638fd310q2sa9mjm6r6hn-nixos-system-nixos-21.11pre-git/init", - "initrd": "/nix/store/69bhfdfv77y0vclnlxqrd8pxjzbkz47w-initrd-linux-5.10.81/initrd", - "initrdSecrets": "/nix/store/3w5kr91xq46638fd310q2sa9mjm6r6hn-nixos-system-nixos-21.11pre-git/append-initrd-secrets", - "specialisation": {}, - "toplevel": "/nix/store/3w5kr91xq46638fd310q2sa9mjm6r6hn-nixos-system-nixos-21.11pre-git" -} \ No newline at end of file diff --git a/synthesize/integration-test-cases/verify.sh b/synthesize/integration-test-cases/verify.sh index 3c06659..5cb60c9 100755 --- a/synthesize/integration-test-cases/verify.sh +++ b/synthesize/integration-test-cases/verify.sh @@ -12,7 +12,7 @@ done) | xargs --max-procs=$(nproc) --max-lines=1 nix-build rm -rf generated-synthesis mkdir generated-synthesis for out in ./builds/*; do - cargo run --bin synthesize -- "$out" "./generated-synthesis/$(basename "$out")" + cargo run --bin synthesize -- "$out" "./generated-synthesis/$(basename "$out").json" done diff -r ./expected-synthesis ./generated-synthesis diff --git a/synthesize/src/lib.rs b/synthesize/src/lib.rs index 9fb23f9..9929853 100644 --- a/synthesize/src/lib.rs +++ b/synthesize/src/lib.rs @@ -3,10 +3,7 @@ use std::error::Error; use std::fs; use std::path::Path; -use bootspec::{ - BootJson, BootSpecPath, SpecialisationDescription, SpecialisationName, SystemConfigurationRoot, - JSON_FILENAME, SCHEMA_VERSION, -}; +use bootspec::{BootJson, SpecialisationName, SystemConfigurationRoot, SCHEMA_VERSION}; #[doc(hidden)] pub type Result> = core::result::Result; @@ -14,12 +11,8 @@ pub type Result> = core::result::R /// Synthesize a [`BootJson`] struct from the path to a generation. /// /// This is useful when used on generations that do not have a bootspec attached to it. -pub fn synthesize_schema_from_generation(generation: &Path, out_path: &Path) -> Result<()> { - fs::create_dir(&out_path)?; - let specialisationdir = out_path.join("specialisation"); - let mut specialisationdir_created = false; - - let mut toplevelspec = describe_system(&generation)?; +pub fn synthesize_schema_from_generation(generation: &Path) -> Result { + let mut toplevelspec = describe_system(generation)?; if let Ok(specialisations) = fs::read_dir(generation.join("specialisation")) { for spec in specialisations.map(|res| res.map(|e| e.path())) { @@ -29,45 +22,16 @@ pub fn synthesize_schema_from_generation(generation: &Path, out_path: &Path) -> .ok_or("Could not get name of specialisation dir")? .to_str() .ok_or("Specialisation dir name was invalid UTF8")?; - let toplevel = fs::canonicalize(generation.join(format!("specialisation/{}", name)))?; - - let boot_json_path = toplevel.join(JSON_FILENAME); - let boot_json_path = match boot_json_path.exists() { - true => boot_json_path, - false => { - if !specialisationdir_created { - fs::create_dir(&specialisationdir)?; - specialisationdir_created = true; - } - - let specname = specialisationdir.join(format!("{name}.json")); - let subspec = describe_system(&toplevel)?; - let pretty = serde_json::to_string_pretty(&subspec) - .map_err(|e| format!("Failed to make pretty JSON from bootspec:\n{e}"))?; - - fs::write(&specname, pretty).map_err(|e| { - format!("Failed to write JSON to '{}':\n{e}", out_path.display()) - })?; - - specname - } - }; + let toplevel = fs::canonicalize(generation.join("specialisation").join(name))?; + toplevelspec.specialisation.insert( SpecialisationName(name.to_string()), - SpecialisationDescription { - bootspec: BootSpecPath(boot_json_path), - }, + describe_system(&toplevel)?, ); } } - let pretty = serde_json::to_string_pretty(&toplevelspec) - .map_err(|e| format!("Failed to make pretty JSON from bootspec:\n{}", e))?; - - fs::write(&out_path.join("boot.v1.json"), pretty) - .map_err(|e| format!("Failed to write JSON to '{}':\n{}", out_path.display(), e))?; - - Ok(()) + Ok(toplevelspec) } fn describe_system(generation: &Path) -> Result { diff --git a/synthesize/src/main.rs b/synthesize/src/main.rs index aef286a..06cffa0 100644 --- a/synthesize/src/main.rs +++ b/synthesize/src/main.rs @@ -1,3 +1,4 @@ +use std::fs; use std::io::{self, Write}; use std::path::PathBuf; @@ -34,7 +35,7 @@ fn cli() -> Result<()> { .ok_or("Expected output path, got none.")? .parse::()?; - synthesize::synthesize_schema_from_generation(&generation_dir, &out_path).map_err(|e| { + let spec = synthesize::synthesize_schema_from_generation(&generation_dir).map_err(|e| { format!( "Failed to synthesize bootspec for {}:\n{}", generation_dir.display(), @@ -42,5 +43,11 @@ fn cli() -> Result<()> { ) })?; + let pretty = serde_json::to_string_pretty(&spec) + .map_err(|e| format!("Failed to make pretty JSON from bootspec:\n{}", e))?; + + fs::write(&out_path, pretty) + .map_err(|e| format!("Failed to write JSON to '{}':\n{}", out_path.display(), e))?; + Ok(()) }