1 package CPANPLUS::Dist::Gentoo::Atom;
12 '<=>' => \&_spaceship,
17 use CPANPLUS::Dist::Gentoo::Version;
19 my $version_rx = $CPANPLUS::Dist::Gentoo::Version::version_rx;
23 $class = ref($class) || $class;
27 my ($category, $name, $version);
28 if (defined $args{name}) {
29 ($category, $name, $version) = @args{qw/category name version/};
30 Carp::confess('Category unspecified') unless defined $category;
31 /[^\w-]/ and Carp::confess('Invalid argument') for $name, $category;
32 } elsif (defined $args{atom}) {
33 my $atom = $args{atom};
34 $atom =~ m{^([\w-]+)/([\w-]+)-v?($version_rx)$}
35 or Carp::confess('Invalid atom');
36 ($category, $name, $version) = ($1, $2, $3);
37 } elsif (defined $args{ebuild}) {
38 my $ebuild = $args{ebuild};
39 $ebuild =~ m{/([\w-]+)/([\w-]+)/\2-v?($version_rx)\.ebuild$}
40 or Carp::confess('Invalid ebuild');
41 ($category, $name, $version) = ($1, $2, $3);
43 Carp::confess('Not enough information for building an atom object');
46 if (defined $version) {
47 unless (Scalar::Util::blessed($version)
48 and $_->isa('CPANPLUS::Dist::Gentoo::Version')) {
49 $version = CPANPLUS::Dist::Gentoo::Version->new($version);
53 my $range = $args{range};
54 if (defined $version) {
56 Carp::confess("Invalid range $range")
57 unless grep $range eq $_, qw|< <= = >= >|;
62 Carp::confess('Range atoms require a valid version')
63 if defined $range and length $range;
67 category => $category,
71 ebuild => $args{ebuild},
76 eval "sub $_ { \$_[0]->{$_} }" for qw/category name version range ebuild/;
79 sub qualified_name { join '/', $_[0]->category, $_[0]->name }
82 my ($a1, $a2, $r) = @_;
84 my $v1 = $a1->version;
87 if (Scalar::Util::blessed($a2) and $a2->isa(__PACKAGE__)) {
88 Carp::confess('Can\'t compare atoms of different packages')
89 if $a1->category ne $a2->category or $a1->name ne $a2->name;
95 ($v1, $v2) = ($v2, $v1) if $r;
101 my ($a1, $a2, $r) = @_;
103 my $s1 = $a1->qualified_name;
104 my $v1 = $a1->version;
105 $s1 .= "-$v1" if defined $v1;
108 if (Scalar::Util::blessed($a2) and $a2->isa(__PACKAGE__)) {
109 $s2 = $a2->qualified_name;
110 my $v2 = $a2->version;
111 $s2 .= "-$v2" if defined $v2;
122 my $atom = $a->qualified_name;
124 my $version = $a->version;
125 $atom = $a->range . $atom . '-' . $version if defined $version;
139 shift unless length ref $_[0];
143 $a2 = $a2->and(@_) if @_;
145 my $p1 = $a1->qualified_name;
146 my $p2 = $a2->qualified_name;
147 Carp::confess("Atoms for different packages $p1 and $p2") unless $p1 eq $p2;
149 my $v1 = $a1->version;
150 return $a2 unless defined $v1;
151 my $r1 = $a1->range; # Defined if $v1 is defined
153 my $v2 = $a2->version;
154 return $a1 unless defined $v2;
155 my $r2 = $a2->range; # defined if $v2 is defined
157 my $o1 = $order{$r1};
158 my $o2 = $order{$r2};
160 Carp::confess("Incompatible ranges $r1$p1 and $r2$p2") if $o1 * $o2 < 0;
163 ($a1, $a2) = ($a2, $a1);
164 ($v1, $v2) = ($v2, $v1);
165 ($r1, $r2) = ($r2, $r1);
166 ($o1, $o2) = ($o2, $o1);
170 my $r = $r2 eq '=' ? '==' : $r2;
171 Carp::confess("Version mismatch $v1 $r $v2") unless eval "\$a1 $r \$a2";
174 return $a1 < $a2 ? $a2 : $a1;
176 return $a1 < $a2 ? $a1 : $a2;
181 shift unless length ref $_[0];
185 my $key = $atom->qualified_name;
187 my $cur = $seen{$key};
188 $seen{$key} = defined $cur ? $cur->and($atom) : $atom;