feat: start of pkg info parsing code
parent
2e118d0283
commit
7be4d83ca3
|
@ -2,4 +2,8 @@ pub mod archive;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
pub mod read;
|
pub mod read;
|
||||||
|
|
||||||
|
pub use archive::{
|
||||||
|
Entry, ExtractOption, ExtractOptions, Handle, ReadCompression, ReadFilter, ReadFormat,
|
||||||
|
WriteFilter, WriteFormat,
|
||||||
|
};
|
||||||
pub use error::Result;
|
pub use error::Result;
|
||||||
|
|
|
@ -5,6 +5,7 @@ mod file;
|
||||||
pub use builder::Builder;
|
pub use builder::Builder;
|
||||||
|
|
||||||
use crate::archive::Handle;
|
use crate::archive::Handle;
|
||||||
|
use crate::ReadFilter;
|
||||||
use entries::Entries;
|
use entries::Entries;
|
||||||
use libarchive3_sys::ffi;
|
use libarchive3_sys::ffi;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
@ -18,4 +19,13 @@ pub trait Archive: Handle + Sized {
|
||||||
fn entries<'a>(&'a mut self) -> Entries<'a, Self> {
|
fn entries<'a>(&'a mut self) -> Entries<'a, Self> {
|
||||||
Entries::new(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"),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
mod manager;
|
mod manager;
|
||||||
|
mod package;
|
||||||
|
|
||||||
use axum::extract::{BodyStream, Path, State};
|
use axum::extract::{BodyStream, Path, State};
|
||||||
use axum::http::StatusCode;
|
use axum::http::StatusCode;
|
||||||
|
|
|
@ -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!()
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue