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;
372 local $Params::Check::NO_DUPLICATES = 1;
373 local $Params::Check::ALLOW_UNKNOWN = 1;
377 modules => { default => [], strict_type => 1,
378 required => 1, store => \$mods },
381 my $args = check( $tmpl, \%hash ) or return;
383 ### make them all into module objects ###
384 my %mods = map {$_ => $self->parse_module(module => $_) || ''} @$mods;
387 while( my($name,$obj) = each %mods ) {
388 $href->{$name} = IS_MODOBJ->( mod => $obj )
389 ? $obj->$func( %$args )
392 $flag++ unless $href->{$name};
395 return CPANPLUS::Backend::RV->new(
406 =head2 $mod_obj = $cb->parse_module( module => $modname|$distname|$modobj|URI )
408 C<parse_module> tries to find a C<CPANPLUS::Module> object that
409 matches your query. Here's a list of examples you could give to
414 =item Text::Bastardize
416 =item Text-Bastardize
418 =item Text-Bastardize-1.06
420 =item AYRNIEU/Text-Bastardize
422 =item AYRNIEU/Text-Bastardize-1.06
424 =item AYRNIEU/Text-Bastardize-1.06.tar.gz
426 =item http://example.com/Text-Bastardize-1.06.tar.gz
428 =item file:///tmp/Text-Bastardize-1.06.tar.gz
432 These items would all come up with a C<CPANPLUS::Module> object for
433 C<Text::Bastardize>. The ones marked explicitly as being version 1.06
434 would give back a C<CPANPLUS::Module> object of that version.
435 Even if the version on CPAN is currently higher.
437 If C<parse_module> is unable to actually find the module you are looking
438 for in its module tree, but you supplied it with an author, module
439 and version part in a distribution name or URI, it will create a fake
440 C<CPANPLUS::Module> object for you, that you can use just like the
443 See L<CPANPLUS::Module> for the operations you can perform on a
446 If even this fancy guessing doesn't enable C<parse_module> to create
447 a fake module object for you to use, it will warn about an error and
454 my $conf = $self->configure_object;
459 module => { required => 1, store => \$mod },
462 my $args = check( $tmpl, \%hash ) or return;
464 return $mod if IS_MODOBJ->( module => $mod );
466 ### ok, so it's not a module object, but a ref nonetheless?
467 ### what are you smoking?
469 error(loc("Can not parse module string from reference '%1'", $mod ));
473 ### check only for allowed characters in a module name
474 unless( $mod =~ /[^\w:]/ ) {
476 ### perhaps we can find it in the module tree?
477 my $maybe = $self->module_tree($mod);
478 return $maybe if IS_MODOBJ->( module => $maybe );
481 ### ok, so it looks like a distribution then?
482 my @parts = split '/', $mod;
483 my $dist = pop @parts;
486 if( $mod =~ m|\w+://.+| ) {
487 my $modobj = CPANPLUS::Module::Fake->new(
491 path => File::Spec::Unix->catdir(
492 $conf->_get_mirror('base'),
493 UNKNOWN_DL_LOCATION ),
494 author => CPANPLUS::Module::Author::Fake->new
497 ### set the fetch_from accessor so we know to by pass the
499 $modobj->status->_fetch_from( $mod );
501 ### better guess for the version
502 $modobj->version( $modobj->package_version )
503 if defined $modobj->package_version;
505 ### better guess at module name, if possible
506 if ( my $pkgname = $modobj->package_name ) {
507 $pkgname =~ s/-/::/g;
509 ### no sense replacing it unless we changed something
510 $modobj->module( $pkgname )
511 if ($pkgname ne $modobj->package_name) || $pkgname !~ /-/;
517 ### perhaps we can find it's a third party module?
518 { my $modobj = CPANPLUS::Module::Fake->new(
522 path => File::Spec::Unix->catdir(
523 $conf->_get_mirror('base'),
524 UNKNOWN_DL_LOCATION ),
525 author => CPANPLUS::Module::Author::Fake->new
527 if( $modobj->is_third_party ) {
528 my $info = $modobj->third_party_information;
530 $modobj->author->author( $info->{author} );
531 $modobj->author->email( $info->{author_url} );
532 $modobj->description( $info->{url} );
539 error( loc("%1 is not a proper distribution name!", $mod) );
543 ### there's wonky uris out there, like this:
544 ### E/EY/EYCK/Net/Lite/Net-Lite-FTP-0.091
545 ### compensate for that
547 ### you probably have an A/AB/ABC/....../Dist.tgz type uri
548 if( (defined $parts[0] and length $parts[0] == 1) and
549 (defined $parts[1] and length $parts[1] == 2) and
550 $parts[2] =~ /^$parts[0]/i and $parts[2] =~ /^$parts[1]/i
552 splice @parts, 0, 2; # remove the first 2 entries from the list
553 $author = shift @parts; # this is the actual author name then
555 ### we''ll assume a ABC/..../Dist.tgz
557 $author = shift @parts || '';
560 my($pkg, $version, $ext) =
561 $self->_split_package_string( package => $dist );
563 ### translate a distribution into a module name ###
565 $guess =~ s/-/::/g if $guess;
567 my $maybe = $self->module_tree( $guess );
568 if( IS_MODOBJ->( module => $maybe ) ) {
570 ### maybe you asked for a package instead
571 if ( $maybe->package eq $mod ) {
574 ### perhaps an outdated version instead?
575 } elsif ( $version ) {
576 my $auth_obj; my $path;
578 ### did you give us an author part? ###
580 $auth_obj = CPANPLUS::Module::Author::Fake->new(
582 cpanid => uc $author,
583 author => uc $author,
585 $path = File::Spec::Unix->catdir(
586 $conf->_get_mirror('base'),
587 substr(uc $author, 0, 1),
588 substr(uc $author, 0, 2),
590 @parts, #possible sub dirs
593 $auth_obj = $maybe->author;
594 $path = $maybe->path;
597 if( $maybe->package_name eq $pkg ) {
599 my $modobj = CPANPLUS::Module::Fake->new(
600 module => $maybe->module,
602 package => $pkg . '-' . $version . '.' .
603 $maybe->package_extension,
610 ### you asked for a specific version?
611 ### assume our $maybe is the one you wanted,
612 ### and fix up the version..
615 my $modobj = $maybe->clone;
616 $modobj->version( $version );
618 $maybe->package_name .'-'.
620 $maybe->package_extension
623 ### you wanted a specific author, but it's not the one
624 ### from the module tree? we'll fix it up
625 if( $author and $author ne $modobj->author->cpanid ) {
626 $modobj->author( $auth_obj );
627 $modobj->path( $path );
633 ### you didn't care about a version, so just return the object then
634 } elsif ( !$version ) {
638 ### ok, so we can't find it, and it's not an outdated dist either
639 ### perhaps we can fake one based on the author name and so on
640 } elsif ( $author and $version ) {
642 ### be extra friendly and pad the .tar.gz suffix where needed
643 ### it's just a guess of course, but most dists are .tar.gz
644 $dist .= '.tar.gz' unless $dist =~ /\.[A-Za-z]+$/;
646 ### XXX duplication from above for generating author obj + path...
647 my $modobj = CPANPLUS::Module::Fake->new(
651 author => CPANPLUS::Module::Author::Fake->new(
652 author => uc $author,
653 cpanid => uc $author,
656 path => File::Spec::Unix->catdir(
657 $conf->_get_mirror('base'),
658 substr(uc $author, 0, 1),
659 substr(uc $author, 0, 2),
661 @parts, #possible subdirs
668 ### face it, we have /no/ idea what he or she wants...
669 ### let's start putting the blame somewhere
673 error( loc( "'%1' does not contain an author part", $mod ) );
676 error( loc( "Cannot find '%1' in the module tree", $mod ) );
684 =head2 $bool = $cb->reload_indices( [update_source => BOOL, verbose => BOOL] );
686 This method reloads the source files.
688 If C<update_source> is set to true, this will fetch new source files
689 from your CPAN mirror. Otherwise, C<reload_indices> will do its
690 usual cache checking and only update them if they are out of date.
692 By default, C<update_source> will be false.
694 The verbose setting defaults to what you have specified in your
697 Returns true on success and false on failure.
704 my $conf = $self->configure_object;
707 update_source => { default => 0, allow => [qr/^\d$/] },
708 verbose => { default => $conf->get_conf('verbose') },
711 my $args = check( $tmpl, \%hash ) or return;
713 ### make a call to the internal _module_tree, so it triggers cache
715 my $uptodate = $self->_check_trees( %$args );
718 return 1 if $self->_build_trees(
719 uptodate => $uptodate,
721 verbose => $conf->get_conf('verbose'),
724 error( loc( "Error rebuilding source trees!" ) );
731 =head2 $bool = $cb->flush(CACHE_NAME)
733 This method allows flushing of caches.
734 There are several things which can be flushed:
740 The return status of methods which have been attempted, such as
741 different ways of fetching files. It is recommended that automatic
742 flushing be used instead.
746 The return status of URIs which have been attempted, such as
747 different hosts of fetching files. It is recommended that automatic
748 flushing be used instead.
752 Information about modules such as prerequisites and whether
753 installation succeeded, failed, or was not attempted.
757 This resets PERL5LIB, which is changed to ensure that while installing
758 modules they are in our @INC.
762 This resets the cache of modules we've attempted to load, but failed.
763 This enables you to load them again after a failed load, if they
764 somehow have become available.
768 Flush all of the aforementioned caches.
772 Returns true on success and false on failure.
778 my $type = shift or return;
781 methods => [ qw( methods load ) ],
782 hosts => [ qw( hosts ) ],
783 modules => [ qw( modules lib) ],
784 lib => [ qw( lib ) ],
785 load => [ qw( load ) ],
786 all => [ qw( hosts lib modules methods load ) ],
789 my $aref = $cache->{$type}
791 error( loc("No such cache '%1'", $type) ),
795 return $self->_flush( list => $aref );
800 =head2 @mods = $cb->installed()
802 Returns a list of module objects of all your installed modules.
803 If an error occurs, it will return false.
805 See L<CPANPLUS::Module> for the operations you can perform on a
812 my $aref = $self->_all_installed;
814 return @$aref if $aref;
820 =head2 $bool = $cb->local_mirror([path => '/dir/to/save/to', index_files => BOOL, force => BOOL, verbose => BOOL] )
822 Creates a local mirror of CPAN, of only the most recent sources in a
823 location you specify. If you set this location equal to a custom host
824 in your C<CPANPLUS::Config> you can use your local mirror to install
827 It takes the following arguments:
833 The location where to create the local mirror.
837 Enable/disable fetching of index files. You can disable fetching of the
838 index files if you don't plan to use the local mirror as your primary
839 site, or if you'd like up-to-date index files be fetched from elsewhere.
845 Forces refetching of packages, even if they are there already.
847 Defaults to whatever setting you have in your C<CPANPLUS::Config>.
851 Prints more messages about what its doing.
853 Defaults to whatever setting you have in your C<CPANPLUS::Config>.
857 Returns true on success and false on error.
863 my $conf = $self->configure_object;
866 my($path, $index, $force, $verbose);
868 path => { default => $conf->get_conf('base'),
870 index_files => { default => 1, store => \$index },
871 force => { default => $conf->get_conf('force'),
873 verbose => { default => $conf->get_conf('verbose'),
874 store => \$verbose },
877 check( $tmpl, \%hash ) or return;
880 $self->_mkdir( dir => $path )
881 or( error( loc( "Could not create '%1', giving up", $path ) ),
885 error( loc( "Could not write to '%1', giving up", $path ) );
891 for my $auth ( sort { $a->cpanid cmp $b->cpanid }
892 values %{$self->author_tree}
897 for my $mod ( $auth->modules ) {
898 my $fetchdir = File::Spec->catdir( $path, $mod->path );
903 fetchdir => $fetchdir,
906 ### only do this the for the first module ###
908 $mod->_get_checksums_file(
911 error( loc( "Could not fetch %1 file, " .
912 "skipping author '%2'",
913 CHECKSUMS, $auth->cpanid ) ),
919 or( error( loc( "Could not fetch '%1'", $mod->module ) ),
926 for my $name (qw[auth dslip mod]) {
927 $self->_update_source(
931 ) or ( $flag++, next );
940 =head2 $file = $cb->autobundle([path => OUTPUT_PATH, force => BOOL, verbose => BOOL])
942 Writes out a snapshot of your current installation in C<CPAN> bundle
943 style. This can then be used to install the same modules for a
944 different or on a different machine.
946 It will, by default, write to an 'autobundle' directory under your
947 cpanplus homedirectory, but you can override that by supplying a
950 It will return the location of the output file on success and false on
957 my $conf = $self->configure_object;
960 my($path,$force,$verbose);
962 force => { default => $conf->get_conf('force'), store => \$force },
963 verbose => { default => $conf->get_conf('verbose'), store => \$verbose },
964 path => { default => File::Spec->catdir(
965 $conf->get_conf('base'),
966 $self->_perl_version( perl => $^X ),
967 $conf->_get_build('distdir'),
968 $conf->_get_build('autobundle') ),
972 check($tmpl, \%hash) or return;
975 $self->_mkdir( dir => $path )
976 or( error(loc("Could not create directory '%1'", $path ) ),
982 { ### default filename for the bundle ###
983 my($year,$month,$day) = (localtime)[5,4,3];
984 $year += 1900; $month++;
988 my $prefix = $conf->_get_build('autobundle_prefix');
989 my $format = "${prefix}_%04d_%02d_%02d_%02d";
992 $name = sprintf( $format, $year, $month, $day, $ext);
994 $file = File::Spec->catfile( $path, $name . '.pm' );
996 -f $file ? ++$ext && redo BLOCK : last BLOCK;
1000 unless( $fh = FileHandle->new( ">$file" ) ) {
1001 error( loc( "Could not open '%1' for writing: %2", $file, $! ) );
1005 ### make sure we load the module tree *before* doing this, as it
1006 ### starts to chdir all over the place
1009 my $string = join "\n\n",
1013 ($_->installed_version(verbose => 0) || 'undef')
1015 $a->module cmp $b->module
1018 my $now = scalar localtime;
1019 my $head = '=head1';
1020 my $pkg = __PACKAGE__;
1021 my $version = $self->VERSION;
1022 my $perl_v = join '', `$^X -V`;
1035 $name - Snapshot of your installation at $now
1039 perl -MCPANPLUS -e "install $name"
1051 This bundle has been generated autotomatically by
1061 ### XXX these wrappers are not individually tested! only the underlying
1062 ### code through source.t and indirectly trought he CustomSource plugin.
1065 =head1 CUSTOM MODULE SOURCES
1067 Besides the sources as provided by the general C<CPAN> mirrors, it's
1068 possible to add your own sources list to your C<CPANPLUS> index.
1070 The methodology behind this works much like C<Debian's apt-sources>.
1072 The methods below show you how to make use of this functionality. Also
1073 note that most of these methods are available through the default shell
1074 plugin command C</cs>, making them available as shortcuts through the
1075 shell and via the commandline.
1077 =head2 %files = $cb->list_custom_sources
1079 Returns a mapping of registered custom sources and their local indices
1082 /full/path/to/local/index => http://remote/source
1084 Note that any file starting with an C<#> is being ignored.
1088 sub list_custom_sources {
1089 return shift->__list_custom_module_sources( @_ );
1092 =head2 $local_index = $cb->add_custom_source( uri => URI, [verbose => BOOL] );
1094 Adds an C<URI> to your own sources list and mirrors its index. See the
1095 documentation on C<< $cb->update_custom_source >> on how this is done.
1097 Returns the full path to the local index on success, or false on failure.
1099 Note that when adding a new C<URI>, the change to the in-memory tree is
1100 not saved until you rebuild or save the tree to disk again. You can do
1101 this using the C<< $cb->reload_indices >> method.
1105 sub add_custom_source {
1106 return shift->_add_custom_module_source( @_ );
1109 =head2 $local_index = $cb->remove_custom_source( uri => URI, [verbose => BOOL] );
1111 Removes an C<URI> from your own sources list and removes its index.
1113 To find out what C<URI>s you have as part of your own sources list, use
1114 the C<< $cb->list_custom_sources >> method.
1116 Returns the full path to the deleted local index file on success, or false
1121 ### XXX do clever dispatching based on arg number?
1122 sub remove_custom_source {
1123 return shift->_remove_custom_module_source( @_ );
1126 =head2 $bool = $cb->update_custom_source( [remote => URI] );
1128 Updates the indexes for all your custom sources. It does this by fetching
1129 a file called C<packages.txt> in the root of the custom sources's C<URI>.
1130 If you provide the C<remote> argument, it will only update the index for
1131 that specific C<URI>.
1133 Here's an example of how custom sources would resolve into index files:
1135 file:///path/to/sources => file:///path/to/sources/packages.txt
1136 http://example.com/sources => http://example.com/sources/packages.txt
1137 ftp://example.com/sources => ftp://example.com/sources/packages.txt
1139 The file C<packages.txt> simply holds a list of packages that can be found
1140 under the root of the C<URI>. This file can be automatically generated for
1141 you when the remote source is a C<file:// URI>. For C<http://>, C<ftp://>,
1142 and similar, the administrator of that repository should run the method
1143 C<< $cb->write_custom_source_index >> on the repository to allow remote
1146 For details, see the C<< $cb->write_custom_source_index >> method below.
1148 All packages that are added via this mechanism will be attributed to the
1149 author with C<CPANID> C<LOCAL>. You can use this id to search for all
1154 sub update_custom_source {
1157 ### if it mentions /remote/, the request is to update a single uri,
1158 ### not all the ones we have, so dispatch appropriately
1159 my $rv = grep( /remote/i, @_)
1160 ? $self->__update_custom_module_source( @_ )
1161 : $self->__update_custom_module_sources( @_ );
1166 =head2 $file = $cb->write_custom_source_index( path => /path/to/package/root, [to => /path/to/index/file, verbose => BOOL] );
1168 Writes the index for a custom repository root. Most users will not have to
1169 worry about this, but administrators of a repository will need to make sure
1170 their indexes are up to date.
1172 The index will be written to a file called C<packages.txt> in your repository
1173 root, which you can specify with the C<path> argument. You can override this
1174 location by specifying the C<to> argument, but in normal operation, that should
1177 Once the index file is written, users can then add the C<URI> pointing to
1178 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.
1182 sub write_custom_source_index {
1183 return shift->__write_custom_module_index( @_ );
1192 Please report bugs or other issues to E<lt>bug-cpanplus@rt.cpan.org<gt>.
1196 This module by Jos Boumans E<lt>kane@cpan.orgE<gt>.
1200 The CPAN++ interface (of which this module is a part of) is copyright (c)
1201 2001 - 2007, Jos Boumans E<lt>kane@cpan.orgE<gt>. All rights reserved.
1203 This library is free software; you may redistribute and/or modify it
1204 under the same terms as Perl itself.
1208 L<CPANPLUS::Configure>, L<CPANPLUS::Module>, L<CPANPLUS::Module::Author>,
1209 L<CPANPLUS::Selfupdate>
1214 # c-indentation-style: bsd
1216 # indent-tabs-mode: nil
1218 # vim: expandtab shiftwidth=4:
1223 sub dist { # not sure about this one -- probably already done
1225 sub reports { # in Module.pm, wrapper here