summaryrefslogtreecommitdiff
path: root/lib/Carton/Tree.pm
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Carton/Tree.pm')
-rw-r--r--lib/Carton/Tree.pm69
1 files changed, 69 insertions, 0 deletions
diff --git a/lib/Carton/Tree.pm b/lib/Carton/Tree.pm
new file mode 100644
index 0000000..6ce22a1
--- /dev/null
+++ b/lib/Carton/Tree.pm
@@ -0,0 +1,69 @@
+package Carton::Tree;
+use strict;
+use Carton::Dependency;
+
+use Class::Tiny qw( cpanfile snapshot );
+
+use constant STOP => -1;
+
+sub walk_down {
+ my($self, $cb) = @_;
+
+ my $dumper; $dumper = sub {
+ my($dependency, $reqs, $level, $parent) = @_;
+
+ my $ret = $cb->($dependency, $reqs, $level);
+ return if $ret && $ret == STOP;
+
+ local $parent->{$dependency->distname} = 1 if $dependency;
+
+ for my $module (sort $reqs->required_modules) {
+ my $dependency = $self->dependency_for($module, $reqs);
+ if ($dependency->dist) {
+ next if $parent->{$dependency->distname};
+ $dumper->($dependency, $dependency->requirements, $level + 1, $parent);
+ } else {
+ # no dist found in lock
+ }
+ }
+ };
+
+ $dumper->(undef, $self->cpanfile->requirements, 0, {});
+ undef $dumper;
+}
+
+sub dependency_for {
+ my($self, $module, $reqs) = @_;
+
+ my $requirement = $reqs->requirements_for_module($module);
+
+ my $dep = Carton::Dependency->new;
+ $dep->module($module);
+ $dep->requirement($requirement);
+
+ if (my $dist = $self->snapshot->find_or_core($module)) {
+ $dep->dist($dist);
+ }
+
+ return $dep;
+}
+
+sub merged_requirements {
+ my $self = shift;
+
+ my $merged_reqs = CPAN::Meta::Requirements->new;
+
+ my %seen;
+ $self->walk_down(sub {
+ my($dependency, $reqs, $level) = @_;
+ return Carton::Tree::STOP if $dependency && $seen{$dependency->distname}++;
+ $merged_reqs->add_requirements($reqs);
+ });
+
+ $merged_reqs->clear_requirement('perl');
+ $merged_reqs->finalize;
+
+ $merged_reqs;
+}
+
+1;