Skip to content

Commit ebed461

Browse files
committed
support history API for CPANMetaDB
1 parent 6167339 commit ebed461

File tree

2 files changed

+72
-10
lines changed

2 files changed

+72
-10
lines changed

lib/CPAN/Common/Index/MetaDB.pm

Lines changed: 49 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use Class::Tiny qw/uri/;
1313

1414
use Carp;
1515
use CPAN::Meta::YAML;
16+
use CPAN::Meta::Requirements;
1617
use HTTP::Tiny;
1718

1819
=attr uri
@@ -38,25 +39,61 @@ sub search_packages {
3839
Carp::croak("Argument to search_packages must be hash reference")
3940
unless ref $args eq 'HASH';
4041

41-
# only support direct package query
4242
return
43-
unless keys %$args == 1 && exists $args->{package} && ref $args->{package} eq '';
43+
unless exists $args->{package} && ref $args->{package} eq '';
4444

4545
my $mod = $args->{package};
46-
my $res = HTTP::Tiny->new->get( $self->uri . "package/$mod" );
47-
return unless $res->{success};
4846

49-
if ( my $yaml = CPAN::Meta::YAML->read_string( $res->{content} ) ) {
50-
my $meta = $yaml->[0];
51-
if ( $meta && $meta->{distfile} ) {
52-
my $file = $meta->{distfile};
47+
if ($args->{version} || $args->{version_range}) {
48+
my $res = HTTP::Tiny->new->get( $self->uri . "history/$mod" );
49+
return unless $res->{success};
50+
51+
my $range = defined $args->{version} ? "== $args->{version}" : $args->{version_range};
52+
my $reqs = CPAN::Meta::Requirements->from_string_hash({ $mod => $range });
53+
54+
my @found;
55+
for my $line ( split /\r?\n/, $res->{content} ) {
56+
if ($line =~ /^$mod\s+(\S+)\s+(\S+)$/) {
57+
push @found, {
58+
version => $1,
59+
version_o => version::->parse($1),
60+
distfile => $2,
61+
};
62+
}
63+
}
64+
65+
my $match;
66+
for my $try (sort { $b->{version_o} <=> $a->{version_o} } @found) {
67+
if ($reqs->accepts_module($mod => $try->{version_o})) {
68+
$match = $try, last;
69+
}
70+
}
71+
72+
if ($match) {
73+
my $file = $match->{distfile};
5374
$file =~ s{^./../}{}; # strip leading
5475
return {
5576
package => $mod,
56-
version => $meta->{version},
77+
version => $match->{version},
5778
uri => "cpan:///distfile/$file",
5879
};
5980
}
81+
} else {
82+
my $res = HTTP::Tiny->new->get( $self->uri . "package/$mod" );
83+
return unless $res->{success};
84+
85+
if ( my $yaml = CPAN::Meta::YAML->read_string( $res->{content} ) ) {
86+
my $meta = $yaml->[0];
87+
if ( $meta && $meta->{distfile} ) {
88+
my $file = $meta->{distfile};
89+
$file =~ s{^./../}{}; # strip leading
90+
return {
91+
package => $mod,
92+
version => $meta->{version},
93+
uri => "cpan:///distfile/$file",
94+
};
95+
}
96+
}
6097
}
6198

6299
return;
@@ -76,6 +113,9 @@ sub search_authors { return }; # not supported
76113
77114
$index = CPAN::Common::Index::MetaDB->new;
78115
116+
$index->search_packages({ package => "Moose" });
117+
$index->search_packages({ package => "Moose", version_range => ">= 2.0" });
118+
79119
=head1 DESCRIPTION
80120
81121
This module implements a CPAN::Common::Index that searches for packages against

t/metadb.t

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ subtest "constructor tests" => sub {
2828
# uri specified
2929
new_ok(
3030
'CPAN::Common::Index::MetaDB' => [ { uri => "http://example.com" } ],
31-
"new with cache"
31+
"new with uri"
3232
);
3333

3434
};
@@ -47,6 +47,28 @@ subtest 'find package' => sub {
4747

4848
};
4949

50+
subtest 'find package with fixed version' => sub {
51+
my $index = new_ok("CPAN::Common::Index::MetaDB");
52+
53+
my $got = $index->search_packages( { package => 'Moose', version => '2.1404' } );
54+
ok( $got, "found package" );
55+
is( $got->{version}, 2.1404, "has a version" );
56+
is(
57+
$got->{uri},
58+
"cpan:///distfile/ETHER/Moose-2.1404.tar.gz",
59+
"uri is OK"
60+
);
61+
62+
};
63+
64+
subtest 'find package with version range' => sub {
65+
my $index = new_ok("CPAN::Common::Index::MetaDB");
66+
67+
my $got = $index->search_packages( { package => 'Moose', version_range => '< 2.14' } );
68+
ok( $got, "found package" );
69+
ok( $got->{version} < 2.14, "has a version" );
70+
};
71+
5072
done_testing;
5173
# COPYRIGHT
5274
# vim: ts=4 sts=4 sw=4 et:

0 commit comments

Comments
 (0)