mirror of
https://github.com/edera-dev/sprout.git
synced 2026-02-04 05:40:18 +00:00
feat(boot): introduce sort keys, which are sorted in reverse order, to make boot order more configurable (#55)
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
use crate::utils;
|
||||
use crate::utils::vercmp;
|
||||
use alloc::collections::BTreeMap;
|
||||
use alloc::string::{String, ToString};
|
||||
use alloc::vec::Vec;
|
||||
@@ -186,17 +185,15 @@ pub fn scan(
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
// Sort the kernel pairs by kernel version, if it has one, newer kernels first.
|
||||
pairs.sort_by(|a, b| vercmp::compare_versions(&a.kernel, &b.kernel).reverse());
|
||||
|
||||
// Generate a unique name for the linux chainload action.
|
||||
let chainload_action_name = format!("{}{}", LINUX_CHAINLOAD_ACTION_PREFIX, root_unique_hash,);
|
||||
let chainload_action_name = format!("{}{}", LINUX_CHAINLOAD_ACTION_PREFIX, root_unique_hash);
|
||||
|
||||
// Kernel pairs are detected, generate a list configuration for it.
|
||||
let generator = ListConfiguration {
|
||||
entry: EntryDeclaration {
|
||||
title: "Boot Linux $name".to_string(),
|
||||
actions: vec![chainload_action_name.clone()],
|
||||
sort_key: Some("$kernel".to_string()),
|
||||
..Default::default()
|
||||
},
|
||||
values: pairs
|
||||
|
||||
@@ -51,13 +51,14 @@ pub fn scan(
|
||||
let chainload_action_name = format!("{}{}", WINDOWS_CHAINLOAD_ACTION_PREFIX, root_unique_hash,);
|
||||
|
||||
// Generate an entry name for Windows.
|
||||
let entry_name = format!("auto-windows-{}", root_unique_hash,);
|
||||
let entry_name = format!("auto-windows-{}", root_unique_hash);
|
||||
|
||||
// Create an entry for Windows and insert it into the configuration.
|
||||
let entry = EntryDeclaration {
|
||||
title: "Boot Windows".to_string(),
|
||||
actions: vec![chainload_action_name.clone()],
|
||||
values: Default::default(),
|
||||
sort_key: None, // Use the default sort key.
|
||||
};
|
||||
config.entries.insert(entry_name, entry);
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ pub struct BootableEntry {
|
||||
declaration: EntryDeclaration,
|
||||
default: bool,
|
||||
pin_name: bool,
|
||||
sort_key: Option<String>,
|
||||
}
|
||||
|
||||
impl BootableEntry {
|
||||
@@ -29,6 +30,7 @@ impl BootableEntry {
|
||||
declaration,
|
||||
default: false,
|
||||
pin_name: false,
|
||||
sort_key: None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,6 +109,22 @@ impl BootableEntry {
|
||||
self.name == needle || self.title == needle
|
||||
}
|
||||
|
||||
/// Set the sort key of the entry. This is used to sort entries via version comparison.
|
||||
pub fn set_sort_key(&mut self, sort_key: String) {
|
||||
self.sort_key = Some(sort_key);
|
||||
}
|
||||
|
||||
/// Retrieve a reference to the sort key of the entry. If one is not specified, we will use the
|
||||
/// name of the entry.
|
||||
pub fn sort_key(&self) -> &str {
|
||||
// Use the sort key specified in the bootable entry, or use the declaration sort key,
|
||||
// or use the name of the entry.
|
||||
self.sort_key
|
||||
.as_deref()
|
||||
.or(self.declaration.sort_key.as_deref())
|
||||
.unwrap_or(&self.name)
|
||||
}
|
||||
|
||||
/// Find an entry by `needle` inside the entry iterator `haystack`.
|
||||
/// This will search for an entry by name, title, or index.
|
||||
pub fn find<'a>(
|
||||
|
||||
@@ -206,6 +206,16 @@ pub fn generate(context: Rc<SproutContext>, bls: &BlsConfiguration) -> Result<Ve
|
||||
// Sort all the entries according to the BLS sort system.
|
||||
entries.sort_by(sort_entries);
|
||||
|
||||
// Grab the number of entries that we have, so we can calculate a reverse index.
|
||||
let entry_count = entries.len();
|
||||
|
||||
// Set the sort keys of all the bootable entries to a semi-unique prefix + the BLS sort order.
|
||||
// The final comparison happens using version comparison, so this will sort
|
||||
// things properly.
|
||||
for (idx, (_bls, boot)) in entries.iter_mut().enumerate() {
|
||||
boot.set_sort_key(format!("bls-{}-{}", path, entry_count - idx - 1));
|
||||
}
|
||||
|
||||
// Collect all the bootable entries and return them.
|
||||
Ok(entries.into_iter().map(|(_, boot)| boot).collect())
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ use crate::context::{RootContext, SproutContext};
|
||||
use crate::entries::BootableEntry;
|
||||
use crate::options::SproutOptions;
|
||||
use crate::phases::phase;
|
||||
use crate::utils::vercmp::compare_versions;
|
||||
use alloc::collections::BTreeMap;
|
||||
use alloc::format;
|
||||
use alloc::string::ToString;
|
||||
@@ -257,6 +258,10 @@ fn run() -> Result<()> {
|
||||
}
|
||||
}
|
||||
|
||||
// Sort the entries by their sort key, finalizing the order to show entries. This happens
|
||||
// in reverse order so that entries that would come last show up first in the menu.
|
||||
entries.sort_by(|a, b| compare_versions(a.sort_key(), b.sort_key()).reverse());
|
||||
|
||||
// Tell the bootloader interface what entries are available.
|
||||
BootloaderInterface::set_entries(entries.iter().map(|entry| entry.name()))
|
||||
.context("unable to set entries in bootloader interface")?;
|
||||
|
||||
@@ -18,4 +18,7 @@ pub struct EntryDeclaration {
|
||||
/// The values to insert into the context when the entry is selected.
|
||||
#[serde(default)]
|
||||
pub values: BTreeMap<String, String>,
|
||||
/// The key to sort entries, via version comparison.
|
||||
#[serde(default, rename = "sort-key")]
|
||||
pub sort_key: Option<String>,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user