Skip to content

Instantly share code, notes, and snippets.

@ugexe
Created August 5, 2017 15:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ugexe/f786039212b2064898b0aee8b4e5cddb to your computer and use it in GitHub Desktop.
Save ugexe/f786039212b2064898b0aee8b4e5cddb to your computer and use it in GitHub Desktop.
unit module Zef::Utils::Distribution;
my grammar DepSpec::Grammar {
regex TOP { ^^ <name> [':' <key> <value>]* $$ }
regex name { <-restricted +name-sep>+ }
token key { <-restricted>+ }
token value { '<' ~ '>' [<( [[ <!before \>|\\> . ]+]* % ['\\' . ] )>] }
token restricted { [':' | '<' | '>' | '(' | ')'] }
token name-sep { < :: > }
}
# todo: handle (ignore?) top level keys that has a non-string value
my class DepSpec::Actions {
method TOP($/) { make %('name'=> $/<name>.made, %($/<key>>>.ast Z=> $/<value>>>.ast)) }
method name($/) { make $/.Str }
method key($/) { make $/.Str }
method value($/) { make $/.Str }
}
# normalize + clean keys/values, set defaults, etc
our sub normalize-depspec(
*%spec
[
:$name!,
:$api = '*',
:$version = '*',
:$ver = $version,
:$auth = '',
*%_
]
--> Hash) is export {
# strip leading 'v'
%spec<ver> = $ver.starts-with('v') ?? $ver.substr(1) !! $ver;
%spec<version>:delete;
%spec;
}
# hash to depspec string
our sub to-depspec(*%_ --> Str) is export {
my %spec = normalize-depspec(|%_);
my $str = %spec.keys.sort({$^a ne 'name'}).map({ $_ eq 'name' ?? %spec{$_} !! sprintf(':%s<%s>', $_, %spec{$_} // '') }).join;
$str;
}
# depspec string to hash
my sub from-depspec(Str $identity --> Hash) is export {
my %hash = DepSpec::Grammar.parse($identity, :actions(DepSpec::Actions.new)).ast;
my %spec = normalize-depspec(|%hash);
%spec;
}
# does %spec match against %query-spec?
# - %spec should contain concrete matchers (:ver<1.5> - e.g. no * or +)
# - %query-spec could contain concrete or ranges (:ver<1.5+>, :ver<1.*>, :ver<1.5>)
our sub depspec-match(%spec is copy, %query-spec is copy, Bool :$strict = True --> Bool) is export {
%spec = normalize-depspec(|%spec);
%query-spec = normalize-depspec(|%query-spec);
# don't even try to match if there is no name
return False unless %query-spec<name>.?chars && %spec<name>;
# match name - if $strict is False it will match the name as a pattern
return False unless $strict
?? (%query-spec<name>.lc eq %spec<name>.lc)
!! (%spec<name>.match(%query-spec<name>) with %query-spec<name>);
# match auth - only accepts an exact string match
return False if %query-spec<auth>.?chars && %query-spec<auth> ne %spec<auth>;
return False if (%query-spec<ver> // '*') ne '*' && (%spec<ver> // '*')
&& Version.new(%query-spec<ver>) !~~ Version.new(%spec<ver>);
# match api - same as `match version`
return False if %query-spec<api>.?chars
&& %query-spec<api> ne '*'
&& %spec<api> ne '*'
&& Version.new(%query-spec<api>) !~~ Version.new(%spec<api>);
# if we made it here then we must be a match
return True;
}
our sub resources-to-files(*@_) is export {
@_.map({
$_ => $_ ~~ m/^libraries\/(.*)/
?? "resources/libraries/{$*VM.platform-library-name($0.IO)}"
!! "resources/{$_}"
}).hash
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment