hpk/src/package/mod.rs

137 lines
4.1 KiB
Rust

mod arch;
mod dependency;
mod specs;
use {
crate::tar::{Node, Owner},
crate::{Plist, Version},
ron::ser::{to_string_pretty, PrettyConfig},
serde::{Deserialize, Serialize},
std::{
error::Error,
fs,
fs::File,
io::{BufWriter, Write},
path::{Path, PathBuf},
},
};
pub use {arch::Arch, dependency::Dependency, specs::Specs};
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct User {
pub name: String,
pub uid: Option<u32>,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct Group {
pub name: String,
pub gid: Option<u32>,
}
#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq)]
/// the metadata associated with a package
pub struct Package {
/// The name of the package minus all version information
pub name: String,
/// The `Version` of the package
pub version: Version,
/// The architecture the package is built for
pub arch: Arch,
/// The release number for this package
pub release: u8,
/// a single line description of the package
pub description: String,
/// a more verbose description of the package
pub long_description: String,
/// a listing of all files, directories and symlinks which are a part of
/// this package
pub plist: Plist,
/// the total size of this package
pub size: usize,
/// all of this package's runtime dependencies
pub dependencies: Vec<Dependency>,
/// an optional list of users to be created upon installation
pub users: Option<Vec<User>>,
/// an optional list of groups to be created upon installation
pub groups: Option<Vec<Group>>,
/// applicable only if this package contains a shell
pub shells: Option<Vec<PathBuf>>,
/// an optional post installation shell script to be run
pub post_install: Option<String>,
}
impl From<Specs> for Package {
fn from(value: Specs) -> Self {
Package {
name: value.name,
version: value.version,
release: value.release,
description: value.description,
long_description: value.long_description,
dependencies: value.dependencies,
users: value.users,
groups: value.groups,
shells: value.shells,
post_install: value.post_install,
..Default::default()
}
}
}
impl Package {
fn as_ron(&self) -> Result<String, ron::Error> {
let cfg = PrettyConfig::new().struct_names(true);
to_string_pretty(self, cfg)
}
pub fn save_ron_and_create_tar_node(&self, outdir: &Path) -> Result<Node, Box<dyn Error>> {
if !outdir.exists() {
fs::create_dir_all(outdir)?;
}
let mut outfile = outdir.to_path_buf();
outfile.push("package.ron");
let fd = File::create(&outfile)?;
let s = self.as_ron()?;
let mut writer = BufWriter::new(&fd);
writer.write_all(s.as_bytes())?;
writer.flush()?;
let node = Node::read_data_to_tar(
s.as_bytes(),
"package.ron",
&outfile.metadata()?,
Some(Owner::default()),
)?;
Ok(node)
}
/// Returns the formatted full package name including version and release strings
pub fn fullname(&self) -> String {
format!(
"{}-{}_{}_{}",
self.name, self.version, self.release, self.arch
)
}
/// Returns the name of the package archive
pub fn archive_name(&self) -> String {
format!(
"{}-{}_{}_{}.tar.zstd",
self.name, self.version, self.release, self.arch
)
}
/// Tests whether this package is an update for another
pub fn is_upgrade(&self, other: &Self) -> bool {
self.arch == other.arch
&& self.name == other.name
&& (self.version > other.version
|| (self.version == other.version && self.release > other.release))
}
pub fn resolve_deps(&self, queue: &mut Vec<Package>) -> Result<(), Box<dyn Error>> {
unimplemented!();
}
}