WIP: impl profile evaluation #7
@@ -20,7 +20,7 @@ fn main() -> Result<(), Box<dyn Error>> {
|
|||||||
|
|
||||||
fs::create_dir_all(&corpus_dir)?;
|
fs::create_dir_all(&corpus_dir)?;
|
||||||
|
|
||||||
let repo = Repo::new("/var/db/repos/gentoo");
|
let repo = Repo::new("/var/db/repos/gentoo").expect("failed to open repo");
|
||||||
let mut atoms = Vec::new();
|
let mut atoms = Vec::new();
|
||||||
|
|
||||||
for category in repo.categories()? {
|
for category in repo.categories()? {
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ fn main() -> Result<(), Box<dyn Error>> {
|
|||||||
|
|
||||||
fs::create_dir_all(&corpus_dir)?;
|
fs::create_dir_all(&corpus_dir)?;
|
||||||
|
|
||||||
let repo = Repo::new("/var/db/repos/gentoo");
|
let repo = Repo::new("/var/db/repos/gentoo").expect("failed to open repo");
|
||||||
let mut versions = Vec::new();
|
let mut versions = Vec::new();
|
||||||
|
|
||||||
for category in repo.categories()? {
|
for category in repo.categories()? {
|
||||||
|
|||||||
@@ -69,7 +69,8 @@ pub mod atom;
|
|||||||
/// ```
|
/// ```
|
||||||
/// use gentoo_utils::repo::Repo;
|
/// use gentoo_utils::repo::Repo;
|
||||||
///
|
///
|
||||||
/// let repo = Repo::new("/var/db/repos/gentoo");
|
/// let repo = Repo::new("/var/db/repos/gentoo")
|
||||||
|
/// .expect("failed to open repo");
|
||||||
///
|
///
|
||||||
/// for result in repo.categories().expect("failed to read categories") {
|
/// for result in repo.categories().expect("failed to read categories") {
|
||||||
/// let category = result.expect("failed to read category");
|
/// let category = result.expect("failed to read category");
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
sources += files('mod.rs')
|
sources += files('mod.rs', 'parsers.rs')
|
||||||
|
|
||||||
subdir('ebuild')
|
subdir('ebuild')
|
||||||
|
subdir('profile')
|
||||||
|
|||||||
@@ -11,14 +11,21 @@ use mon::{Parser, ParserIter, ascii_whitespace1, input::InputIter, tag};
|
|||||||
use crate::{
|
use crate::{
|
||||||
Parseable,
|
Parseable,
|
||||||
atom::{self, Atom},
|
atom::{self, Atom},
|
||||||
repo::ebuild::{Depend, Eapi, Ebuild, Eclass, License, SrcUri},
|
repo::{
|
||||||
|
ebuild::{Depend, Eapi, Ebuild, Eclass, License, SrcUri},
|
||||||
|
profile::{LineBasedFileExpr, Profile},
|
||||||
|
},
|
||||||
useflag::IUseFlag,
|
useflag::IUseFlag,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub mod ebuild;
|
pub mod ebuild;
|
||||||
|
mod parsers;
|
||||||
|
pub mod profile;
|
||||||
|
|
||||||
#[derive(Debug, thiserror::Error)]
|
#[derive(Debug, thiserror::Error)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
|
#[error("invalid repo: {0}")]
|
||||||
|
Invalid(String),
|
||||||
#[error("io error: {0}")]
|
#[error("io error: {0}")]
|
||||||
Io(PathBuf, io::Error),
|
Io(PathBuf, io::Error),
|
||||||
#[error("error while reading directory: {0:?}: {1}")]
|
#[error("error while reading directory: {0:?}: {1}")]
|
||||||
@@ -27,12 +34,23 @@ pub enum Error {
|
|||||||
Unicode(PathBuf),
|
Unicode(PathBuf),
|
||||||
#[error("parser error: {0}")]
|
#[error("parser error: {0}")]
|
||||||
Parser(String),
|
Parser(String),
|
||||||
|
#[error("profile error: {0}")]
|
||||||
|
Profile(profile::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Get)]
|
||||||
|
pub struct Arch(#[get(method = "get", kind = "deref")] String);
|
||||||
|
|
||||||
#[derive(Debug, Clone, Get)]
|
#[derive(Debug, Clone, Get)]
|
||||||
pub struct Repo {
|
pub struct Repo {
|
||||||
#[get(kind = "deref")]
|
#[get(kind = "deref")]
|
||||||
path: PathBuf,
|
path: PathBuf,
|
||||||
|
#[get(kind = "deref")]
|
||||||
|
name: String,
|
||||||
|
#[get(kind = "deref")]
|
||||||
|
package_mask: Vec<Atom>,
|
||||||
|
#[get(kind = "deref")]
|
||||||
|
arch_list: Vec<Arch>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Get)]
|
#[derive(Debug, Clone, Get)]
|
||||||
@@ -49,10 +67,39 @@ pub struct Categories(PathBuf, fs::ReadDir);
|
|||||||
pub struct Ebuilds(PathBuf, fs::ReadDir);
|
pub struct Ebuilds(PathBuf, fs::ReadDir);
|
||||||
|
|
||||||
impl Repo {
|
impl Repo {
|
||||||
pub fn new<P: AsRef<Path>>(path: P) -> Self {
|
pub fn new<P: AsRef<Path>>(path: P) -> Result<Self, Error> {
|
||||||
Self {
|
let name_path = path.as_ref().join("profiles/repo_name");
|
||||||
|
let name = match fs::read_to_string(&name_path) {
|
||||||
|
Ok(repo_name) => repo_name,
|
||||||
|
Err(e) if matches!(e.kind(), io::ErrorKind::NotFound) => {
|
||||||
|
return Err(Error::Invalid("missing repo_name".to_string()));
|
||||||
|
}
|
||||||
|
Err(e) => return Err(Error::Io(name_path, e)),
|
||||||
|
};
|
||||||
|
|
||||||
|
let package_mask_path = path.as_ref().join("profiles/package.mask");
|
||||||
|
let package_mask =
|
||||||
|
match fs::read_to_string(&package_mask_path).map(|s| read_package_mask(&s)) {
|
||||||
|
Ok(Ok(package_mask)) => package_mask,
|
||||||
|
Ok(Err(e)) => return Err(e),
|
||||||
|
Err(e) if matches!(e.kind(), io::ErrorKind::NotFound) => Vec::new(),
|
||||||
|
Err(e) => return Err(Error::Io(package_mask_path, e)),
|
||||||
|
};
|
||||||
|
|
||||||
|
let arch_list_path = path.as_ref().join("profiles/arch.list");
|
||||||
|
let arch_list = match fs::read_to_string(&arch_list_path).map(|s| read_arch_list(&s)) {
|
||||||
|
Ok(Ok(arch_list)) => arch_list,
|
||||||
|
Ok(Err(e)) => return Err(e),
|
||||||
|
Err(e) if matches!(e.kind(), io::ErrorKind::NotFound) => Vec::new(),
|
||||||
|
Err(e) => return Err(Error::Io(arch_list_path, e)),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
path: path.as_ref().to_path_buf(),
|
path: path.as_ref().to_path_buf(),
|
||||||
}
|
name,
|
||||||
|
package_mask,
|
||||||
|
arch_list,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn categories(&self) -> Result<Categories, Error> {
|
pub fn categories(&self) -> Result<Categories, Error> {
|
||||||
@@ -63,6 +110,10 @@ impl Repo {
|
|||||||
fs::read_dir(&path).map_err(|e| Error::Io(path, e))?,
|
fs::read_dir(&path).map_err(|e| Error::Io(path, e))?,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn evaluate_profile<P: AsRef<Path>>(&self, path: P) -> Result<Profile, Error> {
|
||||||
|
Profile::evaluate(self.path.join("profiles").join(path)).map_err(Error::Profile)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Category {
|
impl Category {
|
||||||
@@ -316,6 +367,34 @@ fn read_idepend(input: &str) -> Option<Result<Vec<Depend<Atom>>, Error>> {
|
|||||||
Some(parse_depends(line))
|
Some(parse_depends(line))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn read_package_mask(input: &str) -> Result<Vec<Atom>, Error> {
|
||||||
|
Ok(profile::LineBasedFileExpr::<Atom>::parser()
|
||||||
|
.separated_by_with_opt_trailing(ascii_whitespace1())
|
||||||
|
.many()
|
||||||
|
.parse_finished(InputIter::new(input))
|
||||||
|
.map_err(|it| Error::Parser(it.rest().to_string()))?
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(|expr| match expr {
|
||||||
|
LineBasedFileExpr::Comment => None,
|
||||||
|
LineBasedFileExpr::Expr(atom) => Some(atom),
|
||||||
|
})
|
||||||
|
.collect())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_arch_list(input: &str) -> Result<Vec<Arch>, Error> {
|
||||||
|
Ok(LineBasedFileExpr::<Arch>::parser()
|
||||||
|
.separated_by_with_opt_trailing(ascii_whitespace1())
|
||||||
|
.many()
|
||||||
|
.parse_finished(InputIter::new(input))
|
||||||
|
.map_err(|it| Error::Parser(it.rest().to_string()))?
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(|expr| match expr {
|
||||||
|
LineBasedFileExpr::Comment => None,
|
||||||
|
LineBasedFileExpr::Expr(arch) => Some(arch),
|
||||||
|
})
|
||||||
|
.collect())
|
||||||
|
}
|
||||||
|
|
||||||
fn parse_depends(line: &str) -> Result<Vec<Depend<Atom>>, Error> {
|
fn parse_depends(line: &str) -> Result<Vec<Depend<Atom>>, Error> {
|
||||||
Depend::<Atom>::parser()
|
Depend::<Atom>::parser()
|
||||||
.separated_by(ascii_whitespace1())
|
.separated_by(ascii_whitespace1())
|
||||||
|
|||||||
20
src/repo/parsers.rs
Normal file
20
src/repo/parsers.rs
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
use mon::{Parser, ParserIter, ascii_alphanumeric, one_of};
|
||||||
|
|
||||||
|
use crate::{Parseable, repo::Arch};
|
||||||
|
|
||||||
|
impl<'a> Parseable<'a, &'a str> for Arch {
|
||||||
|
type Parser = impl Parser<&'a str, Output = Self>;
|
||||||
|
|
||||||
|
fn parser() -> Self::Parser {
|
||||||
|
let start = ascii_alphanumeric();
|
||||||
|
let rest = ascii_alphanumeric()
|
||||||
|
.or(one_of("-".chars()))
|
||||||
|
.repeated()
|
||||||
|
.many();
|
||||||
|
|
||||||
|
start
|
||||||
|
.and(rest)
|
||||||
|
.recognize()
|
||||||
|
.map(|output: &str| Arch(output.to_string()))
|
||||||
|
}
|
||||||
|
}
|
||||||
1
src/repo/profile/make_defaults/meson.build
Normal file
1
src/repo/profile/make_defaults/meson.build
Normal file
@@ -0,0 +1 @@
|
|||||||
|
sources += files('mod.rs', 'parsers.rs')
|
||||||
135
src/repo/profile/make_defaults/mod.rs
Normal file
135
src/repo/profile/make_defaults/mod.rs
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
use std::{
|
||||||
|
collections::{HashMap, HashSet},
|
||||||
|
fs, io,
|
||||||
|
path::{Path, PathBuf},
|
||||||
|
};
|
||||||
|
|
||||||
|
use mon::{Parser, ParserIter, ascii_whitespace1, input::InputIter};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
Parseable,
|
||||||
|
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, PartialEq, Eq, Hash)]
|
||||||
|
struct Key(String);
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
struct Literal(String);
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
struct Interpolation(String);
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
enum Segment {
|
||||||
|
Literal(Literal),
|
||||||
|
Interpolation(Interpolation),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
struct Assignment(Key, Vec<Segment>);
|
||||||
|
|
||||||
|
pub(super) fn evaluate<P: AsRef<Path>>(
|
||||||
|
parents: &[Profile],
|
||||||
|
path: P,
|
||||||
|
) -> Result<HashMap<String, String>, Error> {
|
||||||
|
let parsed = match fs::read_to_string(path.as_ref().join("make.defaults")) {
|
||||||
|
Ok(contents) => parse(&contents)?,
|
||||||
|
Err(e) if matches!(e.kind(), io::ErrorKind::NotFound) => HashMap::new(),
|
||||||
|
Err(e) => return Err(Error::Io(path.as_ref().to_path_buf(), e)),
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut vars = interpolate(parents, parsed);
|
||||||
|
|
||||||
|
incremental(parents, &mut vars);
|
||||||
|
|
||||||
|
Ok(vars)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn incremental(parents: &[Profile], vars: &mut HashMap<String, String>) {
|
||||||
|
for key in [
|
||||||
|
"USE",
|
||||||
|
"USE_EXPAND",
|
||||||
|
"USE_EXPAND_HIDDEN",
|
||||||
|
"CONFIG_PROTECT",
|
||||||
|
"CONFIG_PROTECT_MASK",
|
||||||
|
] {
|
||||||
|
let mut accumulated = Vec::new();
|
||||||
|
|
||||||
|
for parent in parents {
|
||||||
|
if let Some(values) = parent.make_defaults().get(key) {
|
||||||
|
accumulated.extend(values.split_ascii_whitespace());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(values) = vars.get(key) {
|
||||||
|
accumulated.extend(values.split_ascii_whitespace());
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut final_values = Vec::new();
|
||||||
|
|
||||||
|
for var in accumulated {
|
||||||
|
if var == "-*" {
|
||||||
|
final_values.clear();
|
||||||
|
} else if let Some(stripped) = var.strip_prefix("-") {
|
||||||
|
final_values.retain(|v| *v != stripped);
|
||||||
|
} else {
|
||||||
|
final_values.push(var);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut seen = HashSet::new();
|
||||||
|
final_values.retain(|v| seen.insert(*v));
|
||||||
|
|
||||||
|
if !final_values.is_empty() {
|
||||||
|
vars.insert(key.to_string(), final_values.join(" "));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn interpolate(parents: &[Profile], vars: HashMap<Key, Vec<Segment>>) -> HashMap<String, String> {
|
||||||
|
let parent_vars = parents
|
||||||
|
.iter()
|
||||||
|
.flat_map(|parent| parent.make_defaults().clone().into_iter())
|
||||||
|
.collect::<HashMap<_, _>>();
|
||||||
|
|
||||||
|
vars.into_iter()
|
||||||
|
.map(|(key, segments)| {
|
||||||
|
let interpolated = segments
|
||||||
|
.into_iter()
|
||||||
|
.map(|segment| match segment {
|
||||||
|
Segment::Interpolation(i) => parent_vars.get(&i.0).cloned().unwrap_or_default(),
|
||||||
|
Segment::Literal(literal) => literal.0.trim().to_string(),
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let joined = interpolated.join("");
|
||||||
|
|
||||||
|
(key.0, joined)
|
||||||
|
})
|
||||||
|
.collect::<HashMap<String, String>>()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse(contents: &str) -> Result<HashMap<Key, Vec<Segment>>, Error> {
|
||||||
|
Ok(LineBasedFileExpr::<Assignment>::parser()
|
||||||
|
.separated_by_with_opt_trailing(ascii_whitespace1())
|
||||||
|
.many()
|
||||||
|
.parse_finished(InputIter::new(contents))
|
||||||
|
.map_err(|e| Error::Parser(dbg!(e).rest().to_string()))?
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(|expr| match expr {
|
||||||
|
LineBasedFileExpr::Comment => None,
|
||||||
|
LineBasedFileExpr::Expr(Assignment(key, value)) => Some((key, value)),
|
||||||
|
})
|
||||||
|
.collect())
|
||||||
|
}
|
||||||
88
src/repo/profile/make_defaults/parsers.rs
Normal file
88
src/repo/profile/make_defaults/parsers.rs
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
use mon::{Parser, ParserIter, ascii_alpha, ascii_alphanumeric, r#if, one_of, tag};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
Parseable,
|
||||||
|
repo::profile::make_defaults::{Assignment, Interpolation, Key, Literal, Segment},
|
||||||
|
};
|
||||||
|
|
||||||
|
impl<'a> Parseable<'a, &'a str> for Key {
|
||||||
|
type Parser = impl Parser<&'a str, Output = Self>;
|
||||||
|
|
||||||
|
fn parser() -> Self::Parser {
|
||||||
|
let start = ascii_alpha();
|
||||||
|
let rest = ascii_alphanumeric()
|
||||||
|
.or(one_of("_".chars()))
|
||||||
|
.repeated()
|
||||||
|
.many();
|
||||||
|
|
||||||
|
start
|
||||||
|
.followed_by(rest)
|
||||||
|
.recognize()
|
||||||
|
.map(|output: &str| Key(output.to_string()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Parseable<'a, &'a str> for Literal {
|
||||||
|
type Parser = impl Parser<&'a str, Output = Self>;
|
||||||
|
|
||||||
|
fn parser() -> Self::Parser {
|
||||||
|
r#if(|c: &char| *c != '"')
|
||||||
|
.and_not(Interpolation::parser())
|
||||||
|
.repeated()
|
||||||
|
.at_least(1)
|
||||||
|
.recognize()
|
||||||
|
.map(|output: &str| Literal(output.to_string()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Parseable<'a, &'a str> for Interpolation {
|
||||||
|
type Parser = impl Parser<&'a str, Output = Self>;
|
||||||
|
|
||||||
|
fn parser() -> Self::Parser {
|
||||||
|
Key::parser()
|
||||||
|
.recognize()
|
||||||
|
.delimited_by(tag("{"), tag("}"))
|
||||||
|
.preceded_by(tag("$"))
|
||||||
|
.map(|output: &str| Interpolation(output.to_string()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Parseable<'a, &'a str> for Segment {
|
||||||
|
type Parser = impl Parser<&'a str, Output = Self>;
|
||||||
|
|
||||||
|
fn parser() -> Self::Parser {
|
||||||
|
Literal::parser()
|
||||||
|
.map(Segment::Literal)
|
||||||
|
.or(Interpolation::parser().map(Segment::Interpolation))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Parseable<'a, &'a str> for Assignment {
|
||||||
|
type Parser = impl Parser<&'a str, Output = Self>;
|
||||||
|
|
||||||
|
fn parser() -> Self::Parser {
|
||||||
|
Key::parser()
|
||||||
|
.followed_by(tag("="))
|
||||||
|
.and(
|
||||||
|
Segment::parser()
|
||||||
|
.repeated()
|
||||||
|
.many()
|
||||||
|
.delimited_by(tag("\""), tag("\"")),
|
||||||
|
)
|
||||||
|
.map(|(key, value)| Assignment(key, value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use mon::input::InputIter;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parse_value() {
|
||||||
|
let it = InputIter::new(r#"KEY="foo ${bar}""#);
|
||||||
|
|
||||||
|
Assignment::parser().check_finished(it).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
6
src/repo/profile/meson.build
Normal file
6
src/repo/profile/meson.build
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
sources += files('mod.rs', 'parsers.rs')
|
||||||
|
|
||||||
|
subdir('make_defaults')
|
||||||
|
subdir('package')
|
||||||
|
subdir('packages')
|
||||||
|
subdir('useflags')
|
||||||
194
src/repo/profile/mod.rs
Normal file
194
src/repo/profile/mod.rs
Normal file
@@ -0,0 +1,194 @@
|
|||||||
|
//! Evaluate profiles:
|
||||||
|
//! ```rust
|
||||||
|
//! use gentoo_utils::repo::Repo;
|
||||||
|
//!
|
||||||
|
//! let repo = Repo::new("/var/db/repos/gentoo")
|
||||||
|
//! .expect("failed to open repo");
|
||||||
|
//! let profile = repo.evaluate_profile("default/linux/23.0")
|
||||||
|
//! .expect("failed to evaluate profile");
|
||||||
|
//!
|
||||||
|
//! for (key, value) in profile.make_defaults() {
|
||||||
|
//! println!("{key} = {value}");
|
||||||
|
//! }
|
||||||
|
//! ```
|
||||||
|
|
||||||
|
use std::{
|
||||||
|
collections::HashMap,
|
||||||
|
fs::{self, File},
|
||||||
|
io::{self, Read},
|
||||||
|
path::{Path, PathBuf},
|
||||||
|
};
|
||||||
|
|
||||||
|
use get::Get;
|
||||||
|
use itertools::Itertools;
|
||||||
|
|
||||||
|
use crate::{Parseable, atom::Atom, repo::ebuild::Eapi, useflag::UseFlag};
|
||||||
|
|
||||||
|
mod make_defaults;
|
||||||
|
mod package;
|
||||||
|
mod package_use;
|
||||||
|
mod packages;
|
||||||
|
mod parsers;
|
||||||
|
mod useflags;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub(super) enum LineBasedFileExpr<T> {
|
||||||
|
Comment,
|
||||||
|
Expr(T),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
enum FlagOperation {
|
||||||
|
Add(UseFlag),
|
||||||
|
Remove(UseFlag),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, thiserror::Error)]
|
||||||
|
pub enum Error {
|
||||||
|
#[error("{0}: io error: {1}")]
|
||||||
|
Io(PathBuf, io::Error),
|
||||||
|
#[error("error evaluating make.defaults settings: {0}")]
|
||||||
|
MakeDefaults(#[from] make_defaults::Error),
|
||||||
|
#[error("error evaluating packages settings: {0}")]
|
||||||
|
Packages(#[from] packages::Error),
|
||||||
|
#[error("error evaluating package settings: {0}")]
|
||||||
|
Package(#[from] package::Error),
|
||||||
|
#[error("error evaluating package.use settings: {0}")]
|
||||||
|
PackageUse(#[from] package_use::Error),
|
||||||
|
#[error("error evaluating use settings: {0}")]
|
||||||
|
Use(#[from] useflags::Error),
|
||||||
|
#[error("parser error: {0}")]
|
||||||
|
Parser(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Get)]
|
||||||
|
pub struct Profile {
|
||||||
|
#[get(kind = "deref")]
|
||||||
|
path: PathBuf,
|
||||||
|
eapi: Eapi,
|
||||||
|
deprecated: Option<String>,
|
||||||
|
#[get(kind = "deref")]
|
||||||
|
parents: Vec<Profile>,
|
||||||
|
make_defaults: HashMap<String, String>,
|
||||||
|
#[get(kind = "deref")]
|
||||||
|
packages: Vec<Atom>,
|
||||||
|
#[get(kind = "deref")]
|
||||||
|
package_mask: Vec<Atom>,
|
||||||
|
#[get(kind = "deref")]
|
||||||
|
package_provided: Vec<Atom>,
|
||||||
|
package_use: HashMap<Atom, Vec<UseFlag>>,
|
||||||
|
package_use_force: HashMap<Atom, Vec<UseFlag>>,
|
||||||
|
package_use_mask: HashMap<Atom, Vec<UseFlag>>,
|
||||||
|
package_use_stable_force: HashMap<Atom, Vec<UseFlag>>,
|
||||||
|
package_use_stable_mask: HashMap<Atom, Vec<UseFlag>>,
|
||||||
|
#[get(kind = "deref")]
|
||||||
|
use_force: Vec<UseFlag>,
|
||||||
|
#[get(kind = "deref")]
|
||||||
|
use_mask: Vec<UseFlag>,
|
||||||
|
#[get(kind = "deref")]
|
||||||
|
use_stable_force: Vec<UseFlag>,
|
||||||
|
#[get(kind = "deref")]
|
||||||
|
use_stable_mask: Vec<UseFlag>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Profile {
|
||||||
|
pub(super) fn evaluate<P: AsRef<Path>>(path: P) -> Result<Self, Error> {
|
||||||
|
let parents_path = path.as_ref().join("parent");
|
||||||
|
|
||||||
|
let parents = match fs::read_to_string(&parents_path) {
|
||||||
|
Ok(parents) => parents
|
||||||
|
.lines()
|
||||||
|
.map(|line| path.as_ref().join(line))
|
||||||
|
.map(Profile::evaluate)
|
||||||
|
.collect::<Result<_, _>>()?,
|
||||||
|
Err(e) if matches!(e.kind(), io::ErrorKind::NotFound) => Vec::new(),
|
||||||
|
Err(e) => return Err(Error::Io(parents_path, e)),
|
||||||
|
};
|
||||||
|
|
||||||
|
let eapi_path = path.as_ref().join("eapi");
|
||||||
|
let eapi = match fs::read_to_string(&eapi_path)
|
||||||
|
.map(|s| Eapi::parse(s.trim()).map_err(str::to_string))
|
||||||
|
{
|
||||||
|
Ok(Ok(eapi)) => eapi,
|
||||||
|
jturnerusa marked this conversation as resolved
Outdated
|
|||||||
|
Ok(Err(rest)) => return Err(Error::Parser(rest)),
|
||||||
|
Err(e) if matches!(e.kind(), io::ErrorKind::NotFound) => Eapi::parse("0").unwrap(),
|
||||||
|
Err(e) => return Err(Error::Io(eapi_path, e)),
|
||||||
|
};
|
||||||
|
|
||||||
|
let deprecated_path = path.as_ref().join("deprecated");
|
||||||
|
let deprecated = match fs::read_to_string(&deprecated_path) {
|
||||||
|
Ok(string) => Some(string),
|
||||||
|
Err(e) if matches!(e.kind(), io::ErrorKind::NotFound) => None,
|
||||||
|
Err(e) => return Err(Error::Io(deprecated_path, e)),
|
||||||
|
};
|
||||||
|
|
||||||
|
let make_defaults = make_defaults::evaluate(&parents, &path)?;
|
||||||
|
|
||||||
|
let packages = packages::evaluate(&parents, &path)?;
|
||||||
|
|
||||||
|
let package_mask = package::evaluate(&parents, package::Kind::Mask, &path)?;
|
||||||
|
let package_provided = package::evaluate(&parents, package::Kind::Provided, &path)?;
|
||||||
|
|
||||||
|
let package_use = package_use::evaluate(&parents, package_use::Kind::Use, &path)?;
|
||||||
|
let package_use_force = package_use::evaluate(&parents, package_use::Kind::Force, &path)?;
|
||||||
|
let package_use_mask = package_use::evaluate(&parents, package_use::Kind::Mask, &path)?;
|
||||||
|
let package_use_stable_force =
|
||||||
|
package_use::evaluate(&parents, package_use::Kind::StableForce, &path)?;
|
||||||
|
let package_use_stable_mask =
|
||||||
|
package_use::evaluate(&parents, package_use::Kind::StableMask, &path)?;
|
||||||
|
|
||||||
|
let use_force = useflags::evaluate(&parents, useflags::Kind::Force, &path)?;
|
||||||
|
let use_mask = useflags::evaluate(&parents, useflags::Kind::Mask, &path)?;
|
||||||
|
let use_stable_force = useflags::evaluate(&parents, useflags::Kind::StableForce, &path)?;
|
||||||
|
let use_stable_mask = useflags::evaluate(&parents, useflags::Kind::StableMask, &path)?;
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
path: path.as_ref().to_path_buf(),
|
||||||
|
parents,
|
||||||
|
eapi,
|
||||||
|
deprecated,
|
||||||
|
make_defaults,
|
||||||
|
packages,
|
||||||
|
package_mask,
|
||||||
|
package_provided,
|
||||||
|
package_use,
|
||||||
|
package_use_force,
|
||||||
|
package_use_mask,
|
||||||
|
package_use_stable_force,
|
||||||
|
package_use_stable_mask,
|
||||||
|
use_force,
|
||||||
|
use_mask,
|
||||||
|
use_stable_force,
|
||||||
|
use_stable_mask,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_config_files<P: AsRef<Path>>(path: P) -> Result<String, io::Error> {
|
||||||
|
let metadata = fs::metadata(&path)?;
|
||||||
|
|
||||||
|
if metadata.is_file() {
|
||||||
|
fs::read_to_string(&path)
|
||||||
|
} else if metadata.is_dir() {
|
||||||
|
let mut buffer = String::new();
|
||||||
|
let paths = fs::read_dir(&path)?
|
||||||
|
.collect::<Result<Vec<_>, _>>()?
|
||||||
|
.into_iter()
|
||||||
|
.map(|entry| entry.path())
|
||||||
|
.filter(|path| path.starts_with("."))
|
||||||
|
.sorted()
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
for path in &paths {
|
||||||
|
let mut file = File::open(path)?;
|
||||||
|
|
||||||
|
file.read_to_string(&mut buffer)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(buffer)
|
||||||
|
} else {
|
||||||
|
let path = fs::canonicalize(&path)?;
|
||||||
|
|
||||||
|
read_config_files(path)
|
||||||
|
}
|
||||||
|
}
|
||||||
1
src/repo/profile/package/meson.build
Normal file
1
src/repo/profile/package/meson.build
Normal file
@@ -0,0 +1 @@
|
|||||||
|
sources += files('mod.rs', 'parsers.rs')
|
||||||
95
src/repo/profile/package/mod.rs
Normal file
95
src/repo/profile/package/mod.rs
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
use std::{
|
||||||
|
io,
|
||||||
|
path::{Path, PathBuf},
|
||||||
|
};
|
||||||
|
|
||||||
|
use mon::{Parser, ParserIter, ascii_whitespace1, input::InputIter};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
Parseable,
|
||||||
|
atom::Atom,
|
||||||
|
repo::profile::{LineBasedFileExpr, Profile, read_config_files},
|
||||||
|
};
|
||||||
|
|
||||||
|
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, Copy)]
|
||||||
|
pub(super) enum Kind {
|
||||||
|
Mask,
|
||||||
|
Provided,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
enum Package {
|
||||||
|
Add(Atom),
|
||||||
|
Remove(Atom),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn evaluate<P: AsRef<Path>>(
|
||||||
|
parents: &[Profile],
|
||||||
|
kind: Kind,
|
||||||
|
path: P,
|
||||||
|
) -> Result<Vec<Atom>, Error> {
|
||||||
|
let file_path = match kind {
|
||||||
|
Kind::Mask => "package.mask",
|
||||||
|
Kind::Provided => "package.provided",
|
||||||
|
};
|
||||||
|
|
||||||
|
let parsed = match read_config_files(path.as_ref().join(file_path)) {
|
||||||
|
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, kind, parsed))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn inherit(parents: &[Profile], kind: Kind, packages: Vec<Package>) -> Vec<Atom> {
|
||||||
|
let mut accumulated = Vec::new();
|
||||||
|
|
||||||
|
for parent in parents {
|
||||||
|
let source = match kind {
|
||||||
|
Kind::Mask => parent.package_mask(),
|
||||||
|
Kind::Provided => parent.package_provided(),
|
||||||
|
};
|
||||||
|
|
||||||
|
for package in source {
|
||||||
|
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())
|
||||||
|
}
|
||||||
13
src/repo/profile/package/parsers.rs
Normal file
13
src/repo/profile/package/parsers.rs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
use mon::{Parser, tag};
|
||||||
|
|
||||||
|
use crate::{Parseable, atom::Atom, repo::profile::package::Package};
|
||||||
|
|
||||||
|
impl<'a> Parseable<'a, &'a str> for Package {
|
||||||
|
type Parser = impl Parser<&'a str, Output = Self>;
|
||||||
|
|
||||||
|
fn parser() -> Self::Parser {
|
||||||
|
Atom::parser()
|
||||||
|
.map(Package::Add)
|
||||||
|
.or(Atom::parser().preceded_by(tag("-")).map(Package::Remove))
|
||||||
|
}
|
||||||
|
}
|
||||||
1
src/repo/profile/package_use/meson.build
Normal file
1
src/repo/profile/package_use/meson.build
Normal file
@@ -0,0 +1 @@
|
|||||||
|
sources += files('mod.rs', 'parsers.rs')
|
||||||
125
src/repo/profile/package_use/mod.rs
Normal file
125
src/repo/profile/package_use/mod.rs
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
use std::{
|
||||||
|
collections::HashMap,
|
||||||
|
io,
|
||||||
|
path::{Path, PathBuf},
|
||||||
|
};
|
||||||
|
|
||||||
|
use mon::{Parser, ParserIter, ascii_whitespace1, input::InputIter};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
Parseable,
|
||||||
|
atom::Atom,
|
||||||
|
repo::profile::{FlagOperation, LineBasedFileExpr, Profile, read_config_files},
|
||||||
|
useflag::UseFlag,
|
||||||
|
};
|
||||||
|
|
||||||
|
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)]
|
||||||
|
struct Expr(Atom, Vec<FlagOperation>);
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub(super) enum Kind {
|
||||||
|
Use,
|
||||||
|
Force,
|
||||||
|
Mask,
|
||||||
|
StableForce,
|
||||||
|
StableMask,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn evaluate<P: AsRef<Path>>(
|
||||||
|
parents: &[Profile],
|
||||||
|
kind: Kind,
|
||||||
|
path: P,
|
||||||
|
) -> Result<HashMap<Atom, Vec<UseFlag>>, Error> {
|
||||||
|
let file_path = match kind {
|
||||||
|
Kind::Use => "package.use",
|
||||||
|
Kind::Force => "package.use.force",
|
||||||
|
Kind::Mask => "package.use.mask",
|
||||||
|
Kind::StableForce => "package.use.stable.force",
|
||||||
|
Kind::StableMask => "package.use.stable.mask",
|
||||||
|
};
|
||||||
|
|
||||||
|
let parsed = match read_config_files(path.as_ref().join(file_path)) {
|
||||||
|
Ok(contents) => parse(&contents)?,
|
||||||
|
Err(e) if matches!(e.kind(), io::ErrorKind::NotFound) => HashMap::new(),
|
||||||
|
Err(e) => return Err(Error::Io(path.as_ref().to_path_buf(), e)),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(inherit(parents, kind, parsed))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn inherit(
|
||||||
|
parents: &[Profile],
|
||||||
|
kind: Kind,
|
||||||
|
vars: HashMap<Atom, Vec<FlagOperation>>,
|
||||||
|
) -> HashMap<Atom, Vec<UseFlag>> {
|
||||||
|
let mut accumulated: HashMap<Atom, Vec<UseFlag>> = HashMap::new();
|
||||||
|
|
||||||
|
for parent in parents {
|
||||||
|
let source = match kind {
|
||||||
|
Kind::Use => parent.package_use(),
|
||||||
|
Kind::Force => parent.package_use_force(),
|
||||||
|
Kind::Mask => parent.package_use_mask(),
|
||||||
|
Kind::StableForce => parent.package_use_stable_force(),
|
||||||
|
Kind::StableMask => parent.package_use_stable_mask(),
|
||||||
|
};
|
||||||
|
|
||||||
|
for (atom, flags) in source {
|
||||||
|
accumulated
|
||||||
|
.entry(atom.clone())
|
||||||
|
.and_modify(|f| f.extend(flags.iter().cloned()))
|
||||||
|
.or_insert(flags.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (atom, flags) in vars {
|
||||||
|
match accumulated.get_mut(&atom) {
|
||||||
|
Some(accumulated) => {
|
||||||
|
for flag in flags {
|
||||||
|
match flag {
|
||||||
|
FlagOperation::Add(flag) => accumulated.push(flag),
|
||||||
|
FlagOperation::Remove(flag) => accumulated.retain(|v| *v != flag),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
accumulated.insert(
|
||||||
|
atom.clone(),
|
||||||
|
flags
|
||||||
|
.iter()
|
||||||
|
.filter_map(|flag| match flag {
|
||||||
|
FlagOperation::Add(flag) => Some(flag),
|
||||||
|
FlagOperation::Remove(_) => None,
|
||||||
|
})
|
||||||
|
.cloned()
|
||||||
|
.collect(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
accumulated
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse(contents: &str) -> Result<HashMap<Atom, Vec<FlagOperation>>, Error> {
|
||||||
|
Ok(LineBasedFileExpr::<Expr>::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(Expr(atom, operations)) => Some((atom, operations)),
|
||||||
|
})
|
||||||
|
.collect())
|
||||||
|
}
|
||||||
36
src/repo/profile/package_use/parsers.rs
Normal file
36
src/repo/profile/package_use/parsers.rs
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
use mon::{Parser, ParserIter, ascii_whitespace, ascii_whitespace1, tag};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
Parseable,
|
||||||
|
atom::Atom,
|
||||||
|
repo::profile::{FlagOperation, package_use::Expr},
|
||||||
|
};
|
||||||
|
|
||||||
|
impl<'a> Parseable<'a, &'a str> for Expr {
|
||||||
|
type Parser = impl Parser<&'a str, Output = Self>;
|
||||||
|
|
||||||
|
fn parser() -> Self::Parser {
|
||||||
|
Atom::parser()
|
||||||
|
.followed_by(ascii_whitespace1())
|
||||||
|
.and(
|
||||||
|
FlagOperation::parser()
|
||||||
|
.separated_by(ascii_whitespace().and_not(tag("\n")).repeated().at_least(1))
|
||||||
|
.at_least(1),
|
||||||
|
)
|
||||||
|
.map(|(atom, operations)| Expr(atom, operations))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use mon::input::InputIter;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parse_expr() {
|
||||||
|
let it = InputIter::new("foo/bar a -b");
|
||||||
|
|
||||||
|
Expr::parser().check_finished(it).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
1
src/repo/profile/packages/meson.build
Normal file
1
src/repo/profile/packages/meson.build
Normal file
@@ -0,0 +1 @@
|
|||||||
|
sources += files('mod.rs', 'parsers.rs')
|
||||||
75
src/repo/profile/packages/mod.rs
Normal file
75
src/repo/profile/packages/mod.rs
Normal file
@@ -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())
|
||||||
|
}
|
||||||
14
src/repo/profile/packages/parsers.rs
Normal file
14
src/repo/profile/packages/parsers.rs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
use mon::{Parser, tag};
|
||||||
|
|
||||||
|
use crate::{Parseable, atom::Atom, repo::profile::packages::Package};
|
||||||
|
|
||||||
|
impl<'a> Parseable<'a, &'a str> for Package {
|
||||||
|
type Parser = impl Parser<&'a str, Output = Self>;
|
||||||
|
|
||||||
|
fn parser() -> Self::Parser {
|
||||||
|
Atom::parser()
|
||||||
|
.preceded_by(tag("*"))
|
||||||
|
.map(Package::Add)
|
||||||
|
.or(Atom::parser().preceded_by(tag("-*")).map(Package::Remove))
|
||||||
|
}
|
||||||
|
}
|
||||||
35
src/repo/profile/parsers.rs
Normal file
35
src/repo/profile/parsers.rs
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
use mon::{Parser, ParserIter, any, ascii_whitespace1, tag};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
Parseable,
|
||||||
|
repo::profile::{FlagOperation, LineBasedFileExpr},
|
||||||
|
useflag::UseFlag,
|
||||||
|
};
|
||||||
|
|
||||||
|
impl<'a, T> Parseable<'a, &'a str> for LineBasedFileExpr<T>
|
||||||
|
where
|
||||||
|
T: Parseable<'a, &'a str>,
|
||||||
|
{
|
||||||
|
type Parser = impl Parser<&'a str, Output = Self>;
|
||||||
|
|
||||||
|
fn parser() -> Self::Parser {
|
||||||
|
let comment = tag("#")
|
||||||
|
.preceded_by(ascii_whitespace1().opt())
|
||||||
|
.followed_by(any().and_not(tag("\n")).repeated().many())
|
||||||
|
.map(|_| LineBasedFileExpr::Comment);
|
||||||
|
let expr = T::parser().map(|expr| LineBasedFileExpr::Expr(expr));
|
||||||
|
|
||||||
|
comment.or(expr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Parseable<'a, &'a str> for FlagOperation {
|
||||||
|
type Parser = impl Parser<&'a str, Output = Self>;
|
||||||
|
|
||||||
|
fn parser() -> Self::Parser {
|
||||||
|
UseFlag::parser()
|
||||||
|
.preceded_by(tag("-"))
|
||||||
|
.map(FlagOperation::Remove)
|
||||||
|
.or(UseFlag::parser().map(FlagOperation::Add))
|
||||||
|
}
|
||||||
|
}
|
||||||
1
src/repo/profile/useflags/meson.build
Normal file
1
src/repo/profile/useflags/meson.build
Normal file
@@ -0,0 +1 @@
|
|||||||
|
sources += files('mod.rs')
|
||||||
94
src/repo/profile/useflags/mod.rs
Normal file
94
src/repo/profile/useflags/mod.rs
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
use std::{
|
||||||
|
io,
|
||||||
|
path::{Path, PathBuf},
|
||||||
|
};
|
||||||
|
|
||||||
|
use mon::{Parser, ParserIter, ascii_whitespace1, input::InputIter};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
Parseable,
|
||||||
|
repo::profile::{FlagOperation, LineBasedFileExpr, Profile, read_config_files},
|
||||||
|
useflag::UseFlag,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[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, Copy)]
|
||||||
|
pub(super) enum Kind {
|
||||||
|
Force,
|
||||||
|
Mask,
|
||||||
|
StableForce,
|
||||||
|
StableMask,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::unnecessary_wraps)]
|
||||||
|
pub(super) fn evaluate<P: AsRef<Path>>(
|
||||||
|
parents: &[Profile],
|
||||||
|
kind: Kind,
|
||||||
|
path: P,
|
||||||
|
) -> Result<Vec<UseFlag>, Error> {
|
||||||
|
let file_path = match kind {
|
||||||
|
Kind::Force => "use.force",
|
||||||
|
Kind::Mask => "use.mask",
|
||||||
|
Kind::StableForce => "use.stable.force",
|
||||||
|
Kind::StableMask => "use.stable.mask",
|
||||||
|
};
|
||||||
|
|
||||||
|
let parsed = match read_config_files(path.as_ref().join(file_path)) {
|
||||||
|
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, kind, parsed))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn inherit(parents: &[Profile], kind: Kind, operations: Vec<FlagOperation>) -> Vec<UseFlag> {
|
||||||
|
let mut accumulated = Vec::new();
|
||||||
|
|
||||||
|
for parent in parents {
|
||||||
|
let source = match kind {
|
||||||
|
Kind::Force => parent.use_force(),
|
||||||
|
Kind::Mask => parent.use_mask(),
|
||||||
|
Kind::StableForce => parent.use_stable_force(),
|
||||||
|
Kind::StableMask => parent.use_stable_mask(),
|
||||||
|
};
|
||||||
|
|
||||||
|
for flag in source {
|
||||||
|
accumulated.push(flag.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for operation in operations {
|
||||||
|
match operation {
|
||||||
|
FlagOperation::Add(flag) => {
|
||||||
|
accumulated.push(flag);
|
||||||
|
}
|
||||||
|
FlagOperation::Remove(flag) => {
|
||||||
|
accumulated.retain(|v| *v != flag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
accumulated
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse(contents: &str) -> Result<Vec<FlagOperation>, Error> {
|
||||||
|
Ok(LineBasedFileExpr::<FlagOperation>::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(flag_operation) => Some(flag_operation),
|
||||||
|
})
|
||||||
|
.collect())
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@ tests = {}
|
|||||||
|
|
||||||
subdir('porthole')
|
subdir('porthole')
|
||||||
subdir('repo')
|
subdir('repo')
|
||||||
|
subdir('profile')
|
||||||
|
|
||||||
foreach test, test_args : tests
|
foreach test, test_args : tests
|
||||||
stem = fs.stem(test)
|
stem = fs.stem(test)
|
||||||
@@ -15,5 +16,6 @@ foreach test, test_args : tests
|
|||||||
link_with: [gentoo_utils],
|
link_with: [gentoo_utils],
|
||||||
),
|
),
|
||||||
args: test_args,
|
args: test_args,
|
||||||
|
timeout: 0,
|
||||||
)
|
)
|
||||||
endforeach
|
endforeach
|
||||||
|
|||||||
7
tests/profile/meson.build
Normal file
7
tests/profile/meson.build
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
tests += {meson.current_source_dir() / 'read_all_profiles.rs': []}
|
||||||
|
tests += {
|
||||||
|
meson.current_source_dir() / 'read_mock_profile.rs': [
|
||||||
|
meson.current_source_dir() / 'mockrepo',
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
2
tests/profile/mockrepo/profiles/arch.list
Normal file
2
tests/profile/mockrepo/profiles/arch.list
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
amd64
|
||||||
|
aarch64
|
||||||
1
tests/profile/mockrepo/profiles/base/make.defaults
Normal file
1
tests/profile/mockrepo/profiles/base/make.defaults
Normal file
@@ -0,0 +1 @@
|
|||||||
|
USE="base"
|
||||||
1
tests/profile/mockrepo/profiles/base/use.force
Normal file
1
tests/profile/mockrepo/profiles/base/use.force
Normal file
@@ -0,0 +1 @@
|
|||||||
|
base
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
app-editors/emacs gui
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
..
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
gui
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
USE="emacs"
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
app-editors/vim
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
app-editors/emacs default
|
||||||
1
tests/profile/mockrepo/profiles/features/emacs/packages
Normal file
1
tests/profile/mockrepo/profiles/features/emacs/packages
Normal file
@@ -0,0 +1 @@
|
|||||||
|
*app-editors/emacs
|
||||||
1
tests/profile/mockrepo/profiles/features/emacs/use.force
Normal file
1
tests/profile/mockrepo/profiles/features/emacs/use.force
Normal file
@@ -0,0 +1 @@
|
|||||||
|
default
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
USE="selinux"
|
||||||
|
SELINUX_TYPE="sys.subj.portage"
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
*sec-policy/selinux-base
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
caps
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
jit
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
USE="-base"
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
app-editors/emacs -default
|
||||||
3
tests/profile/mockrepo/profiles/gentoo-desktop/parent
Normal file
3
tests/profile/mockrepo/profiles/gentoo-desktop/parent
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
../base
|
||||||
|
../features/selinux
|
||||||
|
../features/emacs/gui
|
||||||
1
tests/profile/mockrepo/profiles/gentoo-desktop/use.mask
Normal file
1
tests/profile/mockrepo/profiles/gentoo-desktop/use.mask
Normal file
@@ -0,0 +1 @@
|
|||||||
|
-jit
|
||||||
1
tests/profile/mockrepo/profiles/package.mask
Normal file
1
tests/profile/mockrepo/profiles/package.mask
Normal file
@@ -0,0 +1 @@
|
|||||||
|
app-editors/vim
|
||||||
1
tests/profile/mockrepo/profiles/repo_name
Normal file
1
tests/profile/mockrepo/profiles/repo_name
Normal file
@@ -0,0 +1 @@
|
|||||||
|
mockrepo
|
||||||
483
tests/profile/read_all_profiles.rs
Normal file
483
tests/profile/read_all_profiles.rs
Normal file
@@ -0,0 +1,483 @@
|
|||||||
|
use gentoo_utils::repo::Repo;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let profiles = [
|
||||||
|
"default/linux/alpha/23.0",
|
||||||
|
"default/linux/alpha/23.0/systemd",
|
||||||
|
"default/linux/alpha/23.0/desktop",
|
||||||
|
"default/linux/alpha/23.0/desktop/gnome",
|
||||||
|
"default/linux/alpha/23.0/desktop/gnome/systemd",
|
||||||
|
"default/linux/alpha/23.0/split-usr",
|
||||||
|
"default/linux/alpha/23.0/split-usr/desktop",
|
||||||
|
"default/linux/alpha/23.0/split-usr/desktop/gnome",
|
||||||
|
"default/linux/amd64/23.0",
|
||||||
|
"default/linux/amd64/23.0/systemd",
|
||||||
|
"default/linux/amd64/23.0/desktop",
|
||||||
|
"default/linux/amd64/23.0/desktop/systemd",
|
||||||
|
"default/linux/amd64/23.0/desktop/gnome",
|
||||||
|
"default/linux/amd64/23.0/desktop/gnome/systemd",
|
||||||
|
"default/linux/amd64/23.0/desktop/plasma",
|
||||||
|
"default/linux/amd64/23.0/desktop/plasma/systemd",
|
||||||
|
"default/linux/amd64/23.0/no-multilib",
|
||||||
|
"default/linux/amd64/23.0/no-multilib/systemd",
|
||||||
|
"default/linux/amd64/23.0/no-multilib/hardened",
|
||||||
|
"default/linux/amd64/23.0/no-multilib/hardened/systemd",
|
||||||
|
"default/linux/amd64/23.0/no-multilib/hardened/selinux",
|
||||||
|
"default/linux/amd64/23.0/no-multilib/hardened/selinux/systemd",
|
||||||
|
"default/linux/amd64/23.0/no-multilib/prefix",
|
||||||
|
"default/linux/amd64/23.0/no-multilib/prefix/kernel-2.6.32+",
|
||||||
|
"default/linux/amd64/23.0/no-multilib/prefix/kernel-2.6.16+",
|
||||||
|
"default/linux/amd64/23.0/no-multilib/prefix/kernel-3.2+",
|
||||||
|
"default/linux/amd64/23.0/llvm",
|
||||||
|
"default/linux/amd64/23.0/llvm/systemd",
|
||||||
|
"default/linux/amd64/23.0/hardened",
|
||||||
|
"default/linux/amd64/23.0/hardened/systemd",
|
||||||
|
"default/linux/amd64/23.0/hardened/selinux",
|
||||||
|
"default/linux/amd64/23.0/hardened/selinux/systemd",
|
||||||
|
"default/linux/amd64/23.0/split-usr",
|
||||||
|
"default/linux/amd64/23.0/split-usr/desktop",
|
||||||
|
"default/linux/amd64/23.0/split-usr/desktop/gnome",
|
||||||
|
"default/linux/amd64/23.0/split-usr/desktop/plasma",
|
||||||
|
"default/linux/amd64/23.0/split-usr/no-multilib",
|
||||||
|
"default/linux/amd64/23.0/split-usr/no-multilib/selinux",
|
||||||
|
"default/linux/amd64/23.0/split-usr/no-multilib/hardened",
|
||||||
|
"default/linux/amd64/23.0/split-usr/no-multilib/hardened/selinux",
|
||||||
|
"default/linux/amd64/23.0/split-usr/no-multilib/prefix",
|
||||||
|
"default/linux/amd64/23.0/split-usr/no-multilib/prefix/kernel-2.6.32+",
|
||||||
|
"default/linux/amd64/23.0/split-usr/no-multilib/prefix/kernel-2.6.16+",
|
||||||
|
"default/linux/amd64/23.0/split-usr/no-multilib/prefix/kernel-3.2+",
|
||||||
|
"default/linux/amd64/23.0/split-usr/llvm",
|
||||||
|
"default/linux/amd64/23.0/split-usr/hardened",
|
||||||
|
"default/linux/amd64/23.0/split-usr/hardened/selinux",
|
||||||
|
"default/linux/amd64/23.0/x32",
|
||||||
|
"default/linux/amd64/23.0/x32/systemd",
|
||||||
|
"default/linux/amd64/23.0/split-usr/x32",
|
||||||
|
"default/linux/arm/23.0",
|
||||||
|
"default/linux/arm/23.0/desktop",
|
||||||
|
"default/linux/arm/23.0/desktop/gnome",
|
||||||
|
"default/linux/arm/23.0/desktop/gnome/systemd",
|
||||||
|
"default/linux/arm/23.0/desktop/plasma",
|
||||||
|
"default/linux/arm/23.0/desktop/plasma/systemd",
|
||||||
|
"default/linux/arm/23.0/armv4",
|
||||||
|
"default/linux/arm/23.0/armv4t",
|
||||||
|
"default/linux/arm/23.0/armv4t/systemd",
|
||||||
|
"default/linux/arm/23.0/armv5te",
|
||||||
|
"default/linux/arm/23.0/armv5te/systemd",
|
||||||
|
"default/linux/arm/23.0/armv6j_sf",
|
||||||
|
"default/linux/arm/23.0/armv6j_sf/hardened",
|
||||||
|
"default/linux/arm/23.0/armv6j_sf/hardened/selinux",
|
||||||
|
"default/linux/arm/23.0/armv6j_sf/systemd",
|
||||||
|
"default/linux/arm/23.0/armv6j_hf",
|
||||||
|
"default/linux/arm/23.0/armv6j_hf/hardened",
|
||||||
|
"default/linux/arm/23.0/armv6j_hf/hardened/selinux",
|
||||||
|
"default/linux/arm/23.0/armv6j_hf/systemd",
|
||||||
|
"default/linux/arm/23.0/armv7a_sf",
|
||||||
|
"default/linux/arm/23.0/armv7a_sf/hardened",
|
||||||
|
"default/linux/arm/23.0/armv7a_sf/hardened/selinux",
|
||||||
|
"default/linux/arm/23.0/armv7a_sf/desktop",
|
||||||
|
"default/linux/arm/23.0/armv7a_sf/desktop/gnome",
|
||||||
|
"default/linux/arm/23.0/armv7a_sf/desktop/gnome/systemd",
|
||||||
|
"default/linux/arm/23.0/armv7a_sf/desktop/plasma",
|
||||||
|
"default/linux/arm/23.0/armv7a_sf/desktop/plasma/systemd",
|
||||||
|
"default/linux/arm/23.0/armv7a_sf/systemd",
|
||||||
|
"default/linux/arm/23.0/armv7a_hf",
|
||||||
|
"default/linux/arm/23.0/armv7a_hf/hardened",
|
||||||
|
"default/linux/arm/23.0/armv7a_hf/hardened/selinux",
|
||||||
|
"default/linux/arm/23.0/armv7a_hf/desktop",
|
||||||
|
"default/linux/arm/23.0/armv7a_hf/desktop/gnome",
|
||||||
|
"default/linux/arm/23.0/armv7a_hf/desktop/gnome/systemd",
|
||||||
|
"default/linux/arm/23.0/armv7a_hf/desktop/plasma",
|
||||||
|
"default/linux/arm/23.0/armv7a_hf/desktop/plasma/systemd",
|
||||||
|
"default/linux/arm/23.0/armv7a_hf/systemd",
|
||||||
|
"default/linux/arm/23.0/split-usr",
|
||||||
|
"default/linux/arm/23.0/split-usr/desktop",
|
||||||
|
"default/linux/arm/23.0/split-usr/desktop/gnome",
|
||||||
|
"default/linux/arm/23.0/split-usr/desktop/plasma",
|
||||||
|
"default/linux/arm/23.0/split-usr/armv4",
|
||||||
|
"default/linux/arm/23.0/split-usr/armv4t",
|
||||||
|
"default/linux/arm/23.0/split-usr/armv5te",
|
||||||
|
"default/linux/arm/23.0/split-usr/armv6j_sf",
|
||||||
|
"default/linux/arm/23.0/split-usr/armv6j_sf/hardened",
|
||||||
|
"default/linux/arm/23.0/split-usr/armv6j_sf/hardened/selinux",
|
||||||
|
"default/linux/arm/23.0/split-usr/armv6j_hf",
|
||||||
|
"default/linux/arm/23.0/split-usr/armv6j_hf/hardened",
|
||||||
|
"default/linux/arm/23.0/split-usr/armv6j_hf/hardened/selinux",
|
||||||
|
"default/linux/arm/23.0/split-usr/armv7a_sf",
|
||||||
|
"default/linux/arm/23.0/split-usr/armv7a_sf/hardened",
|
||||||
|
"default/linux/arm/23.0/split-usr/armv7a_sf/hardened/selinux",
|
||||||
|
"default/linux/arm/23.0/split-usr/armv7a_sf/desktop",
|
||||||
|
"default/linux/arm/23.0/split-usr/armv7a_sf/desktop/gnome",
|
||||||
|
"default/linux/arm/23.0/split-usr/armv7a_sf/desktop/plasma",
|
||||||
|
"default/linux/arm/23.0/split-usr/armv7a_hf",
|
||||||
|
"default/linux/arm/23.0/split-usr/armv7a_hf/hardened",
|
||||||
|
"default/linux/arm/23.0/split-usr/armv7a_hf/hardened/selinux",
|
||||||
|
"default/linux/arm/23.0/split-usr/armv7a_hf/desktop",
|
||||||
|
"default/linux/arm/23.0/split-usr/armv7a_hf/desktop/gnome",
|
||||||
|
"default/linux/arm/23.0/split-usr/armv7a_hf/desktop/plasma",
|
||||||
|
"default/linux/arm64/23.0",
|
||||||
|
"default/linux/arm64/23.0/hardened",
|
||||||
|
"default/linux/arm64/23.0/hardened/systemd",
|
||||||
|
"default/linux/arm64/23.0/hardened/selinux",
|
||||||
|
"default/linux/arm64/23.0/hardened/selinux/systemd",
|
||||||
|
"default/linux/arm64/23.0/desktop",
|
||||||
|
"default/linux/arm64/23.0/desktop/gnome",
|
||||||
|
"default/linux/arm64/23.0/desktop/gnome/systemd",
|
||||||
|
"default/linux/arm64/23.0/desktop/plasma",
|
||||||
|
"default/linux/arm64/23.0/desktop/plasma/systemd",
|
||||||
|
"default/linux/arm64/23.0/desktop/systemd",
|
||||||
|
"default/linux/arm64/23.0/systemd",
|
||||||
|
"default/linux/arm64/23.0/llvm",
|
||||||
|
"default/linux/arm64/23.0/llvm/systemd",
|
||||||
|
"default/linux/arm64/23.0/split-usr",
|
||||||
|
"default/linux/arm64/23.0/split-usr/hardened",
|
||||||
|
"default/linux/arm64/23.0/split-usr/hardened/selinux",
|
||||||
|
"default/linux/arm64/23.0/split-usr/desktop",
|
||||||
|
"default/linux/arm64/23.0/split-usr/desktop/gnome",
|
||||||
|
"default/linux/arm64/23.0/split-usr/desktop/plasma",
|
||||||
|
"default/linux/arm64/23.0/split-usr/llvm",
|
||||||
|
"default/linux/arm64/23.0/big-endian",
|
||||||
|
"default/linux/arm64/23.0/big-endian/systemd",
|
||||||
|
"default/linux/arm64/23.0/split-usr/big-endian",
|
||||||
|
"default/linux/hppa/23.0/hppa1.1",
|
||||||
|
"default/linux/hppa/23.0/hppa1.1/systemd",
|
||||||
|
"default/linux/hppa/23.0/hppa1.1/desktop",
|
||||||
|
"default/linux/hppa/23.0/hppa1.1/desktop/systemd",
|
||||||
|
"default/linux/hppa/23.0/hppa1.1/split-usr",
|
||||||
|
"default/linux/hppa/23.0/hppa1.1/split-usr/desktop",
|
||||||
|
"default/linux/hppa/23.0/hppa2.0",
|
||||||
|
"default/linux/hppa/23.0/hppa2.0/systemd",
|
||||||
|
"default/linux/hppa/23.0/hppa2.0/desktop",
|
||||||
|
"default/linux/hppa/23.0/hppa2.0/desktop/systemd",
|
||||||
|
"default/linux/hppa/23.0/hppa2.0/split-usr",
|
||||||
|
"default/linux/hppa/23.0/hppa2.0/split-usr/desktop",
|
||||||
|
"default/linux/loong/23.0/la64v100/lp64d",
|
||||||
|
"default/linux/loong/23.0/la64v100/lp64d/llvm",
|
||||||
|
"default/linux/loong/23.0/la64v100/lp64d/llvm/systemd",
|
||||||
|
"default/linux/loong/23.0/la64v100/lp64d/desktop",
|
||||||
|
"default/linux/loong/23.0/la64v100/lp64d/desktop/gnome",
|
||||||
|
"default/linux/loong/23.0/la64v100/lp64d/desktop/gnome/systemd",
|
||||||
|
"default/linux/loong/23.0/la64v100/lp64d/desktop/plasma",
|
||||||
|
"default/linux/loong/23.0/la64v100/lp64d/desktop/plasma/systemd",
|
||||||
|
"default/linux/loong/23.0/la64v100/lp64d/desktop/systemd",
|
||||||
|
"default/linux/loong/23.0/la64v100/lp64d/systemd",
|
||||||
|
"default/linux/loong/23.0/la64v100/split-usr/lp64d",
|
||||||
|
"default/linux/loong/23.0/la64v100/split-usr/lp64d/desktop",
|
||||||
|
"default/linux/loong/23.0/la64v100/split-usr/lp64d/desktop/gnome",
|
||||||
|
"default/linux/loong/23.0/la64v100/split-usr/lp64d/desktop/plasma",
|
||||||
|
"default/linux/m68k/23.0",
|
||||||
|
"default/linux/m68k/23.0/systemd",
|
||||||
|
"default/linux/m68k/23.0/split-usr",
|
||||||
|
"default/linux/m68k/23.0/time64",
|
||||||
|
"default/linux/mips/23.0/mipsel/o32_sf",
|
||||||
|
"default/linux/mips/23.0/mipsel/o32_sf/systemd",
|
||||||
|
"default/linux/mips/23.0/mipsel/o32",
|
||||||
|
"default/linux/mips/23.0/mipsel/o32/systemd",
|
||||||
|
"default/linux/mips/23.0/mipsel/n32",
|
||||||
|
"default/linux/mips/23.0/mipsel/n32/systemd",
|
||||||
|
"default/linux/mips/23.0/mipsel/n64",
|
||||||
|
"default/linux/mips/23.0/mipsel/n64/systemd",
|
||||||
|
"default/linux/mips/23.0/mipsel/multilib/n32",
|
||||||
|
"default/linux/mips/23.0/mipsel/multilib/n32/systemd",
|
||||||
|
"default/linux/mips/23.0/mipsel/multilib/n64",
|
||||||
|
"default/linux/mips/23.0/mipsel/multilib/n64/systemd",
|
||||||
|
"default/linux/mips/23.0/o32_sf",
|
||||||
|
"default/linux/mips/23.0/o32_sf/systemd",
|
||||||
|
"default/linux/mips/23.0/o32",
|
||||||
|
"default/linux/mips/23.0/o32/systemd",
|
||||||
|
"default/linux/mips/23.0/n32",
|
||||||
|
"default/linux/mips/23.0/n32/systemd",
|
||||||
|
"default/linux/mips/23.0/n64",
|
||||||
|
"default/linux/mips/23.0/n64/systemd",
|
||||||
|
"default/linux/mips/23.0/multilib/n32",
|
||||||
|
"default/linux/mips/23.0/multilib/n32/systemd",
|
||||||
|
"default/linux/mips/23.0/multilib/n64",
|
||||||
|
"default/linux/mips/23.0/multilib/n64/systemd",
|
||||||
|
"default/linux/mips/23.0/split-usr/mipsel/o32_sf",
|
||||||
|
"default/linux/mips/23.0/split-usr/mipsel/o32",
|
||||||
|
"default/linux/mips/23.0/split-usr/mipsel/n32",
|
||||||
|
"default/linux/mips/23.0/split-usr/mipsel/n64",
|
||||||
|
"default/linux/mips/23.0/split-usr/mipsel/multilib/n32",
|
||||||
|
"default/linux/mips/23.0/split-usr/mipsel/multilib/n64",
|
||||||
|
"default/linux/mips/23.0/split-usr/o32_sf",
|
||||||
|
"default/linux/mips/23.0/split-usr/o32",
|
||||||
|
"default/linux/mips/23.0/split-usr/n32",
|
||||||
|
"default/linux/mips/23.0/split-usr/n64",
|
||||||
|
"default/linux/mips/23.0/split-usr/multilib/n32",
|
||||||
|
"default/linux/mips/23.0/split-usr/multilib/n64",
|
||||||
|
"default/linux/mips/23.0/time64/mipsel/o32_sf",
|
||||||
|
"default/linux/mips/23.0/time64/mipsel/o32_sf/systemd",
|
||||||
|
"default/linux/mips/23.0/time64/mipsel/o32",
|
||||||
|
"default/linux/mips/23.0/time64/mipsel/o32/systemd",
|
||||||
|
"default/linux/mips/23.0/time64/mipsel/n32",
|
||||||
|
"default/linux/mips/23.0/time64/mipsel/n32/systemd",
|
||||||
|
"default/linux/mips/23.0/time64/mipsel/multilib/n32",
|
||||||
|
"default/linux/mips/23.0/time64/mipsel/multilib/n32/systemd",
|
||||||
|
"default/linux/mips/23.0/time64/mipsel/multilib/n64",
|
||||||
|
"default/linux/mips/23.0/time64/mipsel/multilib/n64/systemd",
|
||||||
|
"default/linux/mips/23.0/time64/o32_sf",
|
||||||
|
"default/linux/mips/23.0/time64/o32_sf/systemd",
|
||||||
|
"default/linux/mips/23.0/time64/o32",
|
||||||
|
"default/linux/mips/23.0/time64/o32/systemd",
|
||||||
|
"default/linux/mips/23.0/time64/n32",
|
||||||
|
"default/linux/mips/23.0/time64/n32/systemd",
|
||||||
|
"default/linux/mips/23.0/time64/multilib/n32",
|
||||||
|
"default/linux/mips/23.0/time64/multilib/n32/systemd",
|
||||||
|
"default/linux/mips/23.0/time64/multilib/n64",
|
||||||
|
"default/linux/mips/23.0/time64/multilib/n64/systemd",
|
||||||
|
"default/linux/mips/23.0/time64/split-usr/mipsel/o32_sf",
|
||||||
|
"default/linux/mips/23.0/time64/split-usr/mipsel/o32",
|
||||||
|
"default/linux/mips/23.0/time64/split-usr/mipsel/n32",
|
||||||
|
"default/linux/mips/23.0/time64/split-usr/mipsel/multilib/n32",
|
||||||
|
"default/linux/mips/23.0/time64/split-usr/mipsel/multilib/n64",
|
||||||
|
"default/linux/mips/23.0/time64/split-usr/o32_sf",
|
||||||
|
"default/linux/mips/23.0/time64/split-usr/o32",
|
||||||
|
"default/linux/mips/23.0/time64/split-usr/n32",
|
||||||
|
"default/linux/mips/23.0/time64/split-usr/multilib/n32",
|
||||||
|
"default/linux/mips/23.0/time64/split-usr/multilib/n64",
|
||||||
|
"default/linux/ppc/23.0",
|
||||||
|
"default/linux/ppc/23.0/desktop",
|
||||||
|
"default/linux/ppc/23.0/desktop/gnome",
|
||||||
|
"default/linux/ppc/23.0/desktop/gnome/systemd",
|
||||||
|
"default/linux/ppc/23.0/systemd",
|
||||||
|
"default/linux/ppc/23.0/split-usr",
|
||||||
|
"default/linux/ppc/23.0/split-usr/desktop",
|
||||||
|
"default/linux/ppc/23.0/split-usr/desktop/gnome",
|
||||||
|
"default/linux/ppc/23.0/time64",
|
||||||
|
"default/linux/ppc/23.0/time64/desktop",
|
||||||
|
"default/linux/ppc/23.0/time64/desktop/gnome",
|
||||||
|
"default/linux/ppc/23.0/time64/desktop/gnome/systemd",
|
||||||
|
"default/linux/ppc/23.0/time64/systemd",
|
||||||
|
"default/linux/ppc/23.0/time64/split-usr",
|
||||||
|
"default/linux/ppc/23.0/time64/split-usr/desktop",
|
||||||
|
"default/linux/ppc/23.0/time64/split-usr/desktop/gnome",
|
||||||
|
"default/linux/ppc64/23.0",
|
||||||
|
"default/linux/ppc64/23.0/desktop",
|
||||||
|
"default/linux/ppc64/23.0/desktop/gnome",
|
||||||
|
"default/linux/ppc64/23.0/desktop/gnome/systemd",
|
||||||
|
"default/linux/ppc64/23.0/systemd",
|
||||||
|
"default/linux/ppc64/23.0/split-usr",
|
||||||
|
"default/linux/ppc64/23.0/split-usr/desktop",
|
||||||
|
"default/linux/ppc64/23.0/split-usr/desktop/gnome",
|
||||||
|
"default/linux/ppc64le/23.0",
|
||||||
|
"default/linux/ppc64le/23.0/desktop",
|
||||||
|
"default/linux/ppc64le/23.0/desktop/gnome",
|
||||||
|
"default/linux/ppc64le/23.0/desktop/gnome/systemd",
|
||||||
|
"default/linux/ppc64le/23.0/desktop/plasma",
|
||||||
|
"default/linux/ppc64le/23.0/desktop/plasma/systemd",
|
||||||
|
"default/linux/ppc64le/23.0/desktop/systemd",
|
||||||
|
"default/linux/ppc64le/23.0/systemd",
|
||||||
|
"default/linux/ppc64le/23.0/split-usr",
|
||||||
|
"default/linux/ppc64le/23.0/split-usr/desktop",
|
||||||
|
"default/linux/ppc64le/23.0/split-usr/desktop/gnome",
|
||||||
|
"default/linux/ppc64le/23.0/split-usr/desktop/plasma",
|
||||||
|
"default/linux/riscv/23.0/rv64/lp64d",
|
||||||
|
"default/linux/riscv/23.0/rv64/lp64d/desktop",
|
||||||
|
"default/linux/riscv/23.0/rv64/lp64d/desktop/gnome",
|
||||||
|
"default/linux/riscv/23.0/rv64/lp64d/desktop/gnome/systemd",
|
||||||
|
"default/linux/riscv/23.0/rv64/lp64d/desktop/plasma",
|
||||||
|
"default/linux/riscv/23.0/rv64/lp64d/desktop/plasma/systemd",
|
||||||
|
"default/linux/riscv/23.0/rv64/lp64d/desktop/systemd",
|
||||||
|
"default/linux/riscv/23.0/rv64/lp64d/systemd",
|
||||||
|
"default/linux/riscv/23.0/rv64/lp64",
|
||||||
|
"default/linux/riscv/23.0/rv64/lp64/desktop",
|
||||||
|
"default/linux/riscv/23.0/rv64/lp64/desktop/gnome",
|
||||||
|
"default/linux/riscv/23.0/rv64/lp64/desktop/gnome/systemd",
|
||||||
|
"default/linux/riscv/23.0/rv64/lp64/desktop/plasma",
|
||||||
|
"default/linux/riscv/23.0/rv64/lp64/desktop/plasma/systemd",
|
||||||
|
"default/linux/riscv/23.0/rv64/lp64/desktop/systemd",
|
||||||
|
"default/linux/riscv/23.0/rv64/lp64/systemd",
|
||||||
|
"default/linux/riscv/23.0/rv64/multilib",
|
||||||
|
"default/linux/riscv/23.0/rv64/multilib/systemd",
|
||||||
|
"default/linux/riscv/23.0/rv32/ilp32d",
|
||||||
|
"default/linux/riscv/23.0/rv32/ilp32d/systemd",
|
||||||
|
"default/linux/riscv/23.0/rv32/ilp32",
|
||||||
|
"default/linux/riscv/23.0/rv32/ilp32/systemd",
|
||||||
|
"default/linux/riscv/23.0/rv64/split-usr/lp64d",
|
||||||
|
"default/linux/riscv/23.0/rv64/split-usr/lp64d/desktop",
|
||||||
|
"default/linux/riscv/23.0/rv64/split-usr/lp64d/desktop/gnome",
|
||||||
|
"default/linux/riscv/23.0/rv64/split-usr/lp64d/desktop/plasma",
|
||||||
|
"default/linux/riscv/23.0/rv64/split-usr/lp64",
|
||||||
|
"default/linux/riscv/23.0/rv64/split-usr/lp64/desktop",
|
||||||
|
"default/linux/riscv/23.0/rv64/split-usr/lp64/desktop/gnome",
|
||||||
|
"default/linux/riscv/23.0/rv64/split-usr/lp64/desktop/plasma",
|
||||||
|
"default/linux/riscv/23.0/rv64/split-usr/multilib",
|
||||||
|
"default/linux/riscv/23.0/rv32/split-usr/ilp32d",
|
||||||
|
"default/linux/riscv/23.0/rv32/split-usr/ilp32",
|
||||||
|
"default/linux/s390/23.0",
|
||||||
|
"default/linux/s390/23.0/systemd",
|
||||||
|
"default/linux/s390/23.0/split-usr",
|
||||||
|
"default/linux/s390/23.0/split-usr/s390x",
|
||||||
|
"default/linux/s390/23.0/s390x",
|
||||||
|
"default/linux/s390/23.0/s390x/systemd",
|
||||||
|
"default/linux/s390/23.0/time64",
|
||||||
|
"default/linux/s390/23.0/time64/systemd",
|
||||||
|
"default/linux/s390/23.0/time64/split-usr",
|
||||||
|
"default/linux/sparc/23.0",
|
||||||
|
"default/linux/sparc/23.0/desktop",
|
||||||
|
"default/linux/sparc/23.0/systemd",
|
||||||
|
"default/linux/sparc/23.0/64ul",
|
||||||
|
"default/linux/sparc/23.0/64ul/desktop",
|
||||||
|
"default/linux/sparc/23.0/64ul/systemd",
|
||||||
|
"default/linux/sparc/23.0/split-usr",
|
||||||
|
"default/linux/sparc/23.0/split-usr/desktop",
|
||||||
|
"default/linux/sparc/23.0/split-usr/64ul",
|
||||||
|
"default/linux/sparc/23.0/split-usr/64ul/desktop",
|
||||||
|
"default/linux/x86/23.0/i686",
|
||||||
|
"default/linux/x86/23.0/i686/systemd",
|
||||||
|
"default/linux/x86/23.0/i686/hardened",
|
||||||
|
"default/linux/x86/23.0/i686/hardened/selinux",
|
||||||
|
"default/linux/x86/23.0/i686/desktop",
|
||||||
|
"default/linux/x86/23.0/i686/desktop/gnome",
|
||||||
|
"default/linux/x86/23.0/i686/desktop/gnome/systemd",
|
||||||
|
"default/linux/x86/23.0/i686/desktop/plasma",
|
||||||
|
"default/linux/x86/23.0/i686/desktop/plasma/systemd",
|
||||||
|
"default/linux/x86/23.0/i686/prefix",
|
||||||
|
"default/linux/x86/23.0/i686/prefix/kernel-2.6.32+",
|
||||||
|
"default/linux/x86/23.0/i686/prefix/kernel-2.6.16+",
|
||||||
|
"default/linux/x86/23.0/i686/prefix/kernel-3.2+",
|
||||||
|
"default/linux/x86/23.0/i686/split-usr",
|
||||||
|
"default/linux/x86/23.0/i686/split-usr/hardened",
|
||||||
|
"default/linux/x86/23.0/i686/split-usr/hardened/selinux",
|
||||||
|
"default/linux/x86/23.0/i686/split-usr/desktop",
|
||||||
|
"default/linux/x86/23.0/i686/split-usr/desktop/gnome",
|
||||||
|
"default/linux/x86/23.0/i686/split-usr/desktop/plasma",
|
||||||
|
"default/linux/x86/23.0/i686/split-usr/prefix",
|
||||||
|
"default/linux/x86/23.0/i686/split-usr/prefix/kernel-2.6.32+",
|
||||||
|
"default/linux/x86/23.0/i686/split-usr/prefix/kernel-2.6.16+",
|
||||||
|
"default/linux/x86/23.0/i686/split-usr/prefix/kernel-3.2+",
|
||||||
|
"default/linux/x86/23.0/i686/time64",
|
||||||
|
"default/linux/x86/23.0/i686/time64/systemd",
|
||||||
|
"default/linux/x86/23.0/i686/time64/hardened",
|
||||||
|
"default/linux/x86/23.0/i686/time64/hardened/selinux",
|
||||||
|
"default/linux/x86/23.0/i686/time64/desktop",
|
||||||
|
"default/linux/x86/23.0/i686/time64/desktop/gnome",
|
||||||
|
"default/linux/x86/23.0/i686/time64/desktop/gnome/systemd",
|
||||||
|
"default/linux/x86/23.0/i686/time64/desktop/plasma",
|
||||||
|
"default/linux/x86/23.0/i686/time64/desktop/plasma/systemd",
|
||||||
|
"default/linux/x86/23.0/i686/time64/split-usr",
|
||||||
|
"default/linux/x86/23.0/i686/time64/split-usr/hardened",
|
||||||
|
"default/linux/x86/23.0/i686/time64/split-usr/hardened/selinux",
|
||||||
|
"default/linux/x86/23.0/i686/time64/split-usr/desktop",
|
||||||
|
"default/linux/x86/23.0/i686/time64/split-usr/desktop/gnome",
|
||||||
|
"default/linux/x86/23.0/i686/time64/split-usr/desktop/plasma",
|
||||||
|
"default/linux/x86/23.0/i486",
|
||||||
|
"default/linux/x86/23.0/i486/systemd",
|
||||||
|
"default/linux/x86/23.0/i486/hardened",
|
||||||
|
"default/linux/x86/23.0/i486/hardened/selinux",
|
||||||
|
"default/linux/x86/23.0/i486/split-usr",
|
||||||
|
"default/linux/x86/23.0/i486/split-usr/hardened",
|
||||||
|
"default/linux/x86/23.0/i486/split-usr/hardened/selinux",
|
||||||
|
"default/linux/x86/23.0/i486/time64",
|
||||||
|
"default/linux/x86/23.0/i486/time64/systemd",
|
||||||
|
"default/linux/x86/23.0/i486/time64/hardened",
|
||||||
|
"default/linux/x86/23.0/i486/time64/hardened/selinux",
|
||||||
|
"default/linux/x86/23.0/i486/time64/split-usr",
|
||||||
|
"default/linux/x86/23.0/i486/time64/split-usr/hardened",
|
||||||
|
"default/linux/x86/23.0/i486/time64/split-usr/hardened/selinux",
|
||||||
|
"default/linux/amd64/23.0/musl",
|
||||||
|
"default/linux/amd64/23.0/musl/llvm",
|
||||||
|
"default/linux/amd64/23.0/musl/hardened",
|
||||||
|
"default/linux/amd64/23.0/musl/hardened/selinux",
|
||||||
|
"default/linux/amd64/23.0/split-usr/musl",
|
||||||
|
"default/linux/amd64/23.0/split-usr/musl/llvm",
|
||||||
|
"default/linux/amd64/23.0/split-usr/musl/hardened",
|
||||||
|
"default/linux/amd64/23.0/split-usr/musl/hardened/selinux",
|
||||||
|
"default/linux/arm/23.0/armv6j_hf/musl",
|
||||||
|
"default/linux/arm/23.0/armv6j_hf/musl/hardened",
|
||||||
|
"default/linux/arm/23.0/armv6j_hf/musl/hardened/selinux",
|
||||||
|
"default/linux/arm/23.0/armv7a_hf/musl",
|
||||||
|
"default/linux/arm/23.0/armv7a_hf/musl/hardened",
|
||||||
|
"default/linux/arm/23.0/armv7a_hf/musl/hardened/selinux",
|
||||||
|
"default/linux/arm/23.0/split-usr/armv6j_hf/musl",
|
||||||
|
"default/linux/arm/23.0/split-usr/armv6j_hf/musl/hardened",
|
||||||
|
"default/linux/arm/23.0/split-usr/armv6j_hf/musl/hardened/selinux",
|
||||||
|
"default/linux/arm/23.0/split-usr/armv7a_hf/musl",
|
||||||
|
"default/linux/arm/23.0/split-usr/armv7a_hf/musl/hardened",
|
||||||
|
"default/linux/arm/23.0/split-usr/armv7a_hf/musl/hardened/selinux",
|
||||||
|
"default/linux/arm64/23.0/musl",
|
||||||
|
"default/linux/arm64/23.0/musl/llvm",
|
||||||
|
"default/linux/arm64/23.0/musl/hardened",
|
||||||
|
"default/linux/arm64/23.0/musl/hardened/selinux",
|
||||||
|
"default/linux/arm64/23.0/split-usr/musl",
|
||||||
|
"default/linux/arm64/23.0/split-usr/musl/llvm",
|
||||||
|
"default/linux/arm64/23.0/split-usr/musl/hardened",
|
||||||
|
"default/linux/arm64/23.0/split-usr/musl/hardened/selinux",
|
||||||
|
"default/linux/m68k/23.0/musl",
|
||||||
|
"default/linux/m68k/23.0/split-usr/musl",
|
||||||
|
"default/linux/mips/23.0/mipsel/o32/musl",
|
||||||
|
"default/linux/mips/23.0/mipsel/n64/musl",
|
||||||
|
"default/linux/mips/23.0/o32/musl",
|
||||||
|
"default/linux/mips/23.0/n64/musl",
|
||||||
|
"default/linux/mips/23.0/split-usr/mipsel/o32/musl",
|
||||||
|
"default/linux/mips/23.0/split-usr/mipsel/n64/musl",
|
||||||
|
"default/linux/mips/23.0/split-usr/o32/musl",
|
||||||
|
"default/linux/mips/23.0/split-usr/n64/musl",
|
||||||
|
"default/linux/ppc/23.0/musl",
|
||||||
|
"default/linux/ppc/23.0/musl/hardened",
|
||||||
|
"default/linux/ppc/23.0/split-usr/musl",
|
||||||
|
"default/linux/ppc/23.0/split-usr/musl/hardened",
|
||||||
|
"default/linux/ppc64/23.0/musl",
|
||||||
|
"default/linux/ppc64/23.0/musl/hardened",
|
||||||
|
"default/linux/ppc64/23.0/split-usr/musl",
|
||||||
|
"default/linux/ppc64/23.0/split-usr/musl/hardened",
|
||||||
|
"default/linux/ppc64le/23.0/musl",
|
||||||
|
"default/linux/ppc64le/23.0/musl/hardened",
|
||||||
|
"default/linux/ppc64le/23.0/split-usr/musl",
|
||||||
|
"default/linux/ppc64le/23.0/split-usr/musl/hardened",
|
||||||
|
"default/linux/riscv/23.0/rv64/lp64d/musl",
|
||||||
|
"default/linux/riscv/23.0/rv64/lp64/musl",
|
||||||
|
"default/linux/riscv/23.0/rv64/split-usr/lp64d/musl",
|
||||||
|
"default/linux/riscv/23.0/rv64/split-usr/lp64/musl",
|
||||||
|
"default/linux/riscv/23.0/rv32/ilp32d/musl",
|
||||||
|
"default/linux/riscv/23.0/rv32/ilp32/musl",
|
||||||
|
"default/linux/riscv/23.0/rv32/split-usr/ilp32d/musl",
|
||||||
|
"default/linux/riscv/23.0/rv32/split-usr/ilp32/musl",
|
||||||
|
"default/linux/x86/23.0/i686/musl",
|
||||||
|
"default/linux/x86/23.0/i686/musl/selinux",
|
||||||
|
"default/linux/x86/23.0/i686/split-usr/musl",
|
||||||
|
"default/linux/x86/23.0/i686/split-usr/musl/selinux",
|
||||||
|
"default/linux/x86/23.0/i486/musl",
|
||||||
|
"default/linux/x86/23.0/i486/musl/selinux",
|
||||||
|
"default/linux/x86/23.0/i486/split-usr/musl",
|
||||||
|
"default/linux/x86/23.0/i486/split-usr/musl/selinux",
|
||||||
|
"prefix/linux/amd64",
|
||||||
|
"prefix/linux/arm",
|
||||||
|
"prefix/linux/ppc64",
|
||||||
|
"prefix/linux/ppc64le",
|
||||||
|
"prefix/linux/riscv",
|
||||||
|
"prefix/linux/x86",
|
||||||
|
"prefix/darwin/macos/10.5/ppc/gcc",
|
||||||
|
"prefix/darwin/macos/10.5/x86/gcc",
|
||||||
|
"prefix/darwin/macos/10.11/x64",
|
||||||
|
"prefix/darwin/macos/10.13/x64",
|
||||||
|
"prefix/darwin/macos/10.13/x64/gcc",
|
||||||
|
"prefix/darwin/macos/10.14/x64",
|
||||||
|
"prefix/darwin/macos/10.14/x64/gcc",
|
||||||
|
"prefix/darwin/macos/10.15/x64",
|
||||||
|
"prefix/darwin/macos/10.15/x64/gcc",
|
||||||
|
"prefix/darwin/macos/11.0/x64",
|
||||||
|
"prefix/darwin/macos/11.0/x64/gcc",
|
||||||
|
"prefix/darwin/macos/12.0/x64",
|
||||||
|
"prefix/darwin/macos/12.0/x64/gcc",
|
||||||
|
"prefix/darwin/macos/13.0/x64/gcc",
|
||||||
|
"prefix/darwin/macos/14.0/x64/gcc",
|
||||||
|
"prefix/darwin/macos/15.0/x64/gcc",
|
||||||
|
"prefix/darwin/macos/26.0/x64/gcc",
|
||||||
|
"prefix/darwin/macos/11.0/arm64",
|
||||||
|
"prefix/darwin/macos/11.0/arm64/gcc",
|
||||||
|
"prefix/darwin/macos/12.0/arm64",
|
||||||
|
"prefix/darwin/macos/12.0/arm64/gcc",
|
||||||
|
"prefix/darwin/macos/13.0/arm64/gcc",
|
||||||
|
"prefix/darwin/macos/14.0/arm64/gcc",
|
||||||
|
"prefix/darwin/macos/15.0/arm64/gcc",
|
||||||
|
"prefix/darwin/macos/26.0/arm64/gcc",
|
||||||
|
"prefix/sunos/solaris/5.11/x64",
|
||||||
|
];
|
||||||
|
|
||||||
|
let repo = Repo::new("/var/db/repos/gentoo").expect("failed to open repo");
|
||||||
|
|
||||||
|
for profile in profiles {
|
||||||
|
repo.evaluate_profile(profile)
|
||||||
|
.unwrap_or_else(|e| panic!("failed to evaluate profile: {profile}: {e}"));
|
||||||
|
}
|
||||||
|
}
|
||||||
89
tests/profile/read_mock_profile.rs
Normal file
89
tests/profile/read_mock_profile.rs
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
use std::env::args;
|
||||||
|
|
||||||
|
use gentoo_utils::{atom::Atom, repo::Repo, useflag::UseFlag};
|
||||||
|
use itertools::Itertools;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let repo_path = args()
|
||||||
|
.nth(1)
|
||||||
|
.expect("expected path to mockrepo as first argument");
|
||||||
|
let repo = Repo::new(&repo_path).expect("failed to read repo");
|
||||||
|
|
||||||
|
let global_package_mask = repo
|
||||||
|
.package_mask()
|
||||||
|
.iter()
|
||||||
|
.map(Atom::to_string)
|
||||||
|
.sorted()
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
assert_eq!(global_package_mask, vec!["app-editors/vim"]);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
repo.arch_list()
|
||||||
|
.iter()
|
||||||
|
.map(|arch| arch.get())
|
||||||
|
.collect::<Vec<_>>(),
|
||||||
|
vec!["amd64", "aarch64"]
|
||||||
|
);
|
||||||
|
|
||||||
|
let profile = repo
|
||||||
|
.evaluate_profile("gentoo-desktop")
|
||||||
|
.expect("failed to evaluate profile");
|
||||||
|
|
||||||
|
let r#use = profile.make_defaults()["USE"]
|
||||||
|
.split_ascii_whitespace()
|
||||||
|
.sorted()
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
assert_eq!(r#use, vec!["emacs", "selinux",]);
|
||||||
|
|
||||||
|
let packages = profile
|
||||||
|
.packages()
|
||||||
|
.iter()
|
||||||
|
.map(Atom::to_string)
|
||||||
|
.sorted()
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
packages,
|
||||||
|
vec!["app-editors/emacs", "sec-policy/selinux-base"]
|
||||||
|
);
|
||||||
|
|
||||||
|
let packages_mask = profile
|
||||||
|
.package_mask()
|
||||||
|
.iter()
|
||||||
|
.map(Atom::to_string)
|
||||||
|
.sorted()
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
assert_eq!(packages_mask, vec!["app-editors/vim"]);
|
||||||
|
|
||||||
|
let emacs_use = profile
|
||||||
|
.package_use()
|
||||||
|
.iter()
|
||||||
|
.find_map(|(atom, flags)| {
|
||||||
|
if atom.clone().into_cp().to_string() == "app-editors/emacs" {
|
||||||
|
Some(flags)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.unwrap()
|
||||||
|
.iter()
|
||||||
|
.map(UseFlag::to_string)
|
||||||
|
.sorted()
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
assert_eq!(emacs_use, vec!["gui"]);
|
||||||
|
|
||||||
|
let use_force = profile
|
||||||
|
.use_force()
|
||||||
|
.iter()
|
||||||
|
.map(UseFlag::to_string)
|
||||||
|
.sorted()
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
assert_eq!(use_force, vec!["base", "caps", "default", "gui"]);
|
||||||
|
|
||||||
|
assert!(profile.use_mask().is_empty());
|
||||||
|
}
|
||||||
@@ -3,7 +3,7 @@ use std::error::Error;
|
|||||||
use gentoo_utils::repo::Repo;
|
use gentoo_utils::repo::Repo;
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn Error>> {
|
fn main() -> Result<(), Box<dyn Error>> {
|
||||||
let repo = Repo::new("/var/db/repos/gentoo");
|
let repo = Repo::new("/var/db/repos/gentoo").unwrap();
|
||||||
|
|
||||||
for result in repo.categories()? {
|
for result in repo.categories()? {
|
||||||
let cat = result?;
|
let cat = result?;
|
||||||
|
|||||||
Reference in New Issue
Block a user
I think the default behavior for no eapi file per the spec is to treat it as eapi 0. Do we do that here, or are we erroring out if there's no eapi file?
Maybe it should assign eapi 0 on failure to parse (no eapi file), then later during evaluation of the parsed profile you throw an error saying you don't support eapi 0. That way eapi 0 (or other versions) could be supported later without having to change parsing logic.