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/;
78 sub qualified_name { join '/', $_[0]->category, $_[0]->name }
81 my ($a1, $a2, $r) = @_;
83 my $v1 = $a1->version;
86 if (Scalar::Util::blessed($a2) and $a2->isa(__PACKAGE__)) {
87 Carp::confess('Can\'t compare atoms of different packages')
88 if $a1->category ne $a2->category or $a1->name ne $a2->name;
94 ($v1, $v2) = ($v2, $v1) if $r;
102 my $atom = $a->qualified_name;
104 my $version = $a->version;
105 $atom = $a->range . $atom . '-' . $version if defined $version;
119 shift unless length ref $_[0];
123 $a2 = $a2->and(@_) if @_;
125 my $p1 = $a1->qualified_name;
126 my $p2 = $a2->qualified_name;
127 Carp::confess("Atoms for different packages $p1 and $p2") unless $p1 eq $p2;
129 my $v1 = $a1->version;
130 return $a2 unless defined $v1;
131 my $r1 = $a1->range; # Defined if $v1 is defined
133 my $v2 = $a2->version;
134 return $a1 unless defined $v2;
135 my $r2 = $a2->range; # defined if $v2 is defined
137 my $o1 = $order{$r1};
138 my $o2 = $order{$r2};
140 Carp::confess("Incompatible ranges $r1$p1 and $r2$p2") if $o1 * $o2 < 0;
143 ($a1, $a2) = ($a2, $a1);
144 ($v1, $v2) = ($v2, $v1);
145 ($r1, $r2) = ($r2, $r1);
146 ($o1, $o2) = ($o2, $o1);
150 my $r = $r2 eq '=' ? '==' : $r2;
151 Carp::confess("Version mismatch $v1 $r $v2") unless eval "\$a1 $r \$a2";
154 return $a1 < $a2 ? $a2 : $a1;
156 return $a1 < $a2 ? $a1 : $a2;
161 shift unless length ref $_[0];
165 my $key = $atom->qualified_name;
167 my $cur = $seen{$key};
168 $seen{$key} = defined $cur ? $cur->and($atom) : $atom;