apt_sources/
signature.rs

1//! A module implementing `Signature` type that holds info about variants of the signature key used by the repository
2
3use std::path::PathBuf;
4
5use crate::error::RepositoryError;
6
7/// A type to store
8#[derive(Debug, PartialEq, Clone)]
9pub enum Signature {
10    /// The PGP key is stored inside the `.sources` files
11    KeyBlock(String), // TODO: shall we validate PGP Public Key?
12    /// The public key is store in a file of the given path
13    KeyPath(PathBuf), // TODO: man page specifies fingerprints, but there's no example
14}
15
16impl std::str::FromStr for Signature {
17    type Err = RepositoryError;
18
19    fn from_str(text: &str) -> Result<Self, Self::Err> {
20        // Normal examples say PGP line shall start next line after `Signed-By` field
21        // but all my files have it starting after a space in the same line and that works.
22        // It's quite confusing, but let it be... we have to deal with reality.
23        if text.contains("\n") {
24            // If text is multiline, we assume PGP Public Key block
25            Ok(Signature::KeyBlock(text.to_string()))
26        } else {
27            // otherwise one-liner is a path
28            Ok(Signature::KeyPath(text.into()))
29        }
30
31        // if let Some((name, rest)) = text.split_once('\n') {
32        //     if name.is_empty() {
33        //         println!("& Name = {}", name);
34        //         Ok(Signature::KeyBlock(rest.to_string()))
35        //     } else {
36        //         println!("& Name = {}", name);
37        //         Err(RepositoryError::InvalidSignature)
38        //     }
39        // } else {
40        //     println!("& No name");
41        //     Ok(Signature::KeyPath(text.into()))
42        // }
43    }
44}
45
46impl std::fmt::Display for Signature {
47    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
48        match self {
49            Signature::KeyBlock(text) => write!(f, "\n{}", text),
50            Signature::KeyPath(path) => f.write_str(path.to_string_lossy().as_ref()),
51        }
52    }
53}
54
55#[cfg(test)]
56mod tests {
57    use super::*;
58    use std::path::PathBuf;
59
60    #[test]
61    fn test_signature_display() {
62        // Test KeyPath display
63        let path_sig = Signature::KeyPath(PathBuf::from("/etc/apt/trusted.gpg"));
64        assert_eq!(path_sig.to_string(), "/etc/apt/trusted.gpg");
65
66        // Test KeyBlock display
67        let key_block =
68            "-----BEGIN PGP PUBLIC KEY BLOCK-----\ntest key\n-----END PGP PUBLIC KEY BLOCK-----";
69        let block_sig = Signature::KeyBlock(key_block.to_string());
70        assert_eq!(block_sig.to_string(), format!("\n{}", key_block));
71    }
72}