summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2010-11-21 17:10:52 -0600
committerJesse Luehrs <doy@tozt.net>2010-11-21 17:10:52 -0600
commit8cc54374790f8728eb1be75bbbab33b91ae69838 (patch)
tree5f917bbb63de611b4db10e2de6c27408cf17a214
parent6103054b33641423790d0e39c3e369bf79fe2c9c (diff)
downloaddist-checkconflicts-8cc54374790f8728eb1be75bbbab33b91ae69838.tar.gz
dist-checkconflicts-8cc54374790f8728eb1be75bbbab33b91ae69838.zip
initial implementation
-rw-r--r--dist.ini8
-rw-r--r--lib/Dist/CheckConflicts.pm92
-rw-r--r--t/01-basic.t47
-rw-r--r--t/02-conflicts.t70
-rw-r--r--t/lib/01/Bar/Conflicts.pm13
-rw-r--r--t/lib/01/Bar/Conflicts2.pm13
-rw-r--r--t/lib/01/Bar/Conflicts3.pm10
-rw-r--r--t/lib/01/Foo/Conflicts.pm11
-rw-r--r--t/lib/02/Bar.pm7
-rw-r--r--t/lib/02/Bar/Conflicts/Bad.pm13
-rw-r--r--t/lib/02/Bar/Conflicts/Bad2.pm13
-rw-r--r--t/lib/02/Bar/Conflicts/Bad3.pm10
-rw-r--r--t/lib/02/Bar/Conflicts/Good.pm13
-rw-r--r--t/lib/02/Bar/Conflicts/Good2.pm13
-rw-r--r--t/lib/02/Bar/Conflicts/Good3.pm10
-rw-r--r--t/lib/02/Bar/Three.pm7
-rw-r--r--t/lib/02/Bar/Two.pm7
-rw-r--r--t/lib/02/Foo.pm7
-rw-r--r--t/lib/02/Foo/Conflicts/Bad.pm12
-rw-r--r--t/lib/02/Foo/Conflicts/Good.pm12
-rw-r--r--t/lib/02/Foo/Three.pm7
-rw-r--r--t/lib/02/Foo/Two.pm7
22 files changed, 401 insertions, 1 deletions
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;