use std::{
collections::BTreeSet,
env,
fs::{self, File},
io::{Read, Write},
path::PathBuf,
sync::LazyLock,
};
use eyre::{Result, eyre};
use crate::package::{Package, PackageFile};
use crate::vendors::Vendor;
pub fn save_installed_packages(packages: Vec<Package>, fix_revendor: bool) -> Result<()> {
let mut tracks: BTreeSet<Package> = load_tracks()
.unwrap_or_default()
.into_iter()
.collect();
for mut package in packages {
if fix_revendor {
revendor_package(&mut package)?;
}
tracks.insert(package);
}
let tracks: Vec<Package> = tracks.into_iter().collect();
save_tracks(tracks)?;
Ok(())
}
pub fn remove_installed_packages(packages: Vec<Package>) -> Result<()> {
let mut tracks = load_tracks().unwrap_or_default();
if tracks.is_empty() {
return Ok(());
}
for package in &packages {
tracks.retain(|track| *track != *package);
}
save_tracks(tracks)?;
Ok(())
}
pub fn load_tracks() -> Result<Vec<Package>> {
let mut file = File::open(match TRACK.to_str() {
Some(path) => path,
_ => return Err(eyre!("package track file (packages.toml) not found")),
}).map_err(|_| eyre!("error opening package track file (packages.toml)"))?;
let mut content = String::new();
file.read_to_string(&mut content)?;
let data: PackageFile = toml::from_str(&content)?;
Ok(data.installed)
}
fn save_tracks(tracks: Vec<Package>) -> Result<()> {
let data = PackageFile { installed: tracks };
let content = toml::to_string(&data)?;
let mut file = File::create(match TRACK.to_str() {
Some(path) => path,
_ => return Err(eyre!("error creating track file")),
})?;
file.write_all(content.as_bytes())?;
Ok(())
}
fn revendor_package(package: &mut Package) -> Result<()> {
match package.vendor {
Vendor::Pacman |
Vendor::Rua => {
if Vendor::Yay.is_available()? {
package.vendor = Vendor::Yay;
} else if Vendor::Rua.is_available()? {
package.vendor = Vendor::Rua;
}
}
_ => (),
}
Ok(())
}
static TRACK: LazyLock<PathBuf> = LazyLock::new(|| PLEASE_DATA.join("packages.toml"));
static PLEASE_DATA: LazyLock<PathBuf> = LazyLock::new(|| {
let data = DATA_HOME.join("cc.cacilhas.please");
if !data.exists() {
let old = DATA_HOME.join("info.cacilhas.please");
if old.exists() {
let _ = fs::rename(&old, &data);
} else {
let _ = fs::create_dir_all(&data);
}
}
data
});
#[cfg(not(any(target_os = "macos", target_os = "windows")))]
static DATA_HOME: LazyLock<PathBuf> = LazyLock::new(||
env::var("XDG_DATA_HOME")
.map(|dir| PathBuf::from(dir))
.unwrap_or_else(|_|
PathBuf::from(env!["HOME"])
.join(".local")
.join("share")
)
);
#[cfg(target_os = "macos")]
static DATA_HOME: LazyLock<PathBuf> = LazyLock::new(||
env::var("XDG_DATA_HOME")
.map(|dir| PathBuf::from(dir))
.unwrap_or_else(|_|
PathBuf::from(env!["HOME"])
.join("Library")
.join("Application Support")
)
);
#[cfg(target_os = "windows")]
static DATA_HOME: LazyLock<String> = LazyLock::new(||
env::var("APPDATA")
.map(|dir| PathBuf::from(dir))
.unwrap_or_else(|_|
PathBuf::from(env!["HOMEPATH"])
.join("AppData")
.join("Roaming")
)
);