Skip to main content

ispm_wrapper/data/
mod.rs

1// Copyright (C) 2024 Intel Corporation
2// SPDX-License-Identifier: Apache-2.0
3
4//! Data deserializable from ISPM commands and configurations
5
6use anyhow::Result;
7use serde::Deserialize;
8use serde_json::from_slice;
9use std::{fmt::Display, fs::read, path::PathBuf};
10use typed_builder::TypedBuilder;
11use versions::Versioning;
12
13use crate::Internal;
14
15#[derive(TypedBuilder, Deserialize, Clone, Debug, PartialEq, Eq)]
16/// A path object that is optionally an internet URI or local filesystem path
17pub struct IPathObject {
18    /// The unique id of the path
19    pub id: isize,
20    /// The priority of the path
21    pub priority: isize,
22    #[builder(setter(into))]
23    /// The path
24    pub value: String,
25    /// whether this path is enabled
26    pub enabled: bool,
27    #[serde(rename = "isWritable")]
28    #[builder(default, setter(strip_option))]
29    /// Whether this path is writable
30    pub writable: Option<bool>,
31}
32
33#[derive(TypedBuilder, Deserialize, Clone, Debug, PartialEq, Eq)]
34/// A path to a SIMICS repo. This is an artifactory repository.
35pub struct RepoPath {
36    #[builder(setter(into))]
37    /// The path
38    pub value: String,
39    /// Whether this path is enabled
40    pub enabled: bool,
41    /// The priority of the path
42    pub priority: isize,
43    /// The unique id of the path
44    pub id: isize,
45}
46
47#[derive(TypedBuilder, Deserialize, Clone, Debug, PartialEq, Eq)]
48#[builder(field_defaults(setter(into)))]
49/// An electron rectangle definition
50pub struct Rectangle {
51    /// The x value of the rectangle's coordinate
52    pub x: isize,
53    /// The y value of the rectangle's coordinate
54    pub y: isize,
55    /// The width
56    pub width: isize,
57    /// The height
58    pub height: isize,
59}
60
61#[derive(Deserialize, Clone, Debug, PartialEq, Eq)]
62#[serde(rename_all = "lowercase")]
63/// Proxy settings
64pub enum ProxySettingTypes {
65    /// No proxy should be used
66    None,
67    /// Use the proxy settings from environment variables
68    Env,
69    /// Use the proxy settings from the manual configuration
70    Manual,
71}
72
73#[derive(Deserialize, Clone, Debug, PartialEq, Eq)]
74/// Preference for which method should be used to install packages
75pub enum InstallationPreference {
76    /// Install in the order in the repository
77    RepoOrder,
78    /// Install in legacy style
79    LegacyStyle,
80    /// Install in the new style
81    NewStyle,
82}
83
84#[derive(TypedBuilder, Deserialize, Clone, Debug, PartialEq, Eq)]
85#[builder(field_defaults(default, setter(strip_option)))]
86/// V3 ISPM configuration, all fields are optional so older configs that we support should also work
87/// without an issue
88pub struct Settings {
89    #[builder(setter(into))]
90    /// Package repositories that ISPM can install from. Managed by the `ispm config
91    /// package-repos` command.
92    pub archives: Option<Vec<RepoPath>>,
93    #[serde(rename = "cacheTimeout")]
94    /// The timeout of the cache
95    pub cache_timeout: Option<isize>,
96    #[serde(rename = "installPath")]
97    /// Installation path. Managed by the `ispm config install-dir` command.
98    pub install_path: Option<IPathObject>,
99    #[serde(rename = "readOnlyInstallationPaths")]
100    #[builder(setter(into))]
101    /// Installation paths that are set as read-only. Managed by the `ispm config
102    /// ro-install-paths` command.
103    pub read_only_installation_paths: Option<Vec<IPathObject>>,
104    #[serde(rename = "cfgVersion")]
105    /// The configuration version number
106    pub cfg_version: Option<isize>,
107    #[serde(rename = "guiBounds")]
108    /// Last saved bounds of the ISPM GUI
109    pub gui_bounds: Option<Rectangle>,
110    #[serde(rename = "guiMaximized")]
111    /// Whether the GUI was maximized
112    pub gui_maximized: Option<bool>,
113    #[serde(rename = "powershellPath")]
114    /// The path to the powershell executable
115    pub powershell_path: Option<PathBuf>,
116    #[serde(rename = "tempDirectory")]
117    /// The temporary directory used by ISPM. Managed by the `ispm config temp-dir` command.
118    pub temp_directory: Option<PathBuf>,
119    #[serde(rename = "multiUser")]
120    /// Whether this is a multi-user installation
121    pub multi_user: Option<bool>,
122    #[serde(rename = "projectsDefault")]
123    #[builder(setter(into))]
124    /// The default projects
125    pub projects_default: Option<String>,
126    #[serde(rename = "enableRemoteManifests")]
127    /// Whether remtoe manifests are enabled
128    pub enable_remote_manifests: Option<bool>,
129    #[serde(rename = "manifestRepos")]
130    #[builder(setter(into))]
131    /// Platform repositories that ISPM can install from. Managed by the `ispm config
132    /// platform-repos` command.
133    pub manifest_repos: Option<Vec<IPathObject>>,
134    #[serde(rename = "projects")]
135    #[builder(setter(into))]
136    /// A list of registered projects
137    pub projects: Option<Vec<IPathObject>>,
138    #[serde(rename = "manifests")]
139    #[builder(setter(into))]
140    /// A list of manifests
141    pub manifests: Option<Vec<IPathObject>>,
142    #[serde(rename = "keyStore")]
143    #[builder(setter(into))]
144    /// Files that store decryption keys for legacy package installation. Managed by the
145    /// `ispm config decryption-key-files` command.
146    pub key_store: Option<Vec<IPathObject>>,
147    #[serde(rename = "ignoreLegacyPlatformRepoDeprecation")]
148    /// Whether to ignore deprecation warnings for legacy platforms
149    pub ignore_legacy_platform_repo_deprecation: Option<bool>,
150    #[serde(rename = "proxySettingsToUse")]
151    /// Proxy settings that should be used. Managed by the `ispm config proxy
152    /// (--dont-use|--use-env)` command and flags.
153    pub proxy_settings_to_use: Option<ProxySettingTypes>,
154    #[serde(rename = "httpsProxy")]
155    #[builder(setter(into))]
156    /// Proxy settings that should be used for HTTPS. Managed by the `ispm config proxy
157    /// --https` command and flags.
158    pub https_proxy: Option<String>,
159    #[serde(rename = "httpProxy")]
160    #[builder(setter(into))]
161    /// Proxy settings that should be used for HTTPS. Managed by the `ispm config proxy`
162    /// command.
163    pub http_proxy: Option<String>,
164    #[serde(rename = "noProxy")]
165    #[builder(setter(into))]
166    /// URL/IP list (comma-delimited) of resources that should not use a proxy for access.
167    pub no_proxy: Option<String>,
168    #[serde(rename = "AuthenticationConfig")]
169    #[builder(setter(into))]
170    /// The path to the SIMICS authentication file. Not used for public release. Managed by the
171    /// `ispm config auth-file` command.
172    pub authentication_config: Option<String>,
173    #[serde(rename = "logfile")]
174    #[builder(setter(into))]
175    /// The current logfile
176    pub logfile: Option<String>,
177    #[serde(rename = "preferPackageType")]
178    /// The package type that is favored
179    pub prefer_package_type: Option<InstallationPreference>,
180}
181
182impl Settings {
183    /// Get the current settings from the currently set configuration file
184    pub fn get() -> Result<Self> {
185        Ok(from_slice(&read(Internal::cfg_file_path()?)?)?)
186    }
187}
188
189#[derive(TypedBuilder, Deserialize, Clone, Debug, PartialEq, Eq)]
190/// A package that is already installed
191pub struct InstalledPackage {
192    #[serde(rename = "pkgNumber")]
193    /// The package number
194    pub package_number: isize,
195    /// The package version
196    pub version: String,
197    #[builder(setter(into))]
198    /// The package name
199    pub name: String,
200    #[builder(default, setter(into))]
201    /// Paths to this installed package
202    pub paths: Vec<PathBuf>,
203}
204
205impl InstalledPackage {
206    /// Get this package's version as a comparable version object
207    pub fn version(&self) -> Versioning {
208        Versioning::new(&self.version).expect("Failed to parse installed package version")
209    }
210}
211
212#[derive(TypedBuilder, Deserialize, Clone, Debug, PartialEq, Eq)]
213/// A package that can be installed
214pub struct AvailablePackage {
215    #[serde(rename = "pkgNumber")]
216    /// The package number
217    pub package_number: isize,
218    /// The package version
219    pub version: String,
220    #[builder(setter(into))]
221    /// The package name
222    pub name: String,
223    /// Whether this package is installed
224    pub installed: bool,
225}
226
227impl AvailablePackage {
228    /// Get this package's version as a comparable version object
229    pub fn version(&self) -> Versioning {
230        Versioning::new(&self.version).expect("Failed to parse available package version")
231    }
232}
233
234#[derive(TypedBuilder, Deserialize, Clone, Debug, PartialEq, Eq)]
235#[builder(field_defaults(default, setter(strip_option, into)))]
236/// Set of installed and available packages
237pub struct Packages {
238    #[serde(rename = "installedPackages")]
239    /// The list of packages which are installed
240    pub installed_packages: Option<Vec<InstalledPackage>>,
241    #[serde(rename = "availablePackages")]
242    /// The list of packages which are available to install
243    pub available_packages: Option<Vec<AvailablePackage>>,
244}
245
246impl Packages {
247    /// Sort the installed and available packages by their version number (highest first)
248    pub fn sort(&mut self) {
249        if let Some(installed_packages) = self.installed_packages.as_mut() {
250            installed_packages.sort_by_key(|b| std::cmp::Reverse(b.version()))
251        }
252    }
253}
254
255#[derive(TypedBuilder, Deserialize, Clone, Debug, PartialEq, Eq, Hash)]
256/// A package which is added to a project
257pub struct ProjectPackage {
258    #[serde(rename = "pkgNumber")]
259    /// The package number
260    pub package_number: isize,
261    #[builder(setter(into))]
262    /// The package version
263    pub version: String,
264}
265
266impl Display for ProjectPackage {
267    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
268        write!(f, "{}-{}", self.package_number, self.version)
269    }
270}
271
272impl ProjectPackage {
273    /// Get this package's version as a comparable version object
274    pub fn version(&self) -> Versioning {
275        Versioning::new(&self.version).expect("Failed to parse project package version")
276    }
277}
278
279#[derive(TypedBuilder, Deserialize, Clone, Debug, PartialEq, Eq)]
280/// A SIMICS project
281pub struct Project {
282    #[builder(setter(into))]
283    /// The project name
284    pub name: String,
285    #[builder(setter(into))]
286    /// The project description
287    pub description: String,
288    /// The path to the project
289    pub path: PathBuf,
290    #[builder(default, setter(into))]
291    /// The set of packages this project was configured with
292    pub packages: Vec<ProjectPackage>,
293}
294
295#[derive(TypedBuilder, Deserialize, Clone, Debug, PartialEq, Eq)]
296#[builder(field_defaults(default, setter(into)))]
297/// List of known projects associated with this ISPM installation
298pub struct Projects {
299    /// A list of known projects
300    pub projects: Vec<Project>,
301}
302
303#[derive(TypedBuilder, Deserialize, Clone, Debug, PartialEq, Eq)]
304/// A platform, which is a collection of packages
305pub struct Platform {
306    #[builder(setter(into))]
307    /// The name of the platform
308    pub name: String,
309    #[builder(setter(into))]
310    /// The group of the platform
311    pub group: String,
312    #[builder(setter(into))]
313    /// The path to the platform
314    pub path: String,
315    /// Whether this platform is remote
316    pub remote: bool,
317}
318
319#[derive(TypedBuilder, Deserialize, Clone, Debug, PartialEq, Eq)]
320#[builder(field_defaults(default, setter(into)))]
321/// A list of platforms
322pub struct Platforms {
323    /// The list of platforms
324    pub platforms: Vec<Platform>,
325}