15 use Parse::CPAN::Meta;
18 use Parse::CPAN::Packages::Fast;
20 my $target_dist = 'Devel-Cover';
21 my $first_year = 2012;
22 my $cpan_mirror = 'http://www.cpan.org';
26 'Test::Differences' => 1,
30 'PPI::HTML' => 'Devel::Cover lets you optionally pick between L<PPI::HTML> and L<Perl::Tidy>, but it will only use the former if both are installed.',
36 my $home = File::HomeDir->my_home;
37 my $pkgs = File::Spec->catfile($home, qw<.cpanplus 02packages.details.txt.gz>);
38 my $pcp = Parse::CPAN::Packages::Fast->new($pkgs);
40 my $d = $pcp->latest_distribution($dist);
41 die "Could not find distribution '$dist' on the CPAN" unless $d;
49 $cpan_mirror =~s{/+$}{}g;
50 my $cpanid = $d->cpanid;
51 my ($cp, $c) = $cpanid =~ /^((.).)/;
52 my $uri = join '/', $cpan_mirror, 'authors', 'id', $c, $cp, $cpanid,
55 my $tmp_dir = File::Temp->newdir;
56 # Force symlinks resolution
57 my $tmp_dirname = Cwd::abs_path($tmp_dir->dirname);
59 my $ff = File::Fetch->new(uri => $uri);
60 my $archive = $ff->fetch(to => $tmp_dirname);
61 die $ff->error unless $archive;
63 my $ae = Archive::Extract->new(archive => $archive);
64 $ae->extract(to => $tmp_dirname) or die $ae->error;
67 map { File::Spec->catfile($tmp_dirname, $_) => 1 }
70 my $abs_extract_path = Cwd::abs_path($ae->extract_path);
71 my @meta_candidates = map File::Spec->catfile($abs_extract_path, $_),
72 qw<META.json META.yml>;
74 for my $file (@meta_candidates) {
75 if ($files->{$file}) {
80 die 'No META file for ' . $d->distvname . "\n" unless $meta_file;
82 return Parse::CPAN::Meta->load_file($meta_file);
85 my $latest_target = get_latest_dist($target_dist);
86 my $target_version = $latest_target->version;
87 my $meta = get_dist_meta($latest_target);
90 configure => [ qw<configure> ],
91 build => [ qw<build test> ],
92 run => [ qw<runtime> ],
96 'ExtUtils::MakeMaker' => '0',
99 'ExtUtils::MakeMaker' => '0',
105 for my $eumm_phase (keys %eumm_phases) {
106 my $prereqs = $prereqs{$eumm_phase} ||= { };
107 my $skip = $prereq_skip{$eumm_phase};
109 for my $meta_phase (@{$eumm_phases{$eumm_phase}}) {
111 for my $type (qw<requires recommends>) {
112 my $phase_prereqs = $meta->{prereqs}{$meta_phase}{$type};
113 next unless $phase_prereqs;
115 while (my ($module, $version) = each %$phase_prereqs) {
116 next if $skip->{$module};
118 if ($module eq 'perl') {
119 if (not $prereqs{perl} or $prereqs{perl} < $version) {
120 $prereqs{perl} = $version;
122 } elsif (not exists $prereqs->{$module} or
123 version->parse($prereqs->{$module}) < version->parse($version)) {
124 $prereqs->{$module} = $version;
131 (my $target_pkg = $target_dist) =~ s/-/::/g;
132 my $task_pkg = "Task::${target_pkg}::Recommended";
133 (my $task_file = "lib/$task_pkg.pm") =~ s{::}{/}g;
134 my $years = join ',', $first_year .. ((gmtime)[5] + 1900);
136 my $old_task_version = '0.0.0';
138 open my $old_fh, '<', $task_file;
140 if (/our\s*\$VERSION\s*=\s*(.*);/) {
141 $old_task_version = $1;
142 $old_task_version =~ s/^(['"])(.*)\1$/$2/;
147 my ($old_task_revision) = $old_task_version =~ /([0-9]+)$/;
149 my $new_task_version = version->parse($target_version)->normal;
150 my $new_task_revision = $old_task_revision;
152 if version->parse($new_task_version) <= version->parse($old_task_version);
153 if (($target_version =~ tr/.//) < 2) {
154 my @components = split /\./, $new_task_version;
155 $components[2] = $new_task_revision;
156 $new_task_version = join '.', @components;
158 $new_task_version .= ".$new_task_revision";
161 (my $bug_queue = $task_pkg) =~ s/::/-/g;
162 my $bug_email = "bug-\L$bug_queue\E at rt.cpan.org";
163 $bug_queue = "http://rt.cpan.org/NoAuth/ReportBug.html?Queue=$bug_queue";
167 return 'None.' unless @deplist;
169 my $pod = "=over 4\n\n";
171 my ($module, $version) = splice @deplist, 0, 2;
172 my $X = $module eq 'perl' ? 'C' : 'L';
173 $pod .= "=item $X<$module>";
174 $pod .= " $version" if $version;
176 if (my $desc = $prereq_desc{$module}) {
186 sub deplist_to_perl {
188 return '{ }' unless @deplist;
190 my $len = List::Util::max(
191 map length, @deplist[grep not($_ % 2), 0 .. $#deplist ]
196 my ($module, $version) = splice @deplist, 0, 2;
197 my $pad = $len + 1 - length $module;
198 $perl .= sprintf " '%s'%*s=> '%s',\n", $module, $pad, ' ', $version;
207 map { $_ => $hr->{$_} } sort keys %$hr;
211 TARGET_PKG => $target_pkg,
212 TARGET_VERSION => $target_version,
213 TASK_PKG => $task_pkg,
214 TASK_VERSION => $new_task_version,
215 PERL_PREREQ => $prereqs{perl},
216 CONFIGURE_PREREQS_POD => deplist_to_pod(sorthr $prereqs{configure}),
217 BUILD_PREREQS_POD => deplist_to_pod(sorthr $prereqs{build}),
218 RUN_PREREQS_POD => deplist_to_pod(
219 $target_pkg => $target_version,
220 'perl' => $prereqs{perl},
223 CONFIGURE_PREREQS_PERL => deplist_to_perl(sorthr $prereqs{configure}),
224 BUILD_PREREQS_PERL => deplist_to_perl(sorthr $prereqs{build}),
225 RUN_PREREQS_PERL => deplist_to_perl(
226 sorthr $prereqs{run},
227 $target_pkg => $target_version,
229 TESTED_PREREQS => deplist_to_perl(sorthr $prereqs{run}),
230 BUG_EMAIL => $bug_email,
231 BUG_QUEUE => $bug_queue,
236 $task_file => <<'TEMPLATE',
237 package __TASK_PKG__;
244 __TASK_PKG__ - Install __TARGET_PKG__ and its recommended dependencies.
248 Version __TASK_VERSION__
252 our $VERSION = '__TASK_VERSION__';
257 $ cpanp -i __TASK_PKG__
262 This task module lets you easily install L<__TARGET_PKG__> __TARGET_VERSION__ and all its recommended dependencies.
266 =head2 Configure-time dependencies
268 __CONFIGURE_PREREQS_POD__
270 =head2 Build-time and test-time dependencies
272 __BUILD_PREREQS_POD__
274 =head2 Run-time dependencies
280 Vincent Pit, C<< <perl at profvince.com> >>, L<http://www.profvince.com>.
282 You can contact me by mail or on C<irc.perl.org> (vincent).
286 Please report any bugs or feature requests to C<__BUG_EMAIL__>, or through the web interface at L<__BUG_QUEUE__>.
287 I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.
291 You can find documentation for this module with the perldoc command.
295 =head1 COPYRIGHT & LICENSE
297 Copyright __YEARS__ Vincent Pit, all rights reserved.
299 This program is free software; you can redistribute it and/or modify it
300 under the same terms as Perl itself.
304 1; # End of __TASK_PKG__
306 # ----------------------------------------------------------------------------
307 'Makefile.PL' => <<'TEMPLATE',
312 use ExtUtils::MakeMaker;
314 my $dist = 'Task-Devel-Cover-Recommended';
316 (my $name = $dist) =~ s{-}{::}g;
318 (my $file = $dist) =~ s{-}{/}g;
319 $file = "lib/$file.pm";
321 my $CONFIGURE_PREREQS = __CONFIGURE_PREREQS_PERL__;
323 my $BUILD_PREREQS = __BUILD_PREREQS_PERL__;
325 my $RUN_PREREQS = __RUN_PREREQS_PERL__;
328 configure_requires => $CONFIGURE_PREREQS,
329 build_requires => $BUILD_PREREQS,
332 bugtracker => "http://rt.cpan.org/NoAuth/ReportBug.html?Queue=$dist",
333 homepage => "http://search.cpan.org/dist/$dist/",
334 license => 'http://dev.perl.org/licenses/',
335 repository => "http://git.profvince.com/?p=perl%2Fmodules%2F$dist.git",
341 AUTHOR => 'Vincent Pit <perl@profvince.com>',
343 VERSION_FROM => $file,
344 ABSTRACT_FROM => $file,
346 PREREQ_PM => $RUN_PREREQS,
347 MIN_PERL_VERSION => '__PERL_PREREQ__',
348 META_MERGE => \%META,
350 PREOP => "pod2text -u $file > \$(DISTVNAME)/README",
351 COMPRESS => 'gzip -9f', SUFFIX => 'gz'
354 FILES => "$dist-* *.gcov *.gcda *.gcno cover_db Debian_CPANTS.txt*"
358 # ----------------------------------------------------------------------------
359 't/01-deps.t' => <<'TEMPLATE',
367 my $TESTED_PREREQS = __TESTED_PREREQS__;
369 plan tests => keys(%$TESTED_PREREQS) + 1;
371 my @tests = map [ $_ => $TESTED_PREREQS->{$_} ], keys %$TESTED_PREREQS;
372 push @tests, [ '__TARGET_PKG__' => '__TARGET_VERSION__' ];
374 for my $test (@tests) {
375 my ($module, $version) = @$test;
377 if ($version && $version !~ /^[0._]*$/) {
378 eval "use $module $version ()";
379 is $@, '', "$module v$version is available";
381 eval "use $module ()";
382 is $@, '', "any version of $module is available";
388 my $valid_keys = join '|', keys %vars;
389 $valid_keys = qr/$valid_keys/;
391 for my $file (sort keys %templates) {
392 my $template = $templates{$file};
393 $template =~ s/\b__($valid_keys)__\b/$vars{$1}/go;
395 open my $fh, '>', $file;