proto_core/layout/
inventory.rs1use super::layout_error::ProtoLayoutError;
2use super::product::Product;
3use crate::helpers::{is_cache_enabled, is_offline};
4use crate::lockfile::LockRecord;
5use crate::tool_manifest::ToolManifest;
6use proto_pdk_api::{LoadVersionsOutput, ToolInventoryOptions};
7use starbase_utils::{fs, json, path};
8use std::path::PathBuf;
9use std::time::{Duration, SystemTime};
10use tracing::instrument;
11use version_spec::VersionSpec;
12
13#[derive(Clone, Debug, Default)]
14pub struct Inventory {
15 pub config: ToolInventoryOptions,
16 pub dir: PathBuf,
17 pub dir_original: Option<PathBuf>,
18 pub manifest: ToolManifest,
19 pub temp_dir: PathBuf,
20}
21
22impl Inventory {
23 #[instrument(skip(self))]
24 pub fn create_product(&self, spec: &VersionSpec) -> Product {
25 let mut name = spec.to_string();
26
27 if let Some(suffix) = &self.config.version_suffix {
28 name = format!("{name}{suffix}");
29 }
30
31 Product {
32 dir: self.dir.join(path::encode_component(name)),
33 version: spec.to_owned(),
34 }
35 }
36
37 pub fn get_locked_record(&self, version: &VersionSpec) -> Option<&LockRecord> {
38 self.manifest
39 .versions
40 .get(version)
41 .and_then(|man| man.lock.as_ref())
42 }
43
44 #[instrument(skip(self))]
45 pub fn load_remote_versions(
46 &self,
47 disable_cache: bool,
48 ) -> Result<Option<LoadVersionsOutput>, ProtoLayoutError> {
49 let cache_path = self
50 .dir_original
51 .as_ref()
52 .unwrap_or(&self.dir)
53 .join("remote-versions.json");
54
55 if cache_path.exists() {
57 let mut read_cache =
58 if disable_cache || !is_cache_enabled() {
60 false
61 } else {
63 let metadata = fs::metadata(&cache_path)?;
64
65 if let Ok(modified_time) = metadata.modified().or_else(|_| metadata.created()) {
66 modified_time > SystemTime::now() - Duration::from_secs(60 * 60 * 12)
67 } else {
68 false
69 }
70 };
71
72 if !read_cache && is_offline() {
74 read_cache = true;
75 }
76
77 if read_cache {
78 return Ok(Some(json::read_file(&cache_path)?));
79 }
80 }
81
82 Ok(None)
83 }
84
85 #[instrument(skip_all)]
86 pub fn save_remote_versions(&self, data: &LoadVersionsOutput) -> Result<(), ProtoLayoutError> {
87 json::write_file(
88 self.dir_original
89 .as_ref()
90 .unwrap_or(&self.dir)
91 .join("remote-versions.json"),
92 data,
93 false,
94 )?;
95
96 Ok(())
97 }
98}