Fetching contributors…
Cannot retrieve contributors at this time
313 lines (212 sloc) 7.23 KB
#!/usr/bin/perl -w
use strict;
use Pod::Usage 1.12;
use Getopt::Long;
use YAML qw( Load );
use CPAN::Mini::Inject;
use Env;
use File::Slurp 'write_file';
use File::Temp;
our $VERSION = '0.35';
our %options = ();
sub print_version {
printf( "mcpani v%s, using CPAN::Mini::Inject v%s and Perl v%vd\n",
$VERSION, $CPAN::Mini::Inject::VERSION, $^V );
sub chkactions {
for my $action ( qw(add update mirror inject) ) {
return 1 if ( $options{actionname} eq $action );
return 0;
sub setsub {
$options{actionname} = shift;
$options{action} = shift;
sub add {
my $mcpi = shift;
module => $options{module},
authorid => $options{authorid},
version => $options{version},
file => $options{file}
if ( $options{verbose} ) {
my @added = $mcpi->added_modules;
foreach my $added ( @added ){
print "\nAdding File: $added->{file}\n";
print "Author ID: $added->{authorid}\n";
my $modules = $added->{modules};
foreach my $mod ( sort keys %$modules ){
print "Module: $mod\n";
print "Version: $modules->{$mod}\n";
print "To repository: $mcpi->{config}{repository}\n\n";
sub update {
my $mcpi = shift;
mirror( $mcpi );
inject( $mcpi );
sub mirror {
my $mcpi = shift;
my %mirroropts;
$mirroropts{remote} = $options{remote}
if ( defined( $options{remote} ) );
$mirroropts{local} = $options{local}
if ( defined( $options{local} ) );
$mirroropts{trace} = $options{verbose}
if ( defined( $options{verbose} ) );
$mcpi->update_mirror( %mirroropts );
sub inject {
my $mcpi = shift;
print "Injecting modules from $mcpi->{config}{repository}\n"
if ( $options{verbose} );
$mcpi->inject( $options{verbose} );
Getopt::Long::Configure( 'no_ignore_case' );
Getopt::Long::Configure( 'bundling' );
'h|help|?' =>
sub { pod2usage( { -verbose => 1, -input => \*DATA } ); exit },
'H|man' =>
sub { pod2usage( { -verbose => 2, -input => \*DATA } ); exit },
'V|version' => sub { print_version(); exit; },
'v|verbose' => \$options{verbose},
'l|local=s' => \$options{local},
'r|remote=s' => \$options{remote},
'p|passive' => \$ENV{FTP_PASSIVE},
'add' => sub { setsub( 'add', \&add ) },
'update' => sub { setsub( 'update', \&update ) },
'mirror' => sub { setsub( 'mirror', \&mirror ) },
'inject' => sub { setsub( 'inject', \&inject ) },
'module=s' => \$options{module},
'authorid=s' => \$options{authorid},
'modversion=s' => \$options{version},
'file=s' => \$options{file},
'all-in-meta' => \$options{'all-in-meta'},
'signing-key=s' => \$options{'signing_key'},
'discover-packages' => \$options{'discover-packages'},
) or exit 1;
unless ( defined( $options{action} ) && chkactions() ) {
pod2usage( { -verbose => 1, -input => \*DATA } );
my $mcpi = CPAN::Mini::Inject->new->loadcfg( $options{cfg} )->parsecfg;
$CPAN::Checksums::SIGNING_KEY = $options{'signing_key'}
if ($options{'signing_key'});
&{ $options{action} }( $mcpi );
=head1 NAME
mcpani -- A command line tool to manage a CPAN Mini Mirror.
mcpani [options] < --add | --update | --mirror | --inject >
--add Add a new package to the repository
--module Name of the module to add
--authorid Author ID of the module
--modversion Version number of the module
--file tar.gz file of the module
--update Update local CPAN mirror and inject modules
--mirror Update local CPAN mirror from remote
--inject Add modules from repository to CPAN mirror
-h, --help This synopsis
-H, --man Detailed description
-l, --local local location for CPAN::Mini Mirror
-r, --remote CPAN mirror to mirror from
-p, --passive Enable passive ftp for mirroring.
-v, --verbose verbose output
-V, --version Version information.
--signing-key See CPAN::Checksums $SIGNING_KEY
=head2 --add
Add a module to the repository for later inclusion in the CPAN Mini
mirror. The add command requires the following parameters:
=over 4
=item --module
This is the name of the module (ie CPAN::Mini::Inject).
=item --authorid
A CPAN 'like' author ID for the module. The author ID does not need to
exist on CPAN.
=item --modversion
Version number of the module. This must match the version number in the
file name.
=item --all-in-meta
=item --discover-packages
L<CPAN::Mini::Inject/add> adds all modules found in the file.
These options remain for backward compatibility and do nothing.
=item --file
File name and path of the module. The file name must follow the
standard CPAN naming convention (the resulting file from a
C<make tardist>).
mcpani --add --module CPAN::Mini::Inject --authorid SSORICHE
--modversion 0.01 --file ./CPAN-Mini-Inject-0.01.tar.gz
=head2 --update
Update your local CPAN Mini mirror from a CPAN site. Once completed
add the modules contained in the repository to it. This is the same
as running C<mcpani --mirror> followed by C<mcpani --inject>
=head2 --mirror
Update the local CPAN Mini mirror from CPAN.
=head2 --inject
Add the repository modules into the CPAN Mini mirror.
=head2 -l, --local
A local directory to store the CPAN Mini mirror in. Specifying this
option overrides the value in the config file.
=head2 -r, --remote
A CPAN site to create the local CPAN Mini mirror from.
=head2 -v, --verbose
Display verbose processing information
=head2 -V, --version
Display version information.
F<mcpani> uses a simple configuration file in the following format:
local: /www/CPAN
repository: /work/mymodules
passive: yes
dirmode: 0755
Description of options:
=over 4
=item * local
location to store local CPAN::Mini mirror (*REQUIRED*)
=item * remote
CPAN site(s) to mirror from. Multiple sites can be listed, with spaces
between them. (*REQUIRED*)
=item * repository
Location to store modules to add to the local CPAN::Mini mirror.
=item * passive
Enable passive FTP.
=item * dirmode
Set the permissions of created directories to the specified mode
(octal value). The default value is based on the umask (if supported).
F<mcpani> will search the following four places in order:
=over 4
=item * file pointed to by the environment variable MCPANI_CONFIG
=item * $HOME/.mcpani/config
=item * /usr/local/etc/mcpani
=item * /etc/mcpani
Christian Walde C<< <> >>
=head1 AUTHOR
Shawn Sorichetti C<< <> >>
=head1 BUGS
Please report any bugs or feature requests to
C<>, or through the web interface at
L<>. I will be notified, and then you'll automatically
be notified of progress on your bug as I make changes.
=head1 Copyright & License
Copyright 2004 Shawn Sorichetti, All Rights Reserved.
This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.