3 use warnings FATAL => 'all';
5 use ExtUtils::MakeMaker ();
9 our $VERSION = '0.003000';
10 $VERSION = eval $VERSION;
12 my $MM_VER = eval $ExtUtils::MakeMaker::VERSION;
15 author manifest_include readme_generator
20 warnings->import(FATAL => 'all');
21 if (!(@MM::ISA == 1 && $MM::ISA[0] eq 'Distar::MM')) {
22 @Distar::MM::ISA = @MM::ISA;
23 @MM::ISA = qw(Distar::MM);
25 goto &Exporter::import;
42 '' => qr{Changes|MANIFEST|README|LICENSE|META\.yml},
43 'maint' => qr{[^.].*},
46 sub manifest_include {
50 sub readme_generator {
51 die "readme_generator unsupported" if @_ && $_[0];
54 sub write_manifest_skip {
56 my @files = @Manifest;
58 while (my ($dir, $spec) = splice(@files, 0, 2)) {
59 my $re = ($dir ? $dir.'/' : '').
60 ((ref($spec) eq 'Regexp')
64 # print ref as well as stringification in case of overload ""
65 : die "spec must be string or regexp, was: ${spec} (${\ref $spec})");
68 my $dist_name = $mm->{DISTNAME};
69 my $include = join '|', map "${_}\$", @parts;
70 my $final = "^(?:\Q$dist_name\E-v?[0-9_.]+/|(?!$include))";
71 open my $skip, '>', 'MANIFEST.SKIP'
72 or die "can't open MANIFEST.SKIP: $!";
73 print $skip "${final}\n";
81 my ($class, $args) = @_;
82 my %test = %{$args->{test}||{}};
83 my $tests = $test{TESTS} || 't/*.t';
84 $tests !~ /\b\Q$_\E\b/ and $tests .= " $_"
85 for 'xt/*.t', 'xt/*/*.t';
86 $test{TESTS} = $tests;
87 return $class->SUPER::new({
89 MIN_PERL_VERSION => '5.006',
91 AUTHOR => ($MM_VER >= 6.5702 ? $Distar::Author : join(', ', @$Distar::Author)),
93 (exists $args->{ABSTRACT} ? () : (ABSTRACT_FROM => $args->{VERSION_FROM})),
96 realclean => { FILES => (
97 ($args->{realclean}{FILES}||'')
98 . ' Distar/ MANIFEST.SKIP MANIFEST MANIFEST.bak'
105 `git ls-files --error-unmatch MANIFEST.SKIP 2>&1`;
106 my $maniskip_tracked = !$?;
108 Distar::write_manifest_skip($self)
109 unless $maniskip_tracked;
110 $self->SUPER::flush(@_);
113 sub special_targets {
115 my $targets = $self->SUPER::special_targets(@_);
116 my $phony_targets = join ' ', qw(
131 $targets =~ s/^(\.PHONY *:.*)/$1 $phony_targets/m;
137 my $pre_tar = $self->{TAR};
138 my $out = $self->SUPER::init_dist(@_);
140 my $tar = $self->{TAR};
143 my $version = `$tar --version`;
144 if ($version =~ /GNU tar/) {
147 elsif (!$pre_tar && `gtar --version`) {
151 my $tarflags = $self->{TARFLAGS};
152 if (my ($flags) = $tarflags =~ /^-?([cvhlLf]+)$/) {
153 if ($flags =~ s/c// && $flags =~ s/f//) {
154 $tarflags = '--format=ustar -c'.$flags.'f';
156 $tarflags = '--owner=0 --group=0 '.$tarflags;
168 $warn .= ($warn ? ' and ' : '').'gid('.(0+$)).')';
171 warn "$warn too large! Max is ".(2**21-1).".\n"
172 ."Dist creation will likely fail. Install GNU tar to work around.\n";
177 $self->{TARFLAGS} = $tarflags;
184 my $out = $self->SUPER::tarfile_target(@_);
185 my $verify = <<'END_FRAG';
186 $(ABSPERLRUN) $(HELPERS)/verify-tarball $(DISTVNAME).tar $(DISTVNAME)/MANIFEST --tar="$(TAR)"
188 $out =~ s{(\$\(TAR\).*\n)}{$1$verify};
196 if (open my $fh, '<', 'maint/Makefile.include') {
197 $include = "\n# --- Makefile.include:\n\n" . do { local $/; <$fh> };
198 $include =~ s/\n?\z/\n/;
202 grep { $include !~ /^bump$_(?: +\w+)*:/m } ('', 'minor', 'major');
204 my $distar = File::Spec->catdir(
205 File::Spec->catpath((File::Spec->splitpath(__FILE__))[0,1], ''),
208 my $helpers = File::Spec->catdir($distar, 'helpers');
210 my $licenses = $self->{LICENSE} || $self->{META_ADD}{license} || $self->{META_MERGE}{license};
211 my $authors = $self->{AUTHOR};
212 $_ = ref $_ ? $_ : [$_ || ()]
213 for $licenses, $authors;
216 DISTAR => $self->quote_literal($distar),
217 HELPERS => $self->quote_literal($helpers),
218 REMAKE => join(' ', '$(PERLRUN)', '-I$(DISTAR)/lib', '-MDistar', 'Makefile.PL', map { $self->quote_literal($_) } @ARGV),
219 BRANCH => $self->{BRANCH} ||= 'master',
220 CHANGELOG => $self->{CHANGELOG} ||= 'Changes',
221 DEV_NULL_STDOUT => ($self->{DEV_NULL} ? '>'.File::Spec->devnull : ''),
222 DISTTEST_MAKEFILE_PARAMS => '',
223 AUTHORS => $self->quote_literal(join(', ', @$authors)),
224 LICENSES => join(' ', map $self->quote_literal($_), @$licenses),
227 my $dist_test = $self->SUPER::dist_test(@_);
228 $dist_test =~ s/(\bMakefile\.PL\b)/$1 \$(DISTTEST_MAKEFILE_PARAMS)/;
232 "\n\n# --- Distar section:\n\n",
233 (map "$_ = $vars{$_}\n", sort keys %vars),
236 preflight: check-version check-manifest check-cpan-upload
237 $(ABSPERLRUN) $(HELPERS)/preflight $(VERSION) --changelog=$(CHANGELOG) --branch=$(BRANCH)
239 $(ABSPERLRUN) $(HELPERS)/check-version $(VERSION) $(TO_INST_PM) $(EXE_FILES)
241 $(ABSPERLRUN) $(HELPERS)/check-manifest
243 $(NOECHO) cpan-upload -h $(DEV_NULL_STDOUT)
245 $(MAKE) disttest RELEASE_TESTING=1 DISTTEST_MAKEFILE_PARAMS="PREREQ_FATAL=1" PASTHRU="$(PASTHRU) TEST_FILES=\"$(TEST_FILES)\""
248 git commit -a -m "Release commit for $(VERSION)"
249 git tag v$(VERSION) -m "release v$(VERSION)"
250 $(RM_RF) $(DISTVNAME)
251 $(MAKE) $(DISTVNAME).tar$(SUFFIX)
252 $(NOECHO) $(MAKE) pushrelease FAKE_RELEASE=$(FAKE_RELEASE)
255 pushrelease$(FAKE_RELEASE) ::
256 cpan-upload $(DISTVNAME).tar$(SUFFIX)
257 git push origin v$(VERSION) HEAD
258 distdir: readmefile licensefile
259 readmefile: create_distdir
260 $(NOECHO) $(TEST_F) $(DISTVNAME)/README || $(MAKE) $(DISTVNAME)/README
261 $(DISTVNAME)/README: $(VERSION_FROM)
262 $(NOECHO) $(MKPATH) $(DISTVNAME)
263 pod2text $(VERSION_FROM) >$(DISTVNAME)/README
264 $(NOECHO) $(ABSPERLRUN) $(HELPERS)/add-to-manifest -d $(DISTVNAME) README
265 distsignature: readmefile licensefile
266 licensefile: create_distdir
267 $(NOECHO) $(TEST_F) $(DISTVNAME)/LICENSE || $(MAKE) $(DISTVNAME)/LICENSE
268 $(DISTVNAME)/LICENSE: Makefile.PL
269 $(NOECHO) $(MKPATH) $(DISTVNAME)
270 $(ABSPERLRUN) $(HELPERS)/generate-license $(AUTHORS) $(LICENSES) >$(DISTVNAME)/LICENSE
271 $(NOECHO) cd $(DISTVNAME) && $(ABSPERLRUN) $(HELPERS)/add-to-manifest LICENSE
272 $(NOECHO) $(ABSPERLRUN) $(HELPERS)/add-to-manifest -d $(DISTVNAME) LICENSE
273 disttest: distmanicheck
274 distmanicheck: create_distdir
275 cd $(DISTVNAME) && $(ABSPERLRUN) "-MExtUtils::Manifest=manicheck" -e "exit manicheck"
277 $(ABSPERLRUN) $(HELPERS)/add-changelog-heading --git $(VERSION) $(CHANGELOG)
279 cd $(DISTAR) && git pull || $(TRUE)
280 $(RM_F) $(FIRST_MAKEFILE)
283 map(sprintf(<<'END', "bump$_", ($_ || '$(V)')), @bump_targets),
285 $(ABSPERLRUN) $(HELPERS)/bump-version --git $(VERSION) %s
286 $(RM_F) $(FIRST_MAKEFILE)
300 Distar - Additions to ExtUtils::MakeMaker for dist authors
306 use ExtUtils::MakeMaker;
307 (do './maint/Makefile.PL.include' or die $@) unless -f 'META.yml';
311 F<maint/Makefile.PL.include>:
313 BEGIN { -e 'Distar' or system("git clone git://git.shadowcat.co.uk/p5sagit/Distar.git") }
314 use lib 'Distar/lib';
317 author 'A. U. Thor <author@cpan.org>';
319 manifest_include t => 'test-helper.pl';
320 manifest_include corpus => '.txt';
325 $ make bump # bump version
326 $ make bump V=2.000000 # bump to specific version
327 $ make bumpminor # bump minor version component
328 $ make bumpmajor # bump major version component
329 $ make nextrelease # add version heading to Changes file
330 $ make releasetest # build dist and test (with xt/ and RELEASE_TESTING=1)
331 $ make preflight # check that repo and file state is release ready
332 $ make release # check releasetest and preflight, commits and tags,
333 # builds and uploads to CPAN, and pushes commits and
335 $ make release FAKE_RELEASE=1
336 # builds a release INCLUDING committing and tagging,
337 # but does not upload to cpan or push anything to git
341 L<ExtUtils::MakeMaker> works well enough as development tool for
342 builting and testing, but using it to release is annoying and error prone.
343 Distar adds just enough to L<ExtUtils::MakeMaker> for it to be a usable dist
344 author tool. This includes extra commands for releasing and safety checks, and
345 automatic generation of some files. It doesn't require any non-core modules and
346 is compatible with old versions of perl.
350 =head2 author( $author )
352 Set the author to include in generated META files. Can be a single entry, or
355 =head2 manifest_include( $dir, $pattern )
357 Add a pattern to include files in the MANIFEST file, and thus in the generated
360 The pattern can be either a regex, or a path suffix. It will be applied to the
361 full path past the directory specified.
363 The default files that are always included are: F<.pm> and F<.pod> files in
364 F<lib>, F<.t> files in F<t> and F<xt>, F<.pm> files in F<t/lib> and F<xt/lib>,
365 F<Changes>, F<MANIFEST>, F<README>, F<LICENSE>, F<META.yml>, and F<.PL> files in
366 the dist root, and all files in F<maint>.
368 =head1 AUTOGENERATED FILES
372 =item F<MANIFEST.SKIP>
374 The F<MANIFEST.SKIP> will be automatically generated to exclude any files not
375 explicitly allowed via C<manifest_include> or the included defaults. It will be
376 created (or updated) at C<perl Makefile.PL> time.
380 The F<README> file will be generated at dist generation time, inside the built
381 dist. It will be generated using C<pod2text> on the main module.
383 If a F<README> file exists in the repo, it will be used directly instead of
388 =head1 MAKE COMMMANDS
392 test will be adjusted to include F<xt/> tests by default. This will only apply
393 for authors, not users installing from CPAN.
397 Releases the dist. Before releasing, checks will be done on the dist using the
398 C<preflight> and C<releasetest> commands.
400 Releasing will generate a dist tarball and upload it to CPAN using cpan-upload.
401 It will also create a git tag for the release, and push the tag and branch.
405 If release is run with FAKE_RELEASE=1 set, it will skip uploading to CPAN and
406 pushing to git. A release commit will still be created and tagged locally.
410 Performs a number of checks on the files and repository, ensuring it is in a
411 sane state to do a release. The checks are:
415 =item * All version numbers match
417 =item * The F<MANIFEST> file is up to date
419 =item * The branch is correct
421 =item * There is no existing tag for the version
423 =item * There are no unmerged upstream changes
425 =item * There are no outstanding local changes
427 =item * There is an appropriate staged Changes heading
429 =item * cpan-upload is available
435 Test the dist preparing for a release. This generates a dist dir and runs the
436 tests from inside it. This ensures all appropriate files are included inside
437 the dist. C<RELEASE_TESTING> will be set in the environment.
441 Adds an appropriate changelog heading for the release, and prompts to stage the
446 Bumps the version number. This will try to preserve the length and format of
447 the version number. The least significant digit will be incremented. Versions
448 with underscores will preserve the underscore in the same position.
450 Optionally accepts a C<V> option to set the version to a specific value.
452 The version changes will automatically be committed. Unstaged modifications to
453 the files will be left untouched.
457 The V option will be passed along to the version bumping script. It can accept
458 a space separated list of options, including an explicit version number.
466 Updates version numbers even if they do not match the current expected version
471 Attempts to convert the updated version to a stable version, removing any
476 Attempts to convert the updated version to an alpha version, adding an
477 underscore in an appropriate place.
483 Like bump, but increments the minor segment of the version. This will treat
484 numeric versions as x.yyyzzz format, incrementing the yyy segment.
488 Like bumpminor, but bumping the major segment.
492 Updates Distar and re-runs C<perl Makefile.PL>
496 IRC: #web-simple on irc.perl.org
498 Git repository: L<git://git.shadowcat.co.uk/p5sagit/Distar>
500 Git browser: L<http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=p5sagit/Distar.git;a=summary>
504 mst - Matt S. Trout (cpan:MSTROUT) <mst@shadowcat.co.uk>
508 haarg - Graham Knop (cpan:HAARG) <haarg@cpan.org>
510 ether - Karen Etheridge (cpan:ETHER) <ether@cpan.org>
512 frew - Arthur Axel "fREW" Schmidt (cpan:FREW) <frioux@gmail.com>
514 Mithaldu - Christian Walde (cpan:MITHALDU) <walde.christian@googlemail.com>
518 Copyright (c) 2011-2015 the Distar L</AUTHOR> and L</CONTRIBUTORS>
523 This library is free software and may be distributed under the same terms
524 as perl itself. See L<http://dev.perl.org/licenses/>.