all lists on lists.proxmox.com
 help / color / mirror / Atom feed
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
To: pbs-devel@lists.proxmox.com
Subject: [pbs-devel] [PATCH proxmox 4/6] apt: use api types from apt-api-types crate
Date: Tue,  9 Jul 2024 08:18:30 +0200	[thread overview]
Message-ID: <20240709061832.52121-4-w.bumiller@proxmox.com> (raw)
In-Reply-To: <20240709061832.52121-1-w.bumiller@proxmox.com>

From: Dietmar Maurer <dietmar@proxmox.com>

Signed-off-by: Dietmar Maurer <dietmar@proxmox.com>
---
 proxmox-apt/Cargo.toml                        |   5 +-
 proxmox-apt/debian/control                    |  10 +-
 proxmox-apt/src/repositories/file.rs          | 119 ++---------
 .../src/repositories/file/list_parser.rs      |   2 +-
 .../src/repositories/file/sources_parser.rs   |   2 +-
 proxmox-apt/src/repositories/mod.rs           |  37 ++--
 proxmox-apt/src/repositories/repository.rs    | 187 +-----------------
 proxmox-apt/src/repositories/standard.rs      | 107 +---------
 proxmox-apt/tests/repositories.rs             |  24 +--
 9 files changed, 65 insertions(+), 428 deletions(-)

diff --git a/proxmox-apt/Cargo.toml b/proxmox-apt/Cargo.toml
index 34573543..bbd4ff89 100644
--- a/proxmox-apt/Cargo.toml
+++ b/proxmox-apt/Cargo.toml
@@ -8,7 +8,7 @@ license.workspace = true
 repository.workspace = true
 homepage.workspace = true
 
-exclude = [ "debian" ]
+exclude = ["debian"]
 
 [dependencies]
 anyhow.workspace = true
@@ -20,4 +20,5 @@ serde_json.workspace = true
 
 rfc822-like = "0.2.1"
 
-proxmox-schema = { workspace = true, features = [ "api-macro" ] }
+proxmox-apt-api-types.workspace = true
+proxmox-config-digest = { workspace = true, features = ["openssl"] }
diff --git a/proxmox-apt/debian/control b/proxmox-apt/debian/control
index c3248212..347631e6 100644
--- a/proxmox-apt/debian/control
+++ b/proxmox-apt/debian/control
@@ -10,8 +10,9 @@ Build-Depends: debhelper (>= 12),
  librust-hex-0.4+default-dev <!nocheck>,
  librust-once-cell-1+default-dev (>= 1.3.1-~~) <!nocheck>,
  librust-openssl-0.10+default-dev <!nocheck>,
- librust-proxmox-schema-3+api-macro-dev (>= 3.1.1-~~) <!nocheck>,
- librust-proxmox-schema-3+default-dev (>= 3.1.1-~~) <!nocheck>,
+ librust-proxmox-apt-api-types-1+default-dev <!nocheck>,
+ librust-proxmox-config-digest-0.1+default-dev <!nocheck>,
+ librust-proxmox-config-digest-0.1+openssl-dev <!nocheck>,
  librust-rfc822-like-0.2+default-dev (>= 0.2.1-~~) <!nocheck>,
  librust-serde-1+default-dev <!nocheck>,
  librust-serde-1+derive-dev <!nocheck>,
@@ -33,8 +34,9 @@ Depends:
  librust-hex-0.4+default-dev,
  librust-once-cell-1+default-dev (>= 1.3.1-~~),
  librust-openssl-0.10+default-dev,
- librust-proxmox-schema-3+api-macro-dev (>= 3.1.1-~~),
- librust-proxmox-schema-3+default-dev (>= 3.1.1-~~),
+ librust-proxmox-apt-api-types-1+default-dev,
+ librust-proxmox-config-digest-0.1+default-dev,
+ librust-proxmox-config-digest-0.1+openssl-dev,
  librust-rfc822-like-0.2+default-dev (>= 0.2.1-~~),
  librust-serde-1+default-dev,
  librust-serde-1+derive-dev,
diff --git a/proxmox-apt/src/repositories/file.rs b/proxmox-apt/src/repositories/file.rs
index 086abf49..21f612ef 100644
--- a/proxmox-apt/src/repositories/file.rs
+++ b/proxmox-apt/src/repositories/file.rs
@@ -1,123 +1,29 @@
-use std::fmt::Display;
 use std::path::{Path, PathBuf};
 
 use anyhow::{format_err, Error};
