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',
88 AUTHOR => ($MM_VER >= 6.5702 ? $Distar::Author : join(', ', @$Distar::Author)),
89 (exists $args->{ABSTRACT} ? () : (ABSTRACT_FROM => $args->{VERSION_FROM})),
92 realclean => { FILES => (
93 ($args->{realclean}{FILES}||'')
94 . ' Distar/ MANIFEST.SKIP MANIFEST MANIFEST.bak'
101 `git ls-files --error-unmatch MANIFEST.SKIP 2>&1`;
102 my $maniskip_tracked = !$?;
104 Distar::write_manifest_skip($self)
105 unless $maniskip_tracked;
106 $self->SUPER::flush(@_);
109 sub special_targets {
111 my $targets = $self->SUPER::special_targets(@_);
112 my $phony_targets = join ' ', qw(
127 $targets =~ s/^(\.PHONY *:.*)/$1 $phony_targets/m;
133 my $pre_tar = $self->{TAR};
134 my $out = $self->SUPER::init_dist(@_);
136 my $tar = $self->{TAR};
139 my $version = `$tar --version`;
140 if ($version =~ /GNU tar/) {
143 elsif (!$pre_tar && `gtar --version`) {
147 my $tarflags = $self->{TARFLAGS};
148 if (my ($flags) = $tarflags =~ /^-?([cvhlLf]+)$/) {
149 if ($flags =~ s/c// && $flags =~ s/f//) {
150 $tarflags = '--format=ustar -c'.$flags.'f';
152 $tarflags = '--owner=0 --group=0 '.$tarflags;
164 $warn .= ($warn ? ' and ' : '').'gid('.(0+$)).')';
167 warn "$warn too large! Max is ".(2**21-1).".\n"
168 ."Dist creation will likely fail. Install GNU tar to work around.\n";
173 $self->{TARFLAGS} = $tarflags;
180 my $out = $self->SUPER::tarfile_target(@_);
181 my $verify = <<'END_FRAG';
182 $(ABSPERLRUN) $(HELPERS)/verify-tarball $(DISTVNAME).tar $(DISTVNAME)/MANIFEST --tar="$(TAR)"
184 $out =~ s{(\$\(TAR\).*\n)}{$1$verify};
192 if (open my $fh, '<', 'maint/Makefile.include') {
193 $include = "\n# --- Makefile.include:\n\n" . do { local $/; <$fh> };
194 $include =~ s/\n?\z/\n/;
198 grep { $include !~ /^bump$_(?: +\w+)*:/m } ('', 'minor', 'major');
200 my $distar = File::Spec->catdir(
201 File::Spec->catpath((File::Spec->splitpath(__FILE__))[0,1], ''),
204 my $helpers = File::Spec->catdir($distar, 'helpers');
207 DISTAR => $self->quote_literal($distar),
208 HELPERS => $self->quote_literal($helpers),
209 REMAKE => join(' ', '$(PERLRUN)', '-I$(DISTAR)/lib', '-mDistar', 'Makefile.PL', map { $self->quote_literal($_) } @ARGV),
210 BRANCH => $self->{BRANCH} ||= 'master',
211 CHANGELOG => $self->{CHANGELOG} ||= 'Changes',
212 DEV_NULL_STDOUT => ($self->{DEV_NULL} ? '>'.File::Spec->devnull : ''),
213 DISTTEST_MAKEFILE_PARAMS => '',
216 my $dist_test = $self->SUPER::dist_test(@_);
217 $dist_test =~ s/(\bMakefile\.PL\b)/$1 \$(DISTTEST_MAKEFILE_PARAMS)/;
221 "\n\n# --- Distar section:\n\n",
222 (map "$_ = $vars{$_}\n", sort keys %vars),
225 preflight: check-version check-manifest check-cpan-upload
226 $(ABSPERLRUN) $(HELPERS)/preflight $(VERSION) --changelog=$(CHANGELOG) --branch=$(BRANCH)
228 $(ABSPERLRUN) $(HELPERS)/check-version $(VERSION) $(TO_INST_PM) $(EXE_FILES)
230 $(ABSPERLRUN) $(HELPERS)/check-manifest
232 $(NOECHO) cpan-upload -h $(DEV_NULL_STDOUT)
234 $(MAKE) disttest RELEASE_TESTING=1 DISTTEST_MAKEFILE_PARAMS="PREREQ_FATAL=1" PASTHRU="$(PASTHRU) TEST_FILES=\"$(TEST_FILES)\""
237 git commit -a -m "Release commit for $(VERSION)"
238 git tag v$(VERSION) -m "release v$(VERSION)"
239 $(RM_RF) $(DISTVNAME)
240 $(MAKE) $(DISTVNAME).tar$(SUFFIX)
241 $(NOECHO) $(MAKE) pushrelease FAKE_RELEASE=$(FAKE_RELEASE)
244 pushrelease$(FAKE_RELEASE) ::
245 cpan-upload $(DISTVNAME).tar$(SUFFIX)
246 git push origin v$(VERSION) HEAD
248 readmefile: create_distdir
249 $(NOECHO) $(TEST_F) $(DISTVNAME)/README || $(MAKE) $(DISTVNAME)/README
250 $(DISTVNAME)/README: $(VERSION_FROM)
251 $(NOECHO) $(MKPATH) $(DISTVNAME)
252 pod2text $(VERSION_FROM) >$(DISTVNAME)/README
253 $(NOECHO) $(ABSPERLRUN) $(HELPERS)/add-to-manifest -d $(DISTVNAME) README
254 distsignature: readmefile
255 disttest: distmanicheck
256 distmanicheck: create_distdir
257 cd $(DISTVNAME) && $(ABSPERLRUN) "-MExtUtils::Manifest=manicheck" -e "exit manicheck"
259 $(ABSPERLRUN) $(HELPERS)/add-changelog-heading --git $(VERSION) $(CHANGELOG)
261 cd $(DISTAR) && git pull || $(TRUE)
262 $(RM_F) $(FIRST_MAKEFILE)
265 map(sprintf(<<'END', "bump$_", ($_ || '$(V)')), @bump_targets),
267 $(ABSPERLRUN) $(HELPERS)/bump-version --git $(VERSION) %s
268 $(RM_F) $(FIRST_MAKEFILE)
282 Distar - Additions to ExtUtils::MakeMaker for dist authors
288 use ExtUtils::MakeMaker;
289 (do './maint/Makefile.PL.include' or die $@) unless -f 'META.yml';
293 F<maint/Makefile.PL.include>:
295 BEGIN { -e 'Distar' or system("git clone git://git.shadowcat.co.uk/p5sagit/Distar.git") }
296 use lib 'Distar/lib';
299 author 'A. U. Thor <author@cpan.org>';
301 manifest_include t => 'test-helper.pl';
302 manifest_include corpus => '.txt';
307 $ make bump # bump version
308 $ make bump V=2.000000 # bump to specific version
309 $ make bumpminor # bump minor version component
310 $ make bumpmajor # bump major version component
311 $ make nextrelease # add version heading to Changes file
312 $ make releasetest # build dist and test (with xt/ and RELEASE_TESTING=1)
313 $ make preflight # check that repo and file state is release ready
314 $ make release # check releasetest and preflight, commits and tags,
315 # builds and uploads to CPAN, and pushes commits and
317 $ make release FAKE_RELEASE=1
318 # builds a release INCLUDING committing and tagging,
319 # but does not upload to cpan or push anything to git
323 L<ExtUtils::MakeMaker> works well enough as development tool for
324 builting and testing, but using it to release is annoying and error prone.
325 Distar adds just enough to L<ExtUtils::MakeMaker> for it to be a usable dist
326 author tool. This includes extra commands for releasing and safety checks, and
327 automatic generation of some files. It doesn't require any non-core modules and
328 is compatible with old versions of perl.
332 =head2 author( $author )
334 Set the author to include in generated META files. Can be a single entry, or
337 =head2 manifest_include( $dir, $pattern )
339 Add a pattern to include files in the MANIFEST file, and thus in the generated
342 The pattern can be either a regex, or a path suffix. It will be applied to the
343 full path past the directory specified.
345 The default files that are always included are: F<.pm> and F<.pod> files in
346 F<lib>, F<.t> files in F<t> and F<xt>, F<.pm> files in F<t/lib> and F<xt/lib>,
347 F<Changes>, F<MANIFEST>, F<README>, F<LICENSE>, F<META.yml>, and F<.PL> files in
348 the dist root, and all files in F<maint>.
350 =head1 AUTOGENERATED FILES
354 =item F<MANIFEST.SKIP>
356 The F<MANIFEST.SKIP> will be automatically generated to exclude any files not
357 explicitly allowed via C<manifest_include> or the included defaults. It will be
358 created (or updated) at C<perl Makefile.PL> time.
362 The F<README> file will be generated at dist generation time, inside the built
363 dist. It will be generated using C<pod2text> on the main module.
365 If a F<README> file exists in the repo, it will be used directly instead of
370 =head1 MAKE COMMMANDS
374 test will be adjusted to include F<xt/> tests by default. This will only apply
375 for authors, not users installing from CPAN.
379 Releases the dist. Before releasing, checks will be done on the dist using the
380 C<preflight> and C<releasetest> commands.
382 Releasing will generate a dist tarball and upload it to CPAN using cpan-upload.
383 It will also create a git tag for the release, and push the tag and branch.
387 If release is run with FAKE_RELEASE=1 set, it will skip uploading to CPAN and
388 pushing to git. A release commit will still be created and tagged locally.
392 Performs a number of checks on the files and repository, ensuring it is in a
393 sane state to do a release. The checks are:
397 =item * All version numbers match
399 =item * The F<MANIFEST> file is up to date
401 =item * The branch is correct
403 =item * There is no existing tag for the version
405 =item * There are no unmerged upstream changes
407 =item * There are no outstanding local changes
409 =item * There is an appropriate staged Changes heading
411 =item * cpan-upload is available
417 Test the dist preparing for a release. This generates a dist dir and runs the
418 tests from inside it. This ensures all appropriate files are included inside
419 the dist. C<RELEASE_TESTING> will be set in the environment.
423 Adds an appropriate changelog heading for the release, and prompts to stage the
428 Bumps the version number. This will try to preserve the length and format of
429 the version number. The least significant digit will be incremented. Versions
430 with underscores will preserve the underscore in the same position.
432 Optionally accepts a C<V> option to set the version to a specific value.
434 The version changes will automatically be committed. Unstaged modifications to
435 the files will be left untouched.
439 The V option will be passed along to the version bumping script. It can accept
440 a space separated list of options, including an explicit version number.
448 Updates version numbers even if they do not match the current expected version
453 Attempts to convert the updated version to a stable version, removing any
458 Attempts to convert the updated version to an alpha version, adding an
459 underscore in an appropriate place.
465 Like bump, but increments the minor segment of the version. This will treat
466 numeric versions as x.yyyzzz format, incrementing the yyy segment.
470 Like bumpminor, but bumping the major segment.
474 Updates Distar and re-runs C<perl Makefile.PL>
478 IRC: #web-simple on irc.perl.org
480 Git repository: L<git://git.shadowcat.co.uk/p5sagit/Distar>
482 Git browser: L<http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=p5sagit/Distar.git;a=summary>
486 mst - Matt S. Trout (cpan:MSTROUT) <mst@shadowcat.co.uk>
490 haarg - Graham Knop (cpan:HAARG) <haarg@cpan.org>
492 ether - Karen Etheridge (cpan:ETHER) <ether@cpan.org>
494 frew - Arthur Axel "fREW" Schmidt (cpan:FREW) <frioux@gmail.com>
496 Mithaldu - Christian Walde (cpan:MITHALDU) <walde.christian@googlemail.com>
500 Copyright (c) 2011-2015 the Distar L</AUTHOR> and L</CONTRIBUTORS>
505 This library is free software and may be distributed under the same terms
506 as perl itself. See L<http://dev.perl.org/licenses/>.