[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/se3-unattended/var/se3/unattended/install/linuxaux/opt/perl/lib/5.10.0/CPANPLUS/ -> Backend.pm (source)

   1  package CPANPLUS::Backend;
   2  
   3  use strict;
   4  
   5  
   6  use CPANPLUS::Error;
   7  use CPANPLUS::Configure;
   8  use CPANPLUS::Internals;
   9  use CPANPLUS::Internals::Constants;
  10  use CPANPLUS::Module;
  11  use CPANPLUS::Module::Author;
  12  use CPANPLUS::Backend::RV;
  13  
  14  use FileHandle;
  15  use File::Spec                  ();
  16  use File::Spec::Unix            ();
  17  use Params::Check               qw[check];
  18  use Locale::Maketext::Simple    Class => 'CPANPLUS', Style => 'gettext';
  19  
  20  $Params::Check::VERBOSE = 1;
  21  
  22  use vars qw[@ISA $VERSION];
  23  
  24  @ISA     = qw[CPANPLUS::Internals];
  25  $VERSION = $CPANPLUS::Internals::VERSION;
  26  
  27  ### mark that we're running under CPANPLUS to spawned processes
  28  $ENV{'PERL5_CPANPLUS_IS_RUNNING'} = $$;
  29  
  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;
  33  
  34  =pod
  35  
  36  =head1 NAME
  37  
  38  CPANPLUS::Backend
  39  
  40  =head1 SYNOPSIS
  41  
  42      my $cb      = CPANPLUS::Backend->new;
  43      my $conf    = $cb->configure_object;
  44  
  45      my $author  = $cb->author_tree('KANE');
  46      my $mod     = $cb->module_tree('Some::Module');
  47      my $mod     = $cb->parse_module( module => 'Some::Module' );
  48  
  49      my @objs    = $cb->search(  type    => TYPE,
  50                                  allow   => [...] );
  51  
  52      $cb->flush('all');
  53      $cb->reload_indices;
  54      $cb->local_mirror;
  55  
  56  
  57  =head1 DESCRIPTION
  58  
  59  This module provides the programmer's interface to the C<CPANPLUS>
  60  libraries.
  61  
  62  =head1 ENVIRONMENT
  63  
  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.
  67  
  68  Additionally, the environment variable C<PERL5_CPANPLUS_IS_VERSION> 
  69  will be set to the version of C<CPANPLUS::Backend>.
  70  
  71  This information might be useful somehow to spawned processes.
  72  
  73  =head1 METHODS
  74  
  75  =head2 $cb = CPANPLUS::Backend->new( [CONFIGURE_OBJ] )
  76  
  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:
  80  
  81  =over 4
  82  
  83  =item Provide a valid C<CPANPLUS::Configure> object
  84  
  85  This will be used verbatim.
  86  
  87  =item No arguments
  88  
  89  Your default config will be loaded and used.
  90  
  91  =back
  92  
  93  New will return a C<CPANPLUS::Backend> object on success and die on
  94  failure.
  95  
  96  =cut
  97  
  98  sub new {
  99      my $class   = shift;
 100      my $conf;
 101  
 102      if( $_[0] && IS_CONFOBJ->( conf => $_[0] ) ) {
 103          $conf = shift;
 104      } else {
 105          $conf = CPANPLUS::Configure->new() or return;
 106      }
 107  
 108      my $self = $class->SUPER::_init( _conf => $conf );
 109  
 110      return $self;
 111  }
 112  
 113  =pod
 114  
 115  =head2 $href = $cb->module_tree( [@modules_names_list] )
 116  
 117  Returns a reference to the CPANPLUS module tree.
 118  
 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.
 122  
 123  See L<CPANPLUS::Module> for the operations you can perform on a
 124  module object.
 125  
 126  =cut
 127  
 128  sub module_tree {
 129      my $self    = shift;
 130      my $modtree = $self->_module_tree;
 131  
 132      if( @_ ) {
 133          my @rv;
 134          for my $name ( grep { defined } @_) {
 135  
 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 
 141              ### %$modtree hash.
 142              ### 
 143              ### As a fix, we do a search on VMS instead --
 144              ### more cpu cycles, but it gets around the case
 145              ### problem --kane
 146              my ($modobj) = do {
 147                  ON_VMS
 148                      ? $self->search(
 149                            type    => 'module',
 150                            allow   => [qr/^$name$/i],
 151                        )
 152                      : $modtree->{$name}
 153              };
 154              
 155              push @rv, $modobj || '';
 156          }
 157          return @rv == 1 ? $rv[0] : @rv;
 158      } else {
 159          return $modtree;
 160      }
 161  }
 162  
 163  =pod
 164  
 165  =head2 $href = $cb->author_tree( [@author_names_list] )
 166  
 167  Returns a reference to the CPANPLUS author tree.
 168  
 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.
 172  
 173  See L<CPANPLUS::Module::Author> for the operations you can perform on
 174  an author object.
 175  
 176  =cut
 177  
 178  sub author_tree {
 179      my $self        = shift;
 180      my $authtree    = $self->_author_tree;
 181  
 182      if( @_ ) {
 183          my @rv;
 184          for my $name (@_) {
 185              push @rv, $authtree->{$name} || '';
 186          }
 187          return @rv == 1 ? $rv[0] : @rv;
 188      } else {
 189          return $authtree;
 190      }
 191  }
 192  
 193  =pod
 194  
 195  =head2 $conf = $cb->configure_object;
 196  
 197  Returns a copy of the C<CPANPLUS::Configure> object.
 198  
 199  See L<CPANPLUS::Configure> for operations you can perform on a
 200  configure object.
 201  
 202  =cut
 203  
 204  sub configure_object { return shift->_conf() };
 205  
 206  =head2 $su = $cb->selfupdate_object;
 207  
 208  Returns a copy of the C<CPANPLUS::Selfupdate> object.
 209  
 210  See the L<CPANPLUS::Selfupdate> manpage for the operations
 211  you can perform on the selfupdate object.
 212  
 213  =cut
 214  
 215  sub selfupdate_object { return shift->_selfupdate() };
 216  
 217  =pod
 218  
 219  =head2 @mods = $cb->search( type => TYPE, allow => AREF, [data => AREF, verbose => BOOL] )
 220  
 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.
 226  
 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.
 230  
 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.
 233  
 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.
 237  
 238  Returns a list of module or author objects on success and false
 239  on failure.
 240  
 241  See L<CPANPLUS::Module> for the operations you can perform on a
 242  module object.
 243  See L<CPANPLUS::Module::Author> for the operations you can perform on
 244  an author object.
 245  
 246  =cut
 247  
 248  sub search {
 249      my $self = shift;
 250      my $conf = $self->configure_object;
 251      my %hash = @_;
 252  
 253      my ($type);
 254      my $args = do {
 255          local $Params::Check::NO_DUPLICATES = 0;
 256          local $Params::Check::ALLOW_UNKNOWN = 1;
 257  
 258          my $tmpl = {
 259              type    => { required => 1, allow => [CPANPLUS::Module->accessors(),
 260                              CPANPLUS::Module::Author->accessors()], store => \$type },
 261              allow   => { required => 1, default => [ ], strict_type => 1 },
 262          };
 263  
 264          check( $tmpl, \%hash )
 265      } or return;
 266  
 267      ### figure out whether it was an author or a module search
 268      ### when ambiguous, it'll be an author search.
 269      my $aref;
 270      if( grep { $type eq $_ } CPANPLUS::Module::Author->accessors() ) {
 271          $aref = $self->_search_author_tree( %$args );
 272      } else {
 273          $aref = $self->_search_module_tree( %$args );
 274      }
 275  
 276      return @$aref if $aref;
 277      return;
 278  }
 279  
 280  =pod
 281  
 282  =head2 $backend_rv = $cb->fetch( modules => \@mods )
 283  
 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.
 287  
 288  See the equivalent method in C<CPANPLUS::Module> for details on
 289  other options you can pass.
 290  
 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.
 294  
 295  =head2 $backend_rv = $cb->extract( modules => \@mods )
 296  
 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.
 300  
 301  See the equivalent method in C<CPANPLUS::Module> for details on
 302  other options you can pass.
 303  
 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.
 307  
 308  =head2 $backend_rv = $cb->install( modules => \@mods )
 309  
 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.
 313  
 314  See the equivalent method in C<CPANPLUS::Module> for details on
 315  other options you can pass.
 316  
 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.
 320  
 321  =head2 $backend_rv = $cb->readme( modules => \@mods )
 322  
 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.
 326  
 327  See the equivalent method in C<CPANPLUS::Module> for details on
 328  other options you can pass.
 329  
 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.
 333  
 334  =head2 $backend_rv = $cb->files( modules => \@mods )
 335  
 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.
 339  
 340  See the equivalent method in C<CPANPLUS::Module> for details on
 341  other options you can pass.
 342  
 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.
 346  
 347  =head2 $backend_rv = $cb->distributions( modules => \@mods )
 348  
 349  Returns a list of module objects representing all releases for this
 350  module on success.
 351  C<@mods> can be a list of distribution names, module names or module
 352  objects, basically anything that L<parse_module> can understand.
 353  
 354  See the equivalent method in C<CPANPLUS::Module> for details on
 355  other options you can pass.
 356  
 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.
 360  
 361  =cut
 362  
 363  ### XXX add direcotry_tree, packlist etc? or maybe remove files? ###
 364  for my $func (qw[fetch extract install readme files distributions]) {
 365      no strict 'refs';
 366  
 367      *$func = sub {
 368          my $self = shift;
 369          my $conf = $self->configure_object;
 370          my %hash = @_;
 371  
 372          local $Params::Check::NO_DUPLICATES = 1;
 373          local $Params::Check::ALLOW_UNKNOWN = 1;
 374  
 375          my ($mods);
 376          my $tmpl = {
 377              modules     => { default  => [],    strict_type => 1,
 378                               required => 1,     store => \$mods },
 379          };
 380  
 381          my $args = check( $tmpl, \%hash ) or return;
 382  
 383          ### make them all into module objects ###
 384          my %mods = map {$_ => $self->parse_module(module => $_) || ''} @$mods;
 385  
 386          my $flag; my $href;
 387          while( my($name,$obj) = each %mods ) {
 388              $href->{$name} = IS_MODOBJ->( mod => $obj )
 389                                  ? $obj->$func( %$args )
 390                                  : undef;
 391  
 392              $flag++ unless $href->{$name};
 393          }
 394  
 395          return CPANPLUS::Backend::RV->new(
 396                      function    => $func,
 397                      ok          => !$flag,
 398                      rv          => $href,
 399                      args        => \%hash,
 400                  );
 401      }
 402  }
 403  
 404  =pod
 405  
 406  =head2 $mod_obj = $cb->parse_module( module => $modname|$distname|$modobj|URI )
 407  
 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
 410  C<parse_module>;
 411  
 412  =over 4
 413  
 414  =item Text::Bastardize
 415  
 416  =item Text-Bastardize
 417  
 418  =item Text-Bastardize-1.06
 419  
 420  =item AYRNIEU/Text-Bastardize
 421  
 422  =item AYRNIEU/Text-Bastardize-1.06
 423  
 424  =item AYRNIEU/Text-Bastardize-1.06.tar.gz
 425  
 426  =item http://example.com/Text-Bastardize-1.06.tar.gz
 427  
 428  =item file:///tmp/Text-Bastardize-1.06.tar.gz
 429  
 430  =back
 431  
 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.
 436  
 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
 441  real thing.
 442  
 443  See L<CPANPLUS::Module> for the operations you can perform on a
 444  module object.
 445  
 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
 448  return false.
 449  
 450  =cut
 451  
 452  sub parse_module {
 453      my $self = shift;
 454      my $conf = $self->configure_object;
 455      my %hash = @_;
 456  
 457      my $mod;
 458      my $tmpl = {
 459          module  => { required => 1, store => \$mod },
 460      };
 461  
 462      my $args = check( $tmpl, \%hash ) or return;
 463  
 464      return $mod if IS_MODOBJ->( module => $mod );
 465  
 466      ### ok, so it's not a module object, but a ref nonetheless?
 467      ### what are you smoking?
 468      if( ref $mod ) {
 469          error(loc("Can not parse module string from reference '%1'", $mod ));
 470          return;
 471      }
 472      
 473      ### check only for allowed characters in a module name
 474      unless( $mod =~ /[^\w:]/ ) {
 475  
 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 );
 479      }
 480  
 481      ### ok, so it looks like a distribution then?
 482      my @parts   = split '/', $mod;
 483      my $dist    = pop @parts;
 484  
 485      ### ah, it's a URL
 486      if( $mod =~ m|\w+://.+| ) {
 487          my $modobj = CPANPLUS::Module::Fake->new(
 488                          module  => $dist,
 489                          version => 0,
 490                          package => $dist,
 491                          path    => File::Spec::Unix->catdir(
 492                                          $conf->_get_mirror('base'),
 493                                          UNKNOWN_DL_LOCATION ),
 494                          author  => CPANPLUS::Module::Author::Fake->new
 495                      );
 496          
 497          ### set the fetch_from accessor so we know to by pass the
 498          ### usual mirrors
 499          $modobj->status->_fetch_from( $mod );
 500          
 501          ### better guess for the version
 502          $modobj->version( $modobj->package_version ) 
 503              if defined $modobj->package_version;
 504          
 505          ### better guess at module name, if possible
 506          if ( my $pkgname = $modobj->package_name ) {
 507              $pkgname =~ s/-/::/g;
 508          
 509              ### no sense replacing it unless we changed something
 510              $modobj->module( $pkgname ) 
 511                  if ($pkgname ne $modobj->package_name) || $pkgname !~ /-/;
 512          }                
 513          
 514          return $modobj;      
 515      }
 516      
 517      ### perhaps we can find it's a third party module?
 518      {   my $modobj = CPANPLUS::Module::Fake->new(
 519                          module  => $mod,
 520                          version => 0,
 521                          package => $dist,
 522                          path    => File::Spec::Unix->catdir(
 523                                          $conf->_get_mirror('base'),
 524                                          UNKNOWN_DL_LOCATION ),
 525                          author  => CPANPLUS::Module::Author::Fake->new
 526                      );
 527          if( $modobj->is_third_party ) {
 528              my $info = $modobj->third_party_information;
 529              
 530              $modobj->author->author( $info->{author}     );
 531              $modobj->author->email(  $info->{author_url} );
 532              $modobj->description(    $info->{url} );
 533  
 534              return $modobj;
 535          }
 536      }
 537  
 538      unless( $dist ) {
 539          error( loc("%1 is not a proper distribution name!", $mod) );
 540          return;
 541      }
 542      
 543      ### there's wonky uris out there, like this:
 544      ### E/EY/EYCK/Net/Lite/Net-Lite-FTP-0.091
 545      ### compensate for that
 546      my $author;
 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
 551      ) {   
 552          splice @parts, 0, 2;    # remove the first 2 entries from the list
 553          $author = shift @parts; # this is the actual author name then    
 554  
 555      ### we''ll assume a ABC/..../Dist.tgz
 556      } else {
 557          $author = shift @parts || '';
 558      }
 559      
 560      my($pkg, $version, $ext) = 
 561          $self->_split_package_string( package => $dist );
 562      
 563      ### translate a distribution into a module name ###
 564      my $guess = $pkg; 
 565      $guess =~ s/-/::/g if $guess; 
 566  
 567      my $maybe = $self->module_tree( $guess );
 568      if( IS_MODOBJ->( module => $maybe ) ) {
 569  
 570          ### maybe you asked for a package instead
 571          if ( $maybe->package eq $mod ) {
 572              return $maybe;
 573  
 574          ### perhaps an outdated version instead?
 575          } elsif ( $version ) {
 576              my $auth_obj; my $path;
 577  
 578              ### did you give us an author part? ###
 579              if( $author ) {
 580                  $auth_obj   = CPANPLUS::Module::Author::Fake->new(
 581                                      _id     => $maybe->_id,
 582                                      cpanid  => uc $author,
 583                                      author  => uc $author,
 584                                  );
 585                  $path       = File::Spec::Unix->catdir(
 586                                      $conf->_get_mirror('base'),
 587                                      substr(uc $author, 0, 1),
 588                                      substr(uc $author, 0, 2),
 589                                      uc $author,
 590                                      @parts,     #possible sub dirs
 591                                  );
 592              } else {
 593                  $auth_obj   = $maybe->author;
 594                  $path       = $maybe->path;
 595              }        
 596          
 597              if( $maybe->package_name eq $pkg ) {
 598      
 599                  my $modobj = CPANPLUS::Module::Fake->new(
 600                      module  => $maybe->module,
 601                      version => $version,
 602                      package => $pkg . '-' . $version . '.' .
 603                                      $maybe->package_extension,
 604                      path    => $path,
 605                      author  => $auth_obj,
 606                      _id     => $maybe->_id
 607                  );
 608                  return $modobj;
 609  
 610              ### you asked for a specific version?
 611              ### assume our $maybe is the one you wanted,
 612              ### and fix up the version.. 
 613              } else {
 614      
 615                  my $modobj = $maybe->clone;
 616                  $modobj->version( $version );
 617                  $modobj->package( 
 618                          $maybe->package_name .'-'. 
 619                          $version .'.'. 
 620                          $maybe->package_extension 
 621                  );
 622                  
 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 );
 628                  }
 629                  
 630                  return $modobj;
 631              }
 632          
 633          ### you didn't care about a version, so just return the object then
 634          } elsif ( !$version ) {
 635              return $maybe;
 636          }
 637  
 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 ) {
 641  
 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]+$/;
 645  
 646          ### XXX duplication from above for generating author obj + path...
 647          my $modobj = CPANPLUS::Module::Fake->new(
 648              module  => $guess,
 649              version => $version,
 650              package => $dist,
 651              author  => CPANPLUS::Module::Author::Fake->new(
 652                              author  => uc $author,
 653                              cpanid  => uc $author,
 654                              _id     => $self->_id,
 655                          ),
 656              path    => File::Spec::Unix->catdir(
 657                              $conf->_get_mirror('base'),
 658                              substr(uc $author, 0, 1),
 659                              substr(uc $author, 0, 2),
 660                              uc $author,
 661                              @parts,         #possible subdirs
 662                          ),
 663              _id     => $self->_id,
 664          );
 665  
 666          return $modobj;
 667  
 668      ### face it, we have /no/ idea what he or she wants...
 669      ### let's start putting the blame somewhere
 670      } else {
 671  
 672          unless( $author ) {
 673              error( loc( "'%1' does not contain an author part", $mod ) );
 674          }
 675  
 676          error( loc( "Cannot find '%1' in the module tree", $mod ) );
 677      }
 678  
 679      return;
 680  }
 681  
 682  =pod
 683  
 684  =head2 $bool = $cb->reload_indices( [update_source => BOOL, verbose => BOOL] );
 685  
 686  This method reloads the source files.
 687  
 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.
 691  
 692  By default, C<update_source> will be false.
 693  
 694  The verbose setting defaults to what you have specified in your
 695  config file.
 696  
 697  Returns true on success and false on failure.
 698  
 699  =cut
 700  
 701  sub reload_indices {
 702      my $self    = shift;
 703      my %hash    = @_;
 704      my $conf    = $self->configure_object;
 705  
 706      my $tmpl = {
 707          update_source   => { default    => 0, allow => [qr/^\d$/] },
 708          verbose         => { default    => $conf->get_conf('verbose') },
 709      };
 710  
 711      my $args = check( $tmpl, \%hash ) or return;
 712  
 713      ### make a call to the internal _module_tree, so it triggers cache
 714      ### file age
 715      my $uptodate = $self->_check_trees( %$args );
 716  
 717  
 718      return 1 if $self->_build_trees(
 719                                  uptodate    => $uptodate,
 720                                  use_stored  => 0,
 721                                  verbose     => $conf->get_conf('verbose'),
 722                              );
 723  
 724      error( loc( "Error rebuilding source trees!" ) );
 725  
 726      return;
 727  }
 728  
 729  =pod
 730  
 731  =head2 $bool = $cb->flush(CACHE_NAME)
 732  
 733  This method allows flushing of caches.
 734  There are several things which can be flushed:
 735  
 736  =over 4
 737  
 738  =item * C<methods>
 739  
 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.
 743  
 744  =item * C<hosts>
 745  
 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.
 749  
 750  =item * C<modules>
 751  
 752  Information about modules such as prerequisites and whether
 753  installation succeeded, failed, or was not attempted.
 754  
 755  =item * C<lib>
 756  
 757  This resets PERL5LIB, which is changed to ensure that while installing
 758  modules they are in our @INC.
 759  
 760  =item * C<load>
 761  
 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.
 765  
 766  =item * C<all>
 767  
 768  Flush all of the aforementioned caches.
 769  
 770  =back
 771  
 772  Returns true on success and false on failure.
 773  
 774  =cut
 775  
 776  sub flush {
 777      my $self = shift;
 778      my $type = shift or return;
 779  
 780      my $cache = {
 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 ) ],
 787      };
 788  
 789      my $aref = $cache->{$type}
 790                      or (
 791                          error( loc("No such cache '%1'", $type) ),
 792                          return
 793                      );
 794  
 795      return $self->_flush( list => $aref );
 796  }
 797  
 798  =pod
 799  
 800  =head2 @mods = $cb->installed()
 801  
 802  Returns a list of module objects of all your installed modules.
 803  If an error occurs, it will return false.
 804  
 805  See L<CPANPLUS::Module> for the operations you can perform on a
 806  module object.
 807  
 808  =cut
 809  
 810  sub installed {
 811      my $self = shift;
 812      my $aref = $self->_all_installed;
 813  
 814      return @$aref if $aref;
 815      return;
 816  }
 817  
 818  =pod
 819  
 820  =head2 $bool = $cb->local_mirror([path => '/dir/to/save/to', index_files => BOOL, force => BOOL, verbose => BOOL] )
 821  
 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
 825  from.
 826  
 827  It takes the following arguments:
 828  
 829  =over 4
 830  
 831  =item path
 832  
 833  The location where to create the local mirror.
 834  
 835  =item index_files
 836  
 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.
 840  
 841  Defaults to true.
 842  
 843  =item force
 844  
 845  Forces refetching of packages, even if they are there already.
 846  
 847  Defaults to whatever setting you have in your C<CPANPLUS::Config>.
 848  
 849  =item verbose
 850  
 851  Prints more messages about what its doing.
 852  
 853  Defaults to whatever setting you have in your C<CPANPLUS::Config>.
 854  
 855  =back
 856  
 857  Returns true on success and false on error.
 858  
 859  =cut
 860  
 861  sub local_mirror {
 862      my $self = shift;
 863      my $conf = $self->configure_object;
 864      my %hash = @_;
 865  
 866      my($path, $index, $force, $verbose);
 867      my $tmpl = {
 868          path        => { default => $conf->get_conf('base'),
 869                              store => \$path },
 870          index_files => { default => 1, store => \$index },
 871          force       => { default => $conf->get_conf('force'),
 872                              store => \$force },
 873          verbose     => { default => $conf->get_conf('verbose'),
 874                              store => \$verbose },
 875      };
 876  
 877      check( $tmpl, \%hash ) or return;
 878  
 879      unless( -d $path ) {
 880          $self->_mkdir( dir => $path )
 881                  or( error( loc( "Could not create '%1', giving up", $path ) ),
 882                      return
 883                  );
 884      } elsif ( ! -w _ ) {
 885          error( loc( "Could not write to '%1', giving up", $path ) );
 886          return;
 887      }
 888  
 889      my $flag;
 890      AUTHOR: {
 891      for my $auth (  sort { $a->cpanid cmp $b->cpanid }
 892                      values %{$self->author_tree}
 893      ) {
 894  
 895          MODULE: {
 896          my $i;
 897          for my $mod ( $auth->modules ) {
 898              my $fetchdir = File::Spec->catdir( $path, $mod->path );
 899  
 900              my %opts = (
 901                  verbose     => $verbose,
 902                  force       => $force,
 903                  fetchdir    => $fetchdir,
 904              );
 905  
 906              ### only do this the for the first module ###
 907              unless( $i++ ) {
 908                  $mod->_get_checksums_file(
 909                              %opts
 910                          ) or (
 911                              error( loc( "Could not fetch %1 file, " .
 912                                          "skipping author '%2'",
 913                                          CHECKSUMS, $auth->cpanid ) ),
 914                              $flag++, next AUTHOR
 915                          );
 916              }
 917  
 918              $mod->fetch( %opts )
 919                      or( error( loc( "Could not fetch '%1'", $mod->module ) ),
 920                          $flag++, next MODULE
 921                      );
 922          } }
 923      } }
 924  
 925      if( $index ) {
 926          for my $name (qw[auth dslip mod]) {
 927              $self->_update_source(
 928                          name    => $name,
 929                          verbose => $verbose,
 930                          path    => $path,
 931                      ) or ( $flag++, next );
 932          }
 933      }
 934  
 935      return !$flag;
 936  }
 937  
 938  =pod
 939  
 940  =head2 $file = $cb->autobundle([path => OUTPUT_PATH, force => BOOL, verbose => BOOL])
 941  
 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.
 945  
 946  It will, by default, write to an 'autobundle' directory under your
 947  cpanplus homedirectory, but you can override that by supplying a
 948  C<path> argument.
 949  
 950  It will return the location of the output file on success and false on
 951  failure.
 952  
 953  =cut
 954  
 955  sub autobundle {
 956      my $self = shift;
 957      my $conf = $self->configure_object;
 958      my %hash = @_;
 959  
 960      my($path,$force,$verbose);
 961      my $tmpl = {
 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') ),
 969                      store => \$path },
 970      };
 971  
 972      check($tmpl, \%hash) or return;
 973  
 974      unless( -d $path ) {
 975          $self->_mkdir( dir => $path )
 976                  or( error(loc("Could not create directory '%1'", $path ) ),
 977                      return
 978                  );
 979      }
 980  
 981      my $name; my $file;
 982      {   ### default filename for the bundle ###
 983          my($year,$month,$day) = (localtime)[5,4,3];
 984          $year += 1900; $month++;
 985  
 986          my $ext = 0;
 987  
 988          my $prefix  = $conf->_get_build('autobundle_prefix');
 989          my $format  = "$prefix}_%04d_%02d_%02d_%02d";
 990  
 991          BLOCK: {
 992              $name = sprintf( $format, $year, $month, $day, $ext);
 993  
 994              $file = File::Spec->catfile( $path, $name . '.pm' );
 995  
 996              -f $file ? ++$ext && redo BLOCK : last BLOCK;
 997          }
 998      }
 999      my $fh;
