Skip to main content

upstream_rs/models/upstream/
package_reference.rs

1use crate::models::{
2    common::enums::{Channel, Filetype, Provider},
3    upstream::Package,
4};
5use serde::{Deserialize, Serialize};
6
7/// The bare minimum needed to install a package. Essentially the args to
8/// `Package::with_defaults` — no install state, no paths, no version.
9#[derive(Debug, Clone, Serialize, Deserialize)]
10pub struct PackageReference {
11    pub name: String,
12    pub repo_slug: String,
13    pub filetype: Filetype,
14    pub channel: Channel,
15    pub provider: Provider,
16    pub base_url: Option<String>,
17    pub match_pattern: Option<String>,
18    pub exclude_pattern: Option<String>,
19}
20
21impl PackageReference {
22    pub fn into_package(self) -> Package {
23        Package::with_defaults(
24            self.name,
25            self.repo_slug,
26            self.filetype,
27            self.match_pattern,
28            self.exclude_pattern,
29            self.channel,
30            self.provider,
31            self.base_url,
32        )
33    }
34
35    pub fn from_package(package: Package) -> Self {
36        Self {
37            name: package.name,
38            repo_slug: package.repo_slug,
39            filetype: package.filetype,
40            channel: package.channel,
41            provider: package.provider,
42            base_url: package.base_url,
43            match_pattern: package.match_pattern,
44            exclude_pattern: package.exclude_pattern,
45        }
46    }
47}
48
49#[cfg(test)]
50mod tests {
51    use super::PackageReference;
52    use crate::models::common::enums::{Channel, Filetype, Provider};
53    use crate::models::upstream::Package;
54
55    fn reference() -> PackageReference {
56        PackageReference {
57            name: "fd".to_string(),
58            repo_slug: "sharkdp/fd".to_string(),
59            filetype: Filetype::Archive,
60            channel: Channel::Stable,
61            provider: Provider::Github,
62            base_url: Some("https://api.github.com".to_string()),
63            match_pattern: Some("x86_64".to_string()),
64            exclude_pattern: Some("debug".to_string()),
65        }
66    }
67
68    #[test]
69    fn into_package_keeps_install_inputs_and_applies_runtime_defaults() {
70        let package = reference().into_package();
71
72        assert_eq!(package.name, "fd");
73        assert_eq!(package.repo_slug, "sharkdp/fd");
74        assert_eq!(package.filetype, Filetype::Archive);
75        assert_eq!(package.channel, Channel::Stable);
76        assert_eq!(package.provider, Provider::Github);
77        assert_eq!(package.base_url.as_deref(), Some("https://api.github.com"));
78        assert!(package.install_path.is_none());
79        assert!(package.exec_path.is_none());
80        assert_eq!(package.version.to_string(), "0.0.0");
81    }
82
83    #[test]
84    fn from_package_round_trips_reference_fields() {
85        let package = Package::with_defaults(
86            "ripgrep".to_string(),
87            "BurntSushi/ripgrep".to_string(),
88            Filetype::Binary,
89            Some("linux".to_string()),
90            Some("symbols".to_string()),
91            Channel::Preview,
92            Provider::Github,
93            None,
94        );
95
96        let reference = PackageReference::from_package(package);
97        assert_eq!(reference.name, "ripgrep");
98        assert_eq!(reference.repo_slug, "BurntSushi/ripgrep");
99        assert_eq!(reference.filetype, Filetype::Binary);
100        assert_eq!(reference.channel, Channel::Preview);
101        assert_eq!(reference.provider, Provider::Github);
102        assert_eq!(reference.match_pattern.as_deref(), Some("linux"));
103        assert_eq!(reference.exclude_pattern.as_deref(), Some("symbols"));
104    }
105}