forked from gentoo-utils/gentoo-utils
create ebuild module
This commit is contained in:
@@ -1,18 +0,0 @@
|
|||||||
use crate::useflag::UseFlag;
|
|
||||||
|
|
||||||
pub mod parsers;
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
pub enum Conditional {
|
|
||||||
Negative(UseFlag),
|
|
||||||
Positive(UseFlag),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
pub enum Expr<T> {
|
|
||||||
Element(T),
|
|
||||||
AllOf(Vec<Self>),
|
|
||||||
AnyOf(Vec<Self>),
|
|
||||||
OneOf(Vec<Self>),
|
|
||||||
ConditionalGroup(Conditional, Vec<Self>),
|
|
||||||
}
|
|
||||||
@@ -1,86 +0,0 @@
|
|||||||
use mon::{Parser, tag, whitespace1};
|
|
||||||
|
|
||||||
use crate::{
|
|
||||||
Parseable,
|
|
||||||
depend::{Conditional, Expr},
|
|
||||||
useflag::UseFlag,
|
|
||||||
};
|
|
||||||
|
|
||||||
impl<'a, T> Parseable<'a, &'a str> for Expr<T>
|
|
||||||
where
|
|
||||||
T: Parseable<'a, &'a str>,
|
|
||||||
{
|
|
||||||
type Parser = impl Parser<&'a str, Output = Self>;
|
|
||||||
|
|
||||||
fn parser() -> Self::Parser {
|
|
||||||
|it| {
|
|
||||||
let all_of_group = Expr::parser()
|
|
||||||
.separated_list(whitespace1(), 1..)
|
|
||||||
.delimited_by(tag("(").followed_by(whitespace1()), tag(")"))
|
|
||||||
.map(|exprs| Expr::AllOf(exprs));
|
|
||||||
|
|
||||||
let any_of_group = Expr::parser()
|
|
||||||
.separated_list(whitespace1(), 1..)
|
|
||||||
.delimited_by(tag("(").followed_by(whitespace1()), tag(")"))
|
|
||||||
.preceded_by(tag("||").followed_by(whitespace1()))
|
|
||||||
.map(|exprs| Expr::AnyOf(exprs));
|
|
||||||
|
|
||||||
let one_of_group = Expr::parser()
|
|
||||||
.separated_list(whitespace1(), 1..)
|
|
||||||
.delimited_by(tag("(").followed_by(whitespace1()), tag(")"))
|
|
||||||
.preceded_by(tag("^^").followed_by(whitespace1()))
|
|
||||||
.map(|exprs| Expr::OneOf(exprs));
|
|
||||||
|
|
||||||
let conditional_group = Conditional::parser()
|
|
||||||
.followed_by(whitespace1())
|
|
||||||
.and(
|
|
||||||
Expr::parser()
|
|
||||||
.separated_list(whitespace1(), 1..)
|
|
||||||
.delimited_by(tag("(").followed_by(whitespace1()), tag(")")),
|
|
||||||
)
|
|
||||||
.map(|(conditional, exprs)| Expr::ConditionalGroup(conditional, exprs));
|
|
||||||
|
|
||||||
T::parser()
|
|
||||||
.map(|e| Expr::Element(e))
|
|
||||||
.or(conditional_group)
|
|
||||||
.or(any_of_group)
|
|
||||||
.or(all_of_group)
|
|
||||||
.or(one_of_group)
|
|
||||||
.parse(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Parseable<'a, &'a str> for Conditional {
|
|
||||||
type Parser = impl Parser<&'a str, Output = Self>;
|
|
||||||
|
|
||||||
fn parser() -> Self::Parser {
|
|
||||||
UseFlag::parser()
|
|
||||||
.preceded_by(tag("!"))
|
|
||||||
.followed_by(tag("?"))
|
|
||||||
.map(|flag| Conditional::Negative(flag))
|
|
||||||
.or(UseFlag::parser()
|
|
||||||
.followed_by(tag("?"))
|
|
||||||
.map(|flag| Conditional::Positive(flag)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod test {
|
|
||||||
|
|
||||||
use mon::input::InputIter;
|
|
||||||
|
|
||||||
use crate::atom::Atom;
|
|
||||||
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_expr() {
|
|
||||||
let it = InputIter::new("flag? ( || ( foo/bar foo/bar ) )");
|
|
||||||
|
|
||||||
Expr::<Atom>::parser()
|
|
||||||
.separated_list(whitespace1(), 0..)
|
|
||||||
.check_finished(it)
|
|
||||||
.unwrap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
57
src/ebuild/mod.rs
Normal file
57
src/ebuild/mod.rs
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
use get::Get;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
atom::{Atom, Name, Slot, Version},
|
||||||
|
useflag::{IUseFlag, UseFlag},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub mod parsers;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub enum Conditional {
|
||||||
|
Negative(UseFlag),
|
||||||
|
Positive(UseFlag),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub enum Depend<T> {
|
||||||
|
Element(T),
|
||||||
|
AllOf(Vec<Self>),
|
||||||
|
AnyOf(Vec<Self>),
|
||||||
|
OneOf(Vec<Self>),
|
||||||
|
ConditionalGroup(Conditional, Vec<Self>),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Get)]
|
||||||
|
pub struct SrcUri {
|
||||||
|
uri: String,
|
||||||
|
file_name: Option<PathBuf>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Get)]
|
||||||
|
pub struct License(#[get(method = "get", kind = "deref")] String);
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Get)]
|
||||||
|
pub struct Eapi(#[get(method = "get", kind = "deref")] String);
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Get)]
|
||||||
|
pub struct Eclass(#[get(method = "get", kind = "deref")] String);
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Get)]
|
||||||
|
pub struct Ebuild {
|
||||||
|
name: Name,
|
||||||
|
version: Version,
|
||||||
|
slot: Option<Slot>,
|
||||||
|
homepage: Option<String>,
|
||||||
|
src_uri: Vec<Depend<SrcUri>>,
|
||||||
|
eapi: Option<Eapi>,
|
||||||
|
inherit: Vec<Eclass>,
|
||||||
|
iuse: Vec<IUseFlag>,
|
||||||
|
license: Vec<Depend<License>>,
|
||||||
|
description: Option<String>,
|
||||||
|
depend: Vec<Depend<Atom>>,
|
||||||
|
bdepend: Vec<Depend<Atom>>,
|
||||||
|
rdpened: Vec<Depend<Atom>>,
|
||||||
|
idepend: Vec<Depend<Atom>>,
|
||||||
|
}
|
||||||
155
src/ebuild/parsers.rs
Normal file
155
src/ebuild/parsers.rs
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
use mon::{Parser, alpha1, r#if, tag, whitespace1};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
Parseable,
|
||||||
|
ebuild::{Conditional, Depend, Eapi, License, SrcUri},
|
||||||
|
useflag::UseFlag,
|
||||||
|
};
|
||||||
|
|
||||||
|
impl<'a> Parseable<'a, &'a str> for SrcUri {
|
||||||
|
type Parser = impl Parser<&'a str, Output = Self>;
|
||||||
|
|
||||||
|
fn parser() -> Self::Parser {
|
||||||
|
let protocol = alpha1::<&str>().followed_by(tag("://"));
|
||||||
|
|
||||||
|
let uri = r#if(|c: &char| !c.is_ascii_whitespace())
|
||||||
|
.list(1..)
|
||||||
|
.recognize()
|
||||||
|
.map(|output: &str| output.to_string());
|
||||||
|
|
||||||
|
let name = r#if(|c: &char| !c.is_ascii_whitespace())
|
||||||
|
.list(1..)
|
||||||
|
.recognize()
|
||||||
|
.map(|output: &str| PathBuf::from(output));
|
||||||
|
|
||||||
|
uri.preceded_by(protocol)
|
||||||
|
.and(
|
||||||
|
name.preceded_by(tag("->").delimited_by(whitespace1(), whitespace1()))
|
||||||
|
.opt(),
|
||||||
|
)
|
||||||
|
.map(|(uri, file_name)| SrcUri { uri, file_name })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Parseable<'a, &'a str> for License {
|
||||||
|
type Parser = impl Parser<&'a str, Output = Self>;
|
||||||
|
|
||||||
|
fn parser() -> Self::Parser {
|
||||||
|
let start = r#if(|c: &char| c.is_ascii_alphanumeric() || "_".contains(*c));
|
||||||
|
let rest = r#if(|c: &char| c.is_ascii_alphanumeric() || "+_.-".contains(*c)).list(0..);
|
||||||
|
|
||||||
|
start
|
||||||
|
.and(rest)
|
||||||
|
.recognize()
|
||||||
|
.map(|output: &str| License(output.to_string()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Parseable<'a, &'a str> for Eapi {
|
||||||
|
type Parser = impl Parser<&'a str, Output = Self>;
|
||||||
|
|
||||||
|
fn parser() -> Self::Parser {
|
||||||
|
let start = r#if(|c: &char| c.is_ascii_alphanumeric() || "_".contains(*c));
|
||||||
|
let rest = r#if(|c: &char| c.is_ascii_alphanumeric() || "+_.-".contains(*c)).list(0..);
|
||||||
|
|
||||||
|
start
|
||||||
|
.and(rest)
|
||||||
|
.recognize()
|
||||||
|
.map(|output: &str| Eapi(output.to_string()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T> Parseable<'a, &'a str> for Depend<T>
|
||||||
|
where
|
||||||
|
T: Parseable<'a, &'a str>,
|
||||||
|
{
|
||||||
|
type Parser = impl Parser<&'a str, Output = Self>;
|
||||||
|
|
||||||
|
fn parser() -> Self::Parser {
|
||||||
|
|it| {
|
||||||
|
let all_of_group = Depend::parser()
|
||||||
|
.separated_list(whitespace1(), 1..)
|
||||||
|
.delimited_by(tag("(").followed_by(whitespace1()), tag(")"))
|
||||||
|
.map(|exprs| Depend::AllOf(exprs));
|
||||||
|
|
||||||
|
let any_of_group = Depend::parser()
|
||||||
|
.separated_list(whitespace1(), 1..)
|
||||||
|
.delimited_by(tag("(").followed_by(whitespace1()), tag(")"))
|
||||||
|
.preceded_by(tag("||").followed_by(whitespace1()))
|
||||||
|
.map(|exprs| Depend::AnyOf(exprs));
|
||||||
|
|
||||||
|
let one_of_group = Depend::parser()
|
||||||
|
.separated_list(whitespace1(), 1..)
|
||||||
|
.delimited_by(tag("(").followed_by(whitespace1()), tag(")"))
|
||||||
|
.preceded_by(tag("^^").followed_by(whitespace1()))
|
||||||
|
.map(|exprs| Depend::OneOf(exprs));
|
||||||
|
|
||||||
|
let conditional_group = Conditional::parser()
|
||||||
|
.followed_by(whitespace1())
|
||||||
|
.and(
|
||||||
|
Depend::parser()
|
||||||
|
.separated_list(whitespace1(), 1..)
|
||||||
|
.delimited_by(tag("(").followed_by(whitespace1()), tag(")")),
|
||||||
|
)
|
||||||
|
.map(|(conditional, exprs)| Depend::ConditionalGroup(conditional, exprs));
|
||||||
|
|
||||||
|
T::parser()
|
||||||
|
.map(|e| Depend::Element(e))
|
||||||
|
.or(conditional_group)
|
||||||
|
.or(any_of_group)
|
||||||
|
.or(all_of_group)
|
||||||
|
.or(one_of_group)
|
||||||
|
.parse(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Parseable<'a, &'a str> for Conditional {
|
||||||
|
type Parser = impl Parser<&'a str, Output = Self>;
|
||||||
|
|
||||||
|
fn parser() -> Self::Parser {
|
||||||
|
UseFlag::parser()
|
||||||
|
.preceded_by(tag("!"))
|
||||||
|
.followed_by(tag("?"))
|
||||||
|
.map(|flag| Conditional::Negative(flag))
|
||||||
|
.or(UseFlag::parser()
|
||||||
|
.followed_by(tag("?"))
|
||||||
|
.map(|flag| Conditional::Positive(flag)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
|
||||||
|
use mon::input::InputIter;
|
||||||
|
|
||||||
|
use crate::{atom::Atom, ebuild::Depend};
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_src_uri() {
|
||||||
|
let tests = [
|
||||||
|
"https://example.com/foo/bar.tar.gz",
|
||||||
|
"https://example.com/foo/bar.tar.gz -> bar.tar.gz",
|
||||||
|
];
|
||||||
|
|
||||||
|
for test in tests {
|
||||||
|
SrcUri::parser()
|
||||||
|
.check_finished(InputIter::new(test))
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_expr() {
|
||||||
|
let it = InputIter::new("flag? ( || ( foo/bar foo/bar ) )");
|
||||||
|
|
||||||
|
Depend::<Atom>::parser()
|
||||||
|
.separated_list(whitespace1(), 0..)
|
||||||
|
.check_finished(it)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,5 +11,5 @@ pub trait Parseable<'a, I: Input + 'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub mod atom;
|
pub mod atom;
|
||||||
pub mod depend;
|
pub mod ebuild;
|
||||||
pub mod useflag;
|
pub mod useflag;
|
||||||
|
|||||||
@@ -1,8 +1,4 @@
|
|||||||
use gentoo_utils::{
|
use gentoo_utils::{Parseable, atom::Atom, ebuild::Depend};
|
||||||
Parseable,
|
|
||||||
atom::Atom,
|
|
||||||
depend::{self, Expr},
|
|
||||||
};
|
|
||||||
use mon::{Parser, eof, input::InputIter, tag, whitespace1};
|
use mon::{Parser, eof, input::InputIter, tag, whitespace1};
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
|
||||||
@@ -18,7 +14,7 @@ fn parse_md5_cache() {
|
|||||||
if line.starts_with("DEPEND=") {
|
if line.starts_with("DEPEND=") {
|
||||||
eprintln!("{line}");
|
eprintln!("{line}");
|
||||||
eprintln!();
|
eprintln!();
|
||||||
Expr::<Atom>::parser()
|
Depend::<Atom>::parser()
|
||||||
.separated_list(whitespace1(), 0..)
|
.separated_list(whitespace1(), 0..)
|
||||||
.ignore()
|
.ignore()
|
||||||
.or(eof())
|
.or(eof())
|
||||||
|
|||||||
Reference in New Issue
Block a user