5 use CPANPLUS::Internals::Constants;
9 use File::Temp qw|tempfile|;
11 use Locale::Maketext::Simple Class => 'CPANPLUS', Style => 'gettext';
13 local $Data::Dumper::Indent = 1;
15 use constant PREREQ_SKIP_CLASS => 'CPANPLUS::To::Dist::PREREQ_SKIP';
16 use constant ALARM_CLASS => 'CPANPLUS::To::Dist::ALARM';
18 ### print when you can
21 my $cb = CPANPLUS::Backend->new
22 or die loc("Could not create new CPANPLUS::Backend object");
23 my $conf = $cb->configure_object;
25 my %formats = map { $_ => $_ } CPANPLUS::Dist->dist_types;
29 'format=s', 'archive',
31 'skiptest!', 'keepsource!',
32 'makefile!', 'buildprereq!',
34 'ban=s@', 'banlist=s@',
35 'ignore=s@', 'ignorelist=s@',
36 'defaults', 'modulelist=s@',
37 'logfile=s', 'timeout=s',
38 'dist-opts=s%', 'set-config=s%',
39 'default-banlist!', 'set-program=s%',
40 'default-ignorelist!', 'edit-metafile!'
43 die usage() if exists $opts->{'help'};
46 my $tarball = $opts->{'archive'} || 0;
47 my $keep = $opts->{'keepsource'} ? 1 : 0;
48 my $prereqbuild = exists $opts->{'buildprereq'}
49 ? $opts->{'buildprereq'}
51 my $timeout = exists $opts->{'timeout'}
55 ### use default answers?
56 $ENV{'PERL_MM_USE_DEFAULT'} = $opts->{'defaults'} ? 1 : 0;
59 ### if provided, we go with the command line option, fall back to conf setting
60 { $format = $opts->{'format'} || $conf->get_conf('dist_type');
61 $conf->set_conf( dist_type => $format );
63 ### is this a valid format??
64 die loc("Invalid format: " . ($format || "[NONE]") ) . usage()
65 unless $formats{$format};
67 ### any options to fix config entries
68 { my $set_conf = $opts->{'set-config'} || {};
69 while( my($key,$val) = each %$set_conf ) {
70 $conf->set_conf( $key => $val );
74 ### any options to fix program entries
75 { my $set_prog = $opts->{'set-program'} || {};
76 while( my($key,$val) = each %$set_prog ) {
77 $conf->set_program( $key => $val );
81 ### any other options passed
82 { my %map = ( verbose => 'verbose',
84 skiptest => 'skiptest',
85 makefile => 'prefer_makefile'
88 ### set config options from arguments
89 while (my($key,$val) = each %map) {
90 my $bool = exists $opts->{$key}
92 : $conf->get_conf($val);
93 $conf->set_conf( $val => $bool );
99 if( exists $opts->{'modulelist'} ) {
100 push @modules, map { parse_file( $_ ) } @{ $opts->{'modulelist'} };
103 die usage() unless @modules;
105 ### set up munge callback if requested
106 { if( $opts->{'edit-metafile'} ) {
107 my $editor = $conf->get_program('editor');
111 ### register install callback ###
112 $cb->_register_callback(
113 name => 'munge_dist_metafile',
116 my $text = shift or return;
118 my($fh,$file) = tempfile( UNLINK => 1 );
120 unless( print $fh $text ) {
121 warn "Could not print metafile information: $!";
127 system( $editor => $file );
129 my $cont = $cb->_get_file_contents( file => $file );
136 warn "No editor configured. Can not edit metafiles!\n";
143 if( my $file = $opts->{logfile} ) {
144 open $fh, ">$file" or (
145 warn loc("Could not open '%1' for writing: %2", $file,$!),
149 warn "Logging to '$file'\n";
156 ### reload indices if so desired
157 $cb->reload_indices() if $opts->{'flushcache'};
159 { my @ban = exists $opts->{'ban'}
160 ? map { qr/$_/ } @{ $opts->{'ban'} }
164 if( exists $opts->{'banlist'} ) {
165 push @ban, map { parse_file( $_, 1 ) } @{ $opts->{'banlist'} };
168 push @ban, map { s/\s+//; $_ }
169 map { [split /\s*#\s*/]->[0] }
171 map { split /\n/ } _default_ban_list()
172 if $opts->{'default-banlist'};
174 ### use our prereq install callback
175 $conf->set_conf( prereqs => PREREQ_ASK );
177 ### register install callback ###
178 $cb->_register_callback(
179 name => 'install_prerequisite',
180 code => \&__ask_about_install,
184 ### check for ban patterns when handling prereqs
185 sub __ask_about_install {
187 my $mod = shift or return;
188 my $prereq = shift or return;
191 ### die with an error object, so we can verify that
192 ### the die came from this location, and that it's an
193 ### 'acceptable' death
194 my $pat = ban_me( $prereq );
195 die bless sub { loc("Module '%1' requires '%2' to be installed " .
196 "but found in your ban list (%3) -- skipping",
197 $mod->module, $prereq->module, $pat )
198 }, PREREQ_SKIP_CLASS if $pat;
202 ### should we skip this module?
206 for my $pat ( @ban ) {
207 return $pat if $mod->module =~ /$pat/i;
213 ### patterns to strip from prereq lists
214 { my @ignore = exists $opts->{'ignore'}
215 ? map { qr/$_/ } @{ $opts->{'ignore'} }
218 if( exists $opts->{'ignorelist'} ) {
219 push @ignore, map { parse_file( $_, 1 ) } @{ $opts->{'ignorelist'} };
222 push @ignore, map { s/\s+//; $_ }
223 map { [split /\s*#\s*/]->[0] }
225 map { split /\n/ } _default_ignore_list()
226 if $opts->{'default-ignorelist'};
229 ### register install callback ###
230 $cb->_register_callback(
231 name => 'filter_prereqs',
232 code => \&__filter_prereqs,
235 sub __filter_prereqs {
239 for my $name ( keys %$href ) {
240 my $obj = $cb->parse_module( module => $name ) or (
241 warn "Cannot make a module object out of ".
242 "'$name' -- skipping\n",
245 if( my $pat = ignore_me( $obj ) ) {
246 warn loc("'%1' found in your ignore list (%2) ".
247 "-- filtering it out\n", $name, $pat);
249 delete $href->{ $name };
256 ### should we skip this module?
260 for my $pat ( @ignore ) {
261 return $pat if $mod->module =~ /$pat/i;
262 return $pat if $mod->package_name =~ /$pat/i;
270 for my $name (@modules) {
274 ### is it a tarball? then we get it locally and transform it
275 ### and it's dependencies into .debs
277 ### make sure we use an absolute path, so chdirs() dont
279 $name = File::Spec->rel2abs( $name );
283 warn loc("Archive '$name' does not exist");
287 $obj = CPANPLUS::Module::Fake->new(
288 module => basename($name),
289 path => dirname($name),
290 package => basename($name),
293 ### if it's a traditional CPAN package, we can tidy
294 ### up the module name some
295 $obj->module( $obj->package_name ) if $obj->package_name;
297 ### get the version from the package name
298 $obj->version( $obj->package_version || 0 );
300 ### set the location of the tarball
301 $obj->status->fetch($name);
303 ### plain old cpan module?
306 ### find the corresponding module object ###
307 $obj = $cb->parse_module( module => $name ) or (
308 warn "Cannot make a module object out of ".
309 "'$name' -- skipping\n",
314 if( my $pat = ban_me( $obj ) ) {
315 warn loc("'%1' found in your ban list (%2) -- skipping\n",
316 $obj->module, $pat );
320 ### or just ignored it?
321 if( my $pat = ignore_me( $obj ) ) {
322 warn loc("'%1' found in your ignore list (%2) -- skipping\n",
323 $obj->module, $pat );
329 local $SIG{ALRM} = sub { die bless {}, ALARM_CLASS }
334 my $dist_opts = $opts->{'dist-opts'} || {};
336 my $rv = $obj->install(
337 prereq_target => 'create',
339 keep_source => $keep,
340 prereq_build => $prereqbuild,
342 ### any passed arbitrary options
351 ### set here again, in case the install dies
354 ### install failed due to a 'die' in our prereq skipper?
355 if( $@ and ref $@ and $@->isa( PREREQ_SKIP_CLASS ) ) {
356 warn loc("Dist creation of '%1' skipped: '%2'",
357 $obj->module, $@->() );
360 } elsif ( $@ and ref $@ and $@->isa( ALARM_CLASS ) ) {
361 warn loc("\nDist creation of '%1' skipped, build time exceeded: ".
362 "%2 seconds\n", $obj->module, $timeout );
365 ### died for some other reason? just report and skip
367 warn loc("Dist creation of '%1' failed: '%2'",
372 ### we didn't get a dist object back?
373 unless ($dist and $obj->status->dist) {
374 warn loc("Unable to create '%1' dist of '%2'", $format, $obj->module);
378 print "Created '$format' distribution for ", $obj->module,
379 " to:\n\t", $obj->status->dist->status->dist, "\n";
384 my $file = shift or return;
385 my $qr = shift() ? 1 : 0;
387 my $fh = OPEN_FILE->( $file ) or return;
392 next if /^#/; # skip comments
393 next unless /\S/; # skip empty lines
394 s/^(\S+).*/$1/; # skip extra info
395 push @rv, $qr ? qr/$_/ : $_; # add pattern to the list
403 cpan2dist - The CPANPLUS distribution creator
407 This script will create distributions of C<CPAN> modules of the format
408 you specify, including its prerequisites. These packages can then be
409 installed using the corresponding package manager for the format.
411 Note, you can also do this interactively from the default shell,
412 C<CPANPLUS::Shell::Default>. See the C<CPANPLUS::Dist> documentation,
413 as well as the documentation of your format of choice for any format
414 specific documentation.
421 my $me = basename($0);
422 my $formats = join "\n", map { "\t\t$_" } sort keys %formats;
424 my $usage = << '=cut';
427 Usage: cpan2dist [--format FMT] [OPTS] Mod::Name [Mod::Name, ...]
428 cpan2dist [--format FMT] [OPTS] --modulelist /tmp/mods.list
429 cpan2dist [--format FMT] [OPTS] --archive /tmp/dist [/tmp/dist2]
431 Will create a distribution of type FMT of the modules
432 specified on the command line, and all their prerequisites.
434 Can also create a distribution of type FMT from a local
435 archive and all it's prerequisites
440 Possible formats are:
443 You can install more formats from CPAN!
451 ### take no argument:
452 --help Show this help message
453 --skiptest Skip tests. Can be negated using --noskiptest
454 --force Force operation. Can be negated using --noforce
455 --verbose Be verbose. Can be negated using --noverbose
456 --keepsource Keep sources after building distribution. Can be
457 negated by --nokeepsource. May not be supported
459 --makefile Prefer Makefile.PL over Build.PL. Can be negated
460 using --nomakefile. Defaults to your config setting
461 --buildprereq Build packages of any prerequisites, even if they are
462 already uptodate on the local system. Can be negated
463 using --nobuildprereq. Defaults to false.
464 --archive Indicate that all modules listed are actually archives
465 --flushcache Update CPANPLUS' cache before commencing any operation
466 --defaults Instruct ExtUtils::MakeMaker and Module::Build to use
467 default answers during 'perl Makefile.PL' or 'perl
468 Build.PL' calls where possible
469 --edit-metafile Edit the distributions metafile(s) before the distribution
470 is built. Requires a configured editor.
473 --format Installer format to use (defaults to config setting)
474 --ban Patterns of module names to skip during installation,
475 case-insensitive (affects prerequisites too)
476 May be given multiple times
477 --banlist File containing patterns that could be given to --ban
478 Are appended to the ban list built up by --ban
479 May be given multiple times.
480 --ignore Patterns of modules to exclude from prereq list. Useful
481 for when a prereq listed by a CPAN module is resolved
482 in another way than from its corresponding CPAN package
483 (Match is done on both module name, and package name of
484 the package the module is in, case-insensitive)
485 --ignorelist File containing patterns that may be given to --ignore.
486 Are appended to the ban list built up by --ignore.
487 May be given multiple times.
488 --modulelist File containing a list of modules that should be built.
489 Are appended to the list of command line modules.
490 May be given multiple times.
491 --logfile File to log all output to. By default, all output goes
493 --timeout The allowed time for buliding a distribution before
494 aborting. This is useful to terminate any build that
495 hang or happen to be interactive despite being told not
496 to be. Defaults to 300 seconds. To turn off, you can
498 --set-config Change any options as specified in your config for this
499 invocation only. See CPANPLUS::Config for a list of
501 --set-program Change any programs as specified in your config for this
502 invocation only. See CPANPLUS::Config for a list of
504 --dist-opts Arbitrary options passed along to the chosen installer
505 format's prepare()/create() routine. Please see the
506 documentation of the installer of your choice for
510 --default-banlist Use our builtin banlist. Works just like --ban
511 and --banlist, but with pre-set lists. See the
512 "Builtin Lists" section for details.
513 --default-ignorelist Use our builtin ignorelist. Works just like
514 --ignore and --ignorelist but with pre-set lists.
515 See the "Builtin Lists" section for details.
519 ### build a debian package of DBI and it's prerequisites,
520 ### don't bother running tests
521 cpan2dist --format CPANPLUS::Dist::Deb --buildprereq --skiptest DBI
523 ### Build a package, whose format is determined by your config, of
524 ### the local tarball, reloading cpanplus' indices first and using
525 ### the tarballs Makefile.PL if it has one.
526 cpan2dist --makefile --flushcache --archive /path/to/Cwd-1.0.tgz
528 ### build a package from Net::FTP, but dont build any packages or
529 ### dependencies whose name match 'Foo', 'Bar' or any of the
530 ### patterns mentioned in /tmp/ban
531 cpan2dist --ban Foo --ban Bar --banlist /tmp/ban Net::FTP
533 ### build a package from Net::FTP, but ignore it's listed dependency
534 ### on IO::Socket, as it's shipped per default with the OS we're on
535 cpan2dist --ignore IO::Socket Net::FTP
537 ### building all modules listed, plus their prerequisites
538 cpan2dist --ignorelist /tmp/modules.ignore --banlist /tmp/modules.ban
539 --modulelist /tmp/modules.list --buildprereq --flushcache
540 --makefile --defaults
542 ### pass arbitrary options to the format's prepare()/create() routine
543 cpan2dist --dist-opts deb_version=3 --dist-opts prefix=corp
550 Ignore list:] . _default_ignore_list() . qq[
551 Ban list:] . _default_ban_list();
553 ### strip the pod directives
554 $usage =~ s/=pod\n//g;
561 =head1 Built-In Filter Lists
563 Some modules you'd rather not package. Some because they
564 are part of core-perl and you dont want a new package.
565 Some because they won't build on your system. Some because
566 your package manager of choice already packages them for you.
568 There may be a myriad of reasons. You can use the C<--ignore>
569 and C<--ban> options for this, but we provide some built-in
570 lists that catch common cases. You can use these built-in lists
571 if you like, or supply your own if need be.
573 =head2 Built-In Ignore List
577 You can use this list of regexes to ignore modules matching
578 to be listed as prerequisites of a package. Particulaly useful
579 if they are bundled with core-perl anyway and they have known
582 Toggle it by supplying the C<--default-ignorelist> option.
586 sub _default_ignore_list {
588 my $list = << '=cut';
591 ^IO$ # Provided with core anyway
592 ^Cwd$ # Provided with core anyway
593 ^File::Spec # Provided with core anyway
594 ^Config$ # Perl's own config, not shipped separately
595 ^ExtUtils::MakeMaker$ # Shipped with perl, recent versions
596 # have bug 14721 (see rt.cpan.org)
597 ^ExtUtils::Install$ # Part of of EU::MM, same reason
604 =head2 Built-In Ban list
606 You can use this list of regexes to disable building of these
609 Toggle it by supplying the C<--default-banlist> option.
613 sub _default_ban_list {
615 my $list = << '=cut';
618 ^GD$ # Needs c libaries
619 ^Berk.*DB # DB packages require specific options & linking
620 ^DBD:: # DBD drives require database files/headers
621 ^XML:: # XML modules usually require expat libraries
622 Apache # These usually require apache libraries
623 SSL # These usually require SSL certificates & libs
624 Image::Magick # Needs ImageMagick C libraries
625 Mail::ClamAV # Needs ClamAV C Libraries
626 ^Verilog # Needs Verilog C Libraries
627 ^Authen::PAM$ # Needs PAM C libraries & Headers
638 L<CPANPLUS::Dist>, L<CPANPLUS::Module>, L<CPANPLUS::Shell::Default>,
643 Please report bugs or other issues to E<lt>bug-cpanplus@rt.cpan.org<gt>.
647 This module by Jos Boumans E<lt>kane@cpan.orgE<gt>.
651 The CPAN++ interface (of which this module is a part of) is copyright (c)
652 2001 - 2007, Jos Boumans E<lt>kane@cpan.orgE<gt>. All rights reserved.
654 This library is free software; you may redistribute and/or modify it
655 under the same terms as Perl itself.
660 # c-indentation-style: bsd
662 # indent-tabs-mode: nil
664 # vim: expandtab shiftwidth=4: