use std::{
fs::File,
io::{BufReader, Read},
path::Path,
};
use alpm_pkgbuild::bridge::BridgeOutput;
use alpm_types::Architecture;
use fluent_i18n::t;
use serde::{Deserialize, Serialize};
use winnow::Parser;
use writer::{pkgbase_section, pkgname_section};
pub mod merged;
pub mod package;
pub mod package_base;
pub mod writer;
#[cfg(doc)]
use crate::MergedPackage;
use crate::{
error::Error,
source_info::{
parser::SourceInfoContent,
v1::{merged::MergedPackagesIterator, package::Package, package_base::PackageBase},
},
};
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub struct SourceInfoV1 {
pub base: PackageBase,
pub packages: Vec<Package>,
}
impl SourceInfoV1 {
pub fn as_srcinfo(&self) -> String {
let mut srcinfo = String::new();
pkgbase_section(&self.base, &mut srcinfo);
for package in &self.packages {
srcinfo.push('\n');
pkgname_section(package, &self.base.architectures, &mut srcinfo);
}
srcinfo
}
pub fn from_file(path: &Path) -> Result<SourceInfoV1, Error> {
let mut buffer = Vec::new();
let file = File::open(path).map_err(|source| Error::IoPath {
path: path.to_path_buf(),
context: t!("error-io-path-opening-file"),
source,
})?;
let mut buf_reader = BufReader::new(file);
buf_reader
.read_to_end(&mut buffer)
.map_err(|source| Error::IoPath {
path: path.to_path_buf(),
context: t!("error-io-path-reading-file"),
source,
})?;
let content = String::from_utf8(buffer)?.to_string();
Self::from_string(&content)
}
pub fn from_pkgbuild(pkgbuild_path: &Path) -> Result<SourceInfoV1, Error> {
let output = BridgeOutput::from_file(pkgbuild_path)?;
let source_info: SourceInfoV1 = output.try_into()?;
Ok(source_info)
}
pub fn from_string(content: &str) -> Result<SourceInfoV1, Error> {
let content_no_tabs = content.replace('\t', " ");
let parsed = SourceInfoContent::parser
.parse(content_no_tabs.as_str())
.map_err(|err| Error::ParseError(format!("{err}")))?;
let source_info = SourceInfoV1::from_raw(parsed)?;
Ok(source_info)
}
pub fn from_raw(content: SourceInfoContent) -> Result<SourceInfoV1, Error> {
let base = PackageBase::from_parsed(content.package_base)?;
let mut packages = Vec::new();
for package in content.packages {
let package = Package::from_parsed(package)?;
packages.push(package);
}
Ok(SourceInfoV1 { base, packages })
}
pub fn packages_for_architecture<A: Into<Architecture>>(
&self,
architecture: A,
) -> MergedPackagesIterator<'_> {
MergedPackagesIterator {
architecture: architecture.into(),
source_info: self,
package_iterator: self.packages.iter(),
}
}
}