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