diff options
Diffstat (limited to 'src/repo')
| -rw-r--r-- | src/repo/ebuild/meson.build | 1 | ||||
| -rw-r--r-- | src/repo/ebuild/mod.rs | 83 | ||||
| -rw-r--r-- | src/repo/ebuild/parsers.rs | 205 | ||||
| -rw-r--r-- | src/repo/meson.build | 3 | ||||
| -rw-r--r-- | src/repo/mod.rs | 325 |
5 files changed, 0 insertions, 617 deletions
diff --git a/src/repo/ebuild/meson.build b/src/repo/ebuild/meson.build deleted file mode 100644 index a7331a8..0000000 --- a/src/repo/ebuild/meson.build +++ /dev/null @@ -1 +0,0 @@ -sources += files('mod.rs', 'parsers.rs') diff --git a/src/repo/ebuild/mod.rs b/src/repo/ebuild/mod.rs deleted file mode 100644 index 3f52db9..0000000 --- a/src/repo/ebuild/mod.rs +++ /dev/null @@ -1,83 +0,0 @@ -use get::Get; -use std::path::PathBuf; - -use crate::{ - atom::{Atom, Name, Slot, Version}, - useflag::{IUseFlag, UseFlag}, -}; - -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)] -pub enum UriPrefix { - Mirror, - Fetch, -} - -#[derive(Debug, Clone, Get)] -pub struct Uri { - #[get(kind = "deref")] - protocol: String, - #[get(kind = "deref")] - path: String, -} - -#[derive(Debug, Clone)] -pub enum SrcUri { - Filename(PathBuf), - Uri { - prefix: Option<UriPrefix>, - uri: Uri, - filename: 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 { - pub(super) name: Name, - pub(super) version: Version, - pub(super) slot: Option<Slot>, - pub(super) homepage: Option<String>, - #[get(kind = "deref")] - pub(super) src_uri: Vec<Depend<SrcUri>>, - pub(super) eapi: Option<Eapi>, - #[get(kind = "deref")] - pub(super) inherit: Vec<Eclass>, - #[get(kind = "deref")] - pub(super) iuse: Vec<IUseFlag>, - #[get(kind = "deref")] - pub(super) license: Vec<Depend<License>>, - pub(super) description: Option<String>, - #[get(kind = "deref")] - pub(super) depend: Vec<Depend<Atom>>, - #[get(kind = "deref")] - pub(super) bdepend: Vec<Depend<Atom>>, - #[get(kind = "deref")] - pub(super) rdepend: Vec<Depend<Atom>>, - #[get(kind = "deref")] - pub(super) idepend: Vec<Depend<Atom>>, -} diff --git a/src/repo/ebuild/parsers.rs b/src/repo/ebuild/parsers.rs deleted file mode 100644 index c80cdf2..0000000 --- a/src/repo/ebuild/parsers.rs +++ /dev/null @@ -1,205 +0,0 @@ -use std::path::PathBuf; - -use mon::{ - Parser, ParserIter, ascii_alpha1, ascii_alphanumeric, ascii_whitespace1, r#if, one_of, tag, -}; - -use crate::{ - Parseable, - repo::ebuild::{Conditional, Depend, Eapi, Eclass, License, SrcUri, Uri, UriPrefix}, - useflag::UseFlag, -}; - -impl<'a> Parseable<'a, &'a str> for UriPrefix { - type Parser = impl Parser<&'a str, Output = Self>; - - fn parser() -> Self::Parser { - tag("+mirror") - .map(|_| UriPrefix::Mirror) - .or(tag("+fetch").map(|_| UriPrefix::Fetch)) - } -} - -impl<'a> Parseable<'a, &'a str> for Uri { - type Parser = impl Parser<&'a str, Output = Self>; - - fn parser() -> Self::Parser { - let protocol = ascii_alpha1::<&str>() - .followed_by(tag("://")) - .map(|output: &str| output.to_string()); - let path = r#if(|c: &char| !c.is_ascii_whitespace()) - .repeated() - .at_least(1) - .recognize() - .map(|output: &str| output.to_string()); - - protocol - .and(path) - .map(|(protocol, path)| Uri { protocol, path }) - } -} - -impl<'a> Parseable<'a, &'a str> for SrcUri { - type Parser = impl Parser<&'a str, Output = Self>; - - fn parser() -> Self::Parser { - let filename = || { - r#if(|c: &char| !c.is_ascii_whitespace()) - .repeated() - .at_least(1) - .recognize() - .map(|output: &str| PathBuf::from(output)) - }; - - let uri = UriPrefix::parser() - .opt() - .and(Uri::parser()) - .and(filename().preceded_by(tag(" -> ")).opt()) - .map(|((prefix, uri), filename)| SrcUri::Uri { - prefix, - uri, - filename, - }); - - uri.or(filename().map(|path: PathBuf| SrcUri::Filename(path))) - } -} - -impl<'a> Parseable<'a, &'a str> for License { - type Parser = impl Parser<&'a str, Output = Self>; - - fn parser() -> Self::Parser { - let start = ascii_alphanumeric().or(one_of("_".chars())); - let rest = ascii_alphanumeric() - .or(one_of("+_.-".chars())) - .repeated() - .many(); - - 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 = ascii_alphanumeric().or(one_of("_".chars())); - let rest = ascii_alphanumeric() - .or(one_of("+_.-".chars())) - .repeated() - .many(); - - start - .and(rest) - .recognize() - .map(|output: &str| Eapi(output.to_string())) - } -} - -// TODO: -// Cant find information about eclass names in pms so we allow anything except -// for whitespace. -impl<'a> Parseable<'a, &'a str> for Eclass { - type Parser = impl Parser<&'a str, Output = Self>; - - fn parser() -> Self::Parser { - r#if(|c: &char| !c.is_ascii_whitespace()) - .repeated() - .at_least(1) - .recognize() - .map(|output: &str| Eclass(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 exprs = || { - Depend::parser() - .separated_by_with_trailing(ascii_whitespace1()) - .at_least(1) - .delimited_by(tag("(").followed_by(ascii_whitespace1()), tag(")")) - }; - - let all_of_group = exprs().map(|exprs| Depend::AllOf(exprs)); - - let any_of_group = exprs() - .preceded_by(tag("||").followed_by(ascii_whitespace1())) - .map(|exprs| Depend::AnyOf(exprs)); - - let one_of_group = exprs() - .preceded_by(tag("^^").followed_by(ascii_whitespace1())) - .map(|exprs| Depend::OneOf(exprs)); - - let conditional_group = Conditional::parser() - .followed_by(ascii_whitespace1()) - .and(exprs()) - .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(Conditional::Negative) - .or(UseFlag::parser() - .followed_by(tag("?")) - .map(Conditional::Positive)) - } -} - -#[cfg(test)] -mod test { - - use mon::{ParserIter, input::InputIter}; - - use crate::{atom::Atom, repo::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_by(ascii_whitespace1()) - .many() - .check_finished(it) - .unwrap(); - } -} diff --git a/src/repo/meson.build b/src/repo/meson.build deleted file mode 100644 index c1be7a7..0000000 --- a/src/repo/meson.build +++ /dev/null @@ -1,3 +0,0 @@ -sources += files('mod.rs') - -subdir('ebuild') diff --git a/src/repo/mod.rs b/src/repo/mod.rs deleted file mode 100644 index eb68839..0000000 --- a/src/repo/mod.rs +++ /dev/null @@ -1,325 +0,0 @@ -use std::{ - fs, io, - os::unix::ffi::OsStrExt, - path::{Path, PathBuf}, -}; - -use get::Get; - -use mon::{Parser, ParserIter, ascii_whitespace1, input::InputIter, tag}; - -use crate::{ - Parseable, - atom::{self, Atom}, - repo::ebuild::{Depend, Eapi, Ebuild, Eclass, License, SrcUri}, - useflag::IUseFlag, -}; - -pub mod ebuild; - -#[derive(Debug, thiserror::Error)] -pub enum Error { - #[error("io error: {0}")] - Io(PathBuf, io::Error), - #[error("error while reading directory: {0:?}: {1}")] - ReadDir(PathBuf, io::Error), - #[error("failed to decode path: {0}")] - Unicode(PathBuf), - #[error("parser error: {0}")] - Parser(String), -} - -#[derive(Debug, Clone, Get)] -pub struct Repo { - #[get(kind = "deref")] - path: PathBuf, -} - -#[derive(Debug, Clone, Get)] -pub struct Category { - name: atom::Category, - #[get(kind = "deref")] - path: PathBuf, -} - -#[derive(Debug)] -pub struct Categories(PathBuf, fs::ReadDir); - -#[derive(Debug)] -pub struct Ebuilds(PathBuf, fs::ReadDir); - -impl Repo { - pub fn new<P: AsRef<Path>>(path: P) -> Self { - Self { - path: path.as_ref().to_path_buf(), - } - } - - pub fn categories(&self) -> Result<Categories, Error> { - let path = self.path.as_path().join("metadata/md5-cache"); - - Ok(Categories( - path.clone(), - fs::read_dir(&path).map_err(|e| Error::Io(path, e))?, - )) - } -} - -impl Category { - pub fn ebuilds(&self) -> Result<Ebuilds, Error> { - Ok(Ebuilds( - self.path.clone(), - fs::read_dir(&self.path).map_err(|e| Error::Io(self.path.clone(), e))?, - )) - } -} - -impl Iterator for Categories { - type Item = Result<Category, Error>; - - fn next(&mut self) -> Option<Self::Item> { - loop { - match self.1.next()? { - Ok(entry) if entry.path().file_name().unwrap().as_bytes() == b"Manifest.gz" => (), - Ok(entry) => match read_category(entry.path()) { - Ok(category) => break Some(Ok(category)), - Err(e) => break Some(Err(e)), - }, - Err(e) => break Some(Err(Error::ReadDir(self.0.clone(), e))), - } - } - } -} - -impl Iterator for Ebuilds { - type Item = Result<Ebuild, Error>; - - fn next(&mut self) -> Option<Self::Item> { - loop { - match self.1.next()? { - Ok(entry) if entry.path().file_name().unwrap().as_bytes() == b"Manifest.gz" => (), - Ok(entry) => match read_ebuild(entry.path()) { - Ok(ebuild) => break Some(Ok(ebuild)), - Err(e) => break Some(Err(e)), - }, - Err(e) => break Some(Err(Error::ReadDir(self.0.clone(), e))), - } - } - } -} - -fn read_category(path: PathBuf) -> Result<Category, Error> { - let file_name = path - .as_path() - .file_name() - .unwrap() - .to_str() - .ok_or(Error::Unicode(path.clone()))?; - - let name = atom::Category::parser() - .parse_finished(InputIter::new(file_name)) - .map_err(|_| Error::Parser(file_name.to_string()))?; - - Ok(Category { name, path }) -} - -fn read_ebuild(path: PathBuf) -> Result<Ebuild, Error> { - let file_name = path - .as_path() - .file_name() - .unwrap() - .to_str() - .ok_or(Error::Unicode(path.clone()))?; - - let (name, version) = atom::Name::parser() - .and(atom::Version::parser().preceded_by(tag("-"))) - .parse_finished(InputIter::new(file_name)) - .map_err(|_| Error::Parser(file_name.to_string()))?; - - let metadata = fs::read_to_string(path.as_path()).map_err(|e| Error::Io(path, e))?; - - Ok(Ebuild { - name, - version, - slot: match read_slot(&metadata) { - Some(Ok(slot)) => Some(slot), - Some(Err(e)) => return Err(e), - None => None, - }, - homepage: read_homepage(&metadata), - src_uri: match read_src_uri(&metadata) { - Some(Ok(src_uri)) => src_uri, - Some(Err(e)) => return Err(e), - None => Vec::new(), - }, - eapi: match read_eapi(&metadata) { - Some(Ok(eapi)) => Some(eapi), - Some(Err(e)) => return Err(e), - None => None, - }, - inherit: match read_inherit(&metadata) { - Some(Ok(inherit)) => inherit, - Some(Err(e)) => return Err(e), - None => Vec::new(), - }, - iuse: match read_iuse(&metadata) { - Some(Ok(iuse)) => iuse, - Some(Err(e)) => return Err(e), - None => Vec::new(), - }, - license: match read_license(&metadata) { - Some(Ok(license)) => license, - Some(Err(e)) => return Err(e), - None => Vec::new(), - }, - description: read_description(&metadata), - depend: match read_depend(&metadata) { - Some(Ok(depend)) => depend, - Some(Err(e)) => return Err(e), - None => Vec::new(), - }, - bdepend: match read_bdepend(&metadata) { - Some(Ok(depend)) => depend, - Some(Err(e)) => return Err(e), - None => Vec::new(), - }, - rdepend: match read_rdepend(&metadata) { - Some(Ok(depend)) => depend, - Some(Err(e)) => return Err(e), - None => Vec::new(), - }, - idepend: match read_idepend(&metadata) { - Some(Ok(depend)) => depend, - Some(Err(e)) => return Err(e), - None => Vec::new(), - }, - }) -} - -fn read_slot(input: &str) -> Option<Result<atom::Slot, Error>> { - let line = input.lines().find_map(|line| line.strip_prefix("SLOT="))?; - - match atom::Slot::parser().parse_finished(InputIter::new(line)) { - Ok(slot) => Some(Ok(slot)), - Err(_) => Some(Err(Error::Parser(line.to_string()))), - } -} - -fn read_homepage(input: &str) -> Option<String> { - input - .lines() - .find_map(|line| line.strip_prefix("HOMEPAGE=").map(str::to_string)) -} - -fn read_src_uri(input: &str) -> Option<Result<Vec<Depend<SrcUri>>, Error>> { - let line = input - .lines() - .find_map(|line| line.strip_prefix("SRC_URI="))?; - - match Depend::<SrcUri>::parser() - .separated_by(ascii_whitespace1()) - .many() - .parse_finished(InputIter::new(line)) - { - Ok(slot) => Some(Ok(slot)), - Err(_) => Some(Err(Error::Parser(line.to_string()))), - } -} - -fn read_eapi(input: &str) -> Option<Result<Eapi, Error>> { - let line = input.lines().find_map(|line| line.strip_prefix("EAPI="))?; - - match Eapi::parser().parse_finished(InputIter::new(line)) { - Ok(slot) => Some(Ok(slot)), - Err(_) => Some(Err(Error::Parser(line.to_string()))), - } -} - -fn read_inherit(input: &str) -> Option<Result<Vec<Eclass>, Error>> { - let line = input - .lines() - .find_map(|line| line.strip_prefix("INHERIT="))?; - - match Eclass::parser() - .separated_by(ascii_whitespace1()) - .many() - .parse_finished(InputIter::new(line)) - { - Ok(inherit) => Some(Ok(inherit)), - Err(_) => Some(Err(Error::Parser(line.to_string()))), - } -} - -fn read_iuse(input: &str) -> Option<Result<Vec<IUseFlag>, Error>> { - let line = input.lines().find_map(|line| line.strip_prefix("IUSE="))?; - - match IUseFlag::parser() - .separated_by(ascii_whitespace1()) - .many() - .parse_finished(InputIter::new(line)) - { - Ok(iuse) => Some(Ok(iuse)), - Err(_) => Some(Err(Error::Parser(line.to_string()))), - } -} - -fn read_license(input: &str) -> Option<Result<Vec<Depend<License>>, Error>> { - let line = input - .lines() - .find_map(|line| line.strip_suffix("LICENSE="))?; - - match Depend::<License>::parser() - .separated_by(ascii_whitespace1()) - .many() - .parse_finished(InputIter::new(line)) - { - Ok(license) => Some(Ok(license)), - Err(_) => Some(Err(Error::Parser(line.to_string()))), - } -} - -fn read_description(input: &str) -> Option<String> { - input - .lines() - .find_map(|line| line.strip_prefix("DESCRIPTION=").map(str::to_string)) -} - -fn read_depend(input: &str) -> Option<Result<Vec<Depend<Atom>>, Error>> { - let line = input - .lines() - .find_map(|line| line.strip_prefix("DEPEND="))?; - - Some(parse_depends(line)) -} - -fn read_bdepend(input: &str) -> Option<Result<Vec<Depend<Atom>>, Error>> { - let line = input - .lines() - .find_map(|line| line.strip_prefix("BDEPEND="))?; - - Some(parse_depends(line)) -} - -fn read_rdepend(input: &str) -> Option<Result<Vec<Depend<Atom>>, Error>> { - let line = input - .lines() - .find_map(|line| line.strip_prefix("RDEPEND="))?; - - Some(parse_depends(line)) -} - -fn read_idepend(input: &str) -> Option<Result<Vec<Depend<Atom>>, Error>> { - let line = input - .lines() - .find_map(|line| line.strip_prefix("IDEPEND="))?; - - Some(parse_depends(line)) -} - -fn parse_depends(line: &str) -> Result<Vec<Depend<Atom>>, Error> { - Depend::<Atom>::parser() - .separated_by(ascii_whitespace1()) - .many() - .parse_finished(InputIter::new(line)) - .map_err(|_| Error::Parser(line.to_string())) -} |
