use crate::errors::*;
use crate::pkgs::Pkg;
use crate::utils;
use flate2::read::GzDecoder;
use std::io::{BufRead, BufReader, Read};
pub fn parse_pkginfo<R: Read>(reader: R) -> Result<Pkg> {
let reader = BufReader::new(reader);
let mut name = None;
let mut version = None;
for line in reader.lines() {
let line = line?;
if let Some(value) = line.strip_prefix("pkgname = ") {
name = Some(value.to_string());
} else if let Some(value) = line.strip_prefix("pkgver = ") {
version = Some(value.to_string());
}
}
Ok(Pkg {
name: name.context("Could not find pkgname in .PKGINFO")?,
version: version.context("Could not find pkgver in .PKGINFO")?,
})
}
pub fn parse<R: Read>(reader: R) -> Result<Pkg> {
let mut r = BufReader::new(reader);
utils::read_gzip_to_end(&mut r).context("Failed to strip signature")?;
let gz = GzDecoder::new(r);
let mut tar = tar::Archive::new(gz);
for entry in tar.entries()? {
let entry = entry?;
let path = entry.path()?;
if path.to_str() == Some(".PKGINFO") {
return parse_pkginfo(entry);
}
}
bail!("Failed to find .PKGINFO in package file")
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse_pkginfo() -> Result<()> {
let data = br#"# Generated by abuild 3.11.1-r0
# using fakeroot version 1.31
# Thu Jul 20 10:08:19 UTC 2023
pkgname = mpfr4
pkgver = 4.2.0_p12-r0
pkgdesc = multiple-precision floating-point library
url = https://www.mpfr.org/
builddate = 1689847699
packager = Buildozer <alpine-devel@lists.alpinelinux.org>
size = 684032
arch = x86_64
origin = mpfr4
commit = 8910287059187d6e83a13dd2078a2a42ea2121f4
maintainer = Natanael Copa <ncopa@alpinelinux.org>
license = LGPL-3.0-or-later
replaces = mpfr
provides = mpfr=4.2.0_p12-r0
# automatically detected:
provides = so:libmpfr.so.6=6.2.0
depend = so:libc.musl-x86_64.so.1
depend = so:libgmp.so.10
datahash = a2c44c6b313ca65980d7f610026a71e6119d119de6cf2b78e52464d9d80bff45
"#;
let pkg = parse_pkginfo(&data[..])?;
assert_eq!(
pkg,
Pkg {
name: "mpfr4".to_string(),
version: "4.2.0_p12-r0".to_string(),
}
);
Ok(())
}
#[test]
fn test_parse_pkg() -> Result<()> {
let pkg = parse(crate::test_data::ALPINE_APK_EXAMPLE)?;
assert_eq!(
pkg,
Pkg {
name: "alpine-base".to_string(),
version: "3.18.3-r0".to_string(),
}
);
Ok(())
}
}