You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
100 lines
2.5 KiB
Rust
100 lines
2.5 KiB
Rust
use std::collections::HashMap;
|
|
use std::fs;
|
|
use std::fs::File;
|
|
use std::path::Path;
|
|
|
|
use crate::errors::AppResult;
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct PackageFile {
|
|
pub path: String,
|
|
pub package: Package,
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct PackageFiles {
|
|
files: HashMap<String, Vec<PackageFile>>,
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct Package {
|
|
pub name: String,
|
|
pub version: String,
|
|
}
|
|
|
|
impl Package {
|
|
pub fn new(name: String, version: String) -> Self {
|
|
Self { name, version }
|
|
}
|
|
|
|
pub fn read(path: &Path) -> AppResult<PackageFile> {
|
|
let mut file = File::open(path)?;
|
|
let mut buffer = Vec::new();
|
|
|
|
compress_tools::uncompress_archive_file(&mut file, &mut buffer, ".PKGINFO")?;
|
|
let pkginfo = String::from_utf8(buffer)?;
|
|
|
|
let mut pkgname = String::new();
|
|
let mut pkgver = String::new();
|
|
|
|
for line in pkginfo.lines() {
|
|
let line = line.trim();
|
|
if line.starts_with("pkgname") {
|
|
pkgname = line.split('=').nth(1).unwrap().trim().to_string();
|
|
} else if line.starts_with("pkgver") {
|
|
pkgver = line.split('=').nth(1).unwrap().trim().to_string();
|
|
}
|
|
}
|
|
|
|
Ok(PackageFile {
|
|
path: path.display().to_string(),
|
|
package: Package::new(pkgname, pkgver),
|
|
})
|
|
}
|
|
}
|
|
|
|
impl PackageFiles {
|
|
pub fn new() -> Self {
|
|
Self {
|
|
files: HashMap::new(),
|
|
}
|
|
}
|
|
|
|
pub fn add(&mut self, file: PackageFile) {
|
|
self.files
|
|
.entry(file.clone().package.name)
|
|
.or_default()
|
|
.push(file);
|
|
}
|
|
|
|
pub fn scan(&mut self, path: &Path) -> AppResult<()> {
|
|
for entry in fs::read_dir(path)? {
|
|
let entry = entry?;
|
|
let path = entry.path();
|
|
let path_display = path.display().to_string();
|
|
if path.is_file()
|
|
&& path_display.contains(".pkg.tar.")
|
|
&& !path_display.ends_with(".sig")
|
|
{
|
|
let file = Package::read(&path)?;
|
|
self.add(file);
|
|
}
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
pub fn prune(&mut self, keep: u8) -> AppResult<usize> {
|
|
let mut to_delete = Vec::new();
|
|
for (_, files) in self.files.iter_mut() {
|
|
files.sort_by(|a, b| b.package.version.cmp(&a.package.version));
|
|
to_delete.extend(files.iter().skip(keep as usize));
|
|
}
|
|
|
|
for file in &to_delete {
|
|
fs::remove_file(&file.path)?;
|
|
}
|
|
|
|
Ok(to_delete.len())
|
|
}
|
|
}
|