1 package CPANPLUS::Internals;
3 ### we /need/ perl5.6.1 or higher -- we use coderefs in @INC,
4 ### and 5.6.0 is just too buggy
13 use CPANPLUS::Selfupdate;
15 use CPANPLUS::Internals::Extract;
16 use CPANPLUS::Internals::Fetch;
17 use CPANPLUS::Internals::Utils;
18 use CPANPLUS::Internals::Constants;
19 use CPANPLUS::Internals::Search;
20 use CPANPLUS::Internals::Report;
25 use Module::Load qw[load];
26 use Params::Check qw[check];
27 use Locale::Maketext::Simple Class => 'CPANPLUS', Style => 'gettext';
28 use Module::Load::Conditional qw[can_load];
33 local $Params::Check::VERBOSE = 1;
35 use vars qw[@ISA $VERSION];
38 CPANPLUS::Internals::Extract
39 CPANPLUS::Internals::Fetch
40 CPANPLUS::Internals::Utils
41 CPANPLUS::Internals::Search
42 CPANPLUS::Internals::Report
55 my $internals = CPANPLUS::Internals->_init( _conf => $conf );
56 my $backend = CPANPLUS::Internals->_retrieve_id( $ID );
60 This module is the guts of CPANPLUS -- it inherits from all other
61 modules in the CPANPLUS::Internals::* namespace, thus defying normal
62 rules of OO programming -- but if you're reading this, you already
63 know what's going on ;)
65 Please read the C<CPANPLUS::Backend> documentation for the normal API.
73 Get/set the configure object
81 ### autogenerate accessors ###
82 for my $key ( qw[_conf _id _modules _hosts _methods _status
83 _callbacks _selfupdate _mtree _atree]
86 *{__PACKAGE__."::$key"} = sub {
87 $_[0]->{$key} = $_[1] if @_ > 1;
98 =head2 $internals = CPANPLUS::Internals->_init( _conf => CONFIG_OBJ )
100 C<_init> creates a new CPANPLUS::Internals object.
102 You have to pass it a valid C<CPANPLUS::Configure> object.
104 Returns the object on success, or dies on failure.
109 ### if extra callbacks are added, don't forget to update the
110 ### 02-internals.t test script with them!
112 ### name default value
113 install_prerequisite => 1, # install prereqs when 'ask' is set?
114 edit_test_report => 0, # edit the prepared test report?
115 send_test_report => 1, # send the test report?
116 # munge the test report
117 munge_test_report => sub { return $_[1] },
118 # filter out unwanted prereqs
119 filter_prereqs => sub { return $_[1] },
120 # continue if 'make test' fails?
121 proceed_on_test_failure => sub { return 0 },
122 munge_dist_metafile => sub { return $_[1] },
125 my $status = Object::Accessor->new;
126 $status->mk_accessors(qw[pending_prereqs]);
128 my $callback = Object::Accessor->new;
129 $callback->mk_accessors(keys %$callback_map);
133 _conf => { required => 1, store => \$conf,
134 allow => IS_CONFOBJ },
135 _id => { default => '', no_override => 1 },
136 _authortree => { default => '', no_override => 1 },
137 _modtree => { default => '', no_override => 1 },
138 _hosts => { default => {}, no_override => 1 },
139 _methods => { default => {}, no_override => 1 },
140 _status => { default => '<empty>', no_override => 1 },
141 _callbacks => { default => '<empty>', no_override => 1 },
148 ### temporary warning until we fix the storing of multiple id's
149 ### and their serialization:
150 ### probably not going to happen --kane
151 if( my $id = $class->_last_id ) {
152 # make it a singleton.
153 warn loc(q[%1 currently only supports one %2 object per ] .
154 qq[running program\n], 'CPANPLUS', $class);
156 return $class->_retrieve_id( $id );
159 my $args = check($Tmpl, \%hash)
160 or die loc(qq[Could not initialize '%1' object], $class);
164 $args->{'_id'} = $args->_inc_id;
165 $args->{'_status'} = $status;
166 $args->{'_callbacks'} = $callback;
168 ### initialize callbacks to default state ###
169 for my $name ( $callback->ls_accessors ) {
170 my $rv = ref $callback_map->{$name} ? 'sub return value' :
171 $callback_map->{$name} ? 'true' : 'false';
173 $args->_callbacks->$name(
174 sub { msg(loc("DEFAULT '%1' HANDLER RETURNING '%2'",
175 $name, $rv), $args->_conf->get_conf('debug'));
176 return ref $callback_map->{$name}
177 ? $callback_map->{$name}->( @_ )
178 : $callback_map->{$name};
183 ### create a selfupdate object
184 $args->_selfupdate( CPANPLUS::Selfupdate->new( $args ) );
186 ### initialize it as an empty hashref ###
187 $args->_status->pending_prereqs( {} );
189 $conf->_set_build( startdir => cwd() ),
190 or error( loc("couldn't locate current dir!") );
192 $ENV{FTP_PASSIVE} = 1, if $conf->get_conf('passive');
194 my $id = $args->_store_id( $args );
196 unless ( $id == $args->_id ) {
197 error( loc("IDs do not match: %1 != %2. Storage failed!",
201 ### different source engines available now, so set them here
202 { my $store = $conf->get_conf( 'source_engine' )
203 || DEFAULT_SOURCE_ENGINE;
205 unless( can_load( modules => { $store => '0.0' }, verbose => 1 ) ) {
206 error( loc( "Could not load source engine '%1'", $store ) );
208 if( $store ne DEFAULT_SOURCE_ENGINE ) {
209 msg( loc("Falling back to %1", DEFAULT_SOURCE_ENGINE), 1 );
211 load DEFAULT_SOURCE_ENGINE;
213 base->import( DEFAULT_SOURCE_ENGINE );
218 base->import( $store );
227 =head2 $bool = $internals->_flush( list => \@caches )
229 Flushes the designated caches from the C<CPANPLUS> object.
231 Returns true on success, false if one or more caches could not be
238 my $conf = $self->configure_object;
243 list => { required => 1, default => [],
244 strict_type => 1, store => \$aref },
247 my $args = check( $tmpl, \%hash ) or return;
250 for my $what (@$aref) {
251 my $cache = '_' . $what;
253 ### set the include paths back to their original ###
254 if( $what eq 'lib' ) {
255 $ENV{PERL5LIB} = $conf->_perl5lib || '';
256 @INC = @{$conf->_lib};
258 ### give all modules a new status object -- this is slightly
259 ### costly, but the best way to make sure all statuses are
261 } elsif ( $what eq 'modules' ) {
262 for my $modobj ( values %{$self->module_tree} ) {
267 ### blow away the methods cache... currently, that's only
268 ### File::Fetch's method fail list
269 } elsif ( $what eq 'methods' ) {
271 ### still unbelievably p4 :( ###
272 $File'Fetch::METHOD_FAIL = $File'Fetch::METHOD_FAIL = {};
274 ### blow away the m::l::c cache, so modules can be (re)loaded
275 ### again if they become available
276 } elsif ( $what eq 'load' ) {
277 undef $Module::Load::Conditional::CACHE;
280 unless ( exists $self->{$cache} && exists $Tmpl->{$cache} ) {
281 error( loc( "No such cache: '%1'", $what ) );
293 ### if extra callbacks are added, don't forget to update the
294 ### 02-internals.t test script with them!
298 =head2 $bool = $internals->_register_callback( name => CALLBACK_NAME, code => CODEREF );
300 Registers a callback for later use by the internal libraries.
302 Here is a list of the currently used callbacks:
306 =item install_prerequisite
308 Is called when the user wants to be C<asked> about what to do with
309 prerequisites. Should return a boolean indicating true to install
310 the prerequisite and false to skip it.
312 =item send_test_report
314 Is called when the user should be prompted if he wishes to send the
315 test report. Should return a boolean indicating true to send the
316 test report and false to skip it.
318 =item munge_test_report
320 Is called when the test report message has been composed, giving
321 the user a chance to programatically alter it. Should return the
322 (munged) message to be sent.
324 =item edit_test_report
326 Is called when the user should be prompted to edit test reports
327 about to be sent out by Test::Reporter. Should return a boolean
328 indicating true to edit the test report in an editor and false
331 =item proceed_on_test_failure
333 Is called when 'make test' or 'Build test' fails. Should return
334 a boolean indicating whether the install should continue even if
337 =item munge_dist_metafile
339 Is called when the C<CPANPLUS::Dist::*> metafile is created, like
340 C<control> for C<CPANPLUS::Dist::Deb>, giving the user a chance to
341 programatically alter it. Should return the (munged) text to be
342 written to the metafile.
348 sub _register_callback {
349 my $self = shift or return;
354 name => { required => 1, store => \$name,
355 allow => [$callback->ls_accessors] },
356 code => { required => 1, allow => IS_CODEREF,
360 check( $tmpl, \%hash ) or return;
362 $self->_callbacks->$name( $code ) or return;
367 # =head2 $bool = $internals->_add_callback( name => CALLBACK_NAME, code => CODEREF );
369 # Adds a new callback to be used from anywhere in the system. If the callback
370 # is already known, an error is raised and false is returned. If the callback
371 # is not yet known, it is added, and the corresponding coderef is registered
376 # sub _add_callback {
377 # my $self = shift or return;
382 # name => { required => 1, store => \$name, },
383 # code => { required => 1, allow => IS_CODEREF,
387 # check( $tmpl, \%hash ) or return;
389 # if( $callback->can( $name ) ) {
390 # error(loc("Callback '%1' is already registered"));
394 # $callback->mk_accessor( $name );
396 # $self->_register_callback( name => $name, code => $code ) or return;
405 =head2 $bool = $internals->_add_to_includepath( directories => \@dirs )
407 Adds a list of directories to the include path.
408 This means they get added to C<@INC> as well as C<$ENV{PERL5LIB}>.
410 Returns true on success, false on failure.
414 sub _add_to_includepath {
420 directories => { required => 1, default => [], store => \$dirs,
424 check( $tmpl, \%hash ) or return;
426 my $s = $Config{'path_sep'};
428 ### only add if it's not added yet
429 for my $lib (@$dirs) {
430 push @INC, $lib unless grep { $_ eq $lib } @INC;
432 ### it will be complaining if $ENV{PERL5LIB] is not defined (yet).
434 $ENV{'PERL5LIB'} .= $s . $lib
435 unless $ENV{'PERL5LIB'} =~ qr|\Q$s$lib\E|;
443 =head2 $id = CPANPLUS::Internals->_last_id
445 Return the id of the last object stored.
447 =head2 $id = CPANPLUS::Internals->_store_id( $internals )
449 Store this object; return its id.
451 =head2 $obj = CPANPLUS::Internals->_retrieve_id( $ID )
453 Retrieve an object based on its ID -- return false on error.
455 =head2 CPANPLUS::Internals->_remove_id( $ID )
457 Remove the object marked by $ID from storage.
459 =head2 @objs = CPANPLUS::Internals->_return_all_objects
461 Return all stored objects.
466 ### code for storing multiple objects
467 ### -- although we only support one right now
468 ### XXX when support for multiple objects comes, saving source will have
474 sub _inc_id { return ++$count; }
476 sub _last_id { $count }
480 my $obj = shift or return;
482 unless( IS_INTERNALS_OBJ->($obj) ) {
483 error( loc("The object you passed has the wrong ref type: '%1'",
488 $idref->{ $obj->_id } = $obj;
494 my $id = shift or return;
496 my $obj = $idref->{$id};
502 my $id = shift or return;
504 return delete $idref->{$id};
507 sub _return_all_objects { return values %$idref }
513 # c-indentation-style: bsd
515 # indent-tabs-mode: nil
517 # vim: expandtab shiftwidth=4: