- if ($atom->minimum) {
- if ($cur->minimum) {
- $seen{$key} = $atom < $cur ? $cur : $atom;
- } else {
- Carp::confess('Version mismatch') if $atom > $cur;
- }
- } elsif ($cur->minimum) {
- Carp::confess('Version mismatch') if $cur > $atom;
- }
+ my $o1 = $order{$r1};
+ my $o2 = $order{$r2};
+
+ Carp::confess("Incompatible ranges $r1$p1 and $r2$p2") if $o1 * $o2 < 0;
+
+ if ($r2 eq '=') {
+ ($a1, $a2) = ($a2, $a1);
+ ($v1, $v2) = ($v2, $v1);
+ ($r1, $r2) = ($r2, $r1);
+ ($o1, $o2) = ($o2, $o1);
+ }
+
+ if ($r1 eq '=') {
+ my $r = $r2 eq '=' ? '==' : $r2;
+ Carp::confess("Version mismatch $v1 $r $v2") unless eval "\$a1 $r \$a2";
+ return $a1;
+ } elsif ($o1 > 0) {
+ return $a1 < $a2 ? $a2 : $a1;
+ } else {
+ return $a1 < $a2 ? $a1 : $a2;
+ }
+}
+
+sub fold {
+ shift unless length ref $_[0];
+
+ my %seen;
+ for my $atom (@_) {
+ my $key = join '/', $atom->category, $atom->name;
+
+ my $cur = $seen{$key};
+ $seen{$key} = defined $cur ? $cur->and($atom) : $atom;