Let's say I have a pool of packages a, b, c,... each package has name, version and dependencies.
In below code, get-cand sub takes a package and returns the candidates from the pool (along with their dependencies recursively).
so if it took package named c, and the pool has
Package c1: name c, version 1, dep a (any version) and b (version 1)
Package c2: name c, version 2, dep b (version 2)
it will return the following data structure:
((c1 ((((a1 ()) (a2 ()))) (((b1 ()))))) (c2 ((((b2 ())))))) # can't figure out how to get rid of empty lists here
I'm trying to write select-cand sub that will take the above data structure and the goal is to return the first candidate that doesn't conflict (with installed packages), and recursively check it's dependencies as well.
so the sub should work like this:
- Check c1, if conflicts returned False, take c1 and descend to it's deps
- (now in c1 deps) Check a1, if conflicts returned True, check next candidate (a2)
eventually it should return [c1 a2 b1] or [c2 b2] for successful run or nothing if all candidates conflicts.
but at the moment select-cand sub returns: [c1 a1 a2 c2 b2] which is wrong, because I only need either c1 (and it's deps recursively) or c2.
(conflicts is a place holder sub, at the moment it just exclude b1 package for testing purpose)
#!/usr/bin/env perl6
my %pkgs;
class Pkg {
has $.name;
has Version $.version = Version.new;
has Pkg @.dep;
method Str {
$!name ~ $!version;
}
}
my $a1 = Pkg.new: name => 'a', version => Version.new: <1>;
my $a2 = Pkg.new: name => 'a', version => Version.new: <2>;
my $b1 = Pkg.new: name => 'b', version => Version.new: <1>;
my $b2 = Pkg.new: name => 'b', version => Version.new: <2>;
my $c1 = Pkg.new: name => 'c', version => Version.new: <1>;
my $c2 = Pkg.new: name => 'c', version => Version.new: <2>;
$c1.dep.push: Pkg.new(name => 'a');
$c1.dep.push: Pkg.new(name => 'b', version => Version.new: <1>);
$c2.dep.push: Pkg.new(name => 'b', version => Version.new: <2>);
%pkgs<a> .push: $a1, $a2;
%pkgs<b> .push: $b1, $b2;
%pkgs<c> .push: $c1, $c2;
sub return-pkg (Pkg $pkg) {
my @pkgs = flat %pkgs{$pkg.name};
return grep {$_.version ~~ $pkg.version}, @pkgs;
}
sub get-cand (Pkg $pkg) {
gather {
take return-pkg($pkg).map( -> $pkg {
($pkg, $pkg.dep.map( -> $pkg {
get-cand($pkg).Slip
}).Slip)
}).cache;
}
}
sub conflicts (Pkg $pkg) {
return True if $pkg.name eq <a> and $pkg.version eq <1>;
#take $pkg.Str if $pkg.name eq <a> and $pkg.version eq <1>;
}
multi select-cand (Pkg $pkg) {
return $pkg.Str if not conflicts $pkg;
}
multi select-cand (@cand) {
gather {
@cand.map({ .first({ take select-cand $_ })});
}
}
my $c = Pkg.new: name => 'c';
my @cand = get-cand $c;
my @selected = select-cand @cand;
say @selected; # [(c1 () (a2) (b1))]