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 } @_) {
135 push @rv, $modtree->{$name} || '';
137 return @rv == 1 ? $rv[0] : @rv;
145 =head2 $href = $cb->author_tree( [@author_names_list] )
147 Returns a reference to the CPANPLUS author tree.
149 If you give it any arguments, they will be treated as author names
150 and C<author_tree> will try to look up these author names and
151 return the corresponding author objects instead.
153 See L<CPANPLUS::Module::Author> for the operations you can perform on
160 my $authtree = $self->_author_tree;
165 push @rv, $authtree->{$name} || '';
167 return @rv == 1 ? $rv[0] : @rv;
175 =head2 $conf = $cb->configure_object;
177 Returns a copy of the C<CPANPLUS::Configure> object.
179 See L<CPANPLUS::Configure> for operations you can perform on a
184 sub configure_object { return shift->_conf() };
186 =head2 $su = $cb->selfupdate_object;
188 Returns a copy of the C<CPANPLUS::Selfupdate> object.
190 See the L<CPANPLUS::Selfupdate> manpage for the operations
191 you can perform on the selfupdate object.
195 sub selfupdate_object { return shift->_selfupdate() };
199 =head2 @mods = $cb->search( type => TYPE, allow => AREF, [data => AREF, verbose => BOOL] )
201 C<search> enables you to search for either module or author objects,
202 based on their data. The C<type> you can specify is any of the
203 accessors specified in C<CPANPLUS::Module::Author> or
204 C<CPANPLUS::Module>. C<search> will determine by the C<type> you
205 specified whether to search by author object or module object.
207 You have to specify an array reference of regular expressions or
208 strings to match against. The rules used for this array ref are the
209 same as in C<Params::Check>, so read that manpage for details.
211 The search is an C<or> search, meaning that if C<any> of the criteria
212 match, the search is considered to be successful.
214 You can specify the result of a previous search as C<data> to limit
215 the new search to these module or author objects, rather than the
216 entire module or author tree. This is how you do C<and> searches.
218 Returns a list of module or author objects on success and false
221 See L<CPANPLUS::Module> for the operations you can perform on a
223 See L<CPANPLUS::Module::Author> for the operations you can perform on
230 my $conf = $self->configure_object;
233 local $Params::Check::ALLOW_UNKNOWN = 1;
237 type => { required => 1, allow => [CPANPLUS::Module->accessors(),
238 CPANPLUS::Module::Author->accessors()], store => \$type },
239 allow => { required => 1, default => [ ], strict_type => 1 },
242 my $args = check( $tmpl, \%hash ) or return;
244 ### figure out whether it was an author or a module search
245 ### when ambiguous, it'll be an author search.
247 if( grep { $type eq $_ } CPANPLUS::Module::Author->accessors() ) {
248 $aref = $self->_search_author_tree( %$args );
250 $aref = $self->_search_module_tree( %$args );
253 return @$aref if $aref;
259 =head2 $backend_rv = $cb->fetch( modules => \@mods )
261 Fetches a list of modules. C<@mods> can be a list of distribution
262 names, module names or module objects--basically anything that
263 L<parse_module> can understand.
265 See the equivalent method in C<CPANPLUS::Module> for details on
266 other options you can pass.
268 Since this is a multi-module method call, the return value is
269 implemented as a C<CPANPLUS::Backend::RV> object. Please consult
270 that module's documentation on how to interpret the return value.
272 =head2 $backend_rv = $cb->extract( modules => \@mods )
274 Extracts a list of modules. C<@mods> can be a list of distribution
275 names, module names or module objects--basically anything that
276 L<parse_module> can understand.
278 See the equivalent method in C<CPANPLUS::Module> for details on
279 other options you can pass.
281 Since this is a multi-module method call, the return value is
282 implemented as a C<CPANPLUS::Backend::RV> object. Please consult
283 that module's documentation on how to interpret the return value.
285 =head2 $backend_rv = $cb->install( modules => \@mods )
287 Installs a list of modules. C<@mods> can be a list of distribution
288 names, module names or module objects--basically anything that
289 L<parse_module> can understand.
291 See the equivalent method in C<CPANPLUS::Module> for details on
292 other options you can pass.
294 Since this is a multi-module method call, the return value is
295 implemented as a C<CPANPLUS::Backend::RV> object. Please consult
296 that module's documentation on how to interpret the return value.
298 =head2 $backend_rv = $cb->readme( modules => \@mods )
300 Fetches the readme for a list of modules. C<@mods> can be a list of
301 distribution names, module names or module objects--basically
302 anything that L<parse_module> can understand.
304 See the equivalent method in C<CPANPLUS::Module> for details on
305 other options you can pass.
307 Since this is a multi-module method call, the return value is
308 implemented as a C<CPANPLUS::Backend::RV> object. Please consult
309 that module's documentation on how to interpret the return value.
311 =head2 $backend_rv = $cb->files( modules => \@mods )
313 Returns a list of files used by these modules if they are installed.
314 C<@mods> can be a list of distribution names, module names or module
315 objects--basically anything that L<parse_module> can understand.
317 See the equivalent method in C<CPANPLUS::Module> for details on
318 other options you can pass.
320 Since this is a multi-module method call, the return value is
321 implemented as a C<CPANPLUS::Backend::RV> object. Please consult
322 that module's documentation on how to interpret the return value.
324 =head2 $backend_rv = $cb->distributions( modules => \@mods )
326 Returns a list of module objects representing all releases for this
328 C<@mods> can be a list of distribution names, module names or module
329 objects, basically anything that L<parse_module> can understand.
331 See the equivalent method in C<CPANPLUS::Module> for details on
332 other options you can pass.
334 Since this is a multi-module method call, the return value is
335 implemented as a C<CPANPLUS::Backend::RV> object. Please consult
336 that module's documentation on how to interpret the return value.
340 ### XXX add direcotry_tree, packlist etc? or maybe remove files? ###
341 for my $func (qw[fetch extract install readme files distributions]) {
346 my $conf = $self->configure_object;
349 local $Params::Check::NO_DUPLICATES = 1;
350 local $Params::Check::ALLOW_UNKNOWN = 1;
354 modules => { default => [], strict_type => 1,
355 required => 1, store => \$mods },
358 my $args = check( $tmpl, \%hash ) or return;
360 ### make them all into module objects ###
361 my %mods = map {$_ => $self->parse_module(module => $_) || ''} @$mods;
364 while( my($name,$obj) = each %mods ) {
365 $href->{$name} = IS_MODOBJ->( mod => $obj )
366 ? $obj->$func( %$args )
369 $flag++ unless $href->{$name};
372 return CPANPLUS::Backend::RV->new(
383 =head2 $mod_obj = $cb->parse_module( module => $modname|$distname|$modobj|URI )
385 C<parse_module> tries to find a C<CPANPLUS::Module> object that
386 matches your query. Here's a list of examples you could give to
391 =item Text::Bastardize
393 =item Text-Bastardize
395 =item Text-Bastardize-1.06
397 =item AYRNIEU/Text-Bastardize
399 =item AYRNIEU/Text-Bastardize-1.06
401 =item AYRNIEU/Text-Bastardize-1.06.tar.gz
403 =item http://example.com/Text-Bastardize-1.06.tar.gz
405 =item file:///tmp/Text-Bastardize-1.06.tar.gz
409 These items would all come up with a C<CPANPLUS::Module> object for
410 C<Text::Bastardize>. The ones marked explicitly as being version 1.06
411 would give back a C<CPANPLUS::Module> object of that version.
412 Even if the version on CPAN is currently higher.
414 If C<parse_module> is unable to actually find the module you are looking
415 for in its module tree, but you supplied it with an author, module
416 and version part in a distribution name or URI, it will create a fake
417 C<CPANPLUS::Module> object for you, that you can use just like the
420 See L<CPANPLUS::Module> for the operations you can perform on a
423 If even this fancy guessing doesn't enable C<parse_module> to create
424 a fake module object for you to use, it will warn about an error and
431 my $conf = $self->configure_object;
436 module => { required => 1, store => \$mod },
439 my $args = check( $tmpl, \%hash ) or return;
441 return $mod if IS_MODOBJ->( module => $mod );
443 ### ok, so it's not a module object, but a ref nonetheless?
444 ### what are you smoking?
446 error(loc("Can not parse module string from reference '%1'", $mod ));
450 ### check only for allowed characters in a module name
451 unless( $mod =~ /[^\w:]/ ) {
453 ### perhaps we can find it in the module tree?
454 my $maybe = $self->module_tree($mod);
455 return $maybe if IS_MODOBJ->( module => $maybe );
458 ### ok, so it looks like a distribution then?
459 my @parts = split '/', $mod;
460 my $dist = pop @parts;
463 if( $mod =~ m|\w+://.+| ) {
464 my $modobj = CPANPLUS::Module::Fake->new(
468 path => File::Spec::Unix->catdir(
469 $conf->_get_mirror('base'),
470 UNKNOWN_DL_LOCATION ),
471 author => CPANPLUS::Module::Author::Fake->new
474 ### set the fetch_from accessor so we know to by pass the
476 $modobj->status->_fetch_from( $mod );
478 ### better guess for the version
479 $modobj->version( $modobj->package_version )
480 if defined $modobj->package_version;
482 ### better guess at module name, if possible
483 if ( my $pkgname = $modobj->package_name ) {
484 $pkgname =~ s/-/::/g;
486 ### no sense replacing it unless we changed something
487 $modobj->module( $pkgname )
488 if ($pkgname ne $modobj->package_name) || $pkgname !~ /-/;
494 ### perhaps we can find it's a third party module?
495 { my $modobj = CPANPLUS::Module::Fake->new(
499 path => File::Spec::Unix->catdir(
500 $conf->_get_mirror('base'),
501 UNKNOWN_DL_LOCATION ),
502 author => CPANPLUS::Module::Author::Fake->new
504 if( $modobj->is_third_party ) {
505 my $info = $modobj->third_party_information;
507 $modobj->author->author( $info->{author} );
508 $modobj->author->email( $info->{author_url} );
509 $modobj->description( $info->{url} );
516 error( loc("%1 is not a proper distribution name!", $mod) );
520 ### there's wonky uris out there, like this:
521 ### E/EY/EYCK/Net/Lite/Net-Lite-FTP-0.091
522 ### compensate for that
524 ### you probably have an A/AB/ABC/....../Dist.tgz type uri
525 if( (defined $parts[0] and length $parts[0] == 1) and
526 (defined $parts[1] and length $parts[1] == 2) and
527 $parts[2] =~ /^$parts[0]/i and $parts[2] =~ /^$parts[1]/i
529 splice @parts, 0, 2; # remove the first 2 entries from the list
530 $author = shift @parts; # this is the actual author name then
532 ### we''ll assume a ABC/..../Dist.tgz
534 $author = shift @parts || '';
537 my($pkg, $version, $ext) =
538 $self->_split_package_string( package => $dist );
540 ### translate a distribution into a module name ###
542 $guess =~ s/-/::/g if $guess;
544 my $maybe = $self->module_tree( $guess );
545 if( IS_MODOBJ->( module => $maybe ) ) {
547 ### maybe you asked for a package instead
548 if ( $maybe->package eq $mod ) {
551 ### perhaps an outdated version instead?
552 } elsif ( $version ) {
553 my $auth_obj; my $path;
555 ### did you give us an author part? ###
557 $auth_obj = CPANPLUS::Module::Author::Fake->new(
559 cpanid => uc $author,
560 author => uc $author,
562 $path = File::Spec::Unix->catdir(
563 $conf->_get_mirror('base'),
564 substr(uc $author, 0, 1),
565 substr(uc $author, 0, 2),
567 @parts, #possible sub dirs
570 $auth_obj = $maybe->author;
571 $path = $maybe->path;
574 if( $maybe->package_name eq $pkg ) {
576 my $modobj = CPANPLUS::Module::Fake->new(
577 module => $maybe->module,
579 package => $pkg . '-' . $version . '.' .
580 $maybe->package_extension,
587 ### you asked for a specific version?
588 ### assume our $maybe is the one you wanted,
589 ### and fix up the version..
592 my $modobj = $maybe->clone;
593 $modobj->version( $version );
595 $maybe->package_name .'-'.
597 $maybe->package_extension
600 ### you wanted a specific author, but it's not the one
601 ### from the module tree? we'll fix it up
602 if( $author and $author ne $modobj->author->cpanid ) {
603 $modobj->author( $auth_obj );
604 $modobj->path( $path );
610 ### you didn't care about a version, so just return the object then
611 } elsif ( !$version ) {
615 ### ok, so we can't find it, and it's not an outdated dist either
616 ### perhaps we can fake one based on the author name and so on
617 } elsif ( $author and $version ) {
619 ### be extra friendly and pad the .tar.gz suffix where needed
620 ### it's just a guess of course, but most dists are .tar.gz
621 $dist .= '.tar.gz' unless $dist =~ /\.[A-Za-z]+$/;
623 ### XXX duplication from above for generating author obj + path...
624 my $modobj = CPANPLUS::Module::Fake->new(
628 author => CPANPLUS::Module::Author::Fake->new(
629 author => uc $author,
630 cpanid => uc $author,
633 path => File::Spec::Unix->catdir(
634 $conf->_get_mirror('base'),
635 substr(uc $author, 0, 1),
636 substr(uc $author, 0, 2),
638 @parts, #possible subdirs
645 ### face it, we have /no/ idea what he or she wants...
646 ### let's start putting the blame somewhere
650 error( loc( "'%1' does not contain an author part", $mod ) );
653 error( loc( "Cannot find '%1' in the module tree", $mod ) );
661 =head2 $bool = $cb->reload_indices( [update_source => BOOL, verbose => BOOL] );
663 This method reloads the source files.
665 If C<update_source> is set to true, this will fetch new source files
666 from your CPAN mirror. Otherwise, C<reload_indices> will do its
667 usual cache checking and only update them if they are out of date.
669 By default, C<update_source> will be false.
671 The verbose setting defaults to what you have specified in your
674 Returns true on success and false on failure.
681 my $conf = $self->configure_object;
684 update_source => { default => 0, allow => [qr/^\d$/] },
685 verbose => { default => $conf->get_conf('verbose') },
688 my $args = check( $tmpl, \%hash ) or return;
690 ### make a call to the internal _module_tree, so it triggers cache
692 my $uptodate = $self->_check_trees( %$args );
695 return 1 if $self->_build_trees(
696 uptodate => $uptodate,
698 verbose => $conf->get_conf('verbose'),
701 error( loc( "Error rebuilding source trees!" ) );
708 =head2 $bool = $cb->flush(CACHE_NAME)
710 This method allows flushing of caches.
711 There are several things which can be flushed:
717 The return status of methods which have been attempted, such as
718 different ways of fetching files. It is recommended that automatic
719 flushing be used instead.
723 The return status of URIs which have been attempted, such as
724 different hosts of fetching files. It is recommended that automatic
725 flushing be used instead.
729 Information about modules such as prerequisites and whether
730 installation succeeded, failed, or was not attempted.
734 This resets PERL5LIB, which is changed to ensure that while installing
735 modules they are in our @INC.
739 This resets the cache of modules we've attempted to load, but failed.
740 This enables you to load them again after a failed load, if they
741 somehow have become available.
745 Flush all of the aforementioned caches.
749 Returns true on success and false on failure.
755 my $type = shift or return;
758 methods => [ qw( methods load ) ],
759 hosts => [ qw( hosts ) ],
760 modules => [ qw( modules lib) ],
761 lib => [ qw( lib ) ],
762 load => [ qw( load ) ],
763 all => [ qw( hosts lib modules methods load ) ],
766 my $aref = $cache->{$type}
768 error( loc("No such cache '%1'", $type) ),
772 return $self->_flush( list => $aref );
777 =head2 @mods = $cb->installed()
779 Returns a list of module objects of all your installed modules.
780 If an error occurs, it will return false.
782 See L<CPANPLUS::Module> for the operations you can perform on a
789 my $aref = $self->_all_installed;
791 return @$aref if $aref;
797 =head2 $bool = $cb->local_mirror([path => '/dir/to/save/to', index_files => BOOL, force => BOOL, verbose => BOOL] )
799 Creates a local mirror of CPAN, of only the most recent sources in a
800 location you specify. If you set this location equal to a custom host
801 in your C<CPANPLUS::Config> you can use your local mirror to install
804 It takes the following arguments:
810 The location where to create the local mirror.
814 Enable/disable fetching of index files. You can disable fetching of the
815 index files if you don't plan to use the local mirror as your primary
816 site, or if you'd like up-to-date index files be fetched from elsewhere.
822 Forces refetching of packages, even if they are there already.
824 Defaults to whatever setting you have in your C<CPANPLUS::Config>.
828 Prints more messages about what its doing.
830 Defaults to whatever setting you have in your C<CPANPLUS::Config>.
834 Returns true on success and false on error.
840 my $conf = $self->configure_object;
843 my($path, $index, $force, $verbose);
845 path => { default => $conf->get_conf('base'),
847 index_files => { default => 1, store => \$index },
848 force => { default => $conf->get_conf('force'),
850 verbose => { default => $conf->get_conf('verbose'),
851 store => \$verbose },
854 check( $tmpl, \%hash ) or return;
857 $self->_mkdir( dir => $path )
858 or( error( loc( "Could not create '%1', giving up", $path ) ),
862 error( loc( "Could not write to '%1', giving up", $path ) );
868 for my $auth ( sort { $a->cpanid cmp $b->cpanid }
869 values %{$self->author_tree}
874 for my $mod ( $auth->modules ) {
875 my $fetchdir = File::Spec->catdir( $path, $mod->path );
880 fetchdir => $fetchdir,
883 ### only do this the for the first module ###
885 $mod->_get_checksums_file(
888 error( loc( "Could not fetch %1 file, " .
889 "skipping author '%2'",
890 CHECKSUMS, $auth->cpanid ) ),
896 or( error( loc( "Could not fetch '%1'", $mod->module ) ),
903 for my $name (qw[auth dslip mod]) {
904 $self->_update_source(
908 ) or ( $flag++, next );
917 =head2 $file = $cb->autobundle([path => OUTPUT_PATH, force => BOOL, verbose => BOOL])
919 Writes out a snapshot of your current installation in C<CPAN> bundle
920 style. This can then be used to install the same modules for a
921 different or on a different machine.
923 It will, by default, write to an 'autobundle' directory under your
924 cpanplus homedirectory, but you can override that by supplying a
927 It will return the location of the output file on success and false on
934 my $conf = $self->configure_object;
937 my($path,$force,$verbose);
939 force => { default => $conf->get_conf('force'), store => \$force },
940 verbose => { default => $conf->get_conf('verbose'), store => \$verbose },
941 path => { default => File::Spec->catdir(
942 $conf->get_conf('base'),
943 $self->_perl_version( perl => $^X ),
944 $conf->_get_build('distdir'),
945 $conf->_get_build('autobundle') ),
949 check($tmpl, \%hash) or return;
952 $self->_mkdir( dir => $path )
953 or( error(loc("Could not create directory '%1'", $path ) ),
959 { ### default filename for the bundle ###
960 my($year,$month,$day) = (localtime)[5,4,3];
961 $year += 1900; $month++;
965 my $prefix = $conf->_get_build('autobundle_prefix');
966 my $format = "${prefix}_%04d_%02d_%02d_%02d";
969 $name = sprintf( $format, $year, $month, $day, $ext);
971 $file = File::Spec->catfile( $path, $name . '.pm' );
973 -f $file ? ++$ext && redo BLOCK : last BLOCK;
977 unless( $fh = FileHandle->new( ">$file" ) ) {
978 error( loc( "Could not open '%1' for writing: %2", $file, $! ) );
982 ### make sure we load the module tree *before* doing this, as it
983 ### starts to chdir all over the place
986 my $string = join "\n\n",
990 ($_->installed_version(verbose => 0) || 'undef')
992 $a->module cmp $b->module
995 my $now = scalar localtime;
997 my $pkg = __PACKAGE__;
998 my $version = $self->VERSION;
999 my $perl_v = join '', `$^X -V`;
1012 $name - Snapshot of your installation at $now
1016 perl -MCPANPLUS -e "install $name"
1028 This bundle has been generated autotomatically by
1038 ### XXX these wrappers are not individually tested! only the underlying
1039 ### code through source.t and indirectly trought he CustomSource plugin.
1042 =head1 CUSTOM MODULE SOURCES
1044 Besides the sources as provided by the general C<CPAN> mirrors, it's
1045 possible to add your own sources list to your C<CPANPLUS> index.
1047 The methodology behind this works much like C<Debian's apt-sources>.
1049 The methods below show you how to make use of this functionality. Also
1050 note that most of these methods are available through the default shell
1051 plugin command C</cs>, making them available as shortcuts through the
1052 shell and via the commandline.
1054 =head2 %files = $cb->list_custom_sources
1056 Returns a mapping of registered custom sources and their local indices
1059 /full/path/to/local/index => http://remote/source
1061 Note that any file starting with an C<#> is being ignored.
1065 sub list_custom_sources {
1066 return shift->__list_custom_module_sources( @_ );
1069 =head2 $local_index = $cb->add_custom_source( uri => URI, [verbose => BOOL] );
1071 Adds an C<URI> to your own sources list and mirrors its index. See the
1072 documentation on C<< $cb->update_custom_source >> on how this is done.
1074 Returns the full path to the local index on success, or false on failure.
1076 Note that when adding a new C<URI>, the change to the in-memory tree is
1077 not saved until you rebuild or save the tree to disk again. You can do
1078 this using the C<< $cb->reload_indices >> method.
1082 sub add_custom_source {
1083 return shift->_add_custom_module_source( @_ );
1086 =head2 $local_index = $cb->remove_custom_source( uri => URI, [verbose => BOOL] );
1088 Removes an C<URI> from your own sources list and removes its index.
1090 To find out what C<URI>s you have as part of your own sources list, use
1091 the C<< $cb->list_custom_sources >> method.
1093 Returns the full path to the deleted local index file on success, or false
1098 ### XXX do clever dispatching based on arg number?
1099 sub remove_custom_source {
1100 return shift->_remove_custom_module_source( @_ );
1103 =head2 $bool = $cb->update_custom_source( [remote => URI] );
1105 Updates the indexes for all your custom sources. It does this by fetching
1106 a file called C<packages.txt> in the root of the custom sources's C<URI>.
1107 If you provide the C<remote> argument, it will only update the index for
1108 that specific C<URI>.
1110 Here's an example of how custom sources would resolve into index files:
1112 file:///path/to/sources => file:///path/to/sources/packages.txt
1113 http://example.com/sources => http://example.com/sources/packages.txt
1114 ftp://example.com/sources => ftp://example.com/sources/packages.txt
1116 The file C<packages.txt> simply holds a list of packages that can be found
1117 under the root of the C<URI>. This file can be automatically generated for
1118 you when the remote source is a C<file:// URI>. For C<http://>, C<ftp://>,
1119 and similar, the administrator of that repository should run the method
1120 C<< $cb->write_custom_source_index >> on the repository to allow remote
1123 For details, see the C<< $cb->write_custom_source_index >> method below.
1125 All packages that are added via this mechanism will be attributed to the
1126 author with C<CPANID> C<LOCAL>. You can use this id to search for all
1131 sub update_custom_source {
1134 ### if it mentions /remote/, the request is to update a single uri,
1135 ### not all the ones we have, so dispatch appropriately
1136 my $rv = grep( /remote/i, @_)
1137 ? $self->__update_custom_module_source( @_ )
1138 : $self->__update_custom_module_sources( @_ );
1143 =head2 $file = $cb->write_custom_source_index( path => /path/to/package/root, [to => /path/to/index/file, verbose => BOOL] );
1145 Writes the index for a custom repository root. Most users will not have to
1146 worry about this, but administrators of a repository will need to make sure
1147 their indexes are up to date.
1149 The index will be written to a file called C<packages.txt> in your repository
1150 root, which you can specify with the C<path> argument. You can override this
1151 location by specifying the C<to> argument, but in normal operation, that should
1154 Once the index file is written, users can then add the C<URI> pointing to
1155 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.
1159 sub write_custom_source_index {
1160 return shift->__write_custom_module_index( @_ );
1169 Please report bugs or other issues to E<lt>bug-cpanplus@rt.cpan.org<gt>.
1173 This module by Jos Boumans E<lt>kane@cpan.orgE<gt>.
1177 The CPAN++ interface (of which this module is a part of) is copyright (c)
1178 2001 - 2007, Jos Boumans E<lt>kane@cpan.orgE<gt>. All rights reserved.
1180 This library is free software; you may redistribute and/or modify it
1181 under the same terms as Perl itself.
1185 L<CPANPLUS::Configure>, L<CPANPLUS::Module>, L<CPANPLUS::Module::Author>,
1186 L<CPANPLUS::Selfupdate>
1191 # c-indentation-style: bsd
1193 # indent-tabs-mode: nil
1195 # vim: expandtab shiftwidth=4:
1200 sub dist { # not sure about this one -- probably already done
1202 sub reports { # in Module.pm, wrapper here