File Coverage

blib/lib/P5U/Command/Changes.pm
Criterion Covered Total %
statement 10 12 83.3
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 14 16 87.5


line stmt bran cond sub pod time code
1             package P5U::Command::Changes;
2              
3 1     1   20800 use 5.010;
  1         4  
  1         33  
4 1     1   6 use strict;
  1         1  
  1         31  
5 1     1   1080 use utf8;
  1         16  
  1         6  
6 1     1   558 use P5U-command;
  0            
  0            
7              
8             use match::simple;
9              
10             BEGIN {
11             $P5U::Command::Changes::AUTHORITY = 'cpan:TOBYINK';
12             $P5U::Command::Changes::VERSION = '0.002';
13             }
14              
15             use constant {
16             abstract => q[view change logs],
17             usage_desc => q[%c changes DIST_OR_MODULE VERSIONS?],
18             };
19              
20             sub command_names {qw{ changes change changelog ch }}
21              
22             sub opt_spec
23             {
24             (
25             [verbatim => 'show the Changes file verbatim'],
26             );
27             }
28              
29             sub _metacpan
30             {
31             require JSON;
32             require LWP::UserAgent;
33             my ($self, @path) = @_;
34             state $ua = LWP::UserAgent->new(
35             agent => sprintf('%s/%s ', ref $self, $self->VERSION),
36             );
37            
38             my $path = join '/', @path;
39             my $r = $ua->get("http://api.metacpan.org/$path");
40             $r->is_success or die("HTTP request failed");
41             if ($r->content_type =~ /json/i)
42             {
43             return JSON::from_json( $r->decoded_content );
44             }
45             else
46             {
47             return $r->decoded_content;
48             }
49             }
50              
51             my $DATE = qr/^\d{4}-\d{2}-\d{2}/;
52             sub execute
53             {
54             require CPAN::Changes;
55            
56             my ($self, $opt, $args) = @_;
57            
58             my ($dist, $versions) = @$args
59             or $self->usage_error("must provide a distribution name");
60            
61             my ($release, $author, $latest);
62             if ($dist =~ m{::})
63             {
64             $dist =~ s/^:://;
65             $dist =~ s/::$//;
66             my $data = $self->_metacpan('v0', module => $dist);
67             ($release, $author, $latest) = ($data->{release}, $data->{author}, $data->{version});
68             }
69             else
70             {
71             my $data = $self->_metacpan('v0', release => $dist);
72             ($release, $author, $latest) = ($data->{name}, $data->{author}, $data->{version});
73             }
74              
75             my $changes = $self->_metacpan(source => ($author, $release, 'Changes'));
76             if ($opt->{verbatim})
77             {
78             print $changes;
79             exit;
80             }
81              
82             my ($start, $end);
83             if (defined $versions and $versions =~ /\.{2}/)
84             { ($start, $end) = split /\.{2}/, $versions }
85             elsif (defined $versions and $versions |M| $DATE)
86             { ($start, $end) = ($versions, $latest) }
87             elsif (defined $versions and length $versions)
88             { ($start, $end) = ($versions) x 2 }
89             $start ||= 0;
90             $end ||= $latest;
91            
92             my ($start_is_date, $end_is_date);
93             for ($start, $end)
94             {
95             next unless /^C/i;
96             require Module::Info;
97             my $mod = Module::Info->new_from_module($dist)
98             or die "Unable to find local module info for '$dist'";
99             $_ = $mod->version;
100             }
101              
102             my ($start_is_date, $end_is_date) = map { $_ |M| $DATE } ($start, $end);
103              
104             for my $R (CPAN::Changes->load_string($changes)->releases)
105             {
106             next if (
107             ($R->version < $start and not $start_is_date)
108             or ($R->version > $end and not $end_is_date)
109             or ($R->date lt $start and $start_is_date)
110             or ($R->date gt $end and $end_is_date)
111             );
112             print $R->serialize;
113             }
114             }
115              
116             1;
117              
118             __END__