Merge pull request #242 from nix-community/generation-name

Consistently Display Generations in systemd-boot
This commit is contained in:
nikstur 2023-10-21 19:23:18 +02:00 committed by GitHub
commit 4366cd1b4c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 44 additions and 25 deletions

View File

@ -26,14 +26,14 @@ pub struct ExtendedBootJson {
/// contains most of the information necessary to install the generation onto the EFI System /// contains most of the information necessary to install the generation onto the EFI System
/// Partition. The only information missing is the version number which is encoded in the file name /// Partition. The only information missing is the version number which is encoded in the file name
/// of the generation link. /// of the generation link.
#[derive(Debug)] #[derive(Debug, Clone)]
pub struct Generation { pub struct Generation {
/// Profile symlink index /// Profile symlink index
version: u64, pub version: u64,
/// Build time /// Build time
build_time: Option<Date>, pub build_time: Option<Date>,
/// Top-level specialisation name /// Top-level specialisation name
specialisation_name: Option<SpecialisationName>, pub specialisation_name: Option<SpecialisationName>,
/// Top-level extended boot specification /// Top-level extended boot specification
pub spec: ExtendedBootJson, pub spec: ExtendedBootJson,
} }
@ -57,22 +57,26 @@ impl Generation {
}) })
} }
pub fn specialise(&self, name: &SpecialisationName, bootspec: &BootSpec) -> Result<Self> { pub fn specialise(&self, name: &SpecialisationName, bootspec: &BootSpec) -> Self {
Ok(Self { Self {
version: self.version,
build_time: self.build_time,
specialisation_name: Some(name.clone()), specialisation_name: Some(name.clone()),
spec: ExtendedBootJson { spec: ExtendedBootJson {
bootspec: bootspec.clone(), bootspec: bootspec.clone(),
}, },
}) ..self.clone()
}
} }
pub fn is_specialised(&self) -> Option<SpecialisationName> { /// A helper for describe functions below.
self.specialisation_name.clone() fn describe_specialisation(&self) -> String {
if let Some(specialization) = &self.specialisation_name {
format!("-{specialization}")
} else {
"".to_string()
}
} }
/// Describe the generation in a single line. /// Describe the generation in a single line for humans.
/// ///
/// Emulates how NixOS's current systemd-boot-builder.py describes generations so that the user /// Emulates how NixOS's current systemd-boot-builder.py describes generations so that the user
/// interface remains similar. /// interface remains similar.
@ -84,14 +88,18 @@ impl Generation {
.build_time .build_time
.map(|x| x.to_string()) .map(|x| x.to_string())
.unwrap_or_else(|| String::from("Unknown")); .unwrap_or_else(|| String::from("Unknown"));
if self.is_specialised().is_some() {
format!( format!(
"Generation {}-specialised, Built on {}", "Generation {}{}, {}",
self.version, build_time self.version,
self.describe_specialisation(),
build_time
) )
} else {
format!("Generation {}, Built on {}", self.version, build_time)
} }
/// A unique short identifier.
pub fn version_tag(&self) -> String {
format!("{}{}", self.version, self.describe_specialisation(),)
} }
} }

View File

@ -26,10 +26,21 @@ impl OsRelease {
// Because the ID field here does not have the same meaning as in a real os-release file, // Because the ID field here does not have the same meaning as in a real os-release file,
// it is fine to use a dummy value. // it is fine to use a dummy value.
map.insert("ID".into(), String::from("lanza")); map.insert("ID".into(), String::from("lanza"));
// systemd-boot will only show VERSION_ID when PRETTY_NAME is not unique. This is
// confusing to users. Make sure that our PRETTY_NAME is unique, so we get a consistent
// user experience.
//
// See #220.
map.insert( map.insert(
"PRETTY_NAME".into(), "PRETTY_NAME".into(),
generation.spec.bootspec.bootspec.label.clone(), format!(
"{} ({})",
generation.spec.bootspec.bootspec.label,
generation.describe()
),
); );
map.insert("VERSION_ID".into(), generation.describe()); map.insert("VERSION_ID".into(), generation.describe());
Ok(Self(map)) Ok(Self(map))

View File

@ -163,7 +163,7 @@ impl Installer {
self.install_generation(&generation) self.install_generation(&generation)
.context("Failed to install generation.")?; .context("Failed to install generation.")?;
for (name, bootspec) in &generation.spec.bootspec.specialisations { for (name, bootspec) in &generation.spec.bootspec.specialisations {
let specialised_generation = generation.specialise(name, bootspec)?; let specialised_generation = generation.specialise(name, bootspec);
self.install_generation(&specialised_generation) self.install_generation(&specialised_generation)
.context("Failed to install specialisation.")?; .context("Failed to install specialisation.")?;
} }
@ -374,7 +374,7 @@ fn stub_name(generation: &Generation, public_key: &Path) -> Result<PathBuf> {
let stub_input_hash = Base32Unpadded::encode_string(&Sha256::digest( let stub_input_hash = Base32Unpadded::encode_string(&Sha256::digest(
serde_json::to_string(&stub_inputs).unwrap(), serde_json::to_string(&stub_inputs).unwrap(),
)); ));
if let Some(specialisation_name) = generation.is_specialised() { if let Some(specialisation_name) = &generation.specialisation_name {
Ok(PathBuf::from(format!( Ok(PathBuf::from(format!(
"nixos-generation-{}-specialisation-{}-{}.efi", "nixos-generation-{}-specialisation-{}-{}.efi",
generation, specialisation_name, stub_input_hash generation, specialisation_name, stub_input_hash

View File

@ -27,8 +27,8 @@ fn generate_expected_os_release() -> Result<()> {
let expected = expect![[r#" let expected = expect![[r#"
ID=lanza ID=lanza
PRETTY_NAME=LanzaOS PRETTY_NAME=LanzaOS (Generation 1, 1970-01-01)
VERSION_ID=Generation 1, Built on 1970-01-01 VERSION_ID=Generation 1, 1970-01-01
"#]]; "#]];
expected.assert_eq(&String::from_utf8(os_release_section)?); expected.assert_eq(&String::from_utf8(os_release_section)?);