-use serde::{Deserialize, Serialize};
 
 use crate::repositories::release::DebianCodename;
-use crate::repositories::repository::{
-    APTRepository, APTRepositoryFileType, APTRepositoryPackageType,
+use proxmox_apt_api_types::{
+    APTRepository, APTRepositoryFile, APTRepositoryFileError, APTRepositoryFileType,
+    APTRepositoryInfo, APTRepositoryPackageType,
 };
 
 use crate::repositories::repository::APTRepositoryImpl;
 
-use proxmox_schema::api;
-
 mod list_parser;
 use list_parser::APTListFileParser;
 
 mod sources_parser;
 use sources_parser::APTSourcesFileParser;
 
+use proxmox_config_digest::ConfigDigest;
+
 trait APTRepositoryParser {
     /// Parse all repositories including the disabled ones and push them onto
     /// the provided vector.
     fn parse_repositories(&mut self) -> Result<Vec<APTRepository>, Error>;
 }
 
-#[api(
-    properties: {
-        "file-type": {
-            type: APTRepositoryFileType,
-        },
-        repositories: {
-            description: "List of APT repositories.",
-            type: Array,
-            items: {
-                type: APTRepository,
-            },
-        },
-        digest: {
-            description: "Digest for the content of the file.",
-            optional: true,
-            type: Array,
-            items: {
-                description: "Digest byte.",
-                type: u8,
-            },
-        },
-    },
-)]
-#[derive(Debug, Clone, Serialize, Deserialize)]
-#[serde(rename_all = "kebab-case")]
-/// Represents an abstract APT repository file.
-pub struct APTRepositoryFile {
-    /// The path to the file. If None, `contents` must be set directly.
-    #[serde(skip_serializing_if = "Option::is_none")]
-    pub path: Option<String>,
-
-    /// The type of the file.
-    pub file_type: APTRepositoryFileType,
-
-    /// List of repositories in the file.
-    pub repositories: Vec<APTRepository>,
-
-    /// The file content, if already parsed.
-    #[serde(skip_serializing_if = "Option::is_none")]
-    pub content: Option<String>,
-
-    /// Digest of the original contents.
-    #[serde(skip_serializing_if = "Option::is_none")]
-    pub digest: Option<[u8; 32]>,
-}
-
-#[api]
-#[derive(Debug, Clone, Serialize, Deserialize)]
-#[serde(rename_all = "kebab-case")]
-/// Error type for problems with APT repository files.
-pub struct APTRepositoryFileError {
-    /// The path to the problematic file.
-    pub path: String,
-
-    /// The error message.
-    pub error: String,
-}
-
-impl Display for APTRepositoryFileError {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        write!(f, "proxmox-apt error for '{}' - {}", self.path, self.error)
-    }
-}
-
-impl std::error::Error for APTRepositoryFileError {
-    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
-        None
-    }
-}
-
-#[api]
-#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
-#[serde(rename_all = "kebab-case")]
-/// Additional information for a repository.
-pub struct APTRepositoryInfo {
-    /// Path to the defining file.
-    #[serde(default, skip_serializing_if = "String::is_empty")]
-    pub path: String,
-
-    /// Index of the associated respository within the file (starting from 0).
-    pub index: usize,
-
-    /// The property from which the info originates (e.g. "Suites")
-    #[serde(skip_serializing_if = "Option::is_none")]
-    pub property: Option<String>,
-
-    /// Info kind (e.g. "warning")
-    pub kind: String,
-
-    /// Info message
-    pub message: String,
-}
-
 pub trait APTRepositoryFileImpl {
     /// Creates a new `APTRepositoryFile` without parsing.
     ///
@@ -131,7 +37,7 @@ pub trait APTRepositoryFileImpl {
     /// Check if the file exists.
     fn exists(&self) -> bool;
 
-    fn read_with_digest(&self) -> Result<(Vec<u8>, [u8; 32]), APTRepositoryFileError>;
+    fn read_with_digest(&self) -> Result<(Vec<u8>, ConfigDigest), APTRepositoryFileError>;
 
     /// Create an `APTRepositoryFileError`.
     fn err(&self, error: Error) -> APTRepositoryFileError;
@@ -213,7 +119,8 @@ impl APTRepositoryFileImpl for APTRepositoryFile {
             return Ok(None);
         }
 
-        let file_type = APTRepositoryFileType::try_from(&extension[..])
+        let file_type = extension[..]
+            .parse()
             .map_err(|_| new_err("invalid extension"))?;
 
         if !file_name
@@ -250,15 +157,15 @@ impl APTRepositoryFileImpl for APTRepositoryFile {
         }
     }
 
-    fn read_with_digest(&self) -> Result<(Vec<u8>, [u8; 32]), APTRepositoryFileError> {
+    fn read_with_digest(&self) -> Result<(Vec<u8>, ConfigDigest), APTRepositoryFileError> {
         if let Some(path) = &self.path {
             let content = std::fs::read(path).map_err(|err| self.err(format_err!("{}", err)))?;
-            let digest = openssl::sha::sha256(&content);
+            let digest = ConfigDigest::from_slice(&content);
 
             Ok((content, digest))
         } else if let Some(ref content) = self.content {
             let content = content.as_bytes();
-            let digest = openssl::sha::sha256(content);
+            let digest = ConfigDigest::from_slice(content);
             Ok((content.to_vec(), digest))
         } else {
             Err(self.err(format_err!(
@@ -308,13 +215,13 @@ impl APTRepositoryFileImpl for APTRepositoryFile {
             }
         };
 
-        if let Some(digest) = self.digest {
+        if let Some(digest) = &self.digest {
             if !self.exists() {
                 return Err(self.err(format_err!("digest specified, but file does not exist")));
             }
 
             let (_, current_digest) = self.read_with_digest()?;
-            if digest != current_digest {
+            if digest != &current_digest {
                 return Err(self.err(format_err!("digest mismatch")));
             }
         }
diff --git a/proxmox-apt/src/repositories/file/list_parser.rs b/proxmox-apt/src/repositories/file/list_parser.rs
index 93bbcc12..8681509a 100644
--- a/proxmox-apt/src/repositories/file/list_parser.rs
+++ b/proxmox-apt/src/repositories/file/list_parser.rs
@@ -184,7 +184,7 @@ impl<R: BufRead> APTListFileParser<R> {
         // e.g. quoted "deb" is not accepted by APT, so no need for quote word parsing here
         line = match line.split_once(|c| char::is_ascii_whitespace(&c)) {
             Some((package_type, rest)) => {
-                repo.types.push(package_type.try_into()?);
+                repo.types.push(package_type.parse()?);
                 rest
             }
             None => return Ok(None), // empty line
diff --git a/proxmox-apt/src/repositories/file/sources_parser.rs b/proxmox-apt/src/repositories/file/sources_parser.rs
index 213db9d6..017162bb 100644
--- a/proxmox-apt/src/repositories/file/sources_parser.rs
+++ b/proxmox-apt/src/repositories/file/sources_parser.rs
@@ -108,7 +108,7 @@ impl<R: BufRead> APTSourcesFileParser<R> {
                         }
                         let mut types = Vec::<APTRepositoryPackageType>::new();
                         for package_type in values {
-                            types.push((&package_type[..]).try_into()?);
+                            types.push((&package_type[..]).parse()?);
                         }
                         repo.types = types;
                     }
diff --git a/proxmox-apt/src/repositories/mod.rs b/proxmox-apt/src/repositories/mod.rs
index 014f1820..7768a47a 100644
--- a/proxmox-apt/src/repositories/mod.rs
+++ b/proxmox-apt/src/repositories/mod.rs
@@ -4,21 +4,22 @@ use std::path::PathBuf;
 use anyhow::{bail, Error};
 
 mod repository;
-pub use repository::APTRepositoryImpl;
-pub use repository::{
-    APTRepository, APTRepositoryFileType, APTRepositoryOption, APTRepositoryPackageType,
+use proxmox_apt_api_types::{
+    APTRepository, APTRepositoryFile, APTRepositoryFileError, APTRepositoryFileType,
+    APTRepositoryHandle, APTRepositoryInfo, APTRepositoryOption, APTRepositoryPackageType,
+    APTStandardRepository,
 };
+use proxmox_config_digest::ConfigDigest;
+pub use repository::APTRepositoryImpl;
 
 mod file;
 pub use file::APTRepositoryFileImpl;
-pub use file::{APTRepositoryFile, APTRepositoryFileError, APTRepositoryInfo};
 
 mod release;
 pub use release::{get_current_release_codename, DebianCodename};
 
 mod standard;
-pub use standard::APTRepositoryHandleImpl;
-pub use standard::{APTRepositoryHandle, APTStandardRepository};
+pub use standard::{APTRepositoryHandleImpl, APTStandardRepositoryImpl};
 
 const APT_SOURCES_LIST_FILENAME: &str = "/etc/apt/sources.list";
 const APT_SOURCES_LIST_DIRECTORY: &str = "/etc/apt/sources.list.d/";
@@ -28,7 +29,7 @@ const APT_SOURCES_LIST_DIRECTORY: &str = "/etc/apt/sources.list.d/";
 /// The digest is invariant with respect to file order.
 ///
 /// Files without a digest are ignored.
-fn common_digest(files: &[APTRepositoryFile]) -> [u8; 32] {
+fn common_digest(files: &[APTRepositoryFile]) -> ConfigDigest {
     let mut digests = BTreeMap::new();
 
     for file in files.iter() {
@@ -43,7 +44,7 @@ fn common_digest(files: &[APTRepositoryFile]) -> [u8; 32] {
         }
     }
 
-    openssl::sha::sha256(&common_raw[..])
+    ConfigDigest::from_slice(&common_raw[..])
 }
 
 /// Provides additional information about the repositories.
@@ -86,22 +87,22 @@ pub fn standard_repositories(
     suite: DebianCodename,
 ) -> Vec<APTStandardRepository> {
     let mut result = vec![
-        APTStandardRepository::from(APTRepositoryHandle::Enterprise),
-        APTStandardRepository::from(APTRepositoryHandle::NoSubscription),
-        APTStandardRepository::from(APTRepositoryHandle::Test),
+        APTStandardRepository::from_handle(APTRepositoryHandle::Enterprise),
+        APTStandardRepository::from_handle(APTRepositoryHandle::NoSubscription),
+        APTStandardRepository::from_handle(APTRepositoryHandle::Test),
     ];
 
     if product == "pve" {
         result.append(&mut vec![
-            APTStandardRepository::from(APTRepositoryHandle::CephQuincyEnterprise),
-            APTStandardRepository::from(APTRepositoryHandle::CephQuincyNoSubscription),
-            APTStandardRepository::from(APTRepositoryHandle::CephQuincyTest),
+            APTStandardRepository::from_handle(APTRepositoryHandle::CephQuincyEnterprise),
+            APTStandardRepository::from_handle(APTRepositoryHandle::CephQuincyNoSubscription),
+            APTStandardRepository::from_handle(APTRepositoryHandle::CephQuincyTest),
         ]);
         if suite == DebianCodename::Bookworm {
             result.append(&mut vec![
-                APTStandardRepository::from(APTRepositoryHandle::CephReefEnterprise),
-                APTStandardRepository::from(APTRepositoryHandle::CephReefNoSubscription),
-                APTStandardRepository::from(APTRepositoryHandle::CephReefTest),
+                APTStandardRepository::from_handle(APTRepositoryHandle::CephReefEnterprise),
+                APTStandardRepository::from_handle(APTRepositoryHandle::CephReefNoSubscription),
+                APTStandardRepository::from_handle(APTRepositoryHandle::CephReefTest),
             ]);
         }
     }
@@ -128,7 +129,7 @@ pub fn standard_repositories(
 pub type Repositories = (
     Vec<APTRepositoryFile>,
     Vec<APTRepositoryFileError>,
-    [u8; 32],
+    ConfigDigest,
 );
 
 /// Returns all APT repositories configured in `/etc/apt/sources.list` and
diff --git a/proxmox-apt/src/repositories/repository.rs b/proxmox-apt/src/repositories/repository.rs
index a07db7cb..596c6385 100644
--- a/proxmox-apt/src/repositories/repository.rs
+++ b/proxmox-apt/src/repositories/repository.rs
@@ -1,193 +1,12 @@
-use std::fmt::Display;
 use std::io::{BufRead, BufReader, Write};
 use std::path::PathBuf;
 
 use anyhow::{bail, format_err, Error};
-use serde::{Deserialize, Serialize};
 
-use proxmox_schema::api;
-
-use crate::repositories::standard::APTRepositoryHandle;
 use crate::repositories::standard::APTRepositoryHandleImpl;
-
-#[api]
-#[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq, Eq)]
-#[serde(rename_all = "lowercase")]
-pub enum APTRepositoryFileType {
-    /// One-line-style format
-    List,
-    /// DEB822-style format
-    Sources,
-}
-
-impl TryFrom<&str> for APTRepositoryFileType {
-    type Error = Error;
-
-    fn try_from(file_type: &str) -> Result<Self, Error> {
-        match file_type {
-            "list" => Ok(APTRepositoryFileType::List),
-            "sources" => Ok(APTRepositoryFileType::Sources),
-            _ => bail!("invalid file type '{file_type}'"),
-        }
-    }
-}
-
-impl Display for APTRepositoryFileType {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        match self {
-            APTRepositoryFileType::List => write!(f, "list"),
-            APTRepositoryFileType::Sources => write!(f, "sources"),
-        }
-    }
-}
-
-#[api]
-#[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq, Eq)]
-#[serde(rename_all = "kebab-case")]
-pub enum APTRepositoryPackageType {
-    /// Debian package
-    Deb,
-    /// Debian source package
-    DebSrc,
-}
-
-impl TryFrom<&str> for APTRepositoryPackageType {
-    type Error = Error;
-
-    fn try_from(package_type: &str) -> Result<Self, Error> {
-        match package_type {
-            "deb" => Ok(APTRepositoryPackageType::Deb),
-            "deb-src" => Ok(APTRepositoryPackageType::DebSrc),
-            _ => bail!("invalid package type '{package_type}'"),
-        }
-    }
-}
-
-impl Display for APTRepositoryPackageType {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        match self {
-            APTRepositoryPackageType::Deb => write!(f, "deb"),
-            APTRepositoryPackageType::DebSrc => write!(f, "deb-src"),
-        }
-    }
-}
-
-#[api(
-    properties: {
-        Key: {
-            description: "Option key.",
-            type: String,
-        },
-        Values: {
-            description: "Option values.",
-            type: Array,
-            items: {
-                description: "Value.",
-                type: String,
-            },
-        },
-    },
-)]
-#[derive(Debug, Clone, Serialize, Deserialize)]
-#[serde(rename_all = "PascalCase")] // for consistency
-/// Additional options for an APT repository.
-/// Used for both single- and mutli-value options.
-pub struct APTRepositoryOption {
-    /// Option key.
-    pub key: String,
-    /// Option value(s).
-    pub values: Vec<String>,
-}
-
-#[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: {
-                type: APTRepositoryOption,
-            },
-        },
-        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)]
-#[serde(rename_all = "PascalCase")]
-/// Describes an APT repository.
-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<APTRepositoryOption>,
-
-    /// 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,
-}
+use proxmox_apt_api_types::{
+    APTRepository, APTRepositoryFileType, APTRepositoryHandle, APTRepositoryOption,
+};
 
 pub trait APTRepositoryImpl {
     /// Crates an empty repository.
diff --git a/proxmox-apt/src/repositories/standard.rs b/proxmox-apt/src/repositories/standard.rs
index 7858fac4..64fdea2a 100644
--- a/proxmox-apt/src/repositories/standard.rs
+++ b/proxmox-apt/src/repositories/standard.rs
@@ -1,70 +1,14 @@
-use std::fmt::Display;
-
-use anyhow::{bail, Error};
-use serde::{Deserialize, Serialize};
-
-use crate::repositories::repository::{
-    APTRepository, APTRepositoryFileType, APTRepositoryPackageType,
+use proxmox_apt_api_types::{
+    APTRepository, APTRepositoryFileType, APTRepositoryHandle, APTRepositoryPackageType,
+    APTStandardRepository,
 };
 
-use proxmox_schema::api;
-
-#[api(
-    properties: {
-        handle: {
-            description: "Handle referencing a standard repository.",
-            type: String,
-        },
-    },
-)]
-#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
-#[serde(rename_all = "kebab-case")]
-/// Reference to a standard repository and configuration status.
-pub struct APTStandardRepository {
-    /// Handle referencing a standard repository.
-    pub handle: APTRepositoryHandle,
-
-    /// Configuration status of the associated repository, where `None` means
-    /// not configured, and `Some(bool)` indicates enabled or disabled.
-    #[serde(skip_serializing_if = "Option::is_none")]
-    pub status: Option<bool>,
-
-    /// Display name of the repository.
-    pub name: String,
-
-    /// Description of the repository.
-    pub description: String,
-}
-
-#[api]
-#[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq, Eq)]
-#[serde(rename_all = "kebab-case")]
-/// Handles for Proxmox repositories.
-pub enum APTRepositoryHandle {
-    /// The enterprise repository for production use.
-    Enterprise,
-    /// The repository that can be used without subscription.
-    NoSubscription,
-    /// The test repository.
-    Test,
-    /// Ceph Quincy enterprise repository.
-    CephQuincyEnterprise,
-    /// Ceph Quincy no-subscription repository.
-    CephQuincyNoSubscription,
-    /// Ceph Quincy test repository.
-    CephQuincyTest,
-    // TODO: Add separate enum for ceph releases and use something like
-    // `CephTest(CephReleaseCodename),` once the API macro supports it.
-    /// Ceph Reef enterprise repository.
-    CephReefEnterprise,
-    /// Ceph Reef no-subscription repository.
-    CephReefNoSubscription,
-    /// Ceph Reef test repository.
-    CephReefTest,
+pub trait APTStandardRepositoryImpl {
+    fn from_handle(handle: APTRepositoryHandle) -> APTStandardRepository;
 }
 
-impl From<APTRepositoryHandle> for APTStandardRepository {
-    fn from(handle: APTRepositoryHandle) -> Self {
+impl APTStandardRepositoryImpl for APTStandardRepository {
+    fn from_handle(handle: APTRepositoryHandle) -> APTStandardRepository {
         APTStandardRepository {
             handle,
             status: None,
@@ -74,43 +18,6 @@ impl From<APTRepositoryHandle> for APTStandardRepository {
     }
 }
 
-impl TryFrom<&str> for APTRepositoryHandle {
-    type Error = Error;
-
-    fn try_from(string: &str) -> Result<Self, Error> {
-        match string {
-            "enterprise" => Ok(APTRepositoryHandle::Enterprise),
-            "no-subscription" => Ok(APTRepositoryHandle::NoSubscription),
-            "test" => Ok(APTRepositoryHandle::Test),
-            "ceph-quincy-enterprise" => Ok(APTRepositoryHandle::CephQuincyEnterprise),
-            "ceph-quincy-no-subscription" => Ok(APTRepositoryHandle::CephQuincyNoSubscription),
-            "ceph-quincy-test" => Ok(APTRepositoryHandle::CephQuincyTest),
-            "ceph-reef-enterprise" => Ok(APTRepositoryHandle::CephReefEnterprise),
-            "ceph-reef-no-subscription" => Ok(APTRepositoryHandle::CephReefNoSubscription),
-            "ceph-reef-test" => Ok(APTRepositoryHandle::CephReefTest),
-            _ => bail!("unknown repository handle '{}'", string),
-        }
-    }
-}
-
-impl Display for APTRepositoryHandle {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        match self {
-            APTRepositoryHandle::Enterprise => write!(f, "enterprise"),
-            APTRepositoryHandle::NoSubscription => write!(f, "no-subscription"),
-            APTRepositoryHandle::Test => write!(f, "test"),
-            APTRepositoryHandle::CephQuincyEnterprise => write!(f, "ceph-quincy-enterprise"),
-            APTRepositoryHandle::CephQuincyNoSubscription => {
-                write!(f, "ceph-quincy-no-subscription")
-            }
-            APTRepositoryHandle::CephQuincyTest => write!(f, "ceph-quincy-test"),
-            APTRepositoryHandle::CephReefEnterprise => write!(f, "ceph-reef-enterprise"),
-            APTRepositoryHandle::CephReefNoSubscription => write!(f, "ceph-reef-no-subscription"),
-            APTRepositoryHandle::CephReefTest => write!(f, "ceph-reef-test"),
-        }
-    }
-}
-
 pub trait APTRepositoryHandleImpl {
     /// Get the description for the repository.
     fn description(self) -> String;
diff --git a/proxmox-apt/tests/repositories.rs b/proxmox-apt/tests/repositories.rs
index 37d665bf..228ef696 100644
--- a/proxmox-apt/tests/repositories.rs
+++ b/proxmox-apt/tests/repositories.rs
@@ -9,7 +9,7 @@ use proxmox_apt::repositories::{
     APTRepositoryHandle, APTRepositoryInfo, APTStandardRepository, DebianCodename,
 };
 use proxmox_apt::repositories::{
-    APTRepositoryFileImpl, APTRepositoryHandleImpl, APTRepositoryImpl,
+    APTRepositoryFileImpl, APTRepositoryHandleImpl, APTRepositoryImpl, APTStandardRepositoryImpl,
 };
 
 fn create_clean_directory(path: &PathBuf) -> Result<(), Error> {
@@ -114,7 +114,7 @@ fn test_digest() -> Result<(), Error> {
     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();
+    let old_digest = file.digest.clone().unwrap();
 
     // file does not exist yet...
     assert!(file.read_with_digest().is_err());
@@ -132,7 +132,7 @@ fn test_digest() -> Result<(), Error> {
     repo.enabled = !repo.enabled;
 
     // ...then it should work
-    file.digest = Some(old_digest);
+    file.digest = Some(old_digest.clone());
     file.write()?;
 
     // expect a different digest, because the repo was modified
@@ -361,15 +361,15 @@ fn test_standard_repositories() -> Result<(), Error> {
     let read_dir = test_dir.join("sources.list.d");
 
     let mut expected = vec![
-        APTStandardRepository::from(APTRepositoryHandle::Enterprise),
-        APTStandardRepository::from(APTRepositoryHandle::NoSubscription),
-        APTStandardRepository::from(APTRepositoryHandle::Test),
-        APTStandardRepository::from(APTRepositoryHandle::CephQuincyEnterprise),
-        APTStandardRepository::from(APTRepositoryHandle::CephQuincyNoSubscription),
-        APTStandardRepository::from(APTRepositoryHandle::CephQuincyTest),
-        APTStandardRepository::from(APTRepositoryHandle::CephReefEnterprise),
-        APTStandardRepository::from(APTRepositoryHandle::CephReefNoSubscription),
-        APTStandardRepository::from(APTRepositoryHandle::CephReefTest),
+        APTStandardRepository::from_handle(APTRepositoryHandle::Enterprise),
+        APTStandardRepository::from_handle(APTRepositoryHandle::NoSubscription),
+        APTStandardRepository::from_handle(APTRepositoryHandle::Test),
+        APTStandardRepository::from_handle(APTRepositoryHandle::CephQuincyEnterprise),
+        APTStandardRepository::from_handle(APTRepositoryHandle::CephQuincyNoSubscription),
+        APTStandardRepository::from_handle(APTRepositoryHandle::CephQuincyTest),
+        APTStandardRepository::from_handle(APTRepositoryHandle::CephReefEnterprise),
+        APTStandardRepository::from_handle(APTRepositoryHandle::CephReefNoSubscription),
+        APTStandardRepository::from_handle(APTRepositoryHandle::CephReefTest),
     ];
 
     let absolute_suite_list = read_dir.join("absolute_suite.list");
-- 
2.39.2



_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel


  parent reply	other threads:[~2024-07-09  6:18 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-07-09  6:18 [pbs-devel] applied-series: [PATCH proxmox 1/6] apt-api-types: new crate Wolfgang Bumiller
2024-07-09  6:18 ` [pbs-devel] [PATCH proxmox 2/6] apt-api-types: use serde-plain to display/parse enums Wolfgang Bumiller
2024-07-09  6:18 ` [pbs-devel] [PATCH proxmox 3/6] apt: avoid direct impl on api types (use traits instead) Wolfgang Bumiller
2024-07-09  6:18 ` Wolfgang Bumiller [this message]
2024-07-09  6:18 ` [pbs-devel] [PATCH proxmox 5/6] apt: add cache feature Wolfgang Bumiller
2024-07-09  6:18 ` [pbs-devel] [PATCH proxmox 6/6] apt: avoid global apt config Wolfgang Bumiller
2024-07-09 10:34   ` Fiona Ebner
2024-07-09 10:48     ` Wolfgang Bumiller

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240709061832.52121-4-w.bumiller@proxmox.com \
    --to=w.bumiller@proxmox.com \
    --cc=pbs-devel@lists.proxmox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal