Added some release maintenance stuff
[exim.git] / release-process / scripts / mk_exim_release.pl
1 #!/usr/bin/perl
2 #
3 # $Cambridge: exim/release-process/scripts/mk_exim_release.pl,v 1.1 2010/06/03 12:00:38 nm4 Exp $
4 #
5 use strict;
6 use warnings;
7 use Carp;
8 use File::Copy;
9 use File::Spec;
10 use File::Path;
11 use Getopt::Long;
12 use Pod::Usage;
13
14 my $debug   = 0;
15 my $verbose = 0;
16
17 # ------------------------------------------------------------------
18
19 sub get_and_check_version {
20     my $release = shift;
21
22     # make sure this looks like a real release version
23     # which should (currently) be 4.xx
24     unless ( $release =~ /^(4\.\d\d(?:_RC\d+)?)$/ ) {
25         croak "The given version number does not look right - $release";
26     }
27     return $1;    # untainted here...
28 }
29
30 # ------------------------------------------------------------------
31
32 sub build_cvs_tag {
33     my $context = shift;
34
35     # The CVS tag consists of exim-$version where $version
36     # is the version number with . replaced with _
37     my $modversion = $context->{release};
38     $modversion =~ tr/0-9RC/_/cs;
39
40     return sprintf( 'exim-%s', $modversion );
41 }
42
43 # ------------------------------------------------------------------
44
45 sub deal_with_working_directory {
46     my $context = shift;
47     my $delete  = shift;
48
49     # Set default directory
50     $context->{directory} ||= File::Spec->rel2abs( sprintf( 'exim-packaging-%s', $context->{release} ) );
51     my $directory = $context->{directory};
52
53     # ensure the working directory is not in place
54     if ( -d $directory ) {
55         if ($delete) {
56             print "Deleting existing $directory\n" if ($verbose);
57             rmtree( $directory, { verbose => $debug } );
58         }
59         if ( -d $directory ) {
60             croak "Working directory $directory exists";
61         }
62     }
63
64     mkpath( $context->{directory}, { verbose => ( $verbose || $debug ) } );
65 }
66
67 # ------------------------------------------------------------------
68
69 sub export_cvs_tree {
70     my $context = shift;
71
72     # build CVS command
73     my @cmd = ( 'cvs', '-d', $context->{cvsroot}, '-Q', 'export', '-r', $context->{tag}, $context->{pkgname}, );
74
75     # run cvs command
76     print( "Running: ", join( ' ', @cmd ), "\n" ) if ($verbose);
77     system(@cmd) == 0 || croak "Export failed";
78 }
79
80 # ------------------------------------------------------------------
81
82 sub build_documentation {
83     system("cd exim/exim-doc/doc-docbook && ./OS-Fixups && make everything") == 0
84       || croak "Doc build failed";
85 }
86
87 # ------------------------------------------------------------------
88
89 sub move_text_docs_into_pkg {
90     my $context = shift;
91
92     my $old_docdir = 'exim/exim-doc/doc-docbook';
93     my $new_docdir = File::Spec->catdir( $context->{pkgdir}, 'doc' );
94     mkpath( $new_docdir, { verbose => ( $verbose || $debug ) } );
95
96     # move generated documents from docbook stuff
97     foreach my $file (qw/exim.8 spec.txt filter.txt/) {
98         move( File::Spec->catfile( $old_docdir, $file ), File::Spec->catfile( $new_docdir, $file ) );
99     }
100
101     # move text documents across
102     foreach my $file ( glob( File::Spec->catfile( 'exim/exim-doc/doc-txt', '*' ) ) ) {
103
104         # skip a few we dont want
105         my $fn = ( File::Spec->splitpath($file) )[2];
106         next
107           if ( ( $fn eq 'ABOUT' )
108             || ( $fn eq 'ChangeLog.0' )
109             || ( $fn eq 'test-harness.txt' ) );
110         move( $file, File::Spec->catfile( $new_docdir, $fn ) );
111     }
112 }
113
114 # ------------------------------------------------------------------
115
116 sub build_pspdfinfo_directory {
117     my $context = shift;
118
119     ##foreach my $format (qw/pdf postscript texinfo info/) {
120     foreach my $format (qw/pdf postscript/) {
121         my $dir = sprintf( 'exim-%s-%s', $format, $context->{release} );
122         my $target = File::Spec->catdir( $dir, 'doc' );
123         mkpath( $target, { verbose => ( $verbose || $debug ) } );
124
125         # move documents across
126         foreach my $file (
127             glob(
128                 File::Spec->catfile(
129                     'exim/exim-doc/doc-docbook',
130                     (
131                         ( $format eq 'postscript' )
132                         ? '*.ps'
133                         : ( '*.' . $format )
134                     )
135                 )
136             )
137           )
138         {
139             my $fn = ( File::Spec->splitpath($file) )[2];
140             move( $file, File::Spec->catfile( $target, $fn ) );
141         }
142     }
143 }
144
145 # ------------------------------------------------------------------
146
147 sub build_html_directory {
148     my $context = shift;
149
150     my $dir = sprintf( 'exim-%s-%s', 'html', $context->{release} );
151     my $target = File::Spec->catdir( $dir, 'doc', 'html' );
152     mkpath( $target, { verbose => ( $verbose || $debug ) } );
153
154     # move documents across
155     move( File::Spec->catdir( 'exim/exim-doc/doc-docbook', 'spec_html' ), File::Spec->catdir( $target, 'spec_html' ) );
156     foreach my $file ( glob( File::Spec->catfile( 'exim/exim-doc/doc-docbook', '*.html' ) ) ) {
157         my $fn = ( File::Spec->splitpath($file) )[2];
158         move( $file, File::Spec->catfile( $target, $fn ) );
159     }
160 }
161
162 # ------------------------------------------------------------------
163
164 sub build_main_package_directory {
165     my $context = shift;
166
167     # initially we move the exim-src directory to the new directory name
168     my $pkgdir = sprintf( 'exim-%s', $context->{release} );
169     $context->{pkgdir} = $pkgdir;
170     rename( 'exim/exim-src', $pkgdir ) || croak "Rename of src dir failed - $!";
171
172     # add Local subdirectory
173     my $target = File::Spec->catdir( $pkgdir, 'Local' );
174     mkpath( $target, { verbose => ( $verbose || $debug ) } );
175
176     # now add the text docs
177     move_text_docs_into_pkg($context);
178 }
179
180 # ------------------------------------------------------------------
181
182 sub build_package_directories {
183     my $context = shift;
184
185     build_main_package_directory($context);
186     build_pspdfinfo_directory($context);
187     build_html_directory($context);
188 }
189
190 # ------------------------------------------------------------------
191
192 sub create_tar_files {
193     my $context = shift;
194
195     foreach my $dir ( glob( 'exim*-' . $context->{release} ) ) {
196         system("tar cfz ${dir}.tar.gz ${dir}");
197         system("tar cfj ${dir}.tar.bz2 ${dir}");
198     }
199 }
200
201 # ------------------------------------------------------------------
202 {
203     my $man;
204     my $help;
205     my $context = {
206         cvsroot  => ':ext:nm4@vcs.exim.org:/home/cvs',
207         pkgname  => 'exim',
208         orig_dir => File::Spec->curdir(),
209     };
210     my $delete;
211     $ENV{'PATH'} = '/opt/local/bin:' . $ENV{'PATH'};
212
213     unless (
214         GetOptions(
215             'directory=s' => \$context->{directory},
216             'cvsroot=s'   => \$context->{cvsroot},
217             'verbose!'    => \$verbose,
218             'debug!'      => \$debug,
219             'help|?'      => \$help,
220             'man!'        => \$man,
221             'delete!'     => \$delete,
222         )
223       )
224     {
225         pod2usage( -exitval => 1, -verbose => 0 );
226     }
227     pod2usage(0) if $help;
228     pod2usage( -verbose => 2 ) if $man;
229
230     $context->{release} = get_and_check_version(shift);
231     $context->{tag}     = build_cvs_tag($context);
232     deal_with_working_directory( $context, $delete );
233     chdir( $context->{directory} ) || die;
234     export_cvs_tree($context);
235     build_documentation($context);
236     build_package_directories($context);
237     create_tar_files($context);
238 }
239
240 1;
241
242 __END__
243
244 =head1 NAME
245
246 mk_exim_release.pl - Build an exim release
247
248 =head1 SYNOPSIS
249
250 mk_exim_release.pl [options] version
251
252  Options:
253    --debug             force debug mode (SQL Trace)
254    --verbose           force verbose mode
255    --help              display this help and exits
256    --man               displays man page
257    --directory=dir     dir to package
258    --cvsroot=s         CVS root spec
259    --delete            Delete packaging directory at start
260
261 =head1 OPTIONS
262
263 =over 4
264
265 =item B<--debug>
266
267 Forces debug mode cause all SQL statements generated by L<DBIx::Class>
268 to be output.
269
270 =item B<--verbose>
271
272 Force verbose mode - currently this has no effect
273
274 =item B<--help>
275
276 Display help and exits
277
278 =item B<--man>
279
280 Display man page
281
282 =back
283
284 =head1 DESCRIPTION
285
286 Builds an exim release.
287
288 Starting in an empty directory, with the CVS repo already tagged
289 for release, build docs, build packages etc.
290
291 NB The CVS root spec is embedded in the script or can be given via
292 the I<--cvsroot> parameter
293
294 Parameter is the version number to build as - ie 4.72 4.72RC1 etc
295
296 =head1 AUTHOR
297
298 Nigel Metheringham <Nigel.Metheringham@dev.intechnology.co.uk>
299
300 =head1 COPYRIGHT
301
302 Copyright 2009 Someone. All rights reserved.
303
304 =cut