Skip to content

Commit

Permalink
CompUnit::Repository::resolve
Browse files Browse the repository at this point in the history
New method to ask the repository chain if a module matching the given
DependencySpecification is available. This could for example be used
by panda to avoid trying to install an already installed module.
  • Loading branch information
niner authored and hoelzro committed Jan 8, 2016
1 parent f1dd491 commit 1b6ecbd
Show file tree
Hide file tree
Showing 3 changed files with 140 additions and 86 deletions.
10 changes: 10 additions & 0 deletions src/core/CompUnit/Repository.pm
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,16 @@ role CompUnit::Repository {
returns CompUnit:D
{ ... }

# Resolves a dependency specification to a concrete dependency.
# Returns a CompUnit object that represents the selected dependency.
# If there is no matching dependency, an undefined CompUnit is returned.
method resolve(CompUnit::DependencySpecification $spec)
returns CompUnit
{
return self.next-repo.resolve($spec) if self.next-repo;
CompUnit
}

# Just load the file and return a CompUnit object representing it.
method load(IO::Path:D $file)
returns CompUnit:D
Expand Down
95 changes: 55 additions & 40 deletions src/core/CompUnit/Repository/FileSystem.pm
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,13 @@ class CompUnit::Repository::FileSystem does CompUnit::Repository::Locally does C
# global cache of files seen
my %seen;

method need(
CompUnit::DependencySpecification $spec,
CompUnit::PrecompilationRepository $precomp = self.precomp-repository(),
)
returns CompUnit:D
{
method !matching-file(CompUnit::DependencySpecification $spec) {
if $spec.from eq 'Perl6' {
my $name = $spec.short-name;
my $name = $spec.short-name;
return %!loaded{$name} if %!loaded{$name}:exists;

my $base := $!prefix.child($name.subst(:g, "::", $*SPEC.dir-sep) ~ '.').Str;
return $base if %seen{$base}:exists;
my $found;

# find source file
Expand All @@ -42,45 +38,64 @@ class CompUnit::Repository::FileSystem does CompUnit::Repository::Locally does C
}
}
# deduce path to compilation unit from package name
else {
if %seen{$base} -> $compunit {
return $compunit;
}

# have extensions to check
elsif %extensions<Perl6> -> @extensions {
for @extensions -> $extension {
my $path = $base ~ $extension;
$found = $path.IO if IO::Path.new-from-absolute-path($path).f;
}
elsif %extensions<Perl6> -> @extensions {
for @extensions -> $extension {
my $path = $base ~ $extension;
$found = $path.IO if IO::Path.new-from-absolute-path($path).f;
}
}

if $found {
my $id = nqp::sha1($name ~ $*REPO.id);
my $*RESOURCES = Distribution::Resources.new(:repo(self), :dist-id(''));
my $handle = (
$precomp.may-precomp and (
$precomp.load($id, :since($found.modified)) # already precompiled?
or $precomp.precompile($found, $id) and $precomp.load($id) # if not do it now
)
);
my $precompiled = ?$handle;
return $base, $found if $found;
}
False
}

if $*W and $*W.is_precompilation_mode {
if $precompiled {
say "$id $found";
}
else {
nqp::exit(0);
}
}
$handle ||= CompUnit::Loader.load-source-file($found); # precomp failed
method resolve(CompUnit::DependencySpecification $spec) returns CompUnit {
my ($base, $file) = self!matching-file($spec);
return CompUnit.new(
:short-name($spec.short-name),
:repo-id($file.Str),
:repo(self)
) if $base;
return self.next-repo.resolve($spec) if self.next-repo;
Nil
}

return %!loaded{$name} = %seen{$base} = CompUnit.new(
:short-name($name), :$handle, :repo(self), :repo-id($id), :$precompiled
);
method need(
CompUnit::DependencySpecification $spec,
CompUnit::PrecompilationRepository $precomp = self.precomp-repository(),
)
returns CompUnit:D
{
my ($base, $file) = self!matching-file($spec);
if $base {
my $name = $spec.short-name;
return %!loaded{$name} if %!loaded{$name}:exists;
return %seen{$base} if %seen{$base}:exists;

my $id = nqp::sha1($name ~ $*REPO.id);
my $*RESOURCES = Distribution::Resources.new(:repo(self), :dist-id(''));
my $handle = (
$precomp.may-precomp and (
$precomp.load($id, :since($file.modified)) # already precompiled?
or $precomp.precompile($file, $id) and $precomp.load($id) # if not do it now
)
);
my $precompiled = ?$handle;

if $*W and $*W.is_precompilation_mode {
if $precompiled {
say "$id $file";
}
else {
nqp::exit(0);
}
}
$handle ||= CompUnit::Loader.load-source-file($file); # precomp failed

return %!loaded{$name} = %seen{$base} = CompUnit.new(
:short-name($name), :$handle, :repo(self), :repo-id($id), :$precompiled
);
}

return self.next-repo.need($spec, $precomp) if self.next-repo;
Expand Down
121 changes: 75 additions & 46 deletions src/core/CompUnit/Repository/Installation.pm
Original file line number Diff line number Diff line change
Expand Up @@ -238,16 +238,11 @@ sub MAIN(:$name is copy, :$auth, :$ver, *@, *%) {
@candi
}

method need(
CompUnit::DependencySpecification $spec,
CompUnit::PrecompilationRepository $precomp = self.precomp-repository(),
)
returns CompUnit:D
{
method !matching-dist(CompUnit::DependencySpecification $spec) {
if $spec.from eq 'Perl6' {
my $lookup = $.prefix.child('short').child(nqp::sha1($spec.short-name));
if $lookup.e {
my $dist-dir = self!dist-dir;
my $dist-dir = $.prefix.child('dist');
my @dists = $lookup.lines.unique.map({
$_ => from-json($dist-dir.child($_).slurp)
}).grep({
Expand All @@ -256,48 +251,82 @@ sub MAIN(:$name is copy, :$auth, :$ver, *@, *%) {
and $_.value<provides>{$spec.short-name}:exists
});
for @dists.sort(*.value<ver>).reverse.map(*.kv) -> ($dist-id, $dist) {
return %!loaded{$spec.short-name} if %!loaded{$spec.short-name}:exists;
my $dver = $dist<ver>
?? nqp::istype($dist<ver>,Version)
?? $dist<ver>
!! Version.new( ~$dist<ver> )
!! Version.new('0');

my $loader = $.prefix.child('sources').child(
$dist<provides>{$spec.short-name}<pm pm6>.first(*.so)<file>
);
my $*RESOURCES = Distribution::Resources.new(:repo(self), :$dist-id);
my $handle;
my $id = $loader.basename;
if $precomp.may-precomp {
$handle = (
$precomp.load($id, :since($loader.modified)) # already precompiled?
or $precomp.precompile($loader, $id) and $precomp.load($id) # if not do it now
);
if $*W and $*W.is_precompilation_mode {
if $handle {
say "$id $loader";
}
else {
nqp::exit(0);
}
}
$dist<ver> = $dist<ver> ?? Version.new( ~$dist<ver> ) !! Version.new('0');
return ($dist-id, $dist);
}
}
}
Nil
}

method resolve(
CompUnit::DependencySpecification $spec,
)
returns CompUnit
{
my ($dist-id, $dist) = self!matching-dist($spec);
if $dist-id {
my $loader = $.prefix.child('sources').child(
$dist<provides>{$spec.short-name}<pm pm6>.first(*.so)<file>
);
my $id = $loader.basename;
return CompUnit.new(
:handle(CompUnit::Handle),
:short-name($spec.short-name),
:version($dist<ver>),
:auth($dist<auth> // Str),
:repo(self),
:repo-id($id),
:distribution(Distribution.new(|$dist)),
);
}
return self.next-repo.resolve($spec) if self.next-repo;
Nil
}

method need(
CompUnit::DependencySpecification $spec,
CompUnit::PrecompilationRepository $precomp = self.precomp-repository(),
)
returns CompUnit:D
{
my ($dist-id, $dist) = self!matching-dist($spec);
if $dist-id {
return %!loaded{$spec.short-name} if %!loaded{$spec.short-name}:exists;

my $loader = $.prefix.child('sources').child(
$dist<provides>{$spec.short-name}<pm pm6>.first(*.so)<file>
);
my $*RESOURCES = Distribution::Resources.new(:repo(self), :$dist-id);
my $handle;
my $id = $loader.basename;
if $precomp.may-precomp {
$handle = (
$precomp.load($id, :since($loader.modified)) # already precompiled?
or $precomp.precompile($loader, $id) and $precomp.load($id) # if not do it now
);
if $*W and $*W.is_precompilation_mode {
if $handle {
say "$id $loader";
}
else {
nqp::exit(0);
}
my $precompiled = defined $handle;
$handle //= CompUnit::Loader.load-source-file($loader);
my $compunit = CompUnit.new(
:$handle,
:short-name($spec.short-name),
:version($dver),
:auth($dist<auth> // Str),
:repo(self),
:repo-id($id),
:$precompiled,
:distribution(Distribution.new(|$dist)),
);
return %!loaded{$compunit.short-name} = $compunit;
}
}
my $precompiled = defined $handle;
$handle //= CompUnit::Loader.load-source-file($loader);
my $compunit = CompUnit.new(
:$handle,
:short-name($spec.short-name),
:version($dist<ver>),
:auth($dist<auth> // Str),
:repo(self),
:repo-id($id),
:$precompiled,
:distribution(Distribution.new(|$dist)),
);
return %!loaded{$compunit.short-name} = $compunit;
}
return self.next-repo.need($spec, $precomp) if self.next-repo;
X::CompUnit::UnsatisfiedDependency.new(:specification($spec)).throw;
Expand Down

0 comments on commit 1b6ecbd

Please sign in to comment.