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 $out = $self->SUPER::tarfile_target(@_);
134 my $verify = <<'END_FRAG';
135 $(ABSPERLRUN) $(HELPERS)/verify-tarball $(DISTVNAME).tar $(DISTVNAME)/MANIFEST --tar="$(TAR)"
137 $out =~ s{(\$\(TAR\).*\n)}{$1$verify};
145 if (open my $fh, '<', 'maint/Makefile.include') {
146 $include = "\n# --- Makefile.include:\n\n" . do { local $/; <$fh> };
147 $include =~ s/\n?\z/\n/;
151 grep { $include !~ /^bump$_(?: +\w+)*:/m } ('', 'minor', 'major');
153 my $distar = File::Spec->catdir(
154 File::Spec->catpath((File::Spec->splitpath(__FILE__))[0,1], ''),
157 my $helpers = File::Spec->catdir($distar, 'helpers');
160 DISTAR => $self->quote_literal($distar),
161 HELPERS => $self->quote_literal($helpers),
162 REMAKE => join(' ', '$(PERLRUN)', '-I$(DISTAR)/lib', '-mDistar', 'Makefile.PL', map { $self->quote_literal($_) } @ARGV),
163 BRANCH => $self->{BRANCH} ||= 'master',
164 CHANGELOG => $self->{CHANGELOG} ||= 'Changes',
165 DEV_NULL_STDOUT => ($self->{DEV_NULL} ? '>'.File::Spec->devnull : ''),
166 DISTTEST_MAKEFILE_PARAMS => '',
169 my $dist_test = $self->SUPER::dist_test(@_);
170 $dist_test =~ s/(\bMakefile\.PL\b)/$1 \$(DISTTEST_MAKEFILE_PARAMS)/;
174 "\n\n# --- Distar section:\n\n",
175 (map "$_ = $vars{$_}\n", sort keys %vars),
178 preflight: check-version check-manifest check-cpan-upload
179 $(ABSPERLRUN) $(HELPERS)/preflight $(VERSION) --changelog=$(CHANGELOG) --branch=$(BRANCH)
181 $(ABSPERLRUN) $(HELPERS)/check-version $(VERSION) $(TO_INST_PM) $(EXE_FILES)
183 $(ABSPERLRUN) $(HELPERS)/check-manifest
185 $(NOECHO) cpan-upload -h $(DEV_NULL_STDOUT)
187 $(MAKE) disttest RELEASE_TESTING=1 DISTTEST_MAKEFILE_PARAMS="PREREQ_FATAL=1" PASTHRU="$(PASTHRU) TEST_FILES=\"$(TEST_FILES)\""
190 git commit -a -m "Release commit for $(VERSION)"
191 git tag v$(VERSION) -m "release v$(VERSION)"
192 $(RM_RF) $(DISTVNAME)
193 $(MAKE) $(DISTVNAME).tar$(SUFFIX)
194 $(NOECHO) $(MAKE) pushrelease FAKE_RELEASE=$(FAKE_RELEASE)
197 pushrelease$(FAKE_RELEASE) ::
198 cpan-upload $(DISTVNAME).tar$(SUFFIX)
199 git push origin v$(VERSION) HEAD
201 readmefile: create_distdir
202 $(NOECHO) $(TEST_F) $(DISTVNAME)/README || $(MAKE) $(DISTVNAME)/README
203 $(DISTVNAME)/README: $(VERSION_FROM)
204 $(NOECHO) $(MKPATH) $(DISTVNAME)
205 pod2text $(VERSION_FROM) >$(DISTVNAME)/README
206 $(NOECHO) $(ABSPERLRUN) $(HELPERS)/add-to-manifest -d $(DISTVNAME) README
207 distsignature: readmefile
208 disttest: distmanicheck
209 distmanicheck: create_distdir
210 cd $(DISTVNAME) && $(ABSPERLRUN) "-MExtUtils::Manifest=manicheck" -e "exit manicheck"
212 $(ABSPERLRUN) $(HELPERS)/add-changelog-heading --git $(VERSION) $(CHANGELOG)
214 cd $(DISTAR) && git pull || $(TRUE)
215 $(RM_F) $(FIRST_MAKEFILE)
218 map(sprintf(<<'END', "bump$_", ($_ || '$(V)')), @bump_targets),
220 $(ABSPERLRUN) $(HELPERS)/bump-version --git $(VERSION) %s
221 $(RM_F) $(FIRST_MAKEFILE)
235 Distar - Additions to ExtUtils::MakeMaker for dist authors
241 use ExtUtils::MakeMaker;
242 (do './maint/Makefile.PL.include' or die $@) unless -f 'META.yml';
246 F<maint/Makefile.PL.include>:
248 BEGIN { -e 'Distar' or system("git clone git://git.shadowcat.co.uk/p5sagit/Distar.git") }
249 use lib 'Distar/lib';
252 author 'A. U. Thor <author@cpan.org>';
254 manifest_include t => 'test-helper.pl';
255 manifest_include corpus => '.txt';
260 $ make bump # bump version
261 $ make bump V=2.000000 # bump to specific version
262 $ make bumpminor # bump minor version component
263 $ make bumpmajor # bump major version component
264 $ make nextrelease # add version heading to Changes file
265 $ make releasetest # build dist and test (with xt/ and RELEASE_TESTING=1)
266 $ make preflight # check that repo and file state is release ready
267 $ make release # check releasetest and preflight, commits and tags,
268 # builds and uploads to CPAN, and pushes commits and
270 $ make release FAKE_RELEASE=1
271 # builds a release INCLUDING committing and tagging,
272 # but does not upload to cpan or push anything to git
276 L<ExtUtils::MakeMaker> works well enough as development tool for
277 builting and testing, but using it to release is annoying and error prone.
278 Distar adds just enough to L<ExtUtils::MakeMaker> for it to be a usable dist
279 author tool. This includes extra commands for releasing and safety checks, and
280 automatic generation of some files. It doesn't require any non-core modules and
281 is compatible with old versions of perl.
285 =head2 author( $author )
287 Set the author to include in generated META files. Can be a single entry, or
290 =head2 manifest_include( $dir, $pattern )
292 Add a pattern to include files in the MANIFEST file, and thus in the generated
295 The pattern can be either a regex, or a path suffix. It will be applied to the
296 full path past the directory specified.
298 The default files that are always included are: F<.pm> and F<.pod> files in
299 F<lib>, F<.t> files in F<t> and F<xt>, F<.pm> files in F<t/lib> and F<xt/lib>,
300 F<Changes>, F<MANIFEST>, F<README>, F<LICENSE>, F<META.yml>, and F<.PL> files in
301 the dist root, and all files in F<maint>.
303 =head1 AUTOGENERATED FILES
307 =item F<MANIFEST.SKIP>
309 The F<MANIFEST.SKIP> will be automatically generated to exclude any files not
310 explicitly allowed via C<manifest_include> or the included defaults. It will be
311 created (or updated) at C<perl Makefile.PL> time.
315 The F<README> file will be generated at dist generation time, inside the built
316 dist. It will be generated using C<pod2text> on the main module.
318 If a F<README> file exists in the repo, it will be used directly instead of
323 =head1 MAKE COMMMANDS
327 test will be adjusted to include F<xt/> tests by default. This will only apply
328 for authors, not users installing from CPAN.
332 Releases the dist. Before releasing, checks will be done on the dist using the
333 C<preflight> and C<releasetest> commands.
335 Releasing will generate a dist tarball and upload it to CPAN using cpan-upload.
336 It will also create a git tag for the release, and push the tag and branch.
340 If release is run with FAKE_RELEASE=1 set, it will skip uploading to CPAN and
341 pushing to git. A release commit will still be created and tagged locally.
345 Performs a number of checks on the files and repository, ensuring it is in a
346 sane state to do a release. The checks are:
350 =item * All version numbers match
352 =item * The F<MANIFEST> file is up to date
354 =item * The branch is correct
356 =item * There is no existing tag for the version
358 =item * There are no unmerged upstream changes
360 =item * There are no outstanding local changes
362 =item * There is an appropriate staged Changes heading
364 =item * cpan-upload is available
370 Test the dist preparing for a release. This generates a dist dir and runs the
371 tests from inside it. This ensures all appropriate files are included inside
372 the dist. C<RELEASE_TESTING> will be set in the environment.
376 Adds an appropriate changelog heading for the release, and prompts to stage the
381 Bumps the version number. This will try to preserve the length and format of
382 the version number. The least significant digit will be incremented. Versions
383 with underscores will preserve the underscore in the same position.
385 Optionally accepts a C<V> option to set the version to a specific value.
387 The version changes will automatically be committed. Unstaged modifications to
388 the files will be left untouched.
392 The V option will be passed along to the version bumping script. It can accept
393 a space separated list of options, including an explicit version number.
401 Updates version numbers even if they do not match the current expected version
406 Attempts to convert the updated version to a stable version, removing any
411 Attempts to convert the updated version to an alpha version, adding an
412 underscore in an appropriate place.
418 Like bump, but increments the minor segment of the version. This will treat
419 numeric versions as x.yyyzzz format, incrementing the yyy segment.
423 Like bumpminor, but bumping the major segment.
427 Updates Distar and re-runs C<perl Makefile.PL>
431 IRC: #web-simple on irc.perl.org
433 Git repository: L<git://git.shadowcat.co.uk/p5sagit/Distar>
435 Git browser: L<http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=p5sagit/Distar.git;a=summary>
439 mst - Matt S. Trout (cpan:MSTROUT) <mst@shadowcat.co.uk>
443 haarg - Graham Knop (cpan:HAARG) <haarg@cpan.org>
445 ether - Karen Etheridge (cpan:ETHER) <ether@cpan.org>
447 frew - Arthur Axel "fREW" Schmidt (cpan:FREW) <frioux@gmail.com>
449 Mithaldu - Christian Walde (cpan:MITHALDU) <walde.christian@googlemail.com>
453 Copyright (c) 2011-2015 the Distar L</AUTHOR> and L</CONTRIBUTORS>
458 This library is free software and may be distributed under the same terms
459 as perl itself. See L<http://dev.perl.org/licenses/>.