1 package CPANPLUS::Backend;
7 use CPANPLUS::Configure;
8 use CPANPLUS::Internals;
9 use CPANPLUS::Internals::Constants;
11 use CPANPLUS::Module::Author;
12 use CPANPLUS::Backend::RV;
16 use File::Spec::Unix ();
17 use Params::Check qw[check];
18 use Locale::Maketext::Simple Class => 'CPANPLUS', Style => 'gettext';
20 $Params::Check::VERBOSE = 1;
22 use vars qw[@ISA $VERSION];
24 @ISA = qw[CPANPLUS::Internals];
25 $VERSION = $CPANPLUS::Internals::VERSION;
27 ### mark that we're running under CPANPLUS to spawned processes
28 $ENV{'PERL5_CPANPLUS_IS_RUNNING'} = $$;
30 ### XXX version.pm MAY format this version, if it's in use... :(
31 ### so for consistency, just call ->VERSION ourselves as well.
32 $ENV{'PERL5_CPANPLUS_IS_VERSION'} = __PACKAGE__->VERSION;
42 my $cb = CPANPLUS::Backend->new;
43 my $conf = $cb->configure_object;
45 my $author = $cb->author_tree('KANE');
46 my $mod = $cb->module_tree('Some::Module');
47 my $mod = $cb->parse_module( module => 'Some::Module' );
49 my @objs = $cb->search( type => TYPE,
59 This module provides the programmer's interface to the C<CPANPLUS>
64 When C<CPANPLUS::Backend> is loaded, which is necessary for just
65 about every <CPANPLUS> operation, the environment variable
66 C<PERL5_CPANPLUS_IS_RUNNING> is set to the current process id.
68 Additionally, the environment variable C<PERL5_CPANPLUS_IS_VERSION>
69 will be set to the version of C<CPANPLUS::Backend>.
71 This information might be useful somehow to spawned processes.
75 =head2 $cb = CPANPLUS::Backend->new( [CONFIGURE_OBJ] )
77 This method returns a new C<CPANPLUS::Backend> object.
78 This also initialises the config corresponding to this object.
79 You have two choices in this:
83 =item Provide a valid C<CPANPLUS::Configure> object
85 This will be used verbatim.
89 Your default config will be loaded and used.
93 New will return a C<CPANPLUS::Backend> object on success and die on
102 if( $_[0] && IS_CONFOBJ->( conf => $_[0] ) ) {
105 $conf = CPANPLUS::Configure->new() or return;
108 my $self = $class->SUPER::_init( _conf => $conf );
115 =head2 $href = $cb->module_tree( [@modules_names_list] )
117 Returns a reference to the CPANPLUS module tree.
119 If you give it any arguments, they will be treated as module names
120 and C<module_tree> will try to look up these module names and
121 return the corresponding module objects instead.
123 See L<CPANPLUS::Module> for the operations you can perform on a
130 my $modtree = $self->_module_tree;
134 for my $name ( grep { defined } @_) {
136 ### From John Malmberg: This is failing on VMS
137 ### because ODS-2 does not retain the case of
138 ### filenames that are created.
139 ### The problem is the filename is being converted
140 ### to a module name and then looked up in the
143 ### As a fix, we do a search on VMS instead --
144 ### more cpu cycles, but it gets around the case
150 allow => [qr/^$name$/i],
155 push @rv, $modobj || '';
157 return @rv == 1 ? $rv[0] : @rv;
165 =head2 $href = $cb->author_tree( [@author_names_list] )
167 Returns a reference to the CPANPLUS author tree.
169 If you give it any arguments, they will be treated as author names
170 and C<author_tree> will try to look up these author names and
171 return the corresponding author objects instead.
173 See L<CPANPLUS::Module::Author> for the operations you can perform on
180 my $authtree = $self->_author_tree;
185 push @rv, $authtree->{$name} || '';
187 return @rv == 1 ? $rv[0] : @rv;
195 =head2 $conf = $cb->configure_object;
197 Returns a copy of the C<CPANPLUS::Configure> object.
199 See L<CPANPLUS::Configure> for operations you can perform on a
204 sub configure_object { return shift->_conf() };
206 =head2 $su = $cb->selfupdate_object;
208 Returns a copy of the C<CPANPLUS::Selfupdate> object.
210 See the L<CPANPLUS::Selfupdate> manpage for the operations
211 you can perform on the selfupdate object.
215 sub selfupdate_object { return shift->_selfupdate() };
219 =head2 @mods = $cb->search( type => TYPE, allow => AREF, [data => AREF, verbose => BOOL] )
221 C<search> enables you to search for either module or author objects,
222 based on their data. The C<type> you can specify is any of the
223 accessors specified in C<CPANPLUS::Module::Author> or
224 C<CPANPLUS::Module>. C<search> will determine by the C<type> you
225 specified whether to search by author object or module object.
227 You have to specify an array reference of regular expressions or
228 strings to match against. The rules used for this array ref are the
229 same as in C<Params::Check>, so read that manpage for details.
231 The search is an C<or> search, meaning that if C<any> of the criteria
232 match, the search is considered to be successful.
234 You can specify the result of a previous search as C<data> to limit
235 the new search to these module or author objects, rather than the
236 entire module or author tree. This is how you do C<and> searches.
238 Returns a list of module or author objects on success and false
241 See L<CPANPLUS::Module> for the operations you can perform on a
243 See L<CPANPLUS::Module::Author> for the operations you can perform on
250 my $conf = $self->configure_object;
255 local $Params::Check::NO_DUPLICATES = 0;
256 local $Params::Check::ALLOW_UNKNOWN = 1;
259 type => { required => 1, allow => [CPANPLUS::Module->accessors(),
260 CPANPLUS::Module::Author->accessors()], store => \$type },
261 allow => { required => 1, default => [ ], strict_type => 1 },
264 check( $tmpl, \%hash )
267 ### figure out whether it was an author or a module search
268 ### when ambiguous, it'll be an author search.
270 if( grep { $type eq $_ } CPANPLUS::Module::Author->accessors() ) {
271 $aref = $self->_search_author_tree( %$args );
273 $aref = $self->_search_module_tree( %$args );
276 return @$aref if $aref;
282 =head2 $backend_rv = $cb->fetch( modules => \@mods )
284 Fetches a list of modules. C<@mods> can be a list of distribution
285 names, module names or module objects--basically anything that
286 L<parse_module> can understand.
288 See the equivalent method in C<CPANPLUS::Module> for details on
289 other options you can pass.
291 Since this is a multi-module method call, the return value is
292 implemented as a C<CPANPLUS::Backend::RV> object. Please consult
293 that module's documentation on how to interpret the return value.
295 =head2 $backend_rv = $cb->extract( modules => \@mods )
297 Extracts a list of modules. C<@mods> can be a list of distribution
298 names, module names or module objects--basically anything that
299 L<parse_module> can understand.
301 See the equivalent method in C<CPANPLUS::Module> for details on
302 other options you can pass.
304 Since this is a multi-module method call, the return value is
305 implemented as a C<CPANPLUS::Backend::RV> object. Please consult
306 that module's documentation on how to interpret the return value.
308 =head2 $backend_rv = $cb->install( modules => \@mods )
310 Installs a list of modules. C<@mods> can be a list of distribution
311 names, module names or module objects--basically anything that
312 L<parse_module> can understand.
314 See the equivalent method in C<CPANPLUS::Module> for details on
315 other options you can pass.
317 Since this is a multi-module method call, the return value is
318 implemented as a C<CPANPLUS::Backend::RV> object. Please consult
319 that module's documentation on how to interpret the return value.
321 =head2 $backend_rv = $cb->readme( modules => \@mods )
323 Fetches the readme for a list of modules. C<@mods> can be a list of
324 distribution names, module names or module objects--basically
325 anything that L<parse_module> can understand.
327 See the equivalent method in C<CPANPLUS::Module> for details on
328 other options you can pass.
330 Since this is a multi-module method call, the return value is
331 implemented as a C<CPANPLUS::Backend::RV> object. Please consult
332 that module's documentation on how to interpret the return value.
334 =head2 $backend_rv = $cb->files( modules => \@mods )
336 Returns a list of files used by these modules if they are installed.
337 C<@mods> can be a list of distribution names, module names or module
338 objects--basically anything that L<parse_module> can understand.
340 See the equivalent method in C<CPANPLUS::Module> for details on
341 other options you can pass.
343 Since this is a multi-module method call, the return value is
344 implemented as a C<CPANPLUS::Backend::RV> object. Please consult
345 that module's documentation on how to interpret the return value.
347 =head2 $backend_rv = $cb->distributions( modules => \@mods )
349 Returns a list of module objects representing all releases for this
351 C<@mods> can be a list of distribution names, module names or module
352 objects, basically anything that L<parse_module> can understand.
354 See the equivalent method in C<CPANPLUS::Module> for details on
355 other options you can pass.
357 Since this is a multi-module method call, the return value is
358 implemented as a C<CPANPLUS::Backend::RV> object. Please consult
359 that module's documentation on how to interpret the return value.
363 ### XXX add direcotry_tree, packlist etc? or maybe remove files? ###
364 for my $func (qw[fetch extract install readme files distributions]) {
369 my $conf = $self->configure_object;
374 local $Params::Check::NO_DUPLICATES = 1;
375 local $Params::Check::ALLOW_UNKNOWN = 1;
378 modules => { default => [], strict_type => 1,
379 required => 1, store => \$mods },
382 check( $tmpl, \%hash );
385 ### make them all into module objects ###
386 my %mods = map { $_ => $self->parse_module(module => $_) || '' } @$mods;
389 while( my($name,$obj) = each %mods ) {
390 $href->{$name} = IS_MODOBJ->( mod => $obj )
391 ? $obj->$func( %$args )
394 $flag++ unless $href->{$name};
397 return CPANPLUS::Backend::RV->new(
408 =head2 $mod_obj = $cb->parse_module( module => $modname|$distname|$modobj|URI )
410 C<parse_module> tries to find a C<CPANPLUS::Module> object that
411 matches your query. Here's a list of examples you could give to
416 =item Text::Bastardize
418 =item Text-Bastardize
420 =item Text-Bastardize-1.06
422 =item AYRNIEU/Text-Bastardize
424 =item AYRNIEU/Text-Bastardize-1.06
426 =item AYRNIEU/Text-Bastardize-1.06.tar.gz
428 =item http://example.com/Text-Bastardize-1.06.tar.gz
430 =item file:///tmp/Text-Bastardize-1.06.tar.gz
434 These items would all come up with a C<CPANPLUS::Module> object for
435 C<Text::Bastardize>. The ones marked explicitly as being version 1.06
436 would give back a C<CPANPLUS::Module> object of that version.
437 Even if the version on CPAN is currently higher.
439 If C<parse_module> is unable to actually find the module you are looking
440 for in its module tree, but you supplied it with an author, module
441 and version part in a distribution name or URI, it will create a fake
442 C<CPANPLUS::Module> object for you, that you can use just like the
445 See L<CPANPLUS::Module> for the operations you can perform on a
448 If even this fancy guessing doesn't enable C<parse_module> to create
449 a fake module object for you to use, it will warn about an error and
456 my $conf = $self->configure_object;
461 module => { required => 1, store => \$mod },
464 my $args = check( $tmpl, \%hash ) or return;
466 return $mod if IS_MODOBJ->( module => $mod );
468 ### ok, so it's not a module object, but a ref nonetheless?
469 ### what are you smoking?
471 error(loc("Can not parse module string from reference '%1'", $mod ));
475 ### check only for allowed characters in a module name
476 unless( $mod =~ /[^\w:]/ ) {
478 ### perhaps we can find it in the module tree?
479 my $maybe = $self->module_tree($mod);
480 return $maybe if IS_MODOBJ->( module => $maybe );
483 ### ok, so it looks like a distribution then?
484 my @parts = split '/', $mod;
485 my $dist = pop @parts;
488 if( $mod =~ m|\w+://.+| ) {
489 my $modobj = CPANPLUS::Module::Fake->new(
493 path => File::Spec::Unix->catdir(
494 $conf->_get_mirror('base'),
495 UNKNOWN_DL_LOCATION ),
496 author => CPANPLUS::Module::Author::Fake->new
499 ### set the fetch_from accessor so we know to by pass the
501 $modobj->status->_fetch_from( $mod );
503 ### better guess for the version
504 $modobj->version( $modobj->package_version )
505 if defined $modobj->package_version;
507 ### better guess at module name, if possible
508 if ( my $pkgname = $modobj->package_name ) {
509 $pkgname =~ s/-/::/g;
511 ### no sense replacing it unless we changed something
512 $modobj->module( $pkgname )
513 if ($pkgname ne $modobj->package_name) || $pkgname !~ /-/;
519 ### perhaps we can find it's a third party module?
520 { my $modobj = CPANPLUS::Module::Fake->new(
524 path => File::Spec::Unix->catdir(
525 $conf->_get_mirror('base'),
526 UNKNOWN_DL_LOCATION ),
527 author => CPANPLUS::Module::Author::Fake->new
529 if( $modobj->is_third_party ) {
530 my $info = $modobj->third_party_information;
532 $modobj->author->author( $info->{author} );
533 $modobj->author->email( $info->{author_url} );
534 $modobj->description( $info->{url} );
541 error( loc("%1 is not a proper distribution name!", $mod) );
545 ### there's wonky uris out there, like this:
546 ### E/EY/EYCK/Net/Lite/Net-Lite-FTP-0.091
547 ### compensate for that
549 ### you probably have an A/AB/ABC/....../Dist.tgz type uri
550 if( (defined $parts[0] and length $parts[0] == 1) and
551 (defined $parts[1] and length $parts[1] == 2) and
552 $parts[2] =~ /^$parts[0]/i and $parts[2] =~ /^$parts[1]/i
554 splice @parts, 0, 2; # remove the first 2 entries from the list
555 $author = shift @parts; # this is the actual author name then
557 ### we''ll assume a ABC/..../Dist.tgz
559 $author = shift @parts || '';
562 my($pkg, $version, $ext, $full) =
563 $self->_split_package_string( package => $dist );
565 ### translate a distribution into a module name ###
567 $guess =~ s/-/::/g if $guess;
569 my $maybe = $self->module_tree( $guess );
570 if( IS_MODOBJ->( module => $maybe ) ) {
572 ### maybe you asked for a package instead
573 if ( $maybe->package eq $mod ) {
576 ### perhaps an outdated version instead?
577 } elsif ( $version ) {
578 my $auth_obj; my $path;
580 ### did you give us an author part? ###
582 $auth_obj = CPANPLUS::Module::Author::Fake->new(
584 cpanid => uc $author,
585 author => uc $author,
587 $path = File::Spec::Unix->catdir(
588 $conf->_get_mirror('base'),
589 substr(uc $author, 0, 1),
590 substr(uc $author, 0, 2),
592 @parts, #possible sub dirs
595 $auth_obj = $maybe->author;
596 $path = $maybe->path;
599 if( $maybe->package_name eq $pkg ) {
601 my $modobj = CPANPLUS::Module::Fake->new(
602 module => $maybe->module,
604 ### no extension? use the extension the original package
608 : $full .'.'. $maybe->package_extension
616 ### you asked for a specific version?
617 ### assume our $maybe is the one you wanted,
618 ### and fix up the version..
621 my $modobj = $maybe->clone;
622 $modobj->version( $version );
624 $maybe->package_name .'-'.
626 $maybe->package_extension
629 ### you wanted a specific author, but it's not the one
630 ### from the module tree? we'll fix it up
631 if( $author and $author ne $modobj->author->cpanid ) {
632 $modobj->author( $auth_obj );
633 $modobj->path( $path );
639 ### you didn't care about a version, so just return the object then
640 } elsif ( !$version ) {
644 ### ok, so we can't find it, and it's not an outdated dist either
645 ### perhaps we can fake one based on the author name and so on
646 } elsif ( $author and $version ) {
648 ### be extra friendly and pad the .tar.gz suffix where needed
649 ### it's just a guess of course, but most dists are .tar.gz
650 $dist .= '.tar.gz' unless $dist =~ /\.[A-Za-z]+$/;
652 ### XXX duplication from above for generating author obj + path...
653 my $modobj = CPANPLUS::Module::Fake->new(
657 author => CPANPLUS::Module::Author::Fake->new(
658 author => uc $author,
659 cpanid => uc $author,
662 path => File::Spec::Unix->catdir(
663 $conf->_get_mirror('base'),
664 substr(uc $author, 0, 1),
665 substr(uc $author, 0, 2),
667 @parts, #possible subdirs
674 ### face it, we have /no/ idea what he or she wants...
675 ### let's start putting the blame somewhere
679 error( loc( "'%1' does not contain an author part", $mod ) );
682 error( loc( "Cannot find '%1' in the module tree", $mod ) );
690 =head2 $bool = $cb->reload_indices( [update_source => BOOL, verbose => BOOL] );
692 This method reloads the source files.
694 If C<update_source> is set to true, this will fetch new source files
695 from your CPAN mirror. Otherwise, C<reload_indices> will do its
696 usual cache checking and only update them if they are out of date.
698 By default, C<update_source> will be false.
700 The verbose setting defaults to what you have specified in your
703 Returns true on success and false on failure.
710 my $conf = $self->configure_object;
713 update_source => { default => 0, allow => [qr/^\d$/] },
714 verbose => { default => $conf->get_conf('verbose') },
717 my $args = check( $tmpl, \%hash ) or return;
719 ### make a call to the internal _module_tree, so it triggers cache
721 my $uptodate = $self->_check_trees( %$args );
724 return 1 if $self->_build_trees(
725 uptodate => $uptodate,
727 verbose => $conf->get_conf('verbose'),
730 error( loc( "Error rebuilding source trees!" ) );
737 =head2 $bool = $cb->flush(CACHE_NAME)
739 This method allows flushing of caches.
740 There are several things which can be flushed:
746 The return status of methods which have been attempted, such as
747 different ways of fetching files. It is recommended that automatic
748 flushing be used instead.
752 The return status of URIs which have been attempted, such as
753 different hosts of fetching files. It is recommended that automatic
754 flushing be used instead.
758 Information about modules such as prerequisites and whether
759 installation succeeded, failed, or was not attempted.
763 This resets PERL5LIB, which is changed to ensure that while installing
764 modules they are in our @INC.
768 This resets the cache of modules we've attempted to load, but failed.
769 This enables you to load them again after a failed load, if they
770 somehow have become available.
774 Flush all of the aforementioned caches.
778 Returns true on success and false on failure.
784 my $type = shift or return;
787 methods => [ qw( methods load ) ],
788 hosts => [ qw( hosts ) ],
789 modules => [ qw( modules lib) ],
790 lib => [ qw( lib ) ],
791 load => [ qw( load ) ],
792 all => [ qw( hosts lib modules methods load ) ],
795 my $aref = $cache->{$type}
797 error( loc("No such cache '%1'", $type) ),
801 return $self->_flush( list => $aref );
806 =head2 @mods = $cb->installed()
808 Returns a list of module objects of all your installed modules.
809 If an error occurs, it will return false.
811 See L<CPANPLUS::Module> for the operations you can perform on a
818 my $aref = $self->_all_installed;
820 return @$aref if $aref;
826 =head2 $bool = $cb->local_mirror([path => '/dir/to/save/to', index_files => BOOL, force => BOOL, verbose => BOOL] )
828 Creates a local mirror of CPAN, of only the most recent sources in a
829 location you specify. If you set this location equal to a custom host
830 in your C<CPANPLUS::Config> you can use your local mirror to install
833 It takes the following arguments:
839 The location where to create the local mirror.
843 Enable/disable fetching of index files. You can disable fetching of the
844 index files if you don't plan to use the local mirror as your primary
845 site, or if you'd like up-to-date index files be fetched from elsewhere.
851 Forces refetching of packages, even if they are there already.
853 Defaults to whatever setting you have in your C<CPANPLUS::Config>.
857 Prints more messages about what its doing.
859 Defaults to whatever setting you have in your C<CPANPLUS::Config>.
863 Returns true on success and false on error.
869 my $conf = $self->configure_object;
872 my($path, $index, $force, $verbose);
874 path => { default => $conf->get_conf('base'),
876 index_files => { default => 1, store => \$index },
877 force => { default => $conf->get_conf('force'),
879 verbose => { default => $conf->get_conf('verbose'),
880 store => \$verbose },
883 check( $tmpl, \%hash ) or return;
886 $self->_mkdir( dir => $path )
887 or( error( loc( "Could not create '%1', giving up", $path ) ),
891 error( loc( "Could not write to '%1', giving up", $path ) );
897 for my $auth ( sort { $a->cpanid cmp $b->cpanid }
898 values %{$self->author_tree}
903 for my $mod ( $auth->modules ) {
904 my $fetchdir = File::Spec->catdir( $path, $mod->path );
909 fetchdir => $fetchdir,
912 ### only do this the for the first module ###
914 $mod->_get_checksums_file(
917 error( loc( "Could not fetch %1 file, " .
918 "skipping author '%2'",
919 CHECKSUMS, $auth->cpanid ) ),
925 or( error( loc( "Could not fetch '%1'", $mod->module ) ),
932 for my $name (qw[auth dslip mod]) {
933 $self->_update_source(
937 ) or ( $flag++, next );
946 =head2 $file = $cb->autobundle([path => OUTPUT_PATH, force => BOOL, verbose => BOOL])
948 Writes out a snapshot of your current installation in C<CPAN> bundle
949 style. This can then be used to install the same modules for a
950 different or on a different machine by issuing the following commands:
952 ### using the default shell:
953 CPAN Terminal> i file://path/to/Snapshot_XXYY.pm
956 $modobj = $cb->parse_module( module => 'file://path/to/Snapshot_XXYY.pm' );
959 It will, by default, write to an 'autobundle' directory under your
960 cpanplus homedirectory, but you can override that by supplying a
963 It will return the location of the output file on success and false on
970 my $conf = $self->configure_object;
973 my($path,$force,$verbose);
975 force => { default => $conf->get_conf('force'), store => \$force },
976 verbose => { default => $conf->get_conf('verbose'), store => \$verbose },
977 path => { default => File::Spec->catdir(
978 $conf->get_conf('base'),
979 $self->_perl_version( perl => $^X ),
980 $conf->_get_build('distdir'),
981 $conf->_get_build('autobundle') ),
985 check($tmpl, \%hash) or return;
988 $self->_mkdir( dir => $path )
989 or( error(loc("Could not create directory '%1'", $path ) ),
995 { ### default filename for the bundle ###
996 my($year,$month,$day) = (localtime)[5,4,3];
997 $year += 1900; $month++;
1001 my $prefix = $conf->_get_build('autobundle_prefix');
1002 my $format = "${prefix}_%04d_%02d_%02d_%02d";
1005 $name = sprintf( $format, $year, $month, $day, $ext);
1007 $file = File::Spec->catfile( $path, $name . '.pm' );
1009 -f $file ? ++$ext && redo BLOCK : last BLOCK;
1013 unless( $fh = FileHandle->new( ">$file" ) ) {
1014 error( loc( "Could not open '%1' for writing: %2", $file, $! ) );
1018 ### make sure we load the module tree *before* doing this, as it
1019 ### starts to chdir all over the place
1022 my $string = join "\n\n",
1026 ($_->installed_version(verbose => 0) || 'undef')
1028 $a->module cmp $b->module
1031 my $now = scalar localtime;
1032 my $head = '=head1';
1033 my $pkg = __PACKAGE__;
1034 my $version = $self->VERSION;
1035 my $perl_v = join '', `$^X -V`;
1048 $name - Snapshot of your installation at $now
1052 perl -MCPANPLUS -e "install file://full/path/to/$name"
1064 This bundle has been generated autotomatically by
1074 =head2 $bool = $cb->save_state
1076 Explicit command to save memory state to disk. This can be used to save
1077 information to disk about where a module was extracted, the result of
1078 C<make test>, etc. This will then be re-loaded into memory when a new
1081 The capability of saving state to disk depends on the source engine
1082 being used (See C<CPANPLUS::Config> for the option to choose your
1083 source engine). The default storage engine supports this option.
1085 Most users will not need this command, but it can handy for automated
1086 systems like setting up CPAN smoke testers.
1088 The method will return true if it managed to save the state to disk,
1089 or false if it did not.
1095 return $self->_save_state( @_ );
1099 ### XXX these wrappers are not individually tested! only the underlying
1100 ### code through source.t and indirectly trought he CustomSource plugin.
1103 =head1 CUSTOM MODULE SOURCES
1105 Besides the sources as provided by the general C<CPAN> mirrors, it's
1106 possible to add your own sources list to your C<CPANPLUS> index.
1108 The methodology behind this works much like C<Debian's apt-sources>.
1110 The methods below show you how to make use of this functionality. Also
1111 note that most of these methods are available through the default shell
1112 plugin command C</cs>, making them available as shortcuts through the
1113 shell and via the commandline.
1115 =head2 %files = $cb->list_custom_sources
1117 Returns a mapping of registered custom sources and their local indices
1120 /full/path/to/local/index => http://remote/source
1122 Note that any file starting with an C<#> is being ignored.
1126 sub list_custom_sources {
1127 return shift->__list_custom_module_sources( @_ );
1130 =head2 $local_index = $cb->add_custom_source( uri => URI, [verbose => BOOL] );
1132 Adds an C<URI> to your own sources list and mirrors its index. See the
1133 documentation on C<< $cb->update_custom_source >> on how this is done.
1135 Returns the full path to the local index on success, or false on failure.
1137 Note that when adding a new C<URI>, the change to the in-memory tree is
1138 not saved until you rebuild or save the tree to disk again. You can do
1139 this using the C<< $cb->reload_indices >> method.
1143 sub add_custom_source {
1144 return shift->_add_custom_module_source( @_ );
1147 =head2 $local_index = $cb->remove_custom_source( uri => URI, [verbose => BOOL] );
1149 Removes an C<URI> from your own sources list and removes its index.
1151 To find out what C<URI>s you have as part of your own sources list, use
1152 the C<< $cb->list_custom_sources >> method.
1154 Returns the full path to the deleted local index file on success, or false
1159 ### XXX do clever dispatching based on arg number?
1160 sub remove_custom_source {
1161 return shift->_remove_custom_module_source( @_ );
1164 =head2 $bool = $cb->update_custom_source( [remote => URI] );
1166 Updates the indexes for all your custom sources. It does this by fetching
1167 a file called C<packages.txt> in the root of the custom sources's C<URI>.
1168 If you provide the C<remote> argument, it will only update the index for
1169 that specific C<URI>.
1171 Here's an example of how custom sources would resolve into index files:
1173 file:///path/to/sources => file:///path/to/sources/packages.txt
1174 http://example.com/sources => http://example.com/sources/packages.txt
1175 ftp://example.com/sources => ftp://example.com/sources/packages.txt
1177 The file C<packages.txt> simply holds a list of packages that can be found
1178 under the root of the C<URI>. This file can be automatically generated for
1179 you when the remote source is a C<file:// URI>. For C<http://>, C<ftp://>,
1180 and similar, the administrator of that repository should run the method
1181 C<< $cb->write_custom_source_index >> on the repository to allow remote
1184 For details, see the C<< $cb->write_custom_source_index >> method below.
1186 All packages that are added via this mechanism will be attributed to the
1187 author with C<CPANID> C<LOCAL>. You can use this id to search for all
1192 sub update_custom_source {
1195 ### if it mentions /remote/, the request is to update a single uri,
1196 ### not all the ones we have, so dispatch appropriately
1197 my $rv = grep( /remote/i, @_)
1198 ? $self->__update_custom_module_source( @_ )
1199 : $self->__update_custom_module_sources( @_ );
1204 =head2 $file = $cb->write_custom_source_index( path => /path/to/package/root, [to => /path/to/index/file, verbose => BOOL] );
1206 Writes the index for a custom repository root. Most users will not have to
1207 worry about this, but administrators of a repository will need to make sure
1208 their indexes are up to date.
1210 The index will be written to a file called C<packages.txt> in your repository
1211 root, which you can specify with the C<path> argument. You can override this
1212 location by specifying the C<to> argument, but in normal operation, that should
1215 Once the index file is written, users can then add the C<URI> pointing to
1216 the repository to their custom list of sources and start using it right away. See the C<< $cb->add_custom_source >> method for user details.
1220 sub write_custom_source_index {
1221 return shift->__write_custom_module_index( @_ );
1230 Please report bugs or other issues to E<lt>bug-cpanplus@rt.cpan.org<gt>.
1234 This module by Jos Boumans E<lt>kane@cpan.orgE<gt>.
1238 The CPAN++ interface (of which this module is a part of) is copyright (c)
1239 2001 - 2007, Jos Boumans E<lt>kane@cpan.orgE<gt>. All rights reserved.
1241 This library is free software; you may redistribute and/or modify it
1242 under the same terms as Perl itself.
1246 L<CPANPLUS::Configure>, L<CPANPLUS::Module>, L<CPANPLUS::Module::Author>,
1247 L<CPANPLUS::Selfupdate>
1252 # c-indentation-style: bsd
1254 # indent-tabs-mode: nil
1256 # vim: expandtab shiftwidth=4:
1261 sub dist { # not sure about this one -- probably already done
1263 sub reports { # in Module.pm, wrapper here