3 use warnings FATAL => 'all';
5 use ExtUtils::MakeMaker ();
9 our $VERSION = '0.002000';
10 $VERSION = eval $VERSION;
12 my $MM_VER = eval $ExtUtils::MakeMaker::VERSION;
15 author manifest_include readme_generator
20 warnings->import(FATAL => 'all');
21 shift->export_to_level(1,@_);
38 '' => qr{Changes|MANIFEST|README|LICENSE|META\.yml},
39 'maint' => qr{[^.].*},
42 sub manifest_include {
46 sub readme_generator {
47 die "readme_generator unsupported" if @_ && $_[0];
50 sub write_manifest_skip {
52 my @files = @Manifest;
54 while (my ($dir, $spec) = splice(@files, 0, 2)) {
55 my $re = ($dir ? $dir.'/' : '').
56 ((ref($spec) eq 'Regexp')
60 # print ref as well as stringification in case of overload ""
61 : die "spec must be string or regexp, was: ${spec} (${\ref $spec})");
64 my $dist_name = $mm->{DISTNAME};
65 my $include = join '|', map "${_}\$", @parts;
66 my $final = "^(?:\Q$dist_name\E-v?[0-9_.]+/|(?!$include))";
67 open my $skip, '>', 'MANIFEST.SKIP'
68 or die "can't open MANIFEST.SKIP: $!";
69 print $skip "${final}\n";
76 @MM::ISA = (__PACKAGE__);
79 my ($class, $args) = @_;
80 my %test = %{$args->{test}||{}};
81 my $tests = $test{TESTS} || 't/*.t';
82 $tests !~ /\b\Q$_\E\b/ and $tests .= " $_"
83 for 'xt/*.t', 'xt/*/*.t';
84 $test{TESTS} = $tests;
85 return $class->SUPER::new({
87 MIN_PERL_VERSION => '5.006',
89 AUTHOR => ($MM_VER >= 6.5702 ? $Distar::Author : join(', ', @$Distar::Author)),
91 (exists $args->{ABSTRACT} ? () : (ABSTRACT_FROM => $args->{VERSION_FROM})),
94 realclean => { FILES => (
95 ($args->{realclean}{FILES}||'')
96 . ' Distar/ MANIFEST.SKIP MANIFEST MANIFEST.bak'
103 `git ls-files --error-unmatch MANIFEST.SKIP 2>&1`;
104 my $maniskip_tracked = !$?;
106 Distar::write_manifest_skip($self)
107 unless $maniskip_tracked;
108 $self->SUPER::flush(@_);
111 sub special_targets {
113 my $targets = $self->SUPER::special_targets(@_);
114 my $phony_targets = join ' ', qw(
129 $targets =~ s/^(\.PHONY *:.*)/$1 $phony_targets/m;
135 my $pre_tar = $self->{TAR};
136 my $out = $self->SUPER::init_dist(@_);
138 my $tar = $self->{TAR};
141 my $version = `$tar --version`;
142 if ($version =~ /GNU tar/) {
145 elsif (!$pre_tar && `gtar --version`) {
149 my $tarflags = $self->{TARFLAGS};
150 if (my ($flags) = $tarflags =~ /^-?([cvhlLf]+)$/) {
151 if ($flags =~ s/c// && $flags =~ s/f//) {
152 $tarflags = '--format=ustar -c'.$flags.'f';
154 $tarflags = '--owner=0 --group=0 '.$tarflags;
166 $warn .= ($warn ? ' and ' : '').'gid('.(0+$)).')';
169 warn "$warn too large! Max is ".(2**21-1).".\n"
170 ."Dist creation will likely fail. Install GNU tar to work around.\n";
175 $self->{TARFLAGS} = $tarflags;
182 my $out = $self->SUPER::tarfile_target(@_);
183 my $verify = <<'END_FRAG';
184 $(ABSPERLRUN) $(HELPERS)/verify-tarball $(DISTVNAME).tar $(DISTVNAME)/MANIFEST --tar="$(TAR)"
186 $out =~ s{(\$\(TAR\).*\n)}{$1$verify};
194 if (open my $fh, '<', 'maint/Makefile.include') {
195 $include = "\n# --- Makefile.include:\n\n" . do { local $/; <$fh> };
196 $include =~ s/\n?\z/\n/;
200 grep { $include !~ /^bump$_(?: +\w+)*:/m } ('', 'minor', 'major');
202 my $distar = File::Spec->catdir(
203 File::Spec->catpath((File::Spec->splitpath(__FILE__))[0,1], ''),
206 my $helpers = File::Spec->catdir($distar, 'helpers');
209 DISTAR => $self->quote_literal($distar),
210 HELPERS => $self->quote_literal($helpers),
211 REMAKE => join(' ', '$(PERLRUN)', '-I$(DISTAR)/lib', '-mDistar', 'Makefile.PL', map { $self->quote_literal($_) } @ARGV),
212 BRANCH => $self->{BRANCH} ||= 'master',
213 CHANGELOG => $self->{CHANGELOG} ||= 'Changes',
214 DEV_NULL_STDOUT => ($self->{DEV_NULL} ? '>'.File::Spec->devnull : ''),
215 DISTTEST_MAKEFILE_PARAMS => '',
218 my $dist_test = $self->SUPER::dist_test(@_);
219 $dist_test =~ s/(\bMakefile\.PL\b)/$1 \$(DISTTEST_MAKEFILE_PARAMS)/;
223 "\n\n# --- Distar section:\n\n",
224 (map "$_ = $vars{$_}\n", sort keys %vars),
227 preflight: check-version check-manifest check-cpan-upload
228 $(ABSPERLRUN) $(HELPERS)/preflight $(VERSION) --changelog=$(CHANGELOG) --branch=$(BRANCH)
230 $(ABSPERLRUN) $(HELPERS)/check-version $(VERSION) $(TO_INST_PM) $(EXE_FILES)
232 $(ABSPERLRUN) $(HELPERS)/check-manifest
234 $(NOECHO) cpan-upload -h $(DEV_NULL_STDOUT)
236 $(MAKE) disttest RELEASE_TESTING=1 DISTTEST_MAKEFILE_PARAMS="PREREQ_FATAL=1" PASTHRU="$(PASTHRU) TEST_FILES=\"$(TEST_FILES)\""
239 git commit -a -m "Release commit for $(VERSION)"
240 git tag v$(VERSION) -m "release v$(VERSION)"
241 $(RM_RF) $(DISTVNAME)
242 $(MAKE) $(DISTVNAME).tar$(SUFFIX)
243 $(NOECHO) $(MAKE) pushrelease FAKE_RELEASE=$(FAKE_RELEASE)
246 pushrelease$(FAKE_RELEASE) ::
247 cpan-upload $(DISTVNAME).tar$(SUFFIX)
248 git push origin v$(VERSION) HEAD
250 readmefile: create_distdir
251 $(NOECHO) $(TEST_F) $(DISTVNAME)/README || $(MAKE) $(DISTVNAME)/README
252 $(DISTVNAME)/README: $(VERSION_FROM)
253 $(NOECHO) $(MKPATH) $(DISTVNAME)
254 pod2text $(VERSION_FROM) >$(DISTVNAME)/README
255 $(NOECHO) $(ABSPERLRUN) $(HELPERS)/add-to-manifest -d $(DISTVNAME) README
256 distsignature: readmefile
257 disttest: distmanicheck
258 distmanicheck: create_distdir
259 cd $(DISTVNAME) && $(ABSPERLRUN) "-MExtUtils::Manifest=manicheck" -e "exit manicheck"
261 $(ABSPERLRUN) $(HELPERS)/add-changelog-heading --git $(VERSION) $(CHANGELOG)
263 cd $(DISTAR) && git pull || $(TRUE)
264 $(RM_F) $(FIRST_MAKEFILE)
267 map(sprintf(<<'END', "bump$_", ($_ || '$(V)')), @bump_targets),
269 $(ABSPERLRUN) $(HELPERS)/bump-version --git $(VERSION) %s
270 $(RM_F) $(FIRST_MAKEFILE)
284 Distar - Additions to ExtUtils::MakeMaker for dist authors
290 use ExtUtils::MakeMaker;
291 (do './maint/Makefile.PL.include' or die $@) unless -f 'META.yml';
295 F<maint/Makefile.PL.include>:
297 BEGIN { -e 'Distar' or system("git clone git://git.shadowcat.co.uk/p5sagit/Distar.git") }
298 use lib 'Distar/lib';
301 author 'A. U. Thor <author@cpan.org>';
303 manifest_include t => 'test-helper.pl';
304 manifest_include corpus => '.txt';
309 $ make bump # bump version
310 $ make bump V=2.000000 # bump to specific version
311 $ make bumpminor # bump minor version component
312 $ make bumpmajor # bump major version component
313 $ make nextrelease # add version heading to Changes file
314 $ make releasetest # build dist and test (with xt/ and RELEASE_TESTING=1)
315 $ make preflight # check that repo and file state is release ready
316 $ make release # check releasetest and preflight, commits and tags,
317 # builds and uploads to CPAN, and pushes commits and
319 $ make release FAKE_RELEASE=1
320 # builds a release INCLUDING committing and tagging,
321 # but does not upload to cpan or push anything to git
325 L<ExtUtils::MakeMaker> works well enough as development tool for
326 builting and testing, but using it to release is annoying and error prone.
327 Distar adds just enough to L<ExtUtils::MakeMaker> for it to be a usable dist
328 author tool. This includes extra commands for releasing and safety checks, and
329 automatic generation of some files. It doesn't require any non-core modules and
330 is compatible with old versions of perl.
334 =head2 author( $author )
336 Set the author to include in generated META files. Can be a single entry, or
339 =head2 manifest_include( $dir, $pattern )
341 Add a pattern to include files in the MANIFEST file, and thus in the generated
344 The pattern can be either a regex, or a path suffix. It will be applied to the
345 full path past the directory specified.
347 The default files that are always included are: F<.pm> and F<.pod> files in
348 F<lib>, F<.t> files in F<t> and F<xt>, F<.pm> files in F<t/lib> and F<xt/lib>,
349 F<Changes>, F<MANIFEST>, F<README>, F<LICENSE>, F<META.yml>, and F<.PL> files in
350 the dist root, and all files in F<maint>.
352 =head1 AUTOGENERATED FILES
356 =item F<MANIFEST.SKIP>
358 The F<MANIFEST.SKIP> will be automatically generated to exclude any files not
359 explicitly allowed via C<manifest_include> or the included defaults. It will be
360 created (or updated) at C<perl Makefile.PL> time.
364 The F<README> file will be generated at dist generation time, inside the built
365 dist. It will be generated using C<pod2text> on the main module.
367 If a F<README> file exists in the repo, it will be used directly instead of
372 =head1 MAKE COMMMANDS
376 test will be adjusted to include F<xt/> tests by default. This will only apply
377 for authors, not users installing from CPAN.
381 Releases the dist. Before releasing, checks will be done on the dist using the
382 C<preflight> and C<releasetest> commands.
384 Releasing will generate a dist tarball and upload it to CPAN using cpan-upload.
385 It will also create a git tag for the release, and push the tag and branch.
389 If release is run with FAKE_RELEASE=1 set, it will skip uploading to CPAN and
390 pushing to git. A release commit will still be created and tagged locally.
394 Performs a number of checks on the files and repository, ensuring it is in a
395 sane state to do a release. The checks are:
399 =item * All version numbers match
401 =item * The F<MANIFEST> file is up to date
403 =item * The branch is correct
405 =item * There is no existing tag for the version
407 =item * There are no unmerged upstream changes
409 =item * There are no outstanding local changes
411 =item * There is an appropriate staged Changes heading
413 =item * cpan-upload is available
419 Test the dist preparing for a release. This generates a dist dir and runs the
420 tests from inside it. This ensures all appropriate files are included inside
421 the dist. C<RELEASE_TESTING> will be set in the environment.
425 Adds an appropriate changelog heading for the release, and prompts to stage the
430 Bumps the version number. This will try to preserve the length and format of
431 the version number. The least significant digit will be incremented. Versions
432 with underscores will preserve the underscore in the same position.
434 Optionally accepts a C<V> option to set the version to a specific value.
436 The version changes will automatically be committed. Unstaged modifications to
437 the files will be left untouched.
441 The V option will be passed along to the version bumping script. It can accept
442 a space separated list of options, including an explicit version number.
450 Updates version numbers even if they do not match the current expected version
455 Attempts to convert the updated version to a stable version, removing any
460 Attempts to convert the updated version to an alpha version, adding an
461 underscore in an appropriate place.
467 Like bump, but increments the minor segment of the version. This will treat
468 numeric versions as x.yyyzzz format, incrementing the yyy segment.
472 Like bumpminor, but bumping the major segment.
476 Updates Distar and re-runs C<perl Makefile.PL>
480 IRC: #web-simple on irc.perl.org
482 Git repository: L<git://git.shadowcat.co.uk/p5sagit/Distar>
484 Git browser: L<http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=p5sagit/Distar.git;a=summary>
488 mst - Matt S. Trout (cpan:MSTROUT) <mst@shadowcat.co.uk>
492 haarg - Graham Knop (cpan:HAARG) <haarg@cpan.org>
494 ether - Karen Etheridge (cpan:ETHER) <ether@cpan.org>
496 frew - Arthur Axel "fREW" Schmidt (cpan:FREW) <frioux@gmail.com>
498 Mithaldu - Christian Walde (cpan:MITHALDU) <walde.christian@googlemail.com>
502 Copyright (c) 2011-2015 the Distar L</AUTHOR> and L</CONTRIBUTORS>
507 This library is free software and may be distributed under the same terms
508 as perl itself. See L<http://dev.perl.org/licenses/>.