1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
use std::{convert::TryFrom, io::Read};
use debpkg::DebPkg;
use crate::{PkgError, RemotePackage};
#[derive(Debug)]
pub struct DebianRemotePackage {
control: debpkg::Control,
}
impl DebianRemotePackage {
#[cfg(feature = "http")]
pub fn new_from_url(url: &str) -> Result<Self, PkgError> {
let client = reqwest::blocking::Client::new();
let response = client.get(url).send()?;
Self::new_from_read(response)
}
pub fn new_from_read<R: Read>(reader: R) -> Result<Self, PkgError> {
let pkg = debpkg::DebPkg::parse(reader)?;
Self::try_from(pkg)
}
}
impl<T> TryFrom<DebPkg<T>> for DebianRemotePackage
where
T: Read,
{
type Error = PkgError;
fn try_from(mut pkg: DebPkg<T>) -> Result<Self, Self::Error> {
let archive = pkg.control()?;
let control = debpkg::Control::extract(archive)?;
Ok(Self { control })
}
}
impl RemotePackage for DebianRemotePackage {
fn package_type(&self) -> crate::RemotePackageType {
crate::RemotePackageType::Deb
}
fn package_name(&self) -> Result<&str, PkgError> {
Ok(self.control.name())
}
fn package_version(&self) -> Result<&str, PkgError> {
Ok(self.control.version())
}
fn package_arch(&self) -> Result<&str, PkgError> {
self.control
.get("Architecture")
.ok_or_else(|| PkgError::DebianControlFieldNotFound("Architecture".to_string()))
}
fn package_iteration(&self) -> Option<&str> {
let version = self.control.version();
version.rsplit_once('-').map(|(_prefix, suffix)| suffix)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[cfg(feature = "http")]
#[test]
fn test_package() {
let url = "http://cz.archive.ubuntu.com/ubuntu/pool/universe/d/debian-faq/debian-faq_10.1_all.deb";
let deb = DebianRemotePackage::new_from_url(url).expect("Failed to download package");
assert_eq!(deb.package_name().unwrap(), "debian-faq");
}
}