]> mj.ucw.cz Git - pciutils.git/blob - maint/release.pm
bf8afc0706bf86b5923c33bbfd8c4036aaa04726
[pciutils.git] / maint / release.pm
1 #!/usr/bin/perl
2 # A simple system for making software releases
3 # (c) 2003 Martin Mares <mj@ucw.cz>
4
5 package UCW::Release;
6 use strict;
7 use warnings;
8 use Getopt::Long;
9
10 our $verbose = 0;
11
12 sub new($$) {
13         my ($class,$basename) = @_;
14         my $s = {
15                 "PACKAGE" => $basename,
16                 "rules" => [
17                         # p=preprocess, s=subst, -=discard
18                         '(^|/)(CVS|\.arch-ids|{arch}|tmp)/' => '-',
19                         '\.(lsm|spec)$' => 'ps',
20                         '(^|/)README$' => 's'
21                         ],
22                 "conditions" => {
23                         },
24                 "DATE" => `date '+%Y-%m-%d' | tr -d '\n'`,
25                 "LSMDATE" => `date '+%y%m%d' | tr -d '\n'`,
26                 "distfiles" => [
27                         ],
28                 "archivedir" => "/home/mj/tmp/archives/$basename",
29                 "uploads" => [
30                         ],
31                 # Options
32                 "do_test" => 1,
33                 "do_patch" => 1,
34                 "diff_against" => "",
35                 "do_upload" => 1
36         };
37         bless $s;
38         return $s;
39 }
40
41 sub GetVersionFromFile($) {
42         my ($s,$file,$rx) = @_;
43         open F, $file or die "Unable to open $file for version autodetection";
44         while (<F>) {
45                 chomp;
46                 if (/$rx/) {
47                         $s->{"VERSION"} = $1;
48                         print "Detected version $1 from $file\n" if $verbose;
49                         last;
50                 }
51         }
52         close F;
53         if (!defined $s->{"VERSION"}) { die "Failed to auto-detect version"; }
54         return $s->{"VERSION"};
55 }
56
57 sub GetVersionsFromChangelog($) {
58         my ($s,$file,$rx) = @_;
59         open F, $file or die "Unable to open $file for version autodetection";
60         while (<F>) {
61                 chomp;
62                 if (/$rx/) {
63                         if (!defined $s->{"VERSION"}) {
64                                 $s->{"VERSION"} = $1;
65                                 print "Detected version $1 from $file\n" if $verbose;
66                         } elsif ($s->{"VERSION"} eq $1) {
67                                 # do nothing
68                         } else {
69                                 $s->{"OLDVERSION"} = $1;
70                                 print "Detected previous version $1 from $file\n" if $verbose;
71                                 last;
72                         }
73                 }
74         }
75         close F;
76         if (!defined $s->{"VERSION"}) { die "Failed to auto-detect version"; }
77         return $s->{"VERSION"};
78 }
79
80 sub InitDist($) {
81         my ($s,$dd) = @_;
82         $s->{"DISTDIR"} = $dd;
83         print "Initializing dist directory $dd\n" if $verbose;
84         `rm -rf $dd`; die if $?;
85         `mkdir -p $dd`; die if $?;
86 }
87
88 sub ExpandVar($$) {
89         my ($s,$v) = @_;
90         if (defined $s->{$v}) {
91                 return $s->{$v};
92         } else {
93                 die "Reference to unknown variable $v";
94         }
95 }
96
97 sub CopyFile($$$$) {
98         my ($s,$f,$dir,$action) = @_;
99
100         (my $d = $f) =~ s@(^|/)[^/]*$@@;
101         $d = "$dir/$d";
102         -d $d || `mkdir -p $d`; die if $?;
103
104         my $preprocess = ($action =~ /p/);
105         my $subst = ($action =~ /s/);
106         if ($preprocess || $subst) {
107                 open I, "$f" or die "open($f): $?";
108                 open O, ">$dir/$f" or die "open($dir/$f): $!";
109                 my @ifs = ();   # stack of conditions, 1=satisfied
110                 my $empty = 0;  # last line was empty
111                 my $is_makefile = ($f =~ /(Makefile|.mk)$/);
112                 while (<I>) {
113                         if ($subst) {
114                                 s/@([0-9A-Za-z_]+)@/$s->ExpandVar($1)/ge;
115                         }
116                         if ($preprocess) {
117                                 if (/^#/ || $is_makefile) {
118                                         if (/^#?ifdef\s+(\w+)/) {
119                                                 if (defined ${$s->{"conditions"}}{$1}) {
120                                                         push @ifs, ${$s->{"conditions"}}{$1};
121                                                         next;
122                                                 }
123                                                 push @ifs, 0;
124                                         } elsif (/^#ifndef\s+(\w+)/) {
125                                                 if (defined ${$s->{"conditions"}}{$1}) {
126                                                         push @ifs, -${$s->{"conditions"}}{$1};
127                                                         next;
128                                                 }
129                                                 push @ifs, 0;
130                                         } elsif (/^#if\s+/) {
131                                                 push @ifs, 0;
132                                         } elsif (/^#?endif/) {
133                                                 my $x = pop @ifs;
134                                                 defined $x or die "Improper nesting of conditionals";
135                                                 $x && next;
136                                         } elsif (/^#?else/) {
137                                                 my $x = pop @ifs;
138                                                 defined $x or die "Improper nesting of conditionals";
139                                                 push @ifs, -$x;
140                                                 $x && next;
141                                         }
142                                 }
143                                 @ifs && $ifs[$#ifs] < 0 && next;
144                                 if (/^$/) {
145                                         $empty && next;
146                                         $empty = 1;
147                                 } else { $empty = 0; }
148                         }               
149                         print O;
150                 }
151                 close O;
152                 close I;
153                 ! -x $f or chmod(0755, "$dir/$f") or die "chmod($dir/$f): $!";
154         } else {
155                 `cp -a $f $dir/$f`; die if $?;
156         }
157 }
158
159 sub GenPackage($) {
160         my ($s) = @_;
161         $s->{"PKG"} = $s->{"PACKAGE"} . "-" . $s->{"VERSION"};
162         my $dd = $s->{"DISTDIR"};
163         my $pkg = $s->{"PKG"};
164         my $dir = "$dd/$pkg";
165         print "Generating $dir\n";
166
167         FILES: foreach my $f (`find . -type f`) {
168                 chomp $f;
169                 $f =~ s/^\.\///;
170                 my $action = "";
171                 my @rules = @{$s->{"rules"}};
172                 while (@rules) {
173                         my $rule = shift @rules;
174                         my $act = shift @rules;
175                         if ($f =~ $rule) {
176                                 $action = $act;
177                                 last;
178                         }
179                 }
180                 ($action =~ /-/) && next FILES;
181                 print "$f ($action)\n" if $verbose;
182                 $s->CopyFile($f, $dir, $action);
183         }
184
185         if (-f "$dir/Makefile") {
186                 print "Cleaning up\n";
187                 `cd $dir && make distclean >&2`; die if $?;
188         }
189
190         print "Creating $dd/$pkg.tar.gz\n";
191         my $tarvv = $verbose ? "vv" : "";
192         `cd $dd && tar cz${tarvv}f $pkg.tar.gz $pkg >&2`; die if $?;
193         push @{$s->{"distfiles"}}, "$dd/$pkg.tar.gz";
194
195         my $adir = $s->{"archivedir"};
196         my $afile = "$adir/$pkg.tar.gz";
197         print "Archiving to $afile\n";
198         -d $adir or `mkdir -p $adir`;
199         `cp $dd/$pkg.tar.gz $afile`; die if $?;
200
201         return $dir;
202 }
203
204 sub GenFile($$) {
205         my ($s,$f) = @_;
206         my $sf = $s->{"DISTDIR"} . "/" . $s->{"PKG"} . "/$f";
207         my $df = $s->{"DISTDIR"} . "/$f";
208         print "Generating $df\n";
209         `cp $sf $df`; die if $?;
210         push @{$s->{"distfiles"}}, $df;
211 }
212
213 sub ParseOptions($) {
214         my ($s) = @_;
215         GetOptions(
216                 "verbose!" => \$verbose,
217                 "test!" => \$s->{"do_test"},
218                 "patch!" => \$s->{"do_patch"},
219                 "diff-against=s" => \$s->{"diff_against"},
220                 "upload!" => \$s->{"do_upload"}
221         ) || die "Syntax: release [--verbose] [--test] [--nopatch] [--diff-against=<version>] [--noupload]";
222 }
223
224 sub Test($) {
225         my ($s) = @_;
226         my $dd = $s->{"DISTDIR"};
227         my $pkg = $s->{"PKG"};
228         my $log = "$dd/$pkg.log";
229         print "Doing a test compilation\n";
230         `( cd $dd/$pkg && make ) >$log 2>&1`;
231         die "There were errors. Please inspect $log" if $?;
232         `grep -q [Ww]arning $log`;
233         $? or print "There were warnings! Please inspect $log.\n";
234         print "Cleaning up\n";
235         `cd $dd/$pkg && make distclean`; die if $?;
236 }
237
238 sub MakePatch($) {
239         my ($s) = @_;
240         my $dd = $s->{"DISTDIR"};
241         my $pkg1 = $s->{"PKG"};
242         my $oldver;
243         if ($s->{"diff_against"} ne "") {
244                 $oldver = $s->{"diff_against"};
245         } elsif (defined $s->{"OLDVERSION"}) {
246                 $oldver = $s->{"OLDVERSION"};
247         } else {
248                 die "MakePatch: Don't know which is the previous version";
249         }
250         my $pkg0 = $s->{"PACKAGE"} . "-" . $oldver;
251
252         my $oldarch = $s->{"archivedir"} . "/" . $pkg0 . ".tar.gz";
253         -f $oldarch or die "MakePatch: $oldarch not found";
254         print "Unpacking $pkg0 from $oldarch\n";
255         `cd $dd && tar xzf $oldarch`; die if $?;
256
257         my $diff = $s->{"PACKAGE"} . "-" . $oldver . "-" . $s->{"VERSION"} . ".diff.gz";
258         print "Creating a patch from $pkg0 to $pkg1: $diff\n";
259         `cd $dd && diff -ruN $pkg0 $pkg1 | gzip >$diff`; die if $?;
260         push @{$s->{"distfiles"}}, "$dd/$diff";
261 }
262
263 sub Upload($) {
264         my ($s) = @_;
265         foreach my $u (@{$s->{"uploads"}}) {
266                 my $url = $u->{"url"};
267                 print "Upload to $url :\n";
268                 my @files = ();
269                 my $filter = $u->{"filter"} || ".*";
270                 foreach my $f (@{$s->{"distfiles"}}) {
271                         if ($f =~ $filter) {
272                                 print "\t$f\n";
273                                 push @files, $f;
274                         }
275                 }
276                 print "<confirm> "; <STDIN>;
277                 if ($url =~ m@^scp://([^/]+)(.*)@) {
278                         $, = " ";
279                         my $host = $1;
280                         my $dir = $2;
281                         $dir =~ s@^/~@~@;
282                         $dir =~ s@^/\./@@;
283                         my $cmd = "scp @files $host:$dir\n";
284                         `$cmd`; die if $?;
285                 } elsif ($url =~ m@ftp://([^/]+)(.*)@) {
286                         my $host = $1;
287                         my $dir = $2;
288                         open FTP, "|ftp -v $host" or die;
289                         print FTP "cd $dir\n";
290                         foreach my $f (@files) {
291                                 (my $ff = $f) =~ s@.*\/([^/].*)@$1@;
292                                 print FTP "put $f $ff\n";
293                         }
294                         print FTP "bye\n";
295                         close FTP;
296                         die if $?;
297                 } else {
298                         die "Don't know how to handle this URL scheme";
299                 }
300         }
301 }
302
303 sub Dispatch($) {
304         my ($s) = @_;
305         $s->Test if $s->{"do_test"};
306         $s->MakePatch if $s->{"do_patch"};
307         $s->Upload if $s->{"do_upload"};
308 }
309
310 1;