ALT linux support for APT crates #1

Merged
konevsa merged 25 commits from konevsa/proxmox:sisyphus into master 2024-11-07 14:30:43 +03:00
76 changed files with 964 additions and 29 deletions

View File

@ -1,5 +1,5 @@
[source]
[source.debian-packages]
directory = "/usr/share/cargo/registry"
[source.crates-io]
replace-with = "debian-packages"
# [source]
# [source.debian-packages]
# directory = "/usr/share/cargo/registry"
# [source.crates-io]
# replace-with = "debian-packages"

View File

@ -15,3 +15,6 @@ serde = { workspace = true, features = ["derive"] }
serde_plain.workspace = true
proxmox-schema = { workspace = true, features = ["api-macro"] }
proxmox-config-digest.workspace = true
[features]
alt-linux = []

View File

@ -28,6 +28,8 @@ pub enum APTRepositoryPackageType {
Deb,
/// Debian source package
DebSrc,
/// RPM package
Rpm,
}
serde_plain::derive_display_from_serialize!(APTRepositoryPackageType);
@ -117,6 +119,7 @@ pub struct APTRepositoryOption {
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "PascalCase")]
/// Describes an APT repository.
#[cfg(not(feature = "alt-linux"))]
pub struct APTRepository {
/// List of package types.
#[serde(default, skip_serializing_if = "Vec::is_empty")]
@ -150,6 +153,98 @@ pub struct APTRepository {
pub enabled: bool,
}
#[api(
properties: {
Types: {
description: "List of package types.",
type: Array,
items: {
type: APTRepositoryPackageType,
},
},
URIs: {
description: "List of repository URIs.",
type: Array,
items: {
description: "Repository URI.",
type: String,
},
},
Suites: {
description: "List of distributions.",
type: Array,
items: {
description: "Package distribution.",
type: String,
},
},
Components: {
description: "List of repository components.",
type: Array,
items: {
description: "Repository component.",
type: String,
},
},
Options: {
type: Array,
optional: true,
items: {
description: "Vendor ID.",
type: String,
},
},
Comment: {
description: "Associated comment.",
type: String,
optional: true,
},
FileType: {
type: APTRepositoryFileType,
},
Enabled: {
description: "Whether the repository is enabled or not.",
type: Boolean,
},
},
)]
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "PascalCase")]
/// Describes an APT repository.
#[cfg(feature = "alt-linux")]
pub struct APTRepository {
/// List of package types.
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub types: Vec<APTRepositoryPackageType>,
/// List of repository URIs.
#[serde(default, skip_serializing_if = "Vec::is_empty")]
#[serde(rename = "URIs")]
pub uris: Vec<String>,
/// List of package distributions.
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub suites: Vec<String>,
/// List of repository components.
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub components: Vec<String>,
/// Additional options.
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub options: Vec<String>,
/// Associated comment.
#[serde(default, skip_serializing_if = "String::is_empty")]
pub comment: String,
/// Format of the defining file.
pub file_type: APTRepositoryFileType,
/// Whether the repository is enabled or not.
pub enabled: bool,
}
#[api(
properties: {
"file-type": {
@ -291,6 +386,18 @@ pub enum APTRepositoryHandle {
CephReefNoSubscription,
/// Ceph Reef test repository.
CephReefTest,
/// Check install
#[serde(rename = "checkinstall")]
CheckInstall,
/// Debug info
#[serde(rename = "debuginfo")]
DebugInfo,
/// Classic
#[serde(rename = "classic")]
Classic,
/// GOST crypto
#[serde(rename = "gostcrypto")]
GostCrypto,
}
serde_plain::derive_display_from_serialize!(APTRepositoryHandle);

View File

@ -24,7 +24,7 @@ proxmox-apt-api-types.workspace = true
proxmox-config-digest = { workspace = true, features = ["openssl"] }
proxmox-sys.workspace = true
apt-pkg-native = { version = "0.3.2", optional = true }
apt-pkg-native = {version = "0.3.2", git = "https://gitea.basealt.ru/konevsa/apt-pkg-native", optional = true }
regex = { workspace = true, optional = true }
nix = { workspace = true, optional = true }
log = { workspace = true, optional = true }
@ -39,3 +39,5 @@ cache = [
"dep:log",
"dep:proxmox-schema",
]
alt-linux = ["apt-pkg-native/alt-linux", "proxmox-apt-api-types/alt-linux"]

View File

@ -32,7 +32,10 @@ pub fn list_repositories(product: &str) -> Result<APTRepositoriesResult, Error>
let (files, errors, digest) = crate::repositories::repositories()?;
#[cfg(not(feature = "alt-linux"))]
let suite = crate::repositories::get_current_release_codename()?;
#[cfg(feature = "alt-linux")]
let suite = crate::repositories::get_current_release_branch_id()?;
let infos = crate::repositories::check_repositories(&files, suite, apt_lists_dir);
let standard_repos = crate::repositories::standard_repositories(&files, product, suite);
@ -59,7 +62,10 @@ pub fn add_repository_handle(
current_digest.detect_modification(digest.as_ref())?;
#[cfg(not(feature = "alt-linux"))]
let suite = crate::repositories::get_current_release_codename()?;
#[cfg(feature = "alt-linux")]
let suite = crate::repositories::get_current_release_branch_id()?;
// check if it's already configured first
for file in files.iter_mut() {

View File

@ -157,7 +157,7 @@ impl TryFrom<Vec<PackagesFileRaw>> for PackagesFile {
pub fn test_deb_packages_file() {
let input = include_str!(concat!(
env!("CARGO_MANIFEST_DIR"),
"/tests/deb822/packages/deb.debian.org_debian_dists_bullseye_main_binary-amd64_Packages"
"/tests/Debian/deb822/packages/deb.debian.org_debian_dists_bullseye_main_binary-amd64_Packages"
));
let deserialized =

View File

@ -593,7 +593,7 @@ fn merge_references(
pub fn test_deb_release_file() {
let input = include_str!(concat!(
env!("CARGO_MANIFEST_DIR"),
"/tests/deb822/release/deb.debian.org_debian_dists_bullseye_Release"
"/tests/Debian/deb822/release/deb.debian.org_debian_dists_bullseye_Release"
));
let deserialized = ReleaseFileRaw::deserialize(Deserializer::new(input.as_bytes())).unwrap();
@ -609,7 +609,7 @@ pub fn test_deb_release_file() {
pub fn test_deb_release_file_insecure() {
let input = include_str!(concat!(
env!("CARGO_MANIFEST_DIR"),
"/tests/deb822/release/deb.debian.org_debian_dists_bullseye_Release_insecure"
"/tests/Debian/deb822/release/deb.debian.org_debian_dists_bullseye_Release_insecure"
));
let deserialized = ReleaseFileRaw::deserialize(Deserializer::new(input.as_bytes())).unwrap();

View File

@ -236,7 +236,7 @@ pub fn test_deb_packages_file() {
// http://snapshot.debian.org/archive/debian/20221017T212657Z/dists/bullseye/main/source/Sources.xz
let input = include_str!(concat!(
env!("CARGO_MANIFEST_DIR"),
"/tests/deb822/sources/deb.debian.org_debian_dists_bullseye_main_source_Sources"
"/tests/Debian/deb822/sources/deb.debian.org_debian_dists_bullseye_main_source_Sources"
));
let deserialized =

View File

@ -10,5 +10,6 @@ mod cache_api;
#[cfg(feature = "cache")]
pub use cache_api::{get_package_versions, list_available_apt_update, update_database};
#[cfg(not(feature = "alt-linux"))]
pub mod deb822;
pub mod repositories;

View File

@ -2,6 +2,9 @@ use std::path::{Path, PathBuf};
use anyhow::{format_err, Error};
#[cfg(feature = "alt-linux")]
use crate::repositories::release::ALTBranchID;
#[cfg(not(feature = "alt-linux"))]
use crate::repositories::release::DebianCodename;
use proxmox_apt_api_types::{
APTRepository, APTRepositoryFile, APTRepositoryFileError, APTRepositoryFileType,
@ -56,7 +59,11 @@ pub trait APTRepositoryFileImpl {
/// Checks if old or unstable suites are configured and that the Debian security repository
/// has the correct suite. Also checks that the `stable` keyword is not used.
fn check_suites(&self, current_codename: DebianCodename) -> Vec<APTRepositoryInfo>;
fn check_suites(
&self,
#[cfg(not(feature = "alt-linux"))] current_codename: DebianCodename,
#[cfg(feature = "alt-linux")] current_codename: ALTBranchID,
) -> Vec<APTRepositoryInfo>;
/// Checks for official URIs.
fn check_uris(&self, apt_lists_dir: &Path) -> Vec<APTRepositoryInfo>;
@ -119,6 +126,12 @@ impl APTRepositoryFileImpl for APTRepositoryFile {
return Ok(None);
}
#[cfg(feature = "alt-linux")]
// ignore files with .sisyphus (used by README.sisyphus), .rpmnew and .rpmsave
if matches!(extension.as_str(), "rpmnew" | "rpmsave" | "sisyphus") {
return Ok(None);
}
let file_type = extension[..]
.parse()
.map_err(|_| new_err("invalid extension"))?;
@ -268,7 +281,13 @@ impl APTRepositoryFileImpl for APTRepositoryFile {
Ok(())
}
fn check_suites(&self, current_codename: DebianCodename) -> Vec<APTRepositoryInfo> {
/// Checks if old or unstable suites are configured and that the Debian security repository
/// has the correct suite. Also checks that the `stable` keyword is not used.
fn check_suites(
&self,
#[cfg(not(feature = "alt-linux"))] current_codename: DebianCodename,
#[cfg(feature = "alt-linux")] current_codename: ALTBranchID,
) -> Vec<APTRepositoryInfo> {
let mut infos = vec![];
let path = match &self.path {
@ -277,9 +296,14 @@ impl APTRepositoryFileImpl for APTRepositoryFile {
};
for (n, repo) in self.repositories.iter().enumerate() {
#[cfg(not(feature = "alt-linux"))]
if !repo.types.contains(&APTRepositoryPackageType::Deb) {
continue;
}
#[cfg(feature = "alt-linux")]
if !repo.types.contains(&APTRepositoryPackageType::Rpm) {
continue;
}
let is_security_repo = repo.uris.iter().any(|uri| {
let uri = uri.trim_end_matches('/');
@ -292,6 +316,7 @@ impl APTRepositoryFileImpl for APTRepositoryFile {
});
let require_suffix = match is_security_repo {
#[cfg(not(feature = "alt-linux"))]
true if current_codename >= DebianCodename::Bullseye => Some("-security"),
true => Some("/updates"),
false => None,
@ -328,15 +353,18 @@ impl APTRepositoryFileImpl for APTRepositoryFile {
_ => (),
};
#[cfg(not(feature = "alt-linux"))]
let codename: DebianCodename = match base_suite.try_into() {
Ok(codename) => codename,
Err(_) => continue,
};
#[cfg(not(feature = "alt-linux"))]
if codename < current_codename {
add_info("warning", message_old(base_suite));
}
#[cfg(not(feature = "alt-linux"))]
if Some(codename) == current_codename.next() {
add_info("ignore-pre-upgrade-warning", message_new(base_suite));
} else if codename > current_codename {

View File

@ -5,7 +5,9 @@ use anyhow::{bail, format_err, Error};
use super::APTRepositoryParser;
use crate::repositories::APTRepositoryImpl;
use crate::repositories::{APTRepository, APTRepositoryFileType, APTRepositoryOption};
use crate::repositories::{APTRepository, APTRepositoryFileType};
#[cfg(not(feature = "alt-linux"))]
use crate::repositories::APTRepositoryOption;
// TODO convert %-escape characters. Also adapt printing back accordingly,
// because at least '%' needs to be re-escaped when printing.
@ -100,7 +102,10 @@ impl<R: BufRead> APTListFileParser<R> {
///
/// Errors when options are invalid or not closed by `']'`.
fn parse_options(
#[cfg(not(feature = "alt-linux"))]
options: &mut Vec<APTRepositoryOption>,
#[cfg(feature = "alt-linux")]
options: &mut Vec<String>,
tokens: &mut SplitQuoteWord,
) -> Result<(), Error> {
let mut finished = false;
@ -119,6 +124,7 @@ impl<R: BufRead> APTListFileParser<R> {
finished = true; // but still need to handle the last one
};
#[cfg(not(feature = "alt-linux"))]
if let Some(mid) = option.find('=') {
let (key, mut value_str) = option.split_at(mid);
value_str = &value_str[1..];
@ -143,6 +149,10 @@ impl<R: BufRead> APTListFileParser<R> {
} else if !option.is_empty() {
bail!("got invalid option - '{}'", option);
}
#[cfg(feature = "alt-linux")]
if !option.is_empty() {
options.push(option);
}
if finished {
break;

View File

@ -5,8 +5,10 @@ use anyhow::{bail, Error};
use crate::repositories::APTRepositoryImpl;
use crate::repositories::{
APTRepository, APTRepositoryFileType, APTRepositoryOption, APTRepositoryPackageType,
APTRepository, APTRepositoryFileType, APTRepositoryPackageType,
};
#[cfg(not(feature = "alt-linux"))]
use crate::repositories::APTRepositoryOption;
use super::APTRepositoryParser;
@ -133,10 +135,13 @@ impl<R: BufRead> APTSourcesFileParser<R> {
"enabled" => {
repo.set_enabled(Self::string_to_bool(value_str, true));
}
#[cfg(not(feature = "alt-linux"))]
_ => repo.options.push(APTRepositoryOption {
key: key.to_string(),
values,
}),
#[cfg(feature = "alt-linux")]
_ => repo.options.push(key.to_string()),
}
} else {
bail!("got invalid line - '{:?}'", line);

View File

@ -6,9 +6,11 @@ use anyhow::{bail, Error};
mod repository;
use proxmox_apt_api_types::{
APTRepository, APTRepositoryFile, APTRepositoryFileError, APTRepositoryFileType,
APTRepositoryHandle, APTRepositoryInfo, APTRepositoryOption, APTRepositoryPackageType,
APTRepositoryHandle, APTRepositoryInfo, APTRepositoryPackageType,
APTStandardRepository,
};
#[cfg(not(feature = "alt-linux"))]
pub use proxmox_apt_api_types::APTRepositoryOption;
use proxmox_config_digest::ConfigDigest;
pub use repository::APTRepositoryImpl;
@ -16,7 +18,10 @@ mod file;
pub use file::APTRepositoryFileImpl;
mod release;
#[cfg(not(feature = "alt-linux"))]
pub use release::{get_current_release_codename, DebianCodename};
#[cfg(feature = "alt-linux")]
pub use release::{get_current_release_branch_id, ALTBranchID};
mod standard;
pub use standard::{APTRepositoryHandleImpl, APTStandardRepositoryImpl};
@ -55,7 +60,10 @@ fn common_digest(files: &[APTRepositoryFile]) -> ConfigDigest {
/// `badge` for official URIs.
pub fn check_repositories(
files: &[APTRepositoryFile],
#[cfg(not(feature = "alt-linux"))]
current_suite: DebianCodename,
#[cfg(feature = "alt-linux")]
current_suite: ALTBranchID,
apt_lists_dir: &Path,
) -> Vec<APTRepositoryInfo> {
let mut infos = vec![];
@ -72,7 +80,10 @@ pub fn check_repositories(
pub fn get_standard_repository(
handle: APTRepositoryHandle,
product: &str,
#[cfg(not(feature = "alt-linux"))]
suite: DebianCodename,
#[cfg(feature = "alt-linux")]
suite: ALTBranchID,
) -> (APTRepository, String) {
let repo = handle.to_repository(product, &suite.to_string());
let path = handle.path(product);
@ -85,14 +96,26 @@ pub fn get_standard_repository(
pub fn standard_repositories(
files: &[APTRepositoryFile],
product: &str,
#[cfg(not(feature = "alt-linux"))]
suite: DebianCodename,
#[cfg(feature = "alt-linux")]
suite: ALTBranchID,
) -> Vec<APTStandardRepository> {
#[cfg(not(feature = "alt-linux"))]
let mut result = vec![
APTStandardRepository::from_handle(APTRepositoryHandle::Enterprise),
APTStandardRepository::from_handle(APTRepositoryHandle::NoSubscription),
APTStandardRepository::from_handle(APTRepositoryHandle::Test),
];
#[cfg(feature = "alt-linux")]
let mut result = vec![
APTStandardRepository::from_handle(APTRepositoryHandle::CheckInstall),
APTStandardRepository::from_handle(APTRepositoryHandle::Classic),
APTStandardRepository::from_handle(APTRepositoryHandle::DebugInfo),
APTStandardRepository::from_handle(APTRepositoryHandle::GostCrypto),
];
#[cfg(not(feature = "alt-linux"))]
if product == "pve" {
result.append(&mut vec![
APTStandardRepository::from_handle(APTRepositoryHandle::CephQuincyEnterprise),

View File

@ -4,6 +4,7 @@ use std::io::{BufRead, BufReader};
use anyhow::{bail, format_err, Error};
/// The code names of Debian releases. Does not include `sid`.
#[cfg(not(feature = "alt-linux"))]
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum DebianCodename {
Lenny = 5,
@ -17,6 +18,28 @@ pub enum DebianCodename {
Trixie,
}
/// The code names of ALT Branch IDs.
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[cfg(feature = "alt-linux")]
pub enum ALTBranchID {
Sisyphus,
SisyphusE2k,
SisyphusMipsel,
SisyphusRiscV64,
SisyphusLoongarch64,
P11,
P10,
P10E2k,
P9,
P9E2k,
P9Mipsel,
P8,
C10f1,
C9f2,
C7,
}
#[cfg(not(feature = "alt-linux"))]
impl DebianCodename {
pub fn next(&self) -> Option<Self> {
match (*self as u8 + 1).try_into() {
@ -26,6 +49,7 @@ impl DebianCodename {
}
}
#[cfg(not(feature = "alt-linux"))]
impl TryFrom<&str> for DebianCodename {
type Error = Error;
@ -45,6 +69,33 @@ impl TryFrom<&str> for DebianCodename {
}
}
#[cfg(feature = "alt-linux")]
impl TryFrom<&str> for ALTBranchID {
type Error = Error;
fn try_from(string: &str) -> Result<Self, Error> {
match string {
"sisyphus" => Ok(ALTBranchID::Sisyphus),
"sisyphus_e2k" => Ok(ALTBranchID::SisyphusE2k),
"sisyphus_mipsel" => Ok(ALTBranchID::SisyphusMipsel),
"sisyphus_riscv64" => Ok(ALTBranchID::SisyphusRiscV64),
"sisyphus_loongarch64" => Ok(ALTBranchID::SisyphusLoongarch64),
"p11" => Ok(ALTBranchID::P11),
"p10" => Ok(ALTBranchID::P10),
"p10_e2k" => Ok(ALTBranchID::P10E2k),
"p9" => Ok(ALTBranchID::P9),
"p9_e2k" => Ok(ALTBranchID::P9E2k),
"p9_mipsel" => Ok(ALTBranchID::P9Mipsel),
"p8" => Ok(ALTBranchID::P8),
"c10f1" => Ok(ALTBranchID::C10f1),
"c9f2" => Ok(ALTBranchID::C9f2),
"c7" => Ok(ALTBranchID::C7),
_ => bail!("unknown ALT branch ID '{}'", string),
}
}
}
#[cfg(not(feature = "alt-linux"))]
impl TryFrom<u8> for DebianCodename {
type Error = Error;
@ -64,6 +115,7 @@ impl TryFrom<u8> for DebianCodename {
}
}
#[cfg(not(feature = "alt-linux"))]
impl Display for DebianCodename {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
@ -80,7 +132,31 @@ impl Display for DebianCodename {
}
}
#[cfg(feature = "alt-linux")]
impl Display for ALTBranchID {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ALTBranchID::Sisyphus => write!(f, "sisyphus"),
ALTBranchID::SisyphusE2k => write!(f, "sisyphus_e2k"),
ALTBranchID::SisyphusMipsel => write!(f, "sisyphus_mipsel"),
ALTBranchID::SisyphusRiscV64 => write!(f, "sisyphus_riscv64"),
ALTBranchID::SisyphusLoongarch64 => write!(f, "sisyphus_loongarch64"),
ALTBranchID::P11 => write!(f, "p11"),
ALTBranchID::P10 => write!(f, "p10"),
ALTBranchID::P10E2k => write!(f, "p10_e2k"),
ALTBranchID::P9 => write!(f, "p9"),
ALTBranchID::P9E2k => write!(f, "p9_e2k"),
ALTBranchID::P9Mipsel => write!(f, "p9_mipsel"),
ALTBranchID::P8 => write!(f, "p8"),
ALTBranchID::C10f1 => write!(f, "c10f1"),
ALTBranchID::C9f2 => write!(f, "c9f2"),
ALTBranchID::C7 => write!(f, "c7"),
}
}
}
/// Read the `VERSION_CODENAME` from `/etc/os-release`.
#[cfg(not(feature = "alt-linux"))]
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))?;
@ -98,3 +174,23 @@ pub fn get_current_release_codename() -> Result<DebianCodename, Error> {
bail!("unable to parse codename from '/etc/os-release'");
}
/// Read the `ALT_BRANCH_ID` from `/etc/os-release`.
#[cfg(feature = "alt-linux")]
pub fn get_current_release_branch_id() -> Result<ALTBranchID, Error> {
let raw = std::fs::read("/etc/os-release")
.map_err(|err| format_err!("unable to read '/etc/os-release' - {}", err))?;
let reader = BufReader::new(&*raw);
for line in reader.lines() {
let line = line.map_err(|err| format_err!("unable to read '/etc/os-release' - {}", err))?;
if let Some(branch_id) = line.strip_prefix("ALT_BRANCH_ID=") {
let branch_id = branch_id.trim_matches(&['"', '\''][..]);
return branch_id.try_into();
}
}
bail!("unable to parse ALT branch ID from '/etc/os-release'");
}

View File

@ -4,9 +4,10 @@ use std::path::{Path, PathBuf};
use anyhow::{bail, format_err, Error};
use crate::repositories::standard::APTRepositoryHandleImpl;
use proxmox_apt_api_types::{
APTRepository, APTRepositoryFileType, APTRepositoryHandle, APTRepositoryOption,
};
use proxmox_apt_api_types::{APTRepository, APTRepositoryFileType, APTRepositoryHandle};
#[cfg(not(feature = "alt-linux"))]
use crate::repositories::APTRepositoryOption;
pub trait APTRepositoryImpl {
/// Crates an empty repository.
@ -59,20 +60,25 @@ impl APTRepositoryImpl for APTRepository {
self.enabled = enabled;
if self.file_type == APTRepositoryFileType::Sources {
#[cfg(not(feature = "alt-linux"))]
let enabled_string = match enabled {
true => "true".to_string(),
false => "false".to_string(),
};
#[cfg(not(feature = "alt-linux"))]
for option in self.options.iter_mut() {
if option.key == "Enabled" {
option.values = vec![enabled_string];
return;
}
}
#[cfg(not(feature = "alt-linux"))]
self.options.push(APTRepositoryOption {
key: "Enabled".to_string(),
values: vec![enabled_string],
});
#[cfg(feature = "alt-linux")]
self.options.push("Enabled".to_string());
}
}
@ -140,11 +146,23 @@ impl APTRepositoryImpl for APTRepository {
self.components.contains(&component)
};
self.types.contains(&package_type)
#[cfg(not(feature = "alt-linux"))]
{
self.types.contains(&package_type)
&& found_uri
// using contains would require a &String
&& self.suites.iter().any(|self_suite| self_suite == suite)
&& found_component
}
#[cfg(feature = "alt-linux")]
{
self.types.contains(&package_type)
&& found_uri
// ALT's suites looks like `Sisyphus/noarch`
&& self.suites.iter().any(|self_suite| self_suite.to_lowercase().starts_with(suite))
&& found_component
}
}
fn origin_from_uris(&self) -> Option<String> {
@ -157,6 +175,11 @@ impl APTRepositoryImpl for APTRepository {
if host == "debian.org" || host.ends_with(".debian.org") {
return Some("Debian".to_string());
}
#[cfg(feature = "alt-linux")]
if !host.is_empty() {
return Some("ALT Linux Team".to_string());
}
}
}
@ -210,15 +233,24 @@ fn release_filename(apt_lists_dir: &Path, uri: &str, suite: &str, detached: bool
let mut path = PathBuf::from(apt_lists_dir);
let encoded_uri = uri_to_filename(uri);
#[cfg(not(feature = "alt-linux"))]
let filename = if detached { "Release" } else { "InRelease" };
#[cfg(feature = "alt-linux")]
let filename = if detached { "release" } else { "InRelease" };
if suite == "/" {
path.push(format!("{encoded_uri}_{filename}"));
} else if suite == "./" {
path.push(format!("{encoded_uri}_._{filename}"));
} else {
#[cfg(not(feature = "alt-linux"))]
let normalized_suite = suite.replace('/', "_"); // e.g. for buster/updates
#[cfg(not(feature = "alt-linux"))]
path.push(format!("{encoded_uri}_dists_{normalized_suite}_{filename}",));
#[cfg(feature = "alt-linux")]
let normalized_suite = suite.replace('/', "_").replace("x86_64", "x86%5f64");
#[cfg(feature = "alt-linux")]
path.push(format!("{encoded_uri}_{normalized_suite}_base_{filename}",));
}
path
@ -262,7 +294,18 @@ fn uri_to_filename(uri: &str) -> String {
/// Get the host part from a given URI.
fn host_from_uri(uri: &str) -> Option<&str> {
#[cfg(not(feature = "alt-linux"))]
let host = uri.strip_prefix("http")?;
#[cfg(feature = "alt-linux")]
let host = if uri.starts_with("http") {
uri.strip_prefix("http")?
} else if uri.starts_with("ftp") {
uri.strip_prefix("ftp")?
} else {
uri.strip_prefix("rsync")?
};
let host = host.strip_prefix('s').unwrap_or(host);
let mut host = host.strip_prefix("://")?;
@ -339,13 +382,21 @@ fn write_one_line(repo: &APTRepository, w: &mut dyn Write) -> Result<(), Error>
write!(w, "{} ", repo.types[0])?;
if !repo.options.is_empty() {
#[cfg(not(feature = "alt-linux"))]
write!(w, "[ ")?;
for option in repo.options.iter() {
#[cfg(not(feature = "alt-linux"))]
let (key, value) = (&option.key, option.values.join(","));
#[cfg(not(feature = "alt-linux"))]
write!(w, "{} ", quote_for_one_line(&format!("{key}={value}")))?;
#[cfg(feature = "alt-linux")]
let vendor_id = &option;
#[cfg(feature = "alt-linux")]
write!(w, "{} ", quote_for_one_line(&format!("[{vendor_id}]")))?
}
#[cfg(not(feature = "alt-linux"))]
write!(w, "] ")?;
};
@ -393,7 +444,10 @@ fn write_stanza(repo: &APTRepository, w: &mut dyn Write) -> Result<(), Error> {
}
for option in repo.options.iter() {
#[cfg(not(feature = "alt-linux"))]
writeln!(w, "{}: {}", option.key, option.values.join(" "))?;
#[cfg(feature = "alt-linux")]
writeln!(w, "Vendor: {}", option)?;
}
writeln!(w)?;

View File

@ -75,6 +75,21 @@ impl APTRepositoryHandleImpl for APTRepositoryHandle {
"This repository contains the Ceph Reef packages before they are moved to the \
main repository."
}
APTRepositoryHandle::CheckInstall => {
"The repository contains check install information for binary \
executables and libraries."
}
APTRepositoryHandle::Classic => {
"The repository contains binary executables and libraries."
}
APTRepositoryHandle::DebugInfo => {
"The repository contains debugging information for binary \
executables and libraries."
}
APTRepositoryHandle::GostCrypto => {
"The repository contains binary executables and libraries \
with GOST cryptography."
}
}
.to_string()
}
@ -90,6 +105,10 @@ impl APTRepositoryHandleImpl for APTRepositoryHandle {
APTRepositoryHandle::CephReefEnterprise => "Ceph Reef Enterprise",
APTRepositoryHandle::CephReefNoSubscription => "Ceph Reef No-Subscription",
APTRepositoryHandle::CephReefTest => "Ceph Reef Test",
APTRepositoryHandle::CheckInstall => "checkinstall",
APTRepositoryHandle::Classic => "classic",
APTRepositoryHandle::DebugInfo => "debuginfo",
APTRepositoryHandle::GostCrypto => "gostcrypto",
}
.to_string()
}
@ -107,6 +126,10 @@ impl APTRepositoryHandleImpl for APTRepositoryHandle {
| APTRepositoryHandle::CephReefEnterprise
| APTRepositoryHandle::CephReefNoSubscription
| APTRepositoryHandle::CephReefTest => "/etc/apt/sources.list.d/ceph.list".to_string(),
APTRepositoryHandle::CheckInstall
| APTRepositoryHandle::Classic
| APTRepositoryHandle::DebugInfo
| APTRepositoryHandle::GostCrypto => "/etc/apt/sources.list".to_string(),
}
}
@ -175,6 +198,30 @@ impl APTRepositoryHandleImpl for APTRepositoryHandle {
vec!["http://download.proxmox.com/debian/ceph-reef".to_string()],
"test".to_string(),
),
APTRepositoryHandle::CheckInstall => (
APTRepositoryPackageType::Rpm,
vec!["http://ftp.altlinux.org/pub/distributions/ALTLinux".to_string()],
"checkinstall".to_string(),
),
APTRepositoryHandle::Classic => (
APTRepositoryPackageType::Rpm,
vec![
"http://ftp.altlinux.org/pub/distributions/ALTLinux".to_string(),
"ftp://ftp.altlinux.org/pub/distributions/ALTLinux".to_string(),
"rsync://ftp.altlinux.org/ALTLinux".to_string(),
],
"classic".to_string(),
),
APTRepositoryHandle::DebugInfo => (
APTRepositoryPackageType::Rpm,
vec!["http://ftp.altlinux.org/pub/distributions/ALTLinux".to_string()],
"debuginfo".to_string(),
),
APTRepositoryHandle::GostCrypto => (
APTRepositoryPackageType::Rpm,
vec!["http://ftp.altlinux.org/pub/distributions/ALTLinux".to_string()],
"gostcrypto".to_string(),
),
}
}

View File

@ -0,0 +1,20 @@
# ftp.altlinux.org (ALT Linux, Moscow)
# ALT Linux Sisyphus
rpm [alt] ftp://ftp.altlinux.org/pub/distributions/ALTLinux Sisyphus/x86_64 classic
rpm [alt] ftp://ftp.altlinux.org/pub/distributions/ALTLinux Sisyphus/x86_64-i586 classic
rpm [alt] ftp://ftp.altlinux.org/pub/distributions/ALTLinux Sisyphus/noarch classic
# rpm [alt] http://ftp.altlinux.org/pub/distributions/ALTLinux Sisyphus/x86_64 classic
# rpm [alt] http://ftp.altlinux.org/pub/distributions/ALTLinux Sisyphus/x86_64-i586 classic
# rpm [alt] http://ftp.altlinux.org/pub/distributions/ALTLinux Sisyphus/noarch classic
# rpm [alt] rsync://ftp.altlinux.org/ALTLinux Sisyphus/x86_64 classic
# rpm [alt] rsync://ftp.altlinux.org/ALTLinux Sisyphus/x86_64-i586 classic
# rpm [alt] rsync://ftp.altlinux.org/ALTLinux Sisyphus/noarch classic

View File

@ -0,0 +1,20 @@
# mirror.datacenter.by (Beltelecom datacenter, Minsk, Belarus)
# ALT Linux Sisyphus
# rpm [alt] ftp://mirror.datacenter.by/pub/ALTLinux Sisyphus/x86_64 classic
# rpm [alt] ftp://mirror.datacenter.by/pub/ALTLinux Sisyphus/x86_64-i586 classic
# rpm [alt] ftp://mirror.datacenter.by/pub/ALTLinux Sisyphus/noarch classic
rpm [alt] http://mirror.datacenter.by/pub/ALTLinux Sisyphus/x86_64 classic
rpm [alt] http://mirror.datacenter.by/pub/ALTLinux Sisyphus/x86_64-i586 classic
rpm [alt] http://mirror.datacenter.by/pub/ALTLinux Sisyphus/noarch classic
# rpm [alt] rsync://mirror.datacenter.by/ALTLinux Sisyphus/x86_64 classic
# rpm [alt] rsync://mirror.datacenter.by/ALTLinux Sisyphus/x86_64-i586 classic
# rpm [alt] rsync://mirror.datacenter.by/ALTLinux Sisyphus/noarch classic

View File

@ -0,0 +1,20 @@
# ftp.heanet.ie (HEAnet, Ireland)
# ALT Linux Sisyphus
# rpm [alt] ftp://ftp.heanet.ie/mirrors/ftp.altlinux.org Sisyphus/x86_64 classic
# rpm [alt] ftp://ftp.heanet.ie/mirrors/ftp.altlinux.org Sisyphus/x86_64-i586 classic
# rpm [alt] ftp://ftp.heanet.ie/mirrors/ftp.altlinux.org Sisyphus/noarch classic
# rpm [alt] http://ftp.heanet.ie/mirrors/ftp.altlinux.org Sisyphus/x86_64 classic
# rpm [alt] http://ftp.heanet.ie/mirrors/ftp.altlinux.org Sisyphus/x86_64-i586 classic
# rpm [alt] http://ftp.heanet.ie/mirrors/ftp.altlinux.org Sisyphus/noarch classic
rpm [alt] rsync://ftp.heanet.ie/mirrors/ftp.altlinux.org Sisyphus/x86_64 classic
rpm [alt] rsync://ftp.heanet.ie/mirrors/ftp.altlinux.org Sisyphus/x86_64-i586 classic
rpm [alt] rsync://ftp.heanet.ie/mirrors/ftp.altlinux.org Sisyphus/noarch classic

View File

@ -0,0 +1,20 @@
# distrib-coffee.ipsl.jussieu.fr (Institut Pierre Simon Laplace, France)
# ALT Linux Sisyphus
rpm [alt] ftp://distrib-coffee.ipsl.jussieu.fr/pub/linux/altlinux Sisyphus/x86_64 classic
rpm [alt] ftp://distrib-coffee.ipsl.jussieu.fr/pub/linux/altlinux Sisyphus/x86_64-i586 classic
rpm [alt] ftp://distrib-coffee.ipsl.jussieu.fr/pub/linux/altlinux Sisyphus/noarch classic
rpm [alt] http://distrib-coffee.ipsl.jussieu.fr/pub/linux/altlinux Sisyphus/x86_64 classic
rpm [alt] http://distrib-coffee.ipsl.jussieu.fr/pub/linux/altlinux Sisyphus/x86_64-i586 classic
rpm [alt] http://distrib-coffee.ipsl.jussieu.fr/pub/linux/altlinux Sisyphus/noarch classic
rpm [alt] rsync://distrib-coffee.ipsl.jussieu.fr/pub/linux/altlinux Sisyphus/x86_64 classic
rpm [alt] rsync://distrib-coffee.ipsl.jussieu.fr/pub/linux/altlinux Sisyphus/x86_64-i586 classic
rpm [alt] rsync://distrib-coffee.ipsl.jussieu.fr/pub/linux/altlinux Sisyphus/noarch classic

View File

@ -0,0 +1,14 @@
# mirror.cs.msu.ru (CMC MSU, Moscow, Russia)
# ALT Linux Sisyphus
# rpm [alt] http://mirror.cs.msu.ru/alt Sisyphus/x86_64 classic
# rpm [alt] http://mirror.cs.msu.ru/alt Sisyphus/x86_64-i586 classic
# rpm [alt] http://mirror.cs.msu.ru/alt Sisyphus/noarch classic
rpm [alt] rsync://mirror.cs.msu.ru/alt Sisyphus/x86_64 classic
rpm [alt] rsync://mirror.cs.msu.ru/alt Sisyphus/x86_64-i586 classic
rpm [alt] rsync://mirror.cs.msu.ru/alt Sisyphus/noarch classic

View File

@ -0,0 +1,2 @@
rpm cdrom:[ALT Workstation 10.1 x86_64 build 2023-01-26]/ ALTLinux main

View File

@ -0,0 +1,20 @@
# mirror.yandex.ru (Yandex, Moscow)
# ALT Linux Sisyphus
# rpm [alt] ftp://mirror.yandex.ru/altlinux Sisyphus/x86_64 classic
# rpm [alt] ftp://mirror.yandex.ru/altlinux Sisyphus/x86_64-i586 classic
# rpm [alt] ftp://mirror.yandex.ru/altlinux Sisyphus/noarch classic
# rpm [alt] http://mirror.yandex.ru/altlinux Sisyphus/x86_64 classic
# rpm [alt] http://mirror.yandex.ru/altlinux Sisyphus/x86_64-i586 classic
# rpm [alt] http://mirror.yandex.ru/altlinux Sisyphus/noarch classic
# rpm [alt] rsync://mirror.yandex.ru/altlinux Sisyphus/x86_64 classic
# rpm [alt] rsync://mirror.yandex.ru/altlinux Sisyphus/x86_64-i586 classic
# rpm [alt] rsync://mirror.yandex.ru/altlinux Sisyphus/noarch classic

View File

@ -0,0 +1,15 @@
# ftp.altlinux.org (ALT Linux, Moscow)
# ALT Linux Sisyphus
rpm [alt] ftp://ftp.altlinux.org/pub/distributions/ALTLinux Sisyphus/x86_64 classic
rpm [alt] ftp://ftp.altlinux.org/pub/distributions/ALTLinux Sisyphus/x86_64-i586 classic
rpm [alt] ftp://ftp.altlinux.org/pub/distributions/ALTLinux Sisyphus/noarch classic
#rpm [alt] http://ftp.altlinux.org/pub/distributions/ALTLinux Sisyphus/x86_64 classic
#rpm [alt] http://ftp.altlinux.org/pub/distributions/ALTLinux Sisyphus/x86_64-i586 classic
#rpm [alt] http://ftp.altlinux.org/pub/distributions/ALTLinux Sisyphus/noarch classic
#rpm [alt] rsync://ftp.altlinux.org/ALTLinux Sisyphus/x86_64 classic
#rpm [alt] rsync://ftp.altlinux.org/ALTLinux Sisyphus/x86_64-i586 classic
#rpm [alt] rsync://ftp.altlinux.org/ALTLinux Sisyphus/noarch classic

View File

@ -0,0 +1,15 @@
# mirror.datacenter.by (Beltelecom datacenter, Minsk, Belarus)
# ALT Linux Sisyphus
#rpm [alt] ftp://mirror.datacenter.by/pub/ALTLinux Sisyphus/x86_64 classic
#rpm [alt] ftp://mirror.datacenter.by/pub/ALTLinux Sisyphus/x86_64-i586 classic
#rpm [alt] ftp://mirror.datacenter.by/pub/ALTLinux Sisyphus/noarch classic
rpm [alt] http://mirror.datacenter.by/pub/ALTLinux Sisyphus/x86_64 classic
rpm [alt] http://mirror.datacenter.by/pub/ALTLinux Sisyphus/x86_64-i586 classic
rpm [alt] http://mirror.datacenter.by/pub/ALTLinux Sisyphus/noarch classic
#rpm [alt] rsync://mirror.datacenter.by/ALTLinux Sisyphus/x86_64 classic
#rpm [alt] rsync://mirror.datacenter.by/ALTLinux Sisyphus/x86_64-i586 classic
#rpm [alt] rsync://mirror.datacenter.by/ALTLinux Sisyphus/noarch classic

View File

@ -0,0 +1,15 @@
# ftp.heanet.ie (HEAnet, Ireland)
# ALT Linux Sisyphus
#rpm [alt] ftp://ftp.heanet.ie/mirrors/ftp.altlinux.org Sisyphus/x86_64 classic
#rpm [alt] ftp://ftp.heanet.ie/mirrors/ftp.altlinux.org Sisyphus/x86_64-i586 classic
#rpm [alt] ftp://ftp.heanet.ie/mirrors/ftp.altlinux.org Sisyphus/noarch classic
#rpm [alt] http://ftp.heanet.ie/mirrors/ftp.altlinux.org Sisyphus/x86_64 classic
#rpm [alt] http://ftp.heanet.ie/mirrors/ftp.altlinux.org Sisyphus/x86_64-i586 classic
#rpm [alt] http://ftp.heanet.ie/mirrors/ftp.altlinux.org Sisyphus/noarch classic
rpm [alt] rsync://ftp.heanet.ie/mirrors/ftp.altlinux.org Sisyphus/x86_64 classic
rpm [alt] rsync://ftp.heanet.ie/mirrors/ftp.altlinux.org Sisyphus/x86_64-i586 classic
rpm [alt] rsync://ftp.heanet.ie/mirrors/ftp.altlinux.org Sisyphus/noarch classic

View File

@ -0,0 +1,15 @@
# distrib-coffee.ipsl.jussieu.fr (Institut Pierre Simon Laplace, France)
# ALT Linux Sisyphus
rpm [alt] ftp://distrib-coffee.ipsl.jussieu.fr/pub/linux/altlinux Sisyphus/x86_64 classic
rpm [alt] ftp://distrib-coffee.ipsl.jussieu.fr/pub/linux/altlinux Sisyphus/x86_64-i586 classic
rpm [alt] ftp://distrib-coffee.ipsl.jussieu.fr/pub/linux/altlinux Sisyphus/noarch classic
rpm [alt] http://distrib-coffee.ipsl.jussieu.fr/pub/linux/altlinux Sisyphus/x86_64 classic
rpm [alt] http://distrib-coffee.ipsl.jussieu.fr/pub/linux/altlinux Sisyphus/x86_64-i586 classic
rpm [alt] http://distrib-coffee.ipsl.jussieu.fr/pub/linux/altlinux Sisyphus/noarch classic
rpm [alt] rsync://distrib-coffee.ipsl.jussieu.fr/pub/linux/altlinux Sisyphus/x86_64 classic
rpm [alt] rsync://distrib-coffee.ipsl.jussieu.fr/pub/linux/altlinux Sisyphus/x86_64-i586 classic
rpm [alt] rsync://distrib-coffee.ipsl.jussieu.fr/pub/linux/altlinux Sisyphus/noarch classic

View File

@ -0,0 +1,11 @@
# mirror.cs.msu.ru (CMC MSU, Moscow, Russia)
# ALT Linux Sisyphus
#rpm [alt] http://mirror.cs.msu.ru/alt Sisyphus/x86_64 classic
#rpm [alt] http://mirror.cs.msu.ru/alt Sisyphus/x86_64-i586 classic
#rpm [alt] http://mirror.cs.msu.ru/alt Sisyphus/noarch classic
rpm [alt] rsync://mirror.cs.msu.ru/alt Sisyphus/x86_64 classic
rpm [alt] rsync://mirror.cs.msu.ru/alt Sisyphus/x86_64-i586 classic
rpm [alt] rsync://mirror.cs.msu.ru/alt Sisyphus/noarch classic

View File

@ -0,0 +1,2 @@
rpm cdrom:[ALT Workstation 10.1 x86_64 build 2023-01-26]/ ALTLinux main

View File

@ -0,0 +1,15 @@
# mirror.yandex.ru (Yandex, Moscow)
# ALT Linux Sisyphus
#rpm [alt] ftp://mirror.yandex.ru/altlinux Sisyphus/x86_64 classic
#rpm [alt] ftp://mirror.yandex.ru/altlinux Sisyphus/x86_64-i586 classic
#rpm [alt] ftp://mirror.yandex.ru/altlinux Sisyphus/noarch classic
#rpm [alt] http://mirror.yandex.ru/altlinux Sisyphus/x86_64 classic
#rpm [alt] http://mirror.yandex.ru/altlinux Sisyphus/x86_64-i586 classic
#rpm [alt] http://mirror.yandex.ru/altlinux Sisyphus/noarch classic
#rpm [alt] rsync://mirror.yandex.ru/altlinux Sisyphus/x86_64 classic
#rpm [alt] rsync://mirror.yandex.ru/altlinux Sisyphus/x86_64-i586 classic
#rpm [alt] rsync://mirror.yandex.ru/altlinux Sisyphus/noarch classic

View File

@ -2,9 +2,12 @@ use std::path::PathBuf;
use anyhow::{bail, format_err, Error};
use proxmox_apt::repositories::{
check_repositories, get_current_release_codename, standard_repositories, DebianCodename,
};
use proxmox_apt::repositories::{check_repositories, standard_repositories};
#[cfg(feature = "alt-linux")]
use proxmox_apt::repositories::{get_current_release_branch_id, ALTBranchID};
#[cfg(not(feature = "alt-linux"))]
use proxmox_apt::repositories::{get_current_release_codename, DebianCodename};
use proxmox_apt::repositories::{
APTRepositoryFileImpl, APTRepositoryImpl, APTStandardRepositoryImpl,
};
@ -31,7 +34,10 @@ fn test_parse_write() -> Result<(), Error> {
}
fn test_parse_write_dir(read_dir: &str) -> Result<(), Error> {
let test_dir = std::env::current_dir()?.join("tests");
#[cfg(not(feature = "alt-linux"))]
let test_dir = std::env::current_dir()?.join("tests").join("Debian");
#[cfg(feature = "alt-linux")]
let test_dir = std::env::current_dir()?.join("tests").join("ALT");
let tmp_dir = PathBuf::from(env!("CARGO_TARGET_TMPDIR").to_string());
let read_dir = test_dir.join(read_dir);
let write_dir = tmp_dir.join("sources.list.d.actual");
@ -98,8 +104,9 @@ fn test_parse_write_dir(read_dir: &str) -> Result<(), Error> {
}
#[test]
#[cfg(not(feature = "alt-linux"))]
fn test_digest() -> Result<(), Error> {
let test_dir = std::env::current_dir()?.join("tests");
let test_dir = std::env::current_dir()?.join("tests").join("Debian");
let tmp_dir = PathBuf::from(env!("CARGO_TARGET_TMPDIR").to_string());
let read_dir = test_dir.join("sources.list.d");
let write_dir = tmp_dir.join("sources.list.d.digest");
@ -145,13 +152,63 @@ fn test_digest() -> Result<(), Error> {
}
#[test]
#[cfg(feature = "alt-linux")]
fn test_digest() -> Result<(), Error> {
let test_dir = std::env::current_dir()?.join("tests").join("ALT");
let tmp_dir = PathBuf::from(env!("CARGO_TARGET_TMPDIR").to_string());
let read_dir = test_dir.join("sources.list.d");
let write_dir = tmp_dir.join("sources.list.d.digest");
create_clean_directory(&write_dir)?;
let path = read_dir.join("alt.list");
let mut file = APTRepositoryFile::new(&path)?.unwrap();
file.parse()?;
let new_path = write_dir.join(path.file_name().unwrap());
file.path = Some(new_path.clone().into_os_string().into_string().unwrap());
let old_digest = file.digest.unwrap();
// file does not exist yet...
assert!(file.read_with_digest().is_err());
assert!(file.write().is_err());
// ...but it should work if there's no digest
file.digest = None;
file.write()?;
// overwrite with old contents...
std::fs::copy(path, new_path)?;
// modify the repo
let repo = file.repositories.first_mut().unwrap();
repo.enabled = !repo.enabled;
// ...then it should work
file.digest = Some(old_digest);
file.write()?;
// expect a different digest, because the repo was modified
let (_, new_digest) = file.read_with_digest()?;
assert_ne!(old_digest, *new_digest);
assert!(file.write().is_err());
Ok(())
}
#[test]
#[cfg(not(feature = "alt-linux"))]
fn test_empty_write() -> Result<(), Error> {
let write_dir = PathBuf::from(
std::option_env!("CARGO_TARGET_TMPDIR").expect("no test target dir set by cargo!"),
)
.join("tests")
.join("Debian")
.join("sources.list.d.remove");
let test_dir = std::env::current_dir()?.join("tests");
let test_dir = std::env::current_dir()?.join("tests").join("Debian");
let read_dir = test_dir.join("sources.list.d");
create_clean_directory(&write_dir)?;
@ -180,8 +237,41 @@ fn test_empty_write() -> Result<(), Error> {
}
#[test]
#[cfg(feature = "alt-linux")]
fn test_empty_write() -> Result<(), Error> {
let test_dir = std::env::current_dir()?.join("tests").join("ALT");
let read_dir = test_dir.join("sources.list.d");
let write_dir = test_dir.join("sources.list.d.remove");
create_clean_directory(&write_dir)?;
let path = read_dir.join("alt.list");
let mut file = APTRepositoryFile::new(&path)?.unwrap();
file.parse()?;
let new_path = write_dir.join(path.file_name().unwrap());
file.path = Some(new_path.into_os_string().into_string().unwrap());
file.digest = None;
file.write()?;
assert!(file.exists());
file.repositories.clear();
file.write()?;
assert!(!file.exists());
Ok(())
}
#[test]
#[cfg(not(feature = "alt-linux"))]
fn test_check_repositories() -> Result<(), Error> {
let test_dir = std::env::current_dir()?.join("tests");
let test_dir = std::env::current_dir()?.join("tests").join("Debian");
let read_dir = test_dir.join("sources.list.d");
let apt_lists_dir: PathBuf = test_dir.join("lists");
@ -214,7 +304,10 @@ fn test_check_repositories() -> Result<(), Error> {
}
expected_infos.sort();
#[cfg(not(feature = "alt-linux"))]
let mut infos = check_repositories(&[file], DebianCodename::Bullseye, &apt_lists_dir);
#[cfg(feature = "alt-linux")]
let mut infos = check_repositories(&[file], ALTBranchID::Sisyphus);
infos.sort();
assert_eq!(infos, expected_infos);
@ -280,7 +373,10 @@ fn test_check_repositories() -> Result<(), Error> {
}
expected_infos.sort();
#[cfg(not(feature = "alt-linux"))]
let mut infos = check_repositories(&[file], DebianCodename::Bullseye, &apt_lists_dir);
#[cfg(feature = "alt-linux")]
let mut infos = check_repositories(&[file], ALTBranchID::Sisyphus);
infos.sort();
assert_eq!(infos, expected_infos);
@ -312,7 +408,10 @@ fn test_check_repositories() -> Result<(), Error> {
}
expected_infos.sort();
#[cfg(not(feature = "alt-linux"))]
let mut infos = check_repositories(&[file], DebianCodename::Bullseye, &apt_lists_dir);
#[cfg(feature = "alt-linux")]
let mut infos = check_repositories(&[file], ALTBranchID::Sisyphus);
infos.sort();
assert_eq!(infos, expected_infos);
@ -320,8 +419,175 @@ fn test_check_repositories() -> Result<(), Error> {
}
#[test]
#[cfg(feature = "alt-linux")]
fn test_check_repositories() -> Result<(), Error> {
let test_dir = std::env::current_dir()?.join("tests").join("ALT");
let read_dir = test_dir.join("sources.list.d");
let apt_lists_dir: PathBuf = test_dir.join("lists");
let sources_list = read_dir.join("sources.list");
let mut file = APTRepositoryFile::new(&sources_list)?.unwrap();
file.parse()?;
let infos = check_repositories(&[file], ALTBranchID::Sisyphus, &apt_lists_dir);
assert!(infos.is_empty());
let alt_list = read_dir.join("alt.list");
let mut file = APTRepositoryFile::new(&alt_list)?.unwrap();
file.parse()?;
let path_string = alt_list.into_os_string().into_string().unwrap();
let origins = ["ALT Linux Team", "ALT Linux Team", "ALT Linux Team"];
let mut expected_infos = vec![];
for (n, origin) in origins.into_iter().enumerate() {
expected_infos.push(APTRepositoryInfo {
path: path_string.clone(),
index: n + 3,
property: None,
kind: "origin".to_string(),
message: origin.to_string(),
});
}
expected_infos.sort();
let mut infos = check_repositories(&[file], ALTBranchID::Sisyphus, &apt_lists_dir);
infos.sort();
assert_eq!(infos[3..=5], expected_infos);
let dcby_list = read_dir.join("dcby.list");
let mut file = APTRepositoryFile::new(&dcby_list)?.unwrap();
file.parse()?;
let path_string = dcby_list.into_os_string().into_string().unwrap();
let origins = ["ALT Linux Team", "ALT Linux Team", "ALT Linux Team"];
let mut expected_infos = vec![];
for (n, origin) in origins.into_iter().enumerate() {
expected_infos.push(APTRepositoryInfo {
path: path_string.clone(),
index: n + 3,
property: None,
kind: "origin".to_string(),
message: origin.to_string(),
});
}
expected_infos.sort();
let mut infos = check_repositories(&[file], ALTBranchID::Sisyphus, &apt_lists_dir);
infos.sort();
assert_eq!(infos[3..=5], expected_infos);
let heanet_list = read_dir.join("heanet.list");
let mut file = APTRepositoryFile::new(&heanet_list)?.unwrap();
file.parse()?;
let path_string = heanet_list.into_os_string().into_string().unwrap();
let origins = ["ALT Linux Team", "ALT Linux Team", "ALT Linux Team"];
let mut expected_infos = vec![];
for (n, origin) in origins.into_iter().enumerate() {
expected_infos.push(APTRepositoryInfo {
path: path_string.clone(),
index: n + 3,
property: None,
kind: "origin".to_string(),
message: origin.to_string(),
});
}
expected_infos.sort();
let mut infos = check_repositories(&[file], ALTBranchID::Sisyphus, &apt_lists_dir);
infos.sort();
assert_eq!(infos[3..=5], expected_infos);
let ipsl_list = read_dir.join("ipsl.list");
let mut file = APTRepositoryFile::new(&ipsl_list)?.unwrap();
file.parse()?;
let path_string = ipsl_list.into_os_string().into_string().unwrap();
let origins = ["ALT Linux Team", "ALT Linux Team", "ALT Linux Team"];
let mut expected_infos = vec![];
for (n, origin) in origins.into_iter().enumerate() {
expected_infos.push(APTRepositoryInfo {
path: path_string.clone(),
index: n + 3,
property: None,
kind: "origin".to_string(),
message: origin.to_string(),
});
}
expected_infos.sort();
let mut infos = check_repositories(&[file], ALTBranchID::Sisyphus, &apt_lists_dir);
infos.sort();
assert_eq!(infos[3..=5], expected_infos);
let msu_list = read_dir.join("msu.list");
let mut file = APTRepositoryFile::new(&msu_list)?.unwrap();
file.parse()?;
let path_string = msu_list.into_os_string().into_string().unwrap();
let origins = ["ALT Linux Team", "ALT Linux Team", "ALT Linux Team"];
let mut expected_infos = vec![];
for (n, origin) in origins.into_iter().enumerate() {
expected_infos.push(APTRepositoryInfo {
path: path_string.clone(),
index: n,
property: None,
kind: "origin".to_string(),
message: origin.to_string(),
});
}
expected_infos.sort();
let mut infos = check_repositories(&[file], ALTBranchID::Sisyphus, &apt_lists_dir);
infos.sort();
assert_eq!(infos[0..=2], expected_infos);
let yandex_list = read_dir.join("yandex.list");
let mut file = APTRepositoryFile::new(&yandex_list)?.unwrap();
file.parse()?;
let path_string = yandex_list.into_os_string().into_string().unwrap();
let origins = ["ALT Linux Team", "ALT Linux Team", "ALT Linux Team"];
let mut expected_infos = vec![];
for (n, origin) in origins.into_iter().enumerate() {
expected_infos.push(APTRepositoryInfo {
path: path_string.clone(),
index: n + 3,
property: None,
kind: "origin".to_string(),
message: origin.to_string(),
});
}
expected_infos.sort();
let mut infos = check_repositories(&[file], ALTBranchID::Sisyphus, &apt_lists_dir);
infos.sort();
assert_eq!(infos[3..=5], expected_infos);
Ok(())
}
#[test]
#[cfg(not(feature = "alt-linux"))]
fn test_get_cached_origin() -> Result<(), Error> {
let test_dir = std::env::current_dir()?.join("tests");
let test_dir = std::env::current_dir()?.join("tests").join("Debian");
let read_dir = test_dir.join("sources.list.d");
let apt_lists_dir: PathBuf = test_dir.clone().join("lists");
@ -348,8 +614,41 @@ fn test_get_cached_origin() -> Result<(), Error> {
}
#[test]
#[cfg(feature = "alt-linux")]
fn test_get_cached_origin() -> Result<(), Error> {
let test_dir = std::env::current_dir()?.join("tests").join("ALT");
let read_dir = test_dir.join("sources.list.d");
let apt_lists_dir: PathBuf = test_dir.clone().join("lists");
let alt_list = read_dir.join("alt.list");
let mut file = APTRepositoryFile::new(&alt_list)?.unwrap();
file.parse()?;
let origins = [
None, // no cache file exists
None, // no cache file exists
None, // no cache file exists
None, // no cache file exists
None, // no cache file exists
None, // no cache file exists
None, // no cache file exists
None, // no cache file exists
None, // no cache file exists
];
assert_eq!(file.repositories.len(), origins.len());
for (n, repo) in file.repositories.iter().enumerate() {
assert_eq!(repo.get_cached_origin(&apt_lists_dir)?, origins[n]);
}
Ok(())
}
#[test]
#[cfg(not(feature = "alt-linux"))]
fn test_standard_repositories() -> Result<(), Error> {
let test_dir = std::env::current_dir()?.join("tests");
let test_dir = std::env::current_dir()?.join("tests").join("Debian");
let read_dir = test_dir.join("sources.list.d");
let mut expected = vec![
@ -461,6 +760,46 @@ fn test_standard_repositories() -> Result<(), Error> {
}
#[test]
#[cfg(feature = "alt-linux")]
fn test_standard_repositories() -> Result<(), Error> {
let test_dir = std::env::current_dir()?.join("tests").join("ALT");
let read_dir = test_dir.join("sources.list.d");
let mut expected = vec![
APTStandardRepository::from_handle(APTRepositoryHandle::CheckInstall),
APTStandardRepository::from_handle(APTRepositoryHandle::Classic),
APTStandardRepository::from_handle(APTRepositoryHandle::DebugInfo),
APTStandardRepository::from_handle(APTRepositoryHandle::GostCrypto),
];
let alt_list = read_dir.join("alt.list");
let mut file = APTRepositoryFile::new(&alt_list)?.unwrap();
file.parse()?;
expected[1].status = Some(true);
let std_repos = standard_repositories(&[file], "pve", ALTBranchID::Sisyphus);
assert_eq!(std_repos, &expected[0..=3]);
let yandex_list = read_dir.join("yandex.list");
let mut file = APTRepositoryFile::new(&yandex_list)?.unwrap();
file.parse()?;
expected[0].status = None;
expected[1].status = None;
expected[2].status = None;
expected[3].status = None;
let std_repos = standard_repositories(&[file], "pve", ALTBranchID::Sisyphus);
assert_eq!(std_repos, expected);
Ok(())
}
#[test]
#[cfg(not(feature = "alt-linux"))]
fn test_get_current_release_codename() -> Result<(), Error> {
let codename = get_current_release_codename()?;
@ -468,3 +807,13 @@ fn test_get_current_release_codename() -> Result<(), Error> {
Ok(())
}
#[test]
#[cfg(feature = "alt-linux")]
fn test_get_current_release_branch_id() -> Result<(), Error> {
let branch = get_current_release_branch_id()?;
assert!(branch == ALTBranchID::Sisyphus);
Ok(())
}

View File

@ -208,7 +208,7 @@ pub fn make_tmp_dir<P: AsRef<Path>>(
// Push NULL byte so that we have a proper NULL-terminated string
template.push(0);
let returned_buffer = unsafe { libc::mkdtemp(template.as_mut_ptr() as *mut i8) };
let returned_buffer = unsafe { libc::mkdtemp(template.as_mut_ptr() as *mut libc::c_char) };
// Check errno immediately, so that nothing else can overwrite it.
let err = std::io::Error::last_os_error();