support ::repo syntax

This commit is contained in:
John Turner
2025-11-18 01:44:45 +00:00
parent db02762ee1
commit 78398b7ebe
2 changed files with 53 additions and 16 deletions

View File

@@ -103,6 +103,9 @@ pub enum UseDepCondition {
Question, Question,
} }
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Repo(String);
#[derive(Clone, Debug, PartialEq, Eq, Get)] #[derive(Clone, Debug, PartialEq, Eq, Get)]
pub struct UseDep { pub struct UseDep {
negate: Option<UseDepNegate>, negate: Option<UseDepNegate>,
@@ -132,6 +135,7 @@ pub struct Atom {
name: Name, name: Name,
version: Option<(VersionOperator, Version, Option<Wildcard>)>, version: Option<(VersionOperator, Version, Option<Wildcard>)>,
slot: Option<Slot>, slot: Option<Slot>,
repo: Option<Repo>,
#[get(kind = "deref")] #[get(kind = "deref")]
usedeps: Vec<UseDep>, usedeps: Vec<UseDep>,
} }

View File

@@ -5,7 +5,7 @@ use mon::{Parser, ParserIter, alphanumeric, r#if, numeric1, one_of, tag};
use crate::{ use crate::{
Parseable, Parseable,
atom::{ atom::{
Atom, Blocker, Category, Cp, Cpv, Name, Slot, SlotName, SlotOperator, UseDep, Atom, Blocker, Category, Cp, Cpv, Name, Repo, Slot, SlotName, SlotOperator, UseDep,
UseDepCondition, UseDepNegate, UseDepSign, Version, VersionNumber, VersionNumbers, UseDepCondition, UseDepNegate, UseDepSign, Version, VersionNumber, VersionNumbers,
VersionOperator, VersionSuffix, VersionSuffixKind, VersionSuffixes, Wildcard, VersionOperator, VersionSuffix, VersionSuffixKind, VersionSuffixes, Wildcard,
}, },
@@ -201,6 +201,21 @@ impl<'a> Parseable<'a, &'a str> for UseDepSign {
} }
} }
//A slot name may contain any of the characters [A-Za-z0-9+_.-]. It must not begin with a hyphen, a dot or a plus sign.
impl<'a> Parseable<'a, &'a str> for Repo {
type Parser = impl Parser<&'a str, Output = Self>;
fn parser() -> Self::Parser {
let start = alphanumeric().or(one_of("_".chars()));
let rest = alphanumeric().or(one_of("+_.-".chars())).repeated().many();
start
.and(rest)
.recognize()
.map(|output: &str| Repo(output.to_string()))
}
}
impl<'a> Parseable<'a, &'a str> for UseDep { impl<'a> Parseable<'a, &'a str> for UseDep {
type Parser = impl Parser<&'a str, Output = Self>; type Parser = impl Parser<&'a str, Output = Self>;
@@ -288,15 +303,19 @@ impl<'a> Parseable<'a, &'a str> for Atom {
.and(Category::parser()) .and(Category::parser())
.and(Name::parser().preceded_by(tag("/"))) .and(Name::parser().preceded_by(tag("/")))
.and(Slot::parser().preceded_by(tag(":")).opt()) .and(Slot::parser().preceded_by(tag(":")).opt())
.and(Repo::parser().preceded_by(tag("::")).opt())
.and(usedeps()) .and(usedeps())
.map(|((((blocker, category), name), slot), usedeps)| Atom { .map(
|(((((blocker, category), name), slot), repo), usedeps)| Atom {
blocker, blocker,
category, category,
name, name,
version: None, version: None,
slot, slot,
repo,
usedeps: usedeps.unwrap_or(Vec::new()), usedeps: usedeps.unwrap_or(Vec::new()),
}); },
);
let with_version = Blocker::parser() let with_version = Blocker::parser()
.opt() .opt()
@@ -306,16 +325,22 @@ impl<'a> Parseable<'a, &'a str> for Atom {
.and(Version::parser().preceded_by(tag("-"))) .and(Version::parser().preceded_by(tag("-")))
.and(tag("*").map(|_| Wildcard).opt()) .and(tag("*").map(|_| Wildcard).opt())
.and(Slot::parser().preceded_by(tag(":")).opt()) .and(Slot::parser().preceded_by(tag(":")).opt())
.and(Repo::parser().preceded_by(tag("::")).opt())
.and(usedeps()) .and(usedeps())
.verify_output(|(((((((_, version_operator), _), _), _), star), _), _)| { .verify_output(
|((((((((_, version_operator), _), _), _), star), _), _), _)| {
matches!( matches!(
(version_operator, star), (version_operator, star),
(VersionOperator::Eq, Some(_) | None) | (_, None) (VersionOperator::Eq, Some(_) | None) | (_, None)
) )
}) },
)
.map( .map(
|( |(
(
((((((blocker, version_operator), category), name), version), star), slot), ((((((blocker, version_operator), category), name), version), star), slot),
repo,
),
usedeps, usedeps,
)| { )| {
Atom { Atom {
@@ -324,6 +349,7 @@ impl<'a> Parseable<'a, &'a str> for Atom {
name, name,
version: Some((version_operator, version, star)), version: Some((version_operator, version, star)),
slot, slot,
repo,
usedeps: usedeps.unwrap_or(Vec::new()), usedeps: usedeps.unwrap_or(Vec::new()),
} }
}, },
@@ -502,6 +528,13 @@ mod test {
Atom::parser().check_finished(it).unwrap(); Atom::parser().check_finished(it).unwrap();
} }
#[test]
fn test_with_repo() {
let it = InputIter::new("=foo/bar-1.0.0:slot/sub=::gentoo[a,b,c]");
Atom::parser().check_finished(it).unwrap();
}
#[test] #[test]
fn test_against_fuzzer_false_positives() { fn test_against_fuzzer_false_positives() {
let atoms = [ let atoms = [