1 package CPANPLUS::Dist::Gentoo::Atom;
12 '<=>' => \&_spaceship,
16 use CPANPLUS::Dist::Gentoo::Version;
18 my $version_rx = $CPANPLUS::Dist::Gentoo::Version::version_rx;
22 $class = ref($class) || $class;
26 my ($category, $name, $version);
27 if (defined $args{name}) {
28 ($category, $name, $version) = @args{qw/category name version/};
29 Carp::confess('Category unspecified') unless defined $category;
30 /[^\w-]/ and Carp::confess('Invalid argument') for $name, $category;
31 } elsif (defined $args{atom}) {
32 my $atom = $args{atom};
33 $atom =~ m{^([\w-]+)/([\w-]+)-v?($version_rx)$}
34 or Carp::confess('Invalid atom');
35 ($category, $name, $version) = ($1, $2, $3);
36 } elsif (defined $args{ebuild}) {
37 my $ebuild = $args{ebuild};
38 $ebuild =~ m{/([\w-]+)/([\w-]+)/\2-v?($version_rx)\.ebuild$}
39 or Carp::confess('Invalid ebuild');
40 ($category, $name, $version) = ($1, $2, $3);
42 Carp::confess('Not enough information for building an atom object');
45 if (defined $version) {
46 unless (Scalar::Util::blessed($version)
47 and $_->isa('CPANPLUS::Dist::Gentoo::Version')) {
48 $version = CPANPLUS::Dist::Gentoo::Version->new($version);
52 my $range = $args{range};
53 if (defined $version) {
55 Carp::confess("Invalid range $range")
56 unless grep $range eq $_, qw|< <= = >= >|;
61 Carp::confess('Range atoms require a valid version')
62 if defined $range and length $range;
66 category => $category,
70 ebuild => $args{ebuild},
75 eval "sub $_ { \$_[0]->{$_} }" for qw/category name version range ebuild/;
79 my ($a1, $a2, $r) = @_;
81 my $v1 = $a1->version;
84 if (Scalar::Util::blessed($a2) and $a2->isa(__PACKAGE__)) {
85 Carp::confess('Can\'t compare atoms of different packages')
86 if $a1->category ne $a2->category or $a1->name ne $a2->name;
92 ($v1, $v2) = ($v2, $v1) if $r;
100 my $atom = $a->category . '/' . $a->name;
102 my $version = $a->version;
103 $atom = $a->range . $atom . '-' . $version if defined $version;
117 shift unless length ref $_[0];
121 $a2 = $a2->and(@_) if @_;
123 my $p1 = join '/', $a1->category, $a1->name;
124 my $p2 = join '/', $a2->category, $a2->name;
125 Carp::confess("Atoms for different packages $p1 and $p2") unless $p1 eq $p2;
127 my $v1 = $a1->version;
128 return $a2 unless defined $v1;
129 my $r1 = $a1->range; # Defined if $v1 is defined
131 my $v2 = $a2->version;
132 return $a1 unless defined $v2;
133 my $r2 = $a2->range; # defined if $v2 is defined
135 my $o1 = $order{$r1};
136 my $o2 = $order{$r2};
138 Carp::confess("Incompatible ranges $r1$p1 and $r2$p2") if $o1 * $o2 < 0;
141 ($a1, $a2) = ($a2, $a1);
142 ($v1, $v2) = ($v2, $v1);
143 ($r1, $r2) = ($r2, $r1);
144 ($o1, $o2) = ($o2, $o1);
148 my $r = $r2 eq '=' ? '==' : $r2;
149 Carp::confess("Version mismatch $v1 $r $v2") unless eval "\$a1 $r \$a2";
152 return $a1 < $a2 ? $a2 : $a1;
154 return $a1 < $a2 ? $a1 : $a2;
159 shift unless length ref $_[0];
163 my $key = join '/', $atom->category, $atom->name;
165 my $cur = $seen{$key};
166 $seen{$key} = defined $cur ? $cur->and($atom) : $atom;