diff options
Diffstat (limited to 'lib/Carton/Tree.pm')
-rw-r--r-- | lib/Carton/Tree.pm | 69 |
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; |