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 return $class->SUPER::new({
82 MIN_PERL_VERSION => '5.006',
83 AUTHOR => ($MM_VER >= 6.5702 ? $Distar::Author : join(', ', @$Distar::Author)),
84 (exists $args->{ABSTRACT} ? () : (ABSTRACT_FROM => $args->{VERSION_FROM})),
86 test => { TESTS => ($args->{test}{TESTS}||'t/*.t').' xt/*.t xt/*/*.t' },
87 realclean => { FILES => (
88 ($args->{realclean}{FILES}||'')
89 . ' Distar/ MANIFEST.SKIP MANIFEST MANIFEST.bak'
96 `git ls-files --error-unmatch MANIFEST.SKIP 2>&1`;
97 my $maniskip_tracked = !$?;
99 Distar::write_manifest_skip($self)
100 unless $maniskip_tracked;
101 $self->SUPER::flush(@_);
104 sub special_targets {
106 my $targets = $self->SUPER::special_targets(@_);
107 my $phony_targets = join ' ', qw(
122 $targets =~ s/^(\.PHONY *:.*)/$1 $phony_targets/m;
130 if (open my $fh, '<', 'maint/Makefile.include') {
131 $include = "\n# --- Makefile.include:\n\n" . do { local $/; <$fh> };
132 $include =~ s/\n?\z/\n/;
136 grep { $include !~ /^bump$_(?: +\w+)*:/m } ('', 'minor', 'major');
138 my $distar = File::Spec->catdir(
139 File::Spec->catpath((File::Spec->splitpath(__FILE__))[0,1], ''),
142 my $helpers = File::Spec->catdir($distar, 'helpers');
145 DISTAR => $self->quote_literal($distar),
146 HELPERS => $self->quote_literal($helpers),
147 REMAKE => join(' ', '$(PERLRUN)', '-I$(DISTAR)/lib', '-mDistar', 'Makefile.PL', map { $self->quote_literal($_) } @ARGV),
148 BRANCH => $self->{BRANCH} ||= 'master',
149 CHANGELOG => $self->{CHANGELOG} ||= 'Changes',
150 DEV_NULL_STDOUT => ($self->{DEV_NULL} ? '>'.File::Spec->devnull : ''),
155 $self->SUPER::dist_test(@_),
156 "\n\n# --- Distar section:\n\n",
157 (map "$_ = $vars{$_}\n", sort keys %vars),
160 preflight: check-version check-manifest check-cpan-upload
161 $(ABSPERLRUN) $(HELPERS)/preflight $(VERSION) --changelog=$(CHANGELOG) --branch=$(BRANCH)
163 $(ABSPERLRUN) $(HELPERS)/check-version $(VERSION) $(TO_INST_PM) $(EXE_FILES)
165 $(ABSPERLRUN) $(HELPERS)/check-manifest
167 $(NOECHO) cpan-upload -h $(DEV_NULL_STDOUT)
169 $(MAKE) disttest RELEASE_TESTING=1 PASTHRU="$(PASTHRU) TEST_FILES=\"$(TEST_FILES)\""
172 git commit -a -m "Release commit for $(VERSION)"
173 git tag v$(VERSION) -m "release v$(VERSION)"
174 $(RM_RF) $(DISTVNAME)
175 $(MAKE) $(DISTVNAME).tar$(SUFFIX)
176 $(NOECHO) $(MAKE) pushrelease FAKE_RELEASE=$(FAKE_RELEASE)
179 pushrelease$(FAKE_RELEASE) ::
180 cpan-upload $(DISTVNAME).tar$(SUFFIX)
181 git push origin v$(VERSION) HEAD
183 readmefile: create_distdir
184 $(NOECHO) $(MAKE) $(DISTVNAME)/README
185 $(DISTVNAME)/README: $(VERSION_FROM)
186 $(NOECHO) $(MKPATH) $(DISTVNAME)
187 pod2text $(VERSION_FROM) >$(DISTVNAME)/README
188 $(NOECHO) $(ABSPERLRUN) $(HELPERS)/add-to-manifest -d $(DISTVNAME) README
189 disttest: distmanicheck
190 distmanicheck: create_distdir
191 cd $(DISTVNAME) && $(ABSPERLRUN) "-MExtUtils::Manifest=manicheck" -e "exit manicheck"
193 $(ABSPERLRUN) $(HELPERS)/add-changelog-heading --git $(VERSION) $(CHANGELOG)
195 cd $(DISTAR) && git pull
196 $(RM_F) $(FIRST_MAKEFILE)
199 map(sprintf(<<'END', "bump$_", ($_ || '$(V)')), @bump_targets),
201 $(ABSPERLRUN) $(HELPERS)/bump-version --git $(VERSION) %s
202 $(RM_F) $(FIRST_MAKEFILE)
216 Distar - Additions to ExtUtils::MakeMaker for dist authors
222 use ExtUtils::MakeMaker;
223 (do 'maint/Makefile.PL.include' or die $@) unless -f 'META.yml';
227 F<maint/Makefile.PL.include>:
229 BEGIN { -e 'Distar' or system("git clone git://git.shadowcat.co.uk/p5sagit/Distar.git") }
230 use lib 'Distar/lib';
233 author 'A. U. Thor <author@cpan.org>';
235 manifest_include t => 'test-helper.pl';
236 manifest_include corpus => '.txt';
241 $ make bump # bump version
242 $ make bump V=2.000000 # bump to specific version
243 $ make bumpminor # bump minor version component
244 $ make bumpmajor # bump major version component
245 $ make nextrelease # add version heading to Changes file
246 $ make releasetest # build dist and test (with xt/ and RELEASE_TESTING=1)
247 $ make preflight # check that repo and file state is release ready
248 $ make release # check releasetest and preflight, then build and
249 # upload to CPAN, tag release, push tag and branch
253 L<ExtUtils::MakeMaker> works well enough as development tool for
254 builting and testing, but using it to release is annoying and error prone.
255 Distar adds just enough to L<ExtUtils::MakeMaker> for it to be a usable dist
256 author tool. This includes extra commands for releasing and safety checks, and
257 automatic generation of some files. It doesn't require any non-core modules and
258 is compatible with old versions of perl.
262 =head2 author( $author )
264 Set the author to include in generated META files. Can be a single entry, or
267 =head2 manifest_include( $dir, $pattern )
269 Add a pattern to include files in the MANIFEST file, and thus in the generated
272 The pattern can be either a regex, or a path suffix. It will be applied to the
273 full path past the directory specified.
275 The default files that are always included are: F<.pm> and F<.pod> files in
276 F<lib>, F<.t> files in F<t> and F<xt>, F<.pm> files in F<t/lib> and F<xt/lib>,
277 F<Changes>, F<MANIFEST>, F<README>, F<LICENSE>, F<META.yml>, and F<.PL> files in
278 the dist root, and all files in F<maint>.
280 =head1 AUTOGENERATED FILES
284 =item F<MANIFEST.SKIP>
286 The F<MANIFEST.SKIP> will be automatically generated to exclude any files not
287 explicitly allowed via C<manifest_include> or the included defaults. It will be
288 created (or updated) at C<perl Makefile.PL> time.
292 The F<README> file will be generated at dist generation time, inside the built
293 dist. It will be generated using C<pod2text> on the main module.
295 If a F<README> file exists in the repo, it will be used directly instead of
300 =head1 MAKE COMMMANDS
304 test will be adjusted to include F<xt/> tests by default. This will only apply
305 for authors, not users installing from CPAN.
309 Releases the dist. Before releasing, checks will be done on the dist using the
310 C<preflight> and C<releasetest> commands.
312 Releasing will generate a dist tarball and upload it to CPAN using cpan-upload.
313 It will also create a git tag for the release, and push the tag and branch.
317 If release is run with FAKE_RELEASE=1 set, it will skip uploading to CPAN and
318 pushing to git. A release commit will still be created and tagged locally.
322 Performs a number of checks on the files and repository, ensuring it is in a
323 sane state to do a release. The checks are:
327 =item * All version numbers match
329 =item * The F<MANIFEST> file is up to date
331 =item * The branch is correct
333 =item * There is no existing tag for the version
335 =item * There are no unmerged upstream changes
337 =item * There are no outstanding local changes
339 =item * There is an appropriate staged Changes heading
341 =item * cpan-upload is available
347 Test the dist preparing for a release. This generates a dist dir and runs the
348 tests from inside it. This ensures all appropriate files are included inside
349 the dist. C<RELEASE_TESTING> will be set in the environment.
353 Adds an appropriate changelog heading for the release, and prompts to stage the
358 Bumps the version number. This will try to preserve the length and format of
359 the version number. The least significant digit will be incremented.
361 Optionally accepts a C<V> option to set the version to a specific value.
363 The version changes will automatically be committed. Unstaged modifications to
364 the files will be left untouched.
368 Like bump, but increments the minor segment of the version. This will treat
369 numeric versions as x.yyyzzz format, incrementing the yyy segment.
373 Like bumpminor, but bumping the major segment.
377 Updates Distar and re-runs C<perl Makefile.PL>
381 IRC: #web-simple on irc.perl.org
383 Git repository: L<git://git.shadowcat.co.uk/p5sagit/Distar>
385 Git browser: L<http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=p5sagit/Distar.git;a=summary>
389 mst - Matt S. Trout (cpan:MSTROUT) <mst@shadowcat.co.uk>
393 haarg - Graham Knop (cpan:HAARG) <haarg@cpan.org>
395 ether = Karen Etheridge (cpan:ETHER) <ether@cpan.org>
397 frew - Arthur Axel "fREW" Schmidt (cpan:FREW) <frioux@gmail.com>
399 Mithaldu - Christian Walde (cpan:MITHALDU) <walde.christian@googlemail.com>
403 Copyright (c) 2011-2015 the Distar L</AUTHOR> and L</CONTRIBUTORS>
408 This library is free software and may be distributed under the same terms
409 as perl itself. See L<http://dev.perl.org/licenses/>.