forked from Proxmox/proxmox
add type DebianCodename
which allows to get rid of an possible error with check_suites, and easily detect unexpected values with get_current_release_codename. The check_repos function needs to be adapted, since the type does not include suite names like oldstable,experimental,etc. Signed-off-by: Fabian Ebner <f.ebner@proxmox.com>
This commit is contained in:
parent
51c69d76a5
commit
fb51dcf9db
@ -1,11 +1,11 @@
|
||||
use std::convert::TryFrom;
|
||||
use std::convert::{TryFrom, TryInto};
|
||||
use std::fmt::Display;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use anyhow::{bail, format_err, Error};
|
||||
use anyhow::{format_err, Error};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::repositories::release::DEBIAN_SUITES;
|
||||
use crate::repositories::release::DebianCodename;
|
||||
use crate::repositories::repository::{
|
||||
APTRepository, APTRepositoryFileType, APTRepositoryPackageType,
|
||||
};
|
||||
@ -300,7 +300,7 @@ impl APTRepositoryFile {
|
||||
|
||||
/// Checks if old or unstable suites are configured and also that the
|
||||
/// `stable` keyword is not used.
|
||||
pub fn check_suites(&self, current_suite: &str) -> Result<Vec<APTRepositoryInfo>, Error> {
|
||||
pub fn check_suites(&self, current_codename: DebianCodename) -> Vec<APTRepositoryInfo> {
|
||||
let mut infos = vec![];
|
||||
|
||||
for (n, repo) in self.repositories.iter().enumerate() {
|
||||
@ -308,60 +308,55 @@ impl APTRepositoryFile {
|
||||
continue;
|
||||
}
|
||||
|
||||
let mut add_info = |kind, message| {
|
||||
let mut add_info = |kind: &str, message| {
|
||||
infos.push(APTRepositoryInfo {
|
||||
path: self.path.clone(),
|
||||
index: n,
|
||||
property: Some("Suites".to_string()),
|
||||
kind,
|
||||
kind: kind.to_string(),
|
||||
message,
|
||||
})
|
||||
};
|
||||
|
||||
let current_index = match DEBIAN_SUITES
|
||||
.iter()
|
||||
.position(|&suite| suite == current_suite)
|
||||
{
|
||||
Some(index) => index,
|
||||
None => bail!("unknown release {}", current_suite),
|
||||
};
|
||||
let message_old = |suite| format!("old suite '{}' configured!", suite);
|
||||
let message_new =
|
||||
|suite| format!("suite '{}' should not be used in production!", suite);
|
||||
let message_stable = "use the name of the stable distribution instead of 'stable'!";
|
||||
|
||||
for suite in repo.suites.iter() {
|
||||
let base_suite = suite_variant(suite).0;
|
||||
|
||||
if base_suite == "stable" {
|
||||
add_info(
|
||||
"warning".to_string(),
|
||||
"use the name of the stable distribution instead of 'stable'!".to_string(),
|
||||
);
|
||||
match base_suite {
|
||||
"oldoldstable" | "oldstable" => {
|
||||
add_info("warning", message_old(base_suite));
|
||||
}
|
||||
"testing" | "unstable" | "experimental" | "sid" => {
|
||||
add_info("warning", message_new(base_suite));
|
||||
}
|
||||
"stable" => {
|
||||
add_info("warning", message_stable.to_string());
|
||||
}
|
||||
_ => (),
|
||||
};
|
||||
|
||||
let codename: DebianCodename = match base_suite.try_into() {
|
||||
Ok(codename) => codename,
|
||||
Err(_) => continue,
|
||||
};
|
||||
|
||||
if codename < current_codename {
|
||||
add_info("warning", message_old(base_suite));
|
||||
}
|
||||
|
||||
if let Some(n) = DEBIAN_SUITES.iter().position(|&suite| suite == base_suite) {
|
||||
if n < current_index {
|
||||
add_info(
|
||||
"warning".to_string(),
|
||||
format!("old suite '{}' configured!", base_suite),
|
||||
);
|
||||
}
|
||||
|
||||
if n == current_index + 1 {
|
||||
add_info(
|
||||
"ignore-pre-upgrade-warning".to_string(),
|
||||
format!("suite '{}' should not be used in production!", base_suite),
|
||||
);
|
||||
}
|
||||
|
||||
if n > current_index + 1 {
|
||||
add_info(
|
||||
"warning".to_string(),
|
||||
format!("suite '{}' should not be used in production!", base_suite),
|
||||
);
|
||||
}
|
||||
if Some(codename) == current_codename.next() {
|
||||
add_info("ignore-pre-upgrade-warning", message_new(base_suite));
|
||||
} else if codename > current_codename {
|
||||
add_info("warning", message_new(base_suite));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(infos)
|
||||
infos
|
||||
}
|
||||
|
||||
/// Checks for official URIs.
|
||||
|
@ -12,7 +12,7 @@ mod file;
|
||||
pub use file::{APTRepositoryFile, APTRepositoryFileError, APTRepositoryInfo};
|
||||
|
||||
mod release;
|
||||
pub use release::get_current_release_codename;
|
||||
pub use release::{get_current_release_codename, DebianCodename};
|
||||
|
||||
mod standard;
|
||||
pub use standard::{APTRepositoryHandle, APTStandardRepository};
|
||||
@ -51,25 +51,25 @@ fn common_digest(files: &[APTRepositoryFile]) -> [u8; 32] {
|
||||
/// `badge` for official URIs.
|
||||
pub fn check_repositories(
|
||||
files: &[APTRepositoryFile],
|
||||
current_suite: &str,
|
||||
) -> Result<Vec<APTRepositoryInfo>, Error> {
|
||||
current_suite: DebianCodename,
|
||||
) -> Vec<APTRepositoryInfo> {
|
||||
let mut infos = vec![];
|
||||
|
||||
for file in files.iter() {
|
||||
infos.append(&mut file.check_suites(current_suite)?);
|
||||
infos.append(&mut file.check_suites(current_suite));
|
||||
infos.append(&mut file.check_uris());
|
||||
}
|
||||
|
||||
Ok(infos)
|
||||
infos
|
||||
}
|
||||
|
||||
/// Get the repository associated to the handle and the path where it is usually configured.
|
||||
pub fn get_standard_repository(
|
||||
handle: APTRepositoryHandle,
|
||||
product: &str,
|
||||
suite: &str,
|
||||
suite: DebianCodename,
|
||||
) -> (APTRepository, String) {
|
||||
let repo = handle.to_repository(product, &suite);
|
||||
let repo = handle.to_repository(product, &suite.to_string());
|
||||
let path = handle.path(product);
|
||||
|
||||
(repo, path)
|
||||
@ -80,7 +80,7 @@ pub fn get_standard_repository(
|
||||
pub fn standard_repositories(
|
||||
files: &[APTRepositoryFile],
|
||||
product: &str,
|
||||
suite: &str,
|
||||
suite: DebianCodename,
|
||||
) -> Vec<APTStandardRepository> {
|
||||
let mut result = vec![
|
||||
APTStandardRepository::from(APTRepositoryHandle::Enterprise),
|
||||
@ -104,7 +104,7 @@ pub fn standard_repositories(
|
||||
continue;
|
||||
}
|
||||
|
||||
if repo.is_referenced_repository(entry.handle, product, suite) {
|
||||
if repo.is_referenced_repository(entry.handle, product, &suite.to_string()) {
|
||||
entry.status = Some(repo.enabled);
|
||||
}
|
||||
}
|
||||
|
@ -1,29 +1,88 @@
|
||||
use anyhow::{bail, format_err, Error};
|
||||
|
||||
use std::convert::{TryFrom, TryInto};
|
||||
use std::fmt::Display;
|
||||
use std::io::{BufRead, BufReader};
|
||||
|
||||
/// The suites of Debian releases, ordered chronologically, with variable releases
|
||||
/// like 'oldstable' and 'testing' ordered at the extremes. Does not include 'stable'.
|
||||
pub const DEBIAN_SUITES: [&str; 15] = [
|
||||
"oldoldstable",
|
||||
"oldstable",
|
||||
"lenny",
|
||||
"squeeze",
|
||||
"wheezy",
|
||||
"jessie",
|
||||
"stretch",
|
||||
"buster",
|
||||
"bullseye",
|
||||
"bookworm",
|
||||
"trixie",
|
||||
"sid",
|
||||
"testing",
|
||||
"unstable",
|
||||
"experimental",
|
||||
];
|
||||
use anyhow::{bail, format_err, Error};
|
||||
|
||||
/// The code names of Debian releases. Does not include `sid`.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub enum DebianCodename {
|
||||
Lenny = 5,
|
||||
Squeeze,
|
||||
Wheezy,
|
||||
Jessie,
|
||||
Stretch,
|
||||
Buster,
|
||||
Bullseye,
|
||||
Bookworm,
|
||||
Trixie,
|
||||
}
|
||||
|
||||
impl DebianCodename {
|
||||
pub fn next(&self) -> Option<Self> {
|
||||
match (*self as u8 + 1).try_into() {
|
||||
Ok(codename) => Some(codename),
|
||||
Err(_) => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&str> for DebianCodename {
|
||||
type Error = Error;
|
||||
|
||||
fn try_from(string: &str) -> Result<Self, Error> {
|
||||
match string {
|
||||
"lenny" => Ok(DebianCodename::Lenny),
|
||||
"squeeze" => Ok(DebianCodename::Squeeze),
|
||||
"wheezy" => Ok(DebianCodename::Wheezy),
|
||||
"jessie" => Ok(DebianCodename::Jessie),
|
||||
"stretch" => Ok(DebianCodename::Stretch),
|
||||
"buster" => Ok(DebianCodename::Buster),
|
||||
"bullseye" => Ok(DebianCodename::Bullseye),
|
||||
"bookworm" => Ok(DebianCodename::Bookworm),
|
||||
"trixie" => Ok(DebianCodename::Trixie),
|
||||
_ => bail!("unknown Debian code name '{}'", string),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<u8> for DebianCodename {
|
||||
type Error = Error;
|
||||
|
||||
fn try_from(number: u8) -> Result<Self, Error> {
|
||||
match number {
|
||||
5 => Ok(DebianCodename::Lenny),
|
||||
6 => Ok(DebianCodename::Squeeze),
|
||||
7 => Ok(DebianCodename::Wheezy),
|
||||
8 => Ok(DebianCodename::Jessie),
|
||||
9 => Ok(DebianCodename::Stretch),
|
||||
10 => Ok(DebianCodename::Buster),
|
||||
11 => Ok(DebianCodename::Bullseye),
|
||||
12 => Ok(DebianCodename::Bookworm),
|
||||
13 => Ok(DebianCodename::Trixie),
|
||||
_ => bail!("unknown Debian release number '{}'", number),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for DebianCodename {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
DebianCodename::Lenny => write!(f, "lenny"),
|
||||
DebianCodename::Squeeze => write!(f, "squeeze"),
|
||||
DebianCodename::Wheezy => write!(f, "wheezy"),
|
||||
DebianCodename::Jessie => write!(f, "jessie"),
|
||||
DebianCodename::Stretch => write!(f, "stretch"),
|
||||
DebianCodename::Buster => write!(f, "buster"),
|
||||
DebianCodename::Bullseye => write!(f, "bullseye"),
|
||||
DebianCodename::Bookworm => write!(f, "bookworm"),
|
||||
DebianCodename::Trixie => write!(f, "trixie"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Read the `VERSION_CODENAME` from `/etc/os-release`.
|
||||
pub fn get_current_release_codename() -> Result<String, Error> {
|
||||
pub fn get_current_release_codename() -> Result<DebianCodename, Error> {
|
||||
let raw = std::fs::read("/etc/os-release")
|
||||
.map_err(|err| format_err!("unable to read '/etc/os-release' - {}", err))?;
|
||||
|
||||
@ -34,7 +93,7 @@ pub fn get_current_release_codename() -> Result<String, Error> {
|
||||
|
||||
if let Some(codename) = line.strip_prefix("VERSION_CODENAME=") {
|
||||
let codename = codename.trim_matches(&['"', '\''][..]);
|
||||
return Ok(codename.to_string());
|
||||
return codename.try_into();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,7 @@ use proxmox_apt::config::APTConfig;
|
||||
|
||||
use proxmox_apt::repositories::{
|
||||
check_repositories, get_current_release_codename, standard_repositories, APTRepositoryFile,
|
||||
APTRepositoryHandle, APTRepositoryInfo, APTStandardRepository,
|
||||
APTRepositoryHandle, APTRepositoryInfo, APTStandardRepository, DebianCodename,
|
||||
};
|
||||
|
||||
#[test]
|
||||
@ -187,7 +187,7 @@ fn test_check_repositories() -> Result<(), Error> {
|
||||
let mut file = APTRepositoryFile::new(&absolute_suite_list)?.unwrap();
|
||||
file.parse()?;
|
||||
|
||||
let infos = check_repositories(&vec![file], "bullseye")?;
|
||||
let infos = check_repositories(&vec![file], DebianCodename::Bullseye);
|
||||
|
||||
assert_eq!(infos.is_empty(), true);
|
||||
let pve_list = read_dir.join("pve.list");
|
||||
@ -212,7 +212,7 @@ fn test_check_repositories() -> Result<(), Error> {
|
||||
}
|
||||
expected_infos.sort();
|
||||
|
||||
let mut infos = check_repositories(&vec![file], "bullseye")?;
|
||||
let mut infos = check_repositories(&vec![file], DebianCodename::Bullseye);
|
||||
infos.sort();
|
||||
|
||||
assert_eq!(infos, expected_infos);
|
||||
@ -278,7 +278,7 @@ fn test_check_repositories() -> Result<(), Error> {
|
||||
}
|
||||
expected_infos.sort();
|
||||
|
||||
let mut infos = check_repositories(&vec![file], "bullseye")?;
|
||||
let mut infos = check_repositories(&vec![file], DebianCodename::Bullseye);
|
||||
infos.sort();
|
||||
|
||||
assert_eq!(infos, expected_infos);
|
||||
@ -337,7 +337,7 @@ fn test_standard_repositories() -> Result<(), Error> {
|
||||
let mut file = APTRepositoryFile::new(&absolute_suite_list)?.unwrap();
|
||||
file.parse()?;
|
||||
|
||||
let std_repos = standard_repositories(&vec![file], "pve", "bullseye");
|
||||
let std_repos = standard_repositories(&vec![file], "pve", DebianCodename::Bullseye);
|
||||
|
||||
assert_eq!(std_repos, expected);
|
||||
|
||||
@ -347,14 +347,14 @@ fn test_standard_repositories() -> Result<(), Error> {
|
||||
|
||||
let file_vec = vec![file];
|
||||
|
||||
let std_repos = standard_repositories(&file_vec, "pbs", "bullseye");
|
||||
let std_repos = standard_repositories(&file_vec, "pbs", DebianCodename::Bullseye);
|
||||
|
||||
assert_eq!(&std_repos, &expected[0..=2]);
|
||||
|
||||
expected[0].status = Some(false);
|
||||
expected[1].status = Some(true);
|
||||
|
||||
let std_repos = standard_repositories(&file_vec, "pve", "bullseye");
|
||||
let std_repos = standard_repositories(&file_vec, "pve", DebianCodename::Bullseye);
|
||||
|
||||
assert_eq!(std_repos, expected);
|
||||
|
||||
@ -368,7 +368,7 @@ fn test_standard_repositories() -> Result<(), Error> {
|
||||
expected[1].status = Some(true);
|
||||
expected[2].status = Some(false);
|
||||
|
||||
let std_repos = standard_repositories(&file_vec, "pve", "bullseye");
|
||||
let std_repos = standard_repositories(&file_vec, "pve", DebianCodename::Bullseye);
|
||||
|
||||
assert_eq!(std_repos, expected);
|
||||
|
||||
@ -379,7 +379,7 @@ fn test_standard_repositories() -> Result<(), Error> {
|
||||
fn test_get_current_release_codename() -> Result<(), Error> {
|
||||
let codename = get_current_release_codename()?;
|
||||
|
||||
assert_eq!(&codename, "bullseye");
|
||||
assert!(codename == DebianCodename::Bullseye);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user