[pbs-devel] [PATCH proxmox 4/6] apt: use api types from apt-api-types crate

Wolfgang Bumiller w.bumiller at proxmox.com
Tue Jul 9 08:18:30 CEST 2024


From: Dietmar Maurer <dietmar at proxmox.com>

Signed-off-by: Dietmar Maurer <dietmar at 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





More information about the pbs-devel mailing list