1#!/usr/bin/perl 2use strict; 3use warnings; 4 5use Log::Report 'cpan-site', syntax => 'SHORT'; 6use File::Basename qw/basename/; 7use Getopt::Long qw/GetOptions :config gnu_getopt/; 8use CPAN::Site::Index qw/cpan_index cpan_mirror/; 9 10# the server will redirect you to a mirror 11use constant CPAN_CORE => 'ftp://ftp.cpan.org/pub/CPAN'; 12 13# 14# Collect options 15# 16 17my $lazy; 18my $mode = 0; 19my $global_cpan = $ENV{CPANSITE_GLOBAL} || CPAN_CORE; 20my $mycpan = $ENV{CPANSITE_LOCAL} || $ENV{CPANSITE}; 21my $stand_alone = 0; 22my $undefs = 1; 23my $env_proxy = 0; 24 25GetOptions 26 'cpan|c=s' => \$global_cpan 27 , 'lazy|l!' => \$lazy 28 , 'verbose|v+' => \$mode 29 , 'mode|m=s' => \$mode 30 , 'site|s=s' => \$mycpan 31 , 'stand-alone|a!' => \$stand_alone 32 , 'undefs|u!' => \$undefs 33 , 'env-proxy!' => \$env_proxy 34 or exit 1; 35 36defined $lazy or $lazy = 1; 37 38dispatcher mode => $mode, 'ALL' 39 if $mode; 40 41my $action = shift; 42defined $action 43 or error __x"Missing action. Usage {program} [OPTIONS] ACTION" 44 , program => $0; 45 46if($action eq 'version') 47{ print "$CPAN::Site::Index::VERSION\n"; 48 exit 0; 49} 50 51if($action eq 'index') 52{ $mycpan = shift @ARGV if @ARGV; 53 $mycpan 54 or error __x"specify top-directory of your archive as argument"; 55 56 $mycpan =~ s!^file:(?://)?!!; 57 -d $mycpan 58 or fault __x"archive directory '{dir}'", dir => $mycpan; 59 60 cpan_index $mycpan, $global_cpan 61 , lazy => $lazy 62 , fallback => !$stand_alone 63 , undefs => $undefs 64 , env_proxy => $env_proxy; 65 exit 0; 66} 67 68if($action eq 'mirror') 69{ $mycpan 70 or error __x"set CPANSITE_LOCAL in environment or use --site option"; 71 72 @ARGV 73 or error __x"list of module names expected"; 74 75 cpan_mirror $mycpan, $global_cpan, \@ARGV, env_proxy => $env_proxy; 76 exit 0; 77} 78 79error __x"action '{name}' does not exist (anymore)", name => $action; 80 81__END__ 82 83=head1 NAME 84 85cpansite -- extend CPAN with private packages 86 87=head1 SYNOPSIS 88 89 cpansite version 90 cpansite [OPTIONS] index 91 cpansite [OPTIONS] mirror PACKAGE 92 93 OPTIONS: via %ENV: 94 --verbose -v -vv -vvv --mode=DEBUG 95 --no-lazy redo everything 96 --cpan <url> some CPAN mirror CPANSITE_GLOBAL 97 --env-proxy read additional proxy settings 98 --site <dir> local archive directory CPANSITE_LOCAL 99 --stand-alone no fallback to global CPAN 100 --no-undefs do not include "undef" versions in index 101 102=head1 DESCRIPTION 103 104B<WARNING: A lot has changed with the 1.01 release. Please read more 105about these changes in the file "explain_101.txt" included in the 106distribution.> 107 108The C<cpansite> script is used to create your own CPAN server. The 109logic is implemented in L<CPAN::Site::Index> which you may use directly. 110You only need to install this module on one server in your network. 111 112There are two kinds of local CPANs which can be constructed with this 113software: 114 115=over 4 116 117=item 1. local CPAN with fallback to the global CPAN 118 119When you generate a new index for your local set-up, the default 120behavior is to merge that knowledge with the global CPAN. When you 121install a module on a client, it will first attempt to fetch it from 122your own set-up. If not found, it will automatically continue to 123look at the global CPAN. 124 125=item 2. pure local CPAN, without fallback 126 127When you choose to generate the index without fallback, the installation 128of a module will fail when you do not have a local copy of the module 129in your set-up. You can use the C<mirror> action to collect the latest 130version of a module into your own structure. 131 132=back 133 134=head2 Indexing options 135 136The following options are available with all actions: 137 138=over 4 139 140=item --verbose -v -vv -vvv --mode=DEBUG 141 142Produce verbose output via L<Log::Report>. 143 144=item --site <dir> or -s <dir> or $CPANSITE_LOCAL 145 146The location of your local CPAN archive set-up. 147 148Example: 149 150 export CPANSITE_LOCAL="/www/websites/cpan.example.com" 151 cpansite index 152 153 cpansite --site $CPANSITE_LOCAL index # alternative 154 155=item --cpan <url> or -c <url> or $CPANSITE_GLOBAL 156 157Update the list of "real" CPAN modules regularly (daily or more) from 158this url. By default, C<ftp:///ftp.cpan.org> is addressed which 159redirects to a server close to you. 160 161=item --env-proxy 162 163Let L<LWP::UserAgent> read the proxy settings from environment variables. 164See the according method in that manual page. 165 166=item --stand-alone or -a 167 168The "real" CPAN list is not included. For instance, if you have 169downloaded all the releases from CPAN that you need, and you do not want 170unexpected extra downloads. The downloaded versions will prevail over 171newer releases on CPAN, but you may download modules from the core CPAN 172that you do not expect. 173 174=item --no-lazy or --lazy or -l 175 176Try to avoid redo-ing everything. By default, the indexer is 177lazy: it will process only new distributions. When not lazy, all 178distributions on the local disk are processed and a new table is 179created. The default of this option was reversed with release 1.00 180of C<CPAN::Site>. 181 182=item --no-undefs or --undefs or -u 183 184Whether to include package names with "undef" version in the packages 185list. Those packages cannot be used for dependencies, so are hardly 186useful but included by default. 187 188=back 189 190=head1 DETAILS 191 192=head2 Configuring the Clients 193 194To get in touch with your own cpan archive, you have to explicitly provide 195an url to it. Add this to your C<CPAN.pm> configuration file (usually 196F<~/.cpan/CPAN/MyConfig.pm>) option C<urllist>. B<There is no need to 197install the CPAN::Site software on your clients since release 1.01>. 198 199You probably also want to set the variable C<index_expire> to very short: 200the clients need to reload your local index as soon as possible, and not 201wait a day; just after your new local release is put in your local index, 202it must get visible to your client. 203 204You may also consider to have the CPAN install cache to be cleaned 205by the system. Certainly when you set the cache size larger (required 206for more complex recursive installations) it is nice to have it removed 207after a (short) while. Set C<keep_source_where> to a temporary 208directory. 209 210Example for F<~/.cpan/CPAN/MyConfig.pm> 211 212 $CPAN::Config = 213 { ... 214 , index_expire => 1/600 # 5 minutes 215 , urllist => [ $MYCPAN_URL, $BIGCPAN_MIRROR ] 216 , keep_source_where => '/tmp/cpan-cache' 217 , build_cache => 100 # MegaByte cache 218 , ... 219 }; 220 221To avoid manually editing the CPAN config file one can also set the 222MYCPAN_URL from the shell: 223 224 cpan> o conf urllist unshift $MYCPAN_URL 225 cpan> o conf index_expire 0.001 # 86 seconds 226 cpan> o conf commit 227 228=head2 Configuring the Server 229 230=head3 Starting your own CPAN 231 232You have to have a ftp or http server running. Create a directory 233where you will distribute the data from, here named C<$MYCPAN>. 234With a web-server, it is adviced to create a virtual host like 235C<cpan.example.com> which has C<$MYCPAN> as DocumentRoot. 236 237Define a fake pause-id (here the demo is MYID), because if you use 238an existing pause-id you clients will start producing warnings about 239missing checksums on files retreived for the public archive. 240 241 MYMODS=$MYCPAN/authors/id/M/MY/MYID 242 mkdir -p $MYMODS 243 244Although CPAN.pm claims to support a directory format of 245C<$MYCPAN/authors/id/MYID>, experience shows that this does not 246work correctly with some recursively dependencies. 247 248=head3 Adding your own modules to the local archive 249 250Put your own modules in C<$MYMODS> and then rerun the indexer. 251 252 mv MyDist-1.00-tar.gz $MYMODS # local 253 scp MyDist-1.00-tar.gz cpan.example.com:$MYMODS 254 255=head3 Generating an index with fallback 256 257Your own software probably depends on a lot of modules which are 258found on the global CPAN. And those modules require even more 259modules from CPAN. By default, your local CPAN index will know 260about all modules which you have yourself plus all module on 261the global CPAN. 262 263The index only contains the last (highest) version of each file 264(which means that each file must contain a version number otherwise the 265text C<undef> is used for version) In any case, the local packages get 266preference over the global CPAN packages, even when they have a lower 267version number. 268 269With fallback: 270 271 cpansite --site $MYCPAN index 272 cpansite index # when CPANSITE_LOCAL=$MYCPAN 273 274The script traverses I<$MYCPAN>F</authors/id> and merges this with the 275I<$MYCPAN>F</global/02packages.details.txt.gz> data, a copy from the 276original CPAN. It creates a C<CHECKSUMS> file. The result is a private 277I<$MYCPAN>F</modules/02packages.details.txt.gz> file. 278 279The files F<$MYCPAN/authors/01mailrc.txt.gz> and 280F<$MYCPAN/modules/03modlist.data.gz> are downloaded from CPAN. This 281will reduce the number of failing retreivals when you start installing 282software. 283 284B<Be warned:> the indexing scans the archive for the same VERSION 285patterns as pause does: do not make too complex expressions in 286those program lines. Only pm files are indexed, not other files, 287like scripts (pl files). 288 289=head3 Generating an index without fallback 290 291When you wish for a controled environment, where all your systems 292run the same versions of the modules, you should disable the fallback 293to the global CPAN. 294 295Without fallback: 296 297 cpansite --site $MYCPAN --stand-alone index 298 cpansite --stand-alone index # when CPANSITE_LOCAL=$MYCPAN 299 300The index is now very small. But when you start installing your software 301on systems, it will start complaining that the module cannot be found on 302CPAN. Now, add specific distribution versions from the global CPAN to 303your own archive. See next section. 304 305=head3 Adding distributions from global CPAN to your own 306 307When you want a fixed distribution version to be used on your systems, 308you can manually download them and insert them in the C<$MYCPAN> tree. 309 310However, there is also a simple way to retrieve the most recent version. 311The next example shows how to insert the latest versions of the 312distributions which include the packages Mail::Box and Test::More into 313your local CPAN archive. 314 315 cpansite --site $MYCPAN --cpan $GLOBAL mirror Mail::Box Test::More 316 317 # when CPANSITE_LOCAL=$MYCPAN and CPANSITE_GLOBAL=$GLOBAL 318 cpansite mirror Mail::Box Test::More 319 320=head1 AUTHORS 321 322Mark Overmeer E<lt>markov@cpan.org<gt>. 323 324This project is free software; you can redistribute it and/or modify it 325under the same terms as Perl itself. 326See <http://dev.perl.org/licenses/> 327 328=cut 329