From 8cc54374790f8728eb1be75bbbab33b91ae69838 Mon Sep 17 00:00:00 2001 From: Jesse Luehrs Date: Sun, 21 Nov 2010 17:10:52 -0600 Subject: initial implementation --- dist.ini | 8 +++- lib/Dist/CheckConflicts.pm | 92 +++++++++++++++++++++++++++++++++++++++++ t/01-basic.t | 47 +++++++++++++++++++++ t/02-conflicts.t | 70 +++++++++++++++++++++++++++++++ t/lib/01/Bar/Conflicts.pm | 13 ++++++ t/lib/01/Bar/Conflicts2.pm | 13 ++++++ t/lib/01/Bar/Conflicts3.pm | 10 +++++ t/lib/01/Foo/Conflicts.pm | 11 +++++ t/lib/02/Bar.pm | 7 ++++ t/lib/02/Bar/Conflicts/Bad.pm | 13 ++++++ t/lib/02/Bar/Conflicts/Bad2.pm | 13 ++++++ t/lib/02/Bar/Conflicts/Bad3.pm | 10 +++++ t/lib/02/Bar/Conflicts/Good.pm | 13 ++++++ t/lib/02/Bar/Conflicts/Good2.pm | 13 ++++++ t/lib/02/Bar/Conflicts/Good3.pm | 10 +++++ t/lib/02/Bar/Three.pm | 7 ++++ t/lib/02/Bar/Two.pm | 7 ++++ t/lib/02/Foo.pm | 7 ++++ t/lib/02/Foo/Conflicts/Bad.pm | 12 ++++++ t/lib/02/Foo/Conflicts/Good.pm | 12 ++++++ t/lib/02/Foo/Three.pm | 7 ++++ t/lib/02/Foo/Two.pm | 7 ++++ 22 files changed, 401 insertions(+), 1 deletion(-) create mode 100644 t/01-basic.t create mode 100644 t/02-conflicts.t create mode 100644 t/lib/01/Bar/Conflicts.pm create mode 100644 t/lib/01/Bar/Conflicts2.pm create mode 100644 t/lib/01/Bar/Conflicts3.pm create mode 100644 t/lib/01/Foo/Conflicts.pm create mode 100644 t/lib/02/Bar.pm create mode 100644 t/lib/02/Bar/Conflicts/Bad.pm create mode 100644 t/lib/02/Bar/Conflicts/Bad2.pm create mode 100644 t/lib/02/Bar/Conflicts/Bad3.pm create mode 100644 t/lib/02/Bar/Conflicts/Good.pm create mode 100644 t/lib/02/Bar/Conflicts/Good2.pm create mode 100644 t/lib/02/Bar/Conflicts/Good3.pm create mode 100644 t/lib/02/Bar/Three.pm create mode 100644 t/lib/02/Bar/Two.pm create mode 100644 t/lib/02/Foo.pm create mode 100644 t/lib/02/Foo/Conflicts/Bad.pm create mode 100644 t/lib/02/Foo/Conflicts/Good.pm create mode 100644 t/lib/02/Foo/Three.pm create mode 100644 t/lib/02/Foo/Two.pm diff --git a/dist.ini b/dist.ini index 1446041..a688acb 100644 --- a/dist.ini +++ b/dist.ini @@ -6,4 +6,10 @@ copyright_holder = Jesse Luehrs [@DOY] dist = Dist-CheckConflicts -[Prereq] +[Prereqs] +List::MoreUtils = 0.12 +Sub::Exporter = 0 + +[Prereqs / TestRequires] +Test::More = 0.88 +Test::Fatal = 0 diff --git a/lib/Dist/CheckConflicts.pm b/lib/Dist/CheckConflicts.pm index e69de29..da9b859 100644 --- a/lib/Dist/CheckConflicts.pm +++ b/lib/Dist/CheckConflicts.pm @@ -0,0 +1,92 @@ +package Dist::CheckConflicts; +use strict; +use warnings; + +use Carp; +use List::MoreUtils 'first_index'; +use Sub::Exporter; + +my $import = Sub::Exporter::build_exporter({ + exports => [ qw(conflicts check_conflicts calculate_conflicts) ], + groups => { + default => [ qw(conflicts check_conflicts calculate_conflicts) ], + }, +}); + +my %CONFLICTS; + +sub import { + my $for = caller; + + my ($conflicts, $alsos); + ($conflicts, @_) = _strip_opt('-conflicts' => @_); + ($alsos, @_) = _strip_opt('-also' => @_); + + my %conflicts = %{ $conflicts || {} }; + for my $also (@{ $alsos || [] }) { + eval "require $also; 1;" or die "Couldn't find package $also: $@"; + my %also_confs = $also->conflicts; + for my $also_conf (keys %also_confs) { + $conflicts{$also_conf} = $also_confs{$also_conf} + if !exists $conflicts{$also_conf} + || $conflicts{$also_conf} lt $also_confs{$also_conf}; + } + } + + $CONFLICTS{$for} = \%conflicts; + + goto $import; +} + +sub _strip_opt { + my $opt = shift; + my $idx = first_index { ( $_ || '' ) eq $opt } @_; + + return ( undef, @_ ) unless $idx >= 0 && $#_ >= $idx + 1; + + my $val = $_[ $idx + 1 ]; + + splice @_, $idx, 2; + + return ( $val, @_ ); +} + +sub conflicts { + my $package = shift; + return %{ $CONFLICTS{ $package } }; +} + +sub check_conflicts { + my $package = shift; + my @conflicts = $package->calculate_conflicts; + return unless @conflicts; + + my $err = "Conflicts detected for $package:\n"; + for my $conflict (@conflicts) { + $err .= " $conflict->{package} is version " + . "$conflict->{installed}, but must be greater than version " + . "$conflict->{required}\n"; + } + die $err; +} + +sub calculate_conflicts { + my $package = shift; + my %conflicts = $package->conflicts; + + my @ret; + + for my $conflict (keys %conflicts) { + eval "require $conflict; 1" or next; + my $installed = $conflict->VERSION; + push @ret, { + package => $conflict, + installed => $installed, + required => $conflicts{$conflict}, + } if $installed le $conflicts{$conflict}; + } + + return sort { $a->{package} cmp $b->{package} } @ret; +} + +1; diff --git a/t/01-basic.t b/t/01-basic.t new file mode 100644 index 0000000..a4e4c56 --- /dev/null +++ b/t/01-basic.t @@ -0,0 +1,47 @@ +#!/usr/bin/env perl +use strict; +use warnings; +use Test::More; +use lib 't/lib/01'; + +{ + use_ok('Foo::Conflicts'); + is_deeply( + { Foo::Conflicts->conflicts }, + { + 'Foo::Thing' => 0.01, + 'Foo::Thing::Sub' => 0.05, + }, + "basic conflicts work" + ); +} + +{ + use_ok('Bar::Conflicts'); + is_deeply( + { Bar::Conflicts->conflicts }, + { + 'Bar::Local' => 0.02, + 'Bar::Also' => 0.06, + 'Bar::Also::Also' => 0.12, + }, + "nested conflicts work" + ); + is_deeply( + { Bar::Conflicts2->conflicts }, + { + 'Bar::Also' => 0.06, + 'Bar::Also::Also' => 0.12, + }, + "nested conflicts work" + ); + is_deeply( + { Bar::Conflicts3->conflicts }, + { + 'Bar::Also::Also' => 0.12, + }, + "nested conflicts work" + ); +} + +done_testing; diff --git a/t/02-conflicts.t b/t/02-conflicts.t new file mode 100644 index 0000000..7303be2 --- /dev/null +++ b/t/02-conflicts.t @@ -0,0 +1,70 @@ +#!/usr/bin/env perl +use strict; +use warnings; +use Test::More; +use Test::Fatal; +use lib 't/lib/02'; + +{ + use_ok('Foo::Conflicts::Good'); + is_deeply( + [ Foo::Conflicts::Good->calculate_conflicts ], + [], + "correct versions for all conflicts", + ); + is( + exception { Foo::Conflicts::Good->check_conflicts }, + undef, + "no conflict error" + ); +} + +{ + use_ok('Foo::Conflicts::Bad'); + is_deeply( + [ Foo::Conflicts::Bad->calculate_conflicts ], + [ + { package => 'Foo', installed => '0.02', required => '0.03' }, + { package => 'Foo::Two', installed => '0.02', required => '0.02' }, + ], + "correct versions for all conflicts", + ); + is( + exception { Foo::Conflicts::Bad->check_conflicts }, + "Conflicts detected for Foo::Conflicts::Bad:\n Foo is version 0.02, but must be greater than version 0.03\n Foo::Two is version 0.02, but must be greater than version 0.02\n", + "correct conflict error" + ); +} + +{ + use_ok('Bar::Conflicts::Good'); + is_deeply( + [ Bar::Conflicts::Good->calculate_conflicts ], + [], + "correct versions for all conflicts", + ); + is( + exception { Bar::Conflicts::Good->check_conflicts }, + undef, + "no conflict error" + ); +} + +{ + use_ok('Bar::Conflicts::Bad'); + is_deeply( + [ Bar::Conflicts::Bad->calculate_conflicts ], + [ + { package => 'Bar', installed => '0.02', required => '0.03' }, + { package => 'Bar::Two', installed => '0.02', required => '0.02' }, + ], + "correct versions for all conflicts", + ); + is( + exception { Bar::Conflicts::Bad->check_conflicts }, + "Conflicts detected for Bar::Conflicts::Bad:\n Bar is version 0.02, but must be greater than version 0.03\n Bar::Two is version 0.02, but must be greater than version 0.02\n", + "correct conflict error" + ); +} + +done_testing; diff --git a/t/lib/01/Bar/Conflicts.pm b/t/lib/01/Bar/Conflicts.pm new file mode 100644 index 0000000..65ba026 --- /dev/null +++ b/t/lib/01/Bar/Conflicts.pm @@ -0,0 +1,13 @@ +package Bar::Conflicts; +use strict; +use warnings; + +use Dist::CheckConflicts + -conflicts => { + 'Bar::Local' => 0.02, + }, + -also => [ + 'Bar::Conflicts2', + ]; + +1; diff --git a/t/lib/01/Bar/Conflicts2.pm b/t/lib/01/Bar/Conflicts2.pm new file mode 100644 index 0000000..a26606c --- /dev/null +++ b/t/lib/01/Bar/Conflicts2.pm @@ -0,0 +1,13 @@ +package Bar::Conflicts2; +use strict; +use warnings; + +use Dist::CheckConflicts + -conflicts => { + 'Bar::Also' => 0.06, + }, + -also => [ + 'Bar::Conflicts3', + ]; + +1; diff --git a/t/lib/01/Bar/Conflicts3.pm b/t/lib/01/Bar/Conflicts3.pm new file mode 100644 index 0000000..4c30909 --- /dev/null +++ b/t/lib/01/Bar/Conflicts3.pm @@ -0,0 +1,10 @@ +package Bar::Conflicts3; +use strict; +use warnings; + +use Dist::CheckConflicts + -conflicts => { + 'Bar::Also::Also' => 0.12, + }; + +1; diff --git a/t/lib/01/Foo/Conflicts.pm b/t/lib/01/Foo/Conflicts.pm new file mode 100644 index 0000000..0d9d7ef --- /dev/null +++ b/t/lib/01/Foo/Conflicts.pm @@ -0,0 +1,11 @@ +package Foo::Conflicts; +use strict; +use warnings; + +use Dist::CheckConflicts + -conflicts => { + 'Foo::Thing' => 0.01, + 'Foo::Thing::Sub' => 0.05, + }; + +1; diff --git a/t/lib/02/Bar.pm b/t/lib/02/Bar.pm new file mode 100644 index 0000000..0ce51ad --- /dev/null +++ b/t/lib/02/Bar.pm @@ -0,0 +1,7 @@ +package Bar; +use strict; +use warnings; + +our $VERSION = 0.02; + +1; diff --git a/t/lib/02/Bar/Conflicts/Bad.pm b/t/lib/02/Bar/Conflicts/Bad.pm new file mode 100644 index 0000000..32a654e --- /dev/null +++ b/t/lib/02/Bar/Conflicts/Bad.pm @@ -0,0 +1,13 @@ +package Bar::Conflicts::Bad; +use strict; +use warnings; + +use Dist::CheckConflicts + -conflicts => { + 'Bar' => '0.03', + }, + -also => [ + 'Bar::Conflicts::Bad2', + ]; + +1; diff --git a/t/lib/02/Bar/Conflicts/Bad2.pm b/t/lib/02/Bar/Conflicts/Bad2.pm new file mode 100644 index 0000000..9c76862 --- /dev/null +++ b/t/lib/02/Bar/Conflicts/Bad2.pm @@ -0,0 +1,13 @@ +package Bar::Conflicts::Bad2; +use strict; +use warnings; + +use Dist::CheckConflicts + -conflicts => { + 'Bar::Two' => '0.02', + }, + -also => [ + 'Bar::Conflicts::Bad3', + ]; + +1; diff --git a/t/lib/02/Bar/Conflicts/Bad3.pm b/t/lib/02/Bar/Conflicts/Bad3.pm new file mode 100644 index 0000000..fb80b9e --- /dev/null +++ b/t/lib/02/Bar/Conflicts/Bad3.pm @@ -0,0 +1,10 @@ +package Bar::Conflicts::Bad3; +use strict; +use warnings; + +use Dist::CheckConflicts + -conflicts => { + 'Bar::Three' => '0.01', + }; + +1; diff --git a/t/lib/02/Bar/Conflicts/Good.pm b/t/lib/02/Bar/Conflicts/Good.pm new file mode 100644 index 0000000..0f74447 --- /dev/null +++ b/t/lib/02/Bar/Conflicts/Good.pm @@ -0,0 +1,13 @@ +package Bar::Conflicts::Good; +use strict; +use warnings; + +use Dist::CheckConflicts + -conflicts => { + 'Bar' => '0.01', + }, + -also => [ + 'Bar::Conflicts::Good2', + ]; + +1; diff --git a/t/lib/02/Bar/Conflicts/Good2.pm b/t/lib/02/Bar/Conflicts/Good2.pm new file mode 100644 index 0000000..8ba9fd3 --- /dev/null +++ b/t/lib/02/Bar/Conflicts/Good2.pm @@ -0,0 +1,13 @@ +package Bar::Conflicts::Good2; +use strict; +use warnings; + +use Dist::CheckConflicts + -conflicts => { + 'Bar::Two' => '0.01', + }, + -also => [ + 'Bar::Conflicts::Good3', + ]; + +1; diff --git a/t/lib/02/Bar/Conflicts/Good3.pm b/t/lib/02/Bar/Conflicts/Good3.pm new file mode 100644 index 0000000..88b542e --- /dev/null +++ b/t/lib/02/Bar/Conflicts/Good3.pm @@ -0,0 +1,10 @@ +package Bar::Conflicts::Good3; +use strict; +use warnings; + +use Dist::CheckConflicts + -conflicts => { + 'Bar::Three' => '0.01', + }; + +1; diff --git a/t/lib/02/Bar/Three.pm b/t/lib/02/Bar/Three.pm new file mode 100644 index 0000000..8c304fe --- /dev/null +++ b/t/lib/02/Bar/Three.pm @@ -0,0 +1,7 @@ +package Bar::Three; +use strict; +use warnings; + +our $VERSION = 0.02; + +1; diff --git a/t/lib/02/Bar/Two.pm b/t/lib/02/Bar/Two.pm new file mode 100644 index 0000000..172ad51 --- /dev/null +++ b/t/lib/02/Bar/Two.pm @@ -0,0 +1,7 @@ +package Bar::Two; +use strict; +use warnings; + +our $VERSION = 0.02; + +1; diff --git a/t/lib/02/Foo.pm b/t/lib/02/Foo.pm new file mode 100644 index 0000000..9660e6d --- /dev/null +++ b/t/lib/02/Foo.pm @@ -0,0 +1,7 @@ +package Foo; +use strict; +use warnings; + +our $VERSION = 0.02; + +1; diff --git a/t/lib/02/Foo/Conflicts/Bad.pm b/t/lib/02/Foo/Conflicts/Bad.pm new file mode 100644 index 0000000..1cbf30f --- /dev/null +++ b/t/lib/02/Foo/Conflicts/Bad.pm @@ -0,0 +1,12 @@ +package Foo::Conflicts::Bad; +use strict; +use warnings; + +use Dist::CheckConflicts + -conflicts => { + 'Foo' => 0.03, + 'Foo::Two' => 0.02, + 'Foo::Three' => 0.01, + }; + +1; diff --git a/t/lib/02/Foo/Conflicts/Good.pm b/t/lib/02/Foo/Conflicts/Good.pm new file mode 100644 index 0000000..f40a955 --- /dev/null +++ b/t/lib/02/Foo/Conflicts/Good.pm @@ -0,0 +1,12 @@ +package Foo::Conflicts::Good; +use strict; +use warnings; + +use Dist::CheckConflicts + -conflicts => { + 'Foo' => 0.01, + 'Foo::Two' => 0.01, + 'Foo::Three' => 0.01, + }; + +1; diff --git a/t/lib/02/Foo/Three.pm b/t/lib/02/Foo/Three.pm new file mode 100644 index 0000000..b180934 --- /dev/null +++ b/t/lib/02/Foo/Three.pm @@ -0,0 +1,7 @@ +package Foo::Three; +use strict; +use warnings; + +our $VERSION = 0.02; + +1; diff --git a/t/lib/02/Foo/Two.pm b/t/lib/02/Foo/Two.pm new file mode 100644 index 0000000..7a1daff --- /dev/null +++ b/t/lib/02/Foo/Two.pm @@ -0,0 +1,7 @@ +package Foo::Two; +use strict; +use warnings; + +our $VERSION = 0.02; + +1; -- cgit v1.2.3-54-g00ecf