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 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 Distar::write_manifest_skip($self);
97 $self->SUPER::flush(@_);
100 sub special_targets {
102 my $targets = $self->SUPER::special_targets(@_);
103 my $phony_targets = join ' ', qw(
118 $targets =~ s/^(\.PHONY *:.*)/$1 $phony_targets/m;
126 if (open my $fh, '<', 'maint/Makefile.include') {
127 $include = "\n# --- Makefile.include:\n\n" . do { local $/; <$fh> };
128 $include =~ s/\n?\z/\n/;
132 grep { $include !~ /^bump$_(?: +\w+)*:/m } ('', 'minor', 'major');
134 my $distar = File::Spec->catdir(
135 File::Spec->catpath((File::Spec->splitpath(__FILE__))[0,1], ''),
138 my $helpers = File::Spec->catdir($distar, 'helpers');
141 DISTAR => $self->quote_literal($distar),
142 HELPERS => $self->quote_literal($helpers),
143 REMAKE => join(' ', '$(PERLRUN)', 'Makefile.PL', map { $self->quote_literal($_) } @ARGV),
144 BRANCH => $self->{BRANCH} ||= 'master',
145 CHANGELOG => $self->{CHANGELOG} ||= 'Changes',
146 DEV_NULL_STDOUT => ($self->{DEV_NULL} ? '>'.File::Spec->devnull : ''),
151 $self->SUPER::dist_test(@_),
152 "\n\n# --- Distar section:\n\n",
153 (map "$_ = $vars{$_}\n", sort keys %vars),
156 preflight: check-version check-manifest check-cpan-upload
157 $(ABSPERLRUN) $(HELPERS)/preflight $(VERSION) --changelog=$(CHANGELOG) --branch=$(BRANCH)
159 $(ABSPERLRUN) $(HELPERS)/check-version $(VERSION) $(TO_INST_PM) $(EXE_FILES)
161 $(ABSPERLRUN) $(HELPERS)/check-manifest
163 $(NOECHO) cpan-upload -h $(DEV_NULL_STDOUT)
165 $(MAKE) disttest RELEASE_TESTING=1 PASTHRU="$(PASTHRU) TEST_FILES=\"$(TEST_FILES)\""
168 git commit -a -m "Release commit for $(VERSION)"
169 git tag v$(VERSION) -m "release v$(VERSION)"
170 $(RM_RF) $(DISTVNAME)
171 $(MAKE) $(DISTVNAME).tar$(SUFFIX)
172 $(NOECHO) $(MAKE) pushrelease FAKE_RELEASE=$(FAKE_RELEASE)
175 pushrelease$(FAKE_RELEASE) ::
176 cpan-upload $(DISTVNAME).tar$(SUFFIX)
177 git push origin v$(VERSION) HEAD
179 readmefile: create_distdir
180 $(NOECHO) $(MAKE) $(DISTVNAME)/README
181 $(DISTVNAME)/README: $(VERSION_FROM)
182 $(NOECHO) $(MKPATH) $(DISTVNAME)
183 pod2text $(VERSION_FROM) >$(DISTVNAME)/README
184 $(NOECHO) $(ABSPERLRUN) $(HELPERS)/add-to-manifest -d $(DISTVNAME) README
185 disttest: distmanicheck
186 distmanicheck: create_distdir
187 cd $(DISTVNAME) && $(ABSPERLRUN) "-MExtUtils::Manifest=manicheck" -e "exit manicheck"
189 $(ABSPERLRUN) $(HELPERS)/add-changelog-heading --git $(VERSION) $(CHANGELOG)
191 cd $(DISTAR) && git pull
192 $(RM_F) $(FIRST_MAKEFILE)
194 $(FIRST_MAKEFILE): $(DISTAR)/lib/Distar.pm
196 map(sprintf(<<'END', "bump$_", ($_ || '$(V)')), @bump_targets),
198 $(ABSPERLRUN) $(HELPERS)/bump-version --git $(VERSION) %s
199 $(RM_F) $(FIRST_MAKEFILE)
213 Distar - Additions to ExtUtils::MakeMaker for dist authors
219 use ExtUtils::MakeMaker;
220 (do 'maint/Makefile.PL.include' or die $@) unless -f 'META.yml';
224 F<maint/Makefile.PL.include>:
226 BEGIN { -e 'Distar' or system("git clone git://git.shadowcat.co.uk/p5sagit/Distar.git") }
227 use lib 'Distar/lib';
230 author 'A. U. Thor <author@cpan.org>';
232 manifest_include t => 'test-helper.pl';
233 manifest_include corpus => '.txt';
238 $ make bump # bump version
239 $ make bump V=2.000000 # bump to specific version
240 $ make bumpminor # bump minor version component
241 $ make bumpmajor # bump major version component
242 $ make nextrelease # add version heading to Changes file
243 $ make releasetest # build dist and test (with xt/ and RELEASE_TESTING=1)
244 $ make preflight # check that repo and file state is release ready
245 $ make release # check releasetest and preflight, then build and
246 # upload to CPAN, tag release, push tag and branch
250 L<ExtUtils::MakeMaker> works well enough as development tool for
251 builting and testing, but using it to release is annoying and error prone.
252 Distar adds just enough to L<ExtUtils::MakeMaker> for it to be a usable dist
253 author tool. This includes extra commands for releasing and safety checks, and
254 automatic generation of some files. It doesn't require any non-core modules and
255 is compatible with old versions of perl.
259 =head2 author( $author )
261 Set the author to include in generated META files. Can be a single entry, or
264 =head2 manifest_include( $dir, $pattern )
266 Add a pattern to include files in the MANIFEST file, and thus in the generated
269 The pattern can be either a regex, or a path suffix. It will be applied to the
270 full path past the directory specified.
272 The default files that are always included are: F<.pm> and F<.pod> files in
273 F<lib>, F<.t> files in F<t> and F<xt>, F<.pm> files in F<t/lib> and F<xt/lib>,
274 F<Changes>, F<MANIFEST>, F<README>, F<LICENSE>, F<META.yml>, and F<.PL> files in
275 the dist root, and all files in F<maint>.
277 =head1 AUTOGENERATED FILES
281 =item F<MANIFEST.SKIP>
283 The F<MANIFEST.SKIP> will be automatically generated to exclude any files not
284 explicitly allowed via C<manifest_include> or the included defaults. It will be
285 created (or updated) at C<perl Makefile.PL> time.
289 The F<README> file will be generated at dist generation time, inside the built
290 dist. It will be generated using C<pod2text> on the main module.
292 If a F<README> file exists in the repo, it will be used directly instead of
297 =head1 MAKE COMMMANDS
301 test will be adjusted to include F<xt/> tests by default. This will only apply
302 for authors, not users installing from CPAN.
306 Releases the dist. Before releasing, checks will be done on the dist using the
307 C<preflight> and C<releasetest> commands.
309 Releasing will generate a dist tarball and upload it to CPAN using cpan-upload.
310 It will also create a git tag for the release, and push the tag and branch.
314 If release is run with FAKE_RELEASE=1 set, it will skip uploading to CPAN and
315 pushing to git. A release commit will still be created and tagged locally.
319 Performs a number of checks on the files and repository, ensuring it is in a
320 sane state to do a release. The checks are:
324 =item * All version numbers match
326 =item * The F<MANIFEST> file is up to date
328 =item * The branch is correct
330 =item * There is no existing tag for the version
332 =item * There are no unmerged upstream changes
334 =item * There are no outstanding local changes
336 =item * There is an appropriate staged Changes heading
338 =item * cpan-upload is available
344 Test the dist preparing for a release. This generates a dist dir and runs the
345 tests from inside it. This ensures all appropriate files are included inside
346 the dist. C<RELEASE_TESTING> will be set in the environment.
350 Adds an appropriate changelog heading for the release, and prompts to stage the
355 Bumps the version number. This will try to preserve the length and format of
356 the version number. The least significant digit will be incremented.
358 Optionally accepts a C<V> option to set the version to a specific value.
360 The version changes will automatically be committed. Unstaged modifications to
361 the files will be left untouched.
365 Like bump, but increments the minor segment of the version. This will treat
366 numeric versions as x.yyyzzz format, incrementing the yyy segment.
370 Like bumpminor, but bumping the major segment.
374 Updates Distar and re-runs C<perl Makefile.PL>
378 IRC: #web-simple on irc.perl.org
380 Git repository: L<git://git.shadowcat.co.uk/p5sagit/Distar>
382 Git browser: L<http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=p5sagit/Distar.git;a=summary>
386 mst - Matt S. Trout (cpan:MSTROUT) <mst@shadowcat.co.uk>
390 haarg - Graham Knop (cpan:HAARG) <haarg@cpan.org>
392 ether = Karen Etheridge (cpan:ETHER) <ether@cpan.org>
394 frew - Arthur Axel "fREW" Schmidt (cpan:FREW) <frioux@gmail.com>
396 Mithaldu - Christian Walde (cpan:MITHALDU) <walde.christian@googlemail.com>
400 Copyright (c) 2011-2015 the Distar L</AUTHOR> and L</CONTRIBUTORS>
405 This library is free software and may be distributed under the same terms
406 as perl itself. See L<http://dev.perl.org/licenses/>.