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