allow AUTHOR to be overridden
[p5sagit/Distar.git] / lib / Distar.pm
1 package Distar;
2
3 use strict;
4 use warnings FATAL => 'all';
5 use base qw(Exporter);
6 use ExtUtils::MakeMaker ();
7 use ExtUtils::MM ();
8
9 use Config;
10 use File::Spec;
11
12 our $VERSION = '0.001000';
13 $VERSION = eval $VERSION;
14
15 my $MM_VER = eval $ExtUtils::MakeMaker::VERSION;
16
17 our @EXPORT = qw(
18   author manifest_include run_preflight
19 );
20
21 sub import {
22   strict->import;
23   warnings->import(FATAL => 'all');
24   shift->export_to_level(1,@_);
25 }
26
27 sub author {
28   our $Author = shift;
29   $Author = [ $Author ]
30     if !ref $Author;
31 }
32
33 our $Ran_Preflight;
34
35 our @Manifest = (
36   'lib' => '.pm',
37   't' => '.t',
38   't/lib' => '.pm',
39   'xt' => '.t',
40   'xt/lib' => '.pm',
41   '' => qr{[^/]*\.PL},
42   '' => qr{Changes|MANIFEST|README|META\.yml},
43   'maint' => qr{[^.].*},
44 );
45
46 sub manifest_include {
47   push @Manifest, @_;
48 }
49
50 sub write_manifest_skip {
51   my @files = @Manifest;
52   my @parts;
53   while (my ($dir, $spec) = splice(@files, 0, 2)) {
54     my $re = ($dir ? $dir.'/' : '').
55       ((ref($spec) eq 'Regexp')
56         ? $spec
57         : !ref($spec)
58           ? ".*\Q${spec}\E"
59             # print ref as well as stringification in case of overload ""
60           : die "spec must be string or regexp, was: ${spec} (${\ref $spec})");
61     push @parts, $re;
62   }
63   my $final = '^(?!'.join('|', map "${_}\$", @parts).')';
64   open my $skip, '>', 'MANIFEST.SKIP'
65     or die "can't open MANIFEST.SKIP: $!";
66   print $skip "${final}\n";
67   close $skip;
68 }
69
70 sub run_preflight {
71   $Ran_Preflight = 1;
72   my $version = $ARGV[0];
73
74   my $make = $Config{make};
75   my $null = File::Spec->devnull;
76
77   system("git fetch");
78   if (system("git rev-parse --quiet --verify v$version >$null") == 0) {
79     die "Tag v$version already exists!";
80   }
81
82   require File::Find;
83   File::Find::find({ no_chdir => 1, wanted => sub {
84     return
85       unless -f && /\.pm$/;
86     my $file_version = MM->parse_version($_);
87     die "Module $_ version $file_version doesn't match dist version $version"
88       unless $file_version eq 'undef' || $file_version eq $version;
89   }}, 'lib');
90
91   for (scalar `"$make" manifest 2>&1 >$null`) {
92     $_ && die "$make manifest changed:\n$_ Go check it and retry";
93   }
94
95   for (scalar `git status`) {
96     /^(?:# )?On branch master/ || die "Not on master. EEEK";
97     /Your branch is behind|Your branch and .*? have diverged/ && die "Not synced with upstream";
98   }
99
100   for (scalar `git diff`) {
101     length && die "Outstanding changes";
102   }
103   my $ymd = sprintf(
104     "%i-%02i-%02i", (gmtime)[5]+1900, (gmtime)[4]+1, (gmtime)[3]
105   );
106   my $changes_line = "$version - $ymd\n";
107   my @cached = grep /^\+/, `git diff --cached -U0`;
108   @cached > 0 or die "Please add:\n\n$changes_line\nto Changes stage Changes (git add Changes)";
109   @cached == 2 or die "Pre-commit Changes not just Changes line";
110   $cached[0] =~ /^\+\+\+ .\/Changes\n/ or die "Changes not changed";
111   $cached[1] eq "+$changes_line" or die "Changes new line should be: \n\n$changes_line ";
112
113   { no warnings 'exec'; `cpan-upload -h`; }
114   $? and die "cpan-upload not available";
115 }
116
117 {
118   package Distar::MM;
119   our @ISA = @ExtUtils::MM::ISA;
120   @ExtUtils::MM::ISA = (__PACKAGE__);
121
122   sub new {
123     my ($class, $args) = @_;
124     return $class->SUPER::new({
125       LICENSE => 'perl_5',
126       MIN_PERL_VERSION => '5.006',
127       AUTHOR => ($MM_VER >= 6.5702 ? $Distar::Author : $Distar::Author->[0]),
128       %$args,
129       ABSTRACT_FROM => $args->{VERSION_FROM},
130       test => { TESTS => ($args->{test}{TESTS}||'t/*.t').' xt/*.t xt/*/*.t' },
131     });
132   }
133
134   sub dist_test {
135     my $self = shift;
136     my $dist_test = $self->SUPER::dist_test(@_) . <<'END';
137
138 # --- Distar section:
139 preflight:
140         perl -IDistar/lib -MDistar -erun_preflight $(VERSION)
141 release: preflight
142         $(MAKE) disttest
143         rm -rf $(DISTVNAME)
144         $(MAKE) $(DISTVNAME).tar$(SUFFIX)
145         git commit -a -m "Release commit for $(VERSION)"
146         git tag v$(VERSION) -m "release v$(VERSION)"
147         cpan-upload $(DISTVNAME).tar$(SUFFIX)
148         git push origin v$(VERSION) HEAD
149 distdir: readmefile
150 readmefile: create_distdir
151         pod2text $(VERSION_FROM) >$(DISTVNAME)/README
152         $(NOECHO) cd $(DISTVNAME) && $(ABSPERLRUN) ../Distar/helpers/add-readme-to-manifest
153 disttest: distmanicheck
154 distmanicheck: create_distdir
155         cd $(DISTVNAME) && $(ABSPERLRUN) "-MExtUtils::Manifest=manicheck" -e "exit manicheck"
156
157 END
158     if (open my $fh, '<', 'maint/Makefile.include') {
159       $dist_test .= do { local $/; <$fh> };
160     }
161     return $dist_test;
162   }
163 }
164
165 END {
166   write_manifest_skip() unless $Ran_Preflight
167 }
168
169 1;