diff options
| author | John Turner <jturner.usa@gmail.com> | 2025-11-29 20:43:28 +0000 |
|---|---|---|
| committer | John Turner <jturner.usa@gmail.com> | 2025-11-29 20:50:59 +0000 |
| commit | d1127df296aa7871555293e324d125e6d8a843e1 (patch) | |
| tree | baddfab365df586207fa9c1dadf270ee94c3f46f /src/repo/profile/packages/mod.rs | |
| parent | 94f3397d197e47eb58a7391acd9c63c5565fa26e (diff) | |
| download | gentoo-utils-profiles.tar.gz | |
impl profile evaluationprofiles
Diffstat (limited to 'src/repo/profile/packages/mod.rs')
| -rw-r--r-- | src/repo/profile/packages/mod.rs | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/src/repo/profile/packages/mod.rs b/src/repo/profile/packages/mod.rs new file mode 100644 index 0000000..4fd6559 --- /dev/null +++ b/src/repo/profile/packages/mod.rs @@ -0,0 +1,75 @@ +use std::{ + fs, io, + path::{Path, PathBuf}, +}; + +use mon::{Parser, ParserIter, ascii_whitespace1, input::InputIter}; + +use crate::{ + Parseable, + atom::Atom, + repo::profile::{LineBasedFileExpr, Profile}, +}; + +mod parsers; + +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("{0}: io error: {1}")] + Io(PathBuf, io::Error), + #[error("parser error: {0}")] + Parser(String), +} + +#[derive(Debug, Clone)] +enum Package { + Add(Atom), + Remove(Atom), +} + +pub(super) fn evaluate<P: AsRef<Path>>(parents: &[Profile], path: P) -> Result<Vec<Atom>, Error> { + let parsed = match fs::read_to_string(path.as_ref().join("packages")) { + Ok(contents) => parse(&contents)?, + Err(e) if matches!(e.kind(), io::ErrorKind::NotFound) => Vec::new(), + Err(e) => return Err(Error::Io(path.as_ref().to_path_buf(), e)), + }; + + Ok(inherit(parents, parsed)) +} + +fn inherit(parents: &[Profile], packages: Vec<Package>) -> Vec<Atom> { + let mut accumulated = Vec::new(); + + for parent in parents { + for package in parent.packages() { + accumulated.push(package.clone()); + } + } + + for package in packages { + match package { + Package::Add(package) => { + accumulated.push(package); + } + Package::Remove(package) => { + accumulated.retain(|p| *p != package); + } + } + } + + accumulated +} + +fn parse(contents: &str) -> Result<Vec<Package>, Error> { + Ok(LineBasedFileExpr::<Package>::parser() + .separated_by_with_opt_trailing(ascii_whitespace1()) + .many() + .parse_finished(InputIter::new(contents)) + .map_err(|e| Error::Parser(e.rest().to_string()))? + .into_iter() + .filter_map(|expr| match expr { + LineBasedFileExpr::Comment => None, + LineBasedFileExpr::Expr(package) => Some(package), + }) + .collect()) +} |
