1use std::fs::{self, File};
2use std::io::{self, Read, Write};
3use std::path::PathBuf;
4
5use serde::{Deserialize, Serialize};
6
7#[derive(Serialize, Deserialize, Debug, Clone)]
9pub struct PinnedPackage {
10 pub source: String,
12 pub version: String
14}
15
16fn get_pinned_json_path() -> Result<PathBuf, io::Error> {
18 let home_dir = dirs::home_dir().ok_or_else(|| {
19 io::Error::new(io::ErrorKind::NotFound, "Could not find home directory")
20 })?;
21 let zoi_dir = home_dir.join(".zoi");
22 if !zoi_dir.exists() {
23 fs::create_dir_all(&zoi_dir)?;
24 }
25 Ok(zoi_dir.join("pinned.json"))
26}
27
28pub fn get_pinned_packages() -> Result<Vec<PinnedPackage>, io::Error> {
35 let path = get_pinned_json_path()?;
36 if !path.exists() {
37 return Ok(Vec::new());
38 }
39
40 let mut file = File::open(path)?;
41 let mut contents = String::new();
42 file.read_to_string(&mut contents)?;
43
44 let packages: Vec<PinnedPackage> =
45 serde_json::from_str(&contents).unwrap_or_else(|_| Vec::new());
46 Ok(packages)
47}
48
49pub fn write_pinned_packages(
56 packages: &[PinnedPackage]
57) -> Result<(), io::Error> {
58 let path = get_pinned_json_path()?;
59 let mut file = File::create(path)?;
60 let contents = serde_json::to_string_pretty(packages)?;
61 file.write_all(contents.as_bytes())?;
62 Ok(())
63}
64
65pub fn get_pinned_version(source: &str) -> Result<Option<String>, io::Error> {
71 let pinned_packages = get_pinned_packages()?;
72 Ok(pinned_packages
73 .iter()
74 .find(|p| p.source == source)
75 .map(|p| p.version.clone()))
76}
77
78pub fn is_pinned(source: &str) -> Result<bool, io::Error> {
84 let pinned_packages = get_pinned_packages()?;
85 Ok(pinned_packages.iter().any(|p| p.source == source))
86}