Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Consistently Display Generations in systemd-boot #242

Merged
merged 2 commits into from
Oct 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 28 additions & 20 deletions rust/tool/shared/src/generation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,14 @@ pub struct ExtendedBootJson {
/// 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
/// of the generation link.
#[derive(Debug)]
#[derive(Debug, Clone)]
pub struct Generation {
/// Profile symlink index
version: u64,
pub version: u64,
/// Build time
build_time: Option<Date>,
pub build_time: Option<Date>,
/// Top-level specialisation name
specialisation_name: Option<SpecialisationName>,
pub specialisation_name: Option<SpecialisationName>,
/// Top-level extended boot specification
pub spec: ExtendedBootJson,
}
Expand All @@ -57,22 +57,26 @@ impl Generation {
})
}

pub fn specialise(&self, name: &SpecialisationName, bootspec: &BootSpec) -> Result<Self> {
Ok(Self {
version: self.version,
build_time: self.build_time,
pub fn specialise(&self, name: &SpecialisationName, bootspec: &BootSpec) -> Self {
Self {
specialisation_name: Some(name.clone()),
spec: ExtendedBootJson {
bootspec: bootspec.clone(),
},
})
..self.clone()
}
}

pub fn is_specialised(&self) -> Option<SpecialisationName> {
self.specialisation_name.clone()
/// A helper for describe functions below.
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
/// interface remains similar.
Expand All @@ -84,14 +88,18 @@ impl Generation {
.build_time
.map(|x| x.to_string())
.unwrap_or_else(|| String::from("Unknown"));
if self.is_specialised().is_some() {
format!(
"Generation {}-specialised, Built on {}",
self.version, build_time
)
} else {
format!("Generation {}, Built on {}", self.version, build_time)
}

format!(
"Generation {}{}, {}",
self.version,
self.describe_specialisation(),
build_time
)
}

/// A unique short identifier.
pub fn version_tag(&self) -> String {
format!("{}{}", self.version, self.describe_specialisation(),)
}
}

Expand Down
13 changes: 12 additions & 1 deletion rust/tool/shared/src/os_release.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,21 @@ impl OsRelease {
// 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.
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(
"PRETTY_NAME".into(),
generation.spec.bootspec.bootspec.label.clone(),
format!(
"{} ({})",
generation.spec.bootspec.bootspec.label,
generation.describe()
),
);

map.insert("VERSION_ID".into(), generation.describe());

Ok(Self(map))
Expand Down
4 changes: 2 additions & 2 deletions rust/tool/systemd/src/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ impl Installer {
self.install_generation(&generation)
.context("Failed to install generation.")?;
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)
.context("Failed to install specialisation.")?;
}
Expand Down Expand Up @@ -374,7 +374,7 @@ fn stub_name(generation: &Generation, public_key: &Path) -> Result<PathBuf> {
let stub_input_hash = Base32Unpadded::encode_string(&Sha256::digest(
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!(
"nixos-generation-{}-specialisation-{}-{}.efi",
generation, specialisation_name, stub_input_hash
Expand Down
4 changes: 2 additions & 2 deletions rust/tool/systemd/tests/os_release.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ fn generate_expected_os_release() -> Result<()> {

let expected = expect![[r#"
ID=lanza
PRETTY_NAME=LanzaOS
VERSION_ID=Generation 1, Built on 1970-01-01
PRETTY_NAME=LanzaOS (Generation 1, 1970-01-01)
VERSION_ID=Generation 1, 1970-01-01
"#]];

expected.assert_eq(&String::from_utf8(os_release_section)?);
Expand Down