Commits

Toby Inkster committed 9ba53bd

Add BackPAN/CPAN functions to version command.

Comments (0)

Files changed (2)

lib/P5U/Command/Version.pm

 };
 
 use constant {
-	abstract    => q[show version number],
+	abstract    => q[show the version number of a module],
 	usage_desc  => q[%c version %o Module],
 };
 
 	);
 }
 
+sub description
+{
+<<'DESCRIPTION'
+This command is inspired by V.pm. Given one or more module names, it
+locates the modules on your local system and tells you the version
+number. (Note that you may have multiple versions of a module installed
+in different locations.)
+
+	p5u v MooseX::Types MouseX::Types
+
+Unlike V.pm, it also has the ability to reach out to CPAN/BackPAN and find
+versions of the module available there:
+
+	p5u v -c MooseX::Types
+	p5u v -b MooseX::Types
+
+You can even combine options:
+
+	p5u v -lcb MooseX::Types
+	p5u v -lc MooseX::Types MouseX::Types
+
+If no options are provided, defaults to "--local".
+DESCRIPTION
+}
+
 sub opt_spec
 {
-	return;
+	return (
+		['cpan|c'     => 'search CPAN'],
+		['local|l'    => 'search @INC'],
+		['backpan|b'  => 'search BackPAN'],
+	);
 }
 
 sub execute
 {
-	require Module::Info;
-	
 	my ($self, $opt, $args) = @_;
 
+	$opt->{local}++ unless $opt->{cpan} || $opt->{backpan};
 	$self->usage_error("You must provide a module name.")
 		unless @$args;
 	
+	require P5U::Lib::Version;
+	my $helper = 'P5U::Lib::Version';
+		
 	while (my $m = shift @$args)
 	{
 		say $m;
 		
-		my @mods = Module::Info->all_installed($m);
-		if (@mods)
-		{
-			printf("\t%s: %s\n", $_->file, $_->version) foreach @mods;
-		}
-		else
-		{
-			say "\tNot found";
-		}
+		my @lines;
+		push @lines, $helper->local_module_info($m)   if $opt->{local};
+		push @lines, $helper->cpan_module_info($m)    if $opt->{cpan};
+		push @lines, $helper->backpan_module_info($m) if $opt->{backpan};
+		push @lines, q(Not found) unless @lines;
 		
+		say "\t$_" for @lines;
 		say q() if @$args; 
 	}
 }

lib/P5U/Lib/Version.pm

+package P5U::Lib::Version;
+
+use 5.010;
+use utf8;
+
+BEGIN {
+	$P5U::Lib::Version::AUTHORITY = 'cpan:TOBYINK';
+	$P5U::Lib::Version::VERSION   = '0.001';
+};
+
+use JSON qw< from_json >;
+use LWP::Simple qw< get >;
+use Module::Info;
+use Module::Runtime qw< module_notional_filename >;
+
+sub local_module_info
+{
+	my $self = shift;	
+	return
+		map { sprintf "%s: %s", $_->file, $_->version }
+		Module::Info->all_installed(@_);
+}
+
+sub cpan_module_info
+{
+	my $self = shift;
+	my $mod  = shift;
+
+	my $data = from_json get(
+		sprintf
+			'http://api.metacpan.org/v0/module/_search?q=status:cpan+AND+path:lib/%s&fields=version,release,author,path,date&size=1000',
+			module_notional_filename($mod),
+	);
+	return $self->format_hits(cpan => $data);
+}
+
+sub backpan_module_info
+{
+	my $self = shift;
+	my $mod  = shift;
+
+	my $data = from_json get(
+		sprintf
+			'http://api.metacpan.org/v0/module/_search?q=status:backpan+AND+path:lib/%s&fields=version,release,author,path,date&size=1000',
+			module_notional_filename($mod),
+	);
+	return $self->format_hits(backpan => $data);
+}
+
+sub format_hits
+{
+	my ($self, $label, $data) = @_;
+	die "MetaCPAN API timed out" if $data->{timed_out};
+	
+	return
+		map {
+			sprintf
+				'%s:%s/%s.tar.gz#%s: %s (%s)',
+				$label,
+				@{$_}{qw<author release path version date>}
+		}
+		sort { $a->{version} cmp $b->{version} }
+		map  { $_->{fields} }
+		@{ $data->{hits}{hits} };
+}
+
+1;