1000      unless( $fh = FileHandle->new( ">$file" ) ) {
1001          error( loc( "Could not open '%1' for writing: %2", $file, $! ) );
1002          return;
1003      }
1004      
1005      ### make sure we load the module tree *before* doing this, as it
1006      ### starts to chdir all over the place
1007      $self->module_tree;
1008  
1009      my $string = join "\n\n",
1010                      map {
1011                          join ' ',
1012                              $_->module,
1013                              ($_->installed_version(verbose => 0) || 'undef')
1014                      } sort {
1015                          $a->module cmp $b->module
1016                      }  $self->installed;
1017  
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`;
1023  
1024      print $fh <<EOF;
1025  package $name
1026  
1027  \$VERSION = '0.01';
1028  
1029  1;
1030  
1031  __END__
1032  
1033  $head NAME
1034  
1035  $name - Snapshot of your installation at $now
1036  
1037  $head SYNOPSIS
1038  
1039  perl -MCPANPLUS -e "install $name"
1040  
1041  $head CONTENTS
1042  
1043  $string
1044  
1045  $head CONFIGURATION
1046  
1047  $perl_v
1048  
1049  $head AUTHOR
1050  
1051  This bundle has been generated autotomatically by
1052      $pkg $version
1053  
1054  EOF
1055  
1056      close $fh;
1057  
1058      return $file;
1059  }
1060  
1061  ### XXX these wrappers are not individually tested! only the underlying
1062  ### code through source.t and indirectly trought he CustomSource plugin.
1063  =pod
1064  
1065  =head1 CUSTOM MODULE SOURCES
1066  
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.
1069  
1070  The methodology behind this works much like C<Debian's apt-sources>.
1071  
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.
1076  
1077  =head2 %files = $cb->list_custom_sources
1078  
1079  Returns a mapping of registered custom sources and their local indices
1080  as follows:
1081  
1082      /full/path/to/local/index => http://remote/source
1083  
1084  Note that any file starting with an C<#> is being ignored.
1085  
1086  =cut
1087  
1088  sub list_custom_sources {
1089      return shift->__list_custom_module_sources( @_ );
1090  }
1091  
1092  =head2 $local_index = $cb->add_custom_source( uri => URI, [verbose => BOOL] );
1093  
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.
1096  
1097  Returns the full path to the local index on success, or false on failure.
1098  
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.
1102  
1103  =cut
1104  
1105  sub add_custom_source {
1106      return shift->_add_custom_module_source( @_ );
1107  }
1108  
1109  =head2 $local_index = $cb->remove_custom_source( uri => URI, [verbose => BOOL] );
1110  
1111  Removes an C<URI> from your own sources list and removes its index.
1112  
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.
1115  
1116  Returns the full path to the deleted local index file on success, or false
1117  on failure.
1118  
1119  =cut
1120  
1121  ### XXX do clever dispatching based on arg number?
1122  sub remove_custom_source {
1123      return shift->_remove_custom_module_source( @_ );
1124  }
1125  
1126  =head2 $bool = $cb->update_custom_source( [remote => URI] );
1127  
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>.
1132  
1133  Here's an example of how custom sources would resolve into index files:
1134  
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
1138    
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
1144  users to index it.
1145  
1146  For details, see the C<< $cb->write_custom_source_index >> method below.
1147  
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 
1150  added packages.
1151  
1152  =cut
1153  
1154  sub update_custom_source {
1155      my $self = shift;
1156      
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( @_ );
1162  
1163      return $rv;
1164  }    
1165  
1166  =head2 $file = $cb->write_custom_source_index( path => /path/to/package/root, [to => /path/to/index/file, verbose => BOOL] );
1167  
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.
1171  
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
1175  not be required.
1176  
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.
1179  
1180  =cut
1181  
1182  sub write_custom_source_index {
1183      return shift->__write_custom_module_index( @_ );
1184  }
1185  
1186  1;
1187  
1188  =pod
1189  
1190  =head1 BUG REPORTS
1191  
1192  Please report bugs or other issues to E<lt>bug-cpanplus@rt.cpan.org<gt>.
1193  
1194  =head1 AUTHOR
1195  
1196  This module by Jos Boumans E<lt>kane@cpan.orgE<gt>.
1197  
1198  =head1 COPYRIGHT
1199  
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.
1202  
1203  This library is free software; you may redistribute and/or modify it 
1204  under the same terms as Perl itself.
1205  
1206  =head1 SEE ALSO
1207  
1208  L<CPANPLUS::Configure>, L<CPANPLUS::Module>, L<CPANPLUS::Module::Author>, 
1209  L<CPANPLUS::Selfupdate>
1210  
1211  =cut
1212  
1213  # Local variables:
1214  # c-indentation-style: bsd
1215  # c-basic-offset: 4
1216  # indent-tabs-mode: nil
1217  # End:
1218  # vim: expandtab shiftwidth=4:
1219  
1220  __END__
1221  
1222  todo:
1223  sub dist {          # not sure about this one -- probably already done
1224                        enough in Module.pm
1225  sub reports {       # in Module.pm, wrapper here
1226  
1227  


Generated: Tue Mar 17 22:47:18 2015 Cross-referenced by PHPXref 0.7.1