NAME
Langertha::Raider::Detect - Internal evaluator for declarative pack detection rules
VERSION
version 0.503
SYNOPSIS
# Internal to Langertha-Raider -- no API promise.
my $detect = Langertha::Raider::Detect->new( root => $workspace );
Langertha::Raider::Detect->validate_rule($rule, 'perl'); # croaks when invalid
my $result = $detect->evaluate({
must => [ { file => 'cpanfile' } ],
may => [ { file => 'dist.ini' }, { file => 'lib/**/*.pm' } ],
must_not => [ { file => '.raider/no-perl' } ],
}, 'perl');
print $result->{matched} ? 'perl: '.$result->{reason} : 'no perl';
DESCRIPTION
Internal module. Its interface may change without notice.
Evaluates one detection rule of ADR 0012 against a workspace root. A rule is a map of up to three clause lists:
must-- every condition holds.may-- when the list is non-empty, at least one condition holds.must_not-- no condition holds.
A rule without any condition never matches. The clauses are evaluated in the order must, must_not, may, and evaluation stops as soon as the outcome is decided.
A condition is a map; every key in it must hold:
file: GLOB-- a file matching the glob exists.dir: GLOB-- a directory matching the glob exists.contains: STRING-- withfile, a matching file contains the literal string.matches: REGEX-- withfile, a matching file matches the regex (multi-line:^and$anchor at line ends). Withcontainsas well, both must hold in the same file.
Globs are relative to the workspace root and know * and ? (within one path segment) and ** (any number of directories, including none; a trailing ** matches everything below). Wildcards do not match names that start with a dot unless the pattern segment does, so ** never walks .git. .. and absolute globs are invalid.
Evaluation is bounded: symlinks are followed only when they resolve inside the root, and ** never descends into a symlinked directory; a ** descends at most "max_depth" directories; one condition looks at no more than "max_entries" directory entries; content checks read at most the first "max_bytes" of a file. Hitting a limit makes the condition false and is reported in notes, it never stops the run. Content is matched as UTF-8 text when it decodes, as bytes otherwise.
root
The workspace root the globs are relative to. Required.
max_depth
How many directories one ** descends at most. Defaults to 8.
max_entries
How many directory entries one condition looks at before it gives up. Defaults to 5000.
max_bytes
How many bytes of a file a content check reads. Defaults to 65536 (64 KiB).
validate_rule
Langertha::Raider::Detect->validate_rule($rule, $label);
Croaks with Invalid detect rule LABEL...: problem when $rule is not a valid rule: not a map, an unknown clause or condition key, a clause that is not a list, a condition without file or dir, contains or matches without file, an empty, absolute or .. glob, or a regex that does not compile. $label (e.g. the pack name) prefixes the location; it defaults to rule. Returns true. Callable on the class.
describe_condition
my $text = Langertha::Raider::Detect->describe_condition({ file => 'dist.ini', contains => 'GETTY' });
# 'file=dist.ini contains="GETTY"'
One-line form of a condition, as used in reason and checks. Callable on the class.
evaluate
my $result = $detect->evaluate($rule, $label);
Validates the rule (see "validate_rule") and evaluates it against "root":
{
matched => 1,
reason => 'must file=cpanfile (cpanfile); may file=dist.ini (dist.ini)',
checks => [
{ clause => 'must', condition => 'file=cpanfile', held => 1, path => 'cpanfile' },
{ clause => 'may', condition => 'file=dist.ini', held => 1, path => 'dist.ini' },
],
notes => [],
}
reason names the conditions that decided the outcome -- what matched and where for a match, the condition that failed (no match, found PATH, none of ... held) otherwise; no clauses for an empty rule. checks lists every condition that was evaluated, notes every limit that was hit by a condition that did not hold.
SEE ALSO
SUPPORT
Issues
Please report bugs and feature requests on GitHub at https://github.com/Getty/langertha-raider/issues.
IRC
Join #langertha on irc.perl.org or message Getty directly.
CONTRIBUTING
Contributions are welcome! Please fork the repository and submit a pull request.
AUTHOR
Torsten Raudssus <torsten@raudssus.de> https://raudssus.de/
COPYRIGHT AND LICENSE
This software is copyright (c) 2026 by Torsten Raudssus.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.