Created
August 5, 2017 15:55
-
-
Save ugexe/f786039212b2064898b0aee8b4e5cddb to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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