feat: start of pkg info parsing code

main
Jef Roosens 2023-07-12 23:51:07 +02:00
parent 2e118d0283
commit 7be4d83ca3
Signed by: Jef Roosens
GPG Key ID: B75D4F293C7052DB
5 changed files with 178 additions and 0 deletions

View File

@ -2,4 +2,8 @@ pub mod archive;
pub mod error;
pub mod read;
pub use archive::{
Entry, ExtractOption, ExtractOptions, Handle, ReadCompression, ReadFilter, ReadFormat,
WriteFilter, WriteFormat,
};
pub use error::Result;

View File

@ -5,6 +5,7 @@ mod file;
pub use builder::Builder;
use crate::archive::Handle;
use crate::ReadFilter;
use entries::Entries;
use libarchive3_sys::ffi;
use std::path::Path;
@ -18,4 +19,13 @@ pub trait Archive: Handle + Sized {
fn entries<'a>(&'a mut self) -> Entries<'a, Self> {
Entries::new(self)
}
fn filter(&mut self, index: i32) -> ReadFilter {
let res = unsafe { ffi::archive_filter_code(self.handle_mut(), index) };
match res {
0 => ReadFilter::None,
_ => panic!("Unknown filter type"),
}
}
}

View File

@ -0,0 +1,16 @@
use std::path::{Path, PathBuf};
/// Overarching abstraction that orchestrates updating the repositories stored on the server
pub struct RepoGroupManager {
repo_dir: PathBuf,
pkg_dir: PathBuf,
}
impl RepoGroupManager {
fn new<P1: AsRef<Path>, P2: AsRef<Path>>(repo_dir: P1, pkg_dir: P2) -> Self {
RepoGroupManager {
repo_dir: repo_dir.as_ref().to_path_buf(),
pkg_dir: pkg_dir.as_ref().to_path_buf(),
}
}
}

View File

@ -1,4 +1,5 @@
mod manager;
mod package;
use axum::extract::{BodyStream, Path, State};
use axum::http::StatusCode;

View File

@ -0,0 +1,147 @@
use libarchive::read::{Archive, Builder};
use libarchive::{Entry, ReadFilter};
use std::fmt;
use std::io::{self, BufRead, BufReader, Read};
use std::path::{Path, PathBuf};
const IGNORED_FILES: [&str; 5] = [".BUILDINFO", ".INSTALL", ".MTREE", ".PKGINFO", ".CHANGELOG"];
pub struct Package {
path: PathBuf,
info: PkgInfo,
files: Vec<PathBuf>,
compression: ReadFilter,
}
#[derive(Default)]
pub struct PkgInfo {
name: String,
base: String,
version: String,
description: String,
size: i64,
csize: i64,
url: String,
arch: String,
build_date: i64,
packager: String,
pgpsig: String,
pgpsigsize: i64,
groups: Vec<String>,
licenses: Vec<String>,
replaces: Vec<String>,
depends: Vec<String>,
conflicts: Vec<String>,
provides: Vec<String>,
optdepends: Vec<String>,
makedepends: Vec<String>,
checkdepends: Vec<String>,
}
#[derive(Debug, PartialEq, Eq)]
enum ParsePkgInfoError {
InvalidSize,
InvalidBuildDate,
InvalidPgpSigSize,
}
impl fmt::Display for ParsePkgInfoError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let s = match self {
Self::InvalidSize => "invalid size",
Self::InvalidBuildDate => "invalid build date",
Self::InvalidPgpSigSize => "invalid pgp sig size",
};
write!(f, "{}", s)
}
}
impl PkgInfo {
pub fn extend<S: AsRef<str>>(&mut self, line: S) -> Result<(), ParsePkgInfoError> {
let line = line.as_ref();
if !line.starts_with('#') {
if let Some((key, value)) = line.split_once(',').map(|(k, v)| (k.trim(), v.trim())) {
match key {
"pkgname" => self.name = value.to_string(),
"pkgbase" => self.base = value.to_string(),
"pkgver" => self.version = value.to_string(),
"pkgdesc" => self.description = value.to_string(),
"size" => {
self.size = value.parse().map_err(|_| ParsePkgInfoError::InvalidSize)?
}
"url" => self.url = value.to_string(),
"arch" => self.arch = value.to_string(),
"builddate" => {
self.build_date = value
.parse()
.map_err(|_| ParsePkgInfoError::InvalidBuildDate)?
}
"packager" => self.packager = value.to_string(),
"pgpsig" => self.pgpsig = value.to_string(),
"pgpsigsize" => {
self.pgpsigsize = value
.parse()
.map_err(|_| ParsePkgInfoError::InvalidBuildDate)?
}
"group" => self.groups.push(value.to_string()),
"license" => self.licenses.push(value.to_string()),
"replaces" => self.replaces.push(value.to_string()),
"depend" => self.depends.push(value.to_string()),
"conflict" => self.conflicts.push(value.to_string()),
"provides" => self.provides.push(value.to_string()),
"optdepend" => self.optdepends.push(value.to_string()),
"makedepend" => self.makedepends.push(value.to_string()),
"checkdepend" => self.checkdepends.push(value.to_string()),
_ => (),
}
}
}
Ok(())
}
pub fn parse<R: Read>(reader: R) -> io::Result<Self> {
let mut info = Self::default();
let buf_reader = BufReader::new(reader);
for line in buf_reader.lines() {
info.extend(line?).map_err(|e| {
io::Error::new(io::ErrorKind::Other, format!("pkg info parse error: {}", e))
})?;
}
Ok(info)
}
}
impl Package {
pub fn open<P: AsRef<Path>>(path: P) -> io::Result<Self> {
let mut builder = Builder::new();
builder.support_format(libarchive::ReadFormat::Tar)?;
builder.support_filter(libarchive::ReadFilter::All)?;
let mut ar = builder.open_file(path)?;
let mut info: PkgInfo;
let mut files: Vec<PathBuf> = Vec::new();
for entry in ar.entries() {
let entry = entry?;
let path_name = entry.pathname();
if !IGNORED_FILES.iter().any(|p| p == &path_name) {
files.push(PathBuf::from(path_name));
}
if path_name == ".PKGINFO" {
let size = entry.size();
info = PkgInfo::parse(entry)?;
info.size = size;
}
}
todo!()
}
}