2 # A simple system for making software releases
3 # (c) 2003 Martin Mares <mj@ucw.cz>
13 my ($class,$basename) = @_;
15 "PACKAGE" => $basename,
17 # p=preprocess, s=subst, -=discard
18 '(^|/)(CVS|\.arch-ids|{arch}|tmp)/' => '-',
19 '\.(lsm|spec)$' => 'ps',
24 "DATE" => `date '+%Y-%m-%d' | tr -d '\n'`,
25 "LSMDATE" => `date '+%y%m%d' | tr -d '\n'`,
28 "archivedir" => "/home/mj/tmp/archives/$basename",
41 sub GetVersionFromFile($) {
42 my ($s,$file,$rx) = @_;
43 open F, $file or die "Unable to open $file for version autodetection";
48 print "Detected version $1 from $file\n" if $verbose;
53 if (!defined $s->{"VERSION"}) { die "Failed to auto-detect version"; }
54 return $s->{"VERSION"};
57 sub GetVersionsFromChangelog($) {
58 my ($s,$file,$rx) = @_;
59 open F, $file or die "Unable to open $file for version autodetection";
63 if (!defined $s->{"VERSION"}) {
65 print "Detected version $1 from $file\n" if $verbose;
66 } elsif ($s->{"VERSION"} eq $1) {
69 $s->{"OLDVERSION"} = $1;
70 print "Detected previous version $1 from $file\n" if $verbose;
76 if (!defined $s->{"VERSION"}) { die "Failed to auto-detect version"; }
77 return $s->{"VERSION"};
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 $?;
90 if (defined $s->{$v}) {
93 die "Reference to unknown variable $v";
98 my ($s,$f,$dir,$action) = @_;
100 (my $d = $f) =~ s@(^|/)[^/]*$@@;
102 -d $d || `mkdir -p $d`; die if $?;
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)$/);
114 s/@([0-9A-Za-z_]+)@/$s->ExpandVar($1)/ge;
117 if (/^#/ || $is_makefile) {
118 if (/^#?ifdef\s+(\w+)/) {
119 if (defined ${$s->{"conditions"}}{$1}) {
120 push @ifs, ${$s->{"conditions"}}{$1};
124 } elsif (/^#ifndef\s+(\w+)/) {
125 if (defined ${$s->{"conditions"}}{$1}) {
126 push @ifs, -${$s->{"conditions"}}{$1};
130 } elsif (/^#if\s+/) {
132 } elsif (/^#?endif/) {
134 defined $x or die "Improper nesting of conditionals";
136 } elsif (/^#?else/) {
138 defined $x or die "Improper nesting of conditionals";
143 @ifs && $ifs[$#ifs] < 0 && next;
147 } else { $empty = 0; }
153 ! -x $f or chmod(0755, "$dir/$f") or die "chmod($dir/$f): $!";
155 `cp -a $f $dir/$f`; die if $?;
161 $s->{"PKG"} = $s->{"PACKAGE"} . "-" . $s->{"VERSION"};
162 my $dir = $s->{"DISTDIR"} . "/" . $s->{"PKG"};
163 print "Generating $dir\n";
165 FILES: foreach my $f (`find . -type f`) {
169 my @rules = @{$s->{"rules"}};
171 my $rule = shift @rules;
172 my $act = shift @rules;
178 ($action =~ /-/) && next FILES;
179 print "$f ($action)\n" if $verbose;
180 $s->CopyFile($f, $dir, $action);
183 if (-f "$dir/Makefile") {
184 print "Cleaning up\n";
185 `cd $dir && make distclean >&2`; die if $?;
188 my $arch = "$dir.tar.gz";
189 print "Creating $arch\n";
190 my $tarvv = $verbose ? "vv" : "";
191 `tar cz${tarvv}f $arch $dir >&2`; die if $?;
192 push @{$s->{"distfiles"}}, $arch;
194 my $adir = $s->{"archivedir"};
195 my $afile = $adir . "/" . $s->{"PKG"} . ".tar.gz";
196 print "Archiving $arch in $afile\n";
197 -d $adir or `mkdir -p $adir`;
198 `cp $arch $afile`; die if $?;
205 my $sf = $s->{"DISTDIR"} . "/" . $s->{"PKG"} . "/$f";
206 my $df = $s->{"DISTDIR"} . "/$f";
207 print "Generating $df\n";
208 `cp $sf $df`; die if $?;
209 push @{$s->{"distfiles"}}, $df;
212 sub ParseOptions($) {
215 "verbose!" => \$verbose,
216 "test!" => \$s->{"do_test"},
217 "patch!" => \$s->{"do_patch"},
218 "diff-against=s" => \$s->{"diff_against"},
219 "upload!" => \$s->{"do_upload"}
220 ) || die "Syntax: release [--verbose] [--test] [--nopatch] [--diff-against=<version>] [--noupload]";
225 my $dd = $s->{"DISTDIR"};
226 my $pkg = $s->{"PKG"};
227 my $log = "$dd/$pkg.log";
228 print "Doing a test compilation\n";
229 `( cd $dd/$pkg && make ) >$log 2>&1`;
230 die "There were errors. Please inspect $log" if $?;
231 `grep -q [Ww]arning $log`;
232 $? or print "There were warnings! Please inspect $log.\n";
233 print "Cleaning up\n";
234 `cd $dd/$pkg && make distclean`; die if $?;
239 my $dd = $s->{"DISTDIR"};
240 my $pkg1 = $s->{"PKG"};
242 if ($s->{"diff_against"} ne "") {
243 $oldver = $s->{"diff_against"};
244 } elsif (defined $s->{"OLDVERSION"}) {
245 $oldver = $s->{"OLDVERSION"};
247 die "MakePatch: Don't know which is the previous version";
249 my $pkg0 = $s->{"PACKAGE"} . "-" . $oldver;
251 my $oldarch = $s->{"archivedir"} . "/" . $pkg0 . ".tar.gz";
252 -f $oldarch or die "MakePatch: $oldarch not found";
253 print "Unpacking $pkg0 from $oldarch\n";
254 `cd $dd && tar xzf $oldarch`; die if $?;
256 my $diff = $s->{"PACKAGE"} . "-" . $oldver . "-" . $s->{"VERSION"} . ".diff.gz";
257 print "Creating a patch from $pkg0 to $pkg1: $diff\n";
258 `cd $dd && diff -ruN $pkg0 $pkg1 | gzip >$diff`; die if $?;
259 push @{$s->{"distfiles"}}, "$dd/$diff";
264 foreach my $u (@{$s->{"uploads"}}) {
265 my $url = $u->{"url"};
266 print "Upload to $url :\n";
268 my $filter = $u->{"filter"} || ".*";
269 foreach my $f (@{$s->{"distfiles"}}) {
275 print "<confirm> "; <STDIN>;
276 if ($url =~ m@^scp://([^/]+)(.*)@) {
278 my $cmd = "scp @files $1:$2\n";
280 } elsif ($url =~ m@ftp://([^/]+)(.*)@) {
283 open FTP, "|ftp -v $host" or die;
284 print FTP "cd $dir\n";
285 foreach my $f (@files) {
286 (my $ff = $f) =~ s@.*\/([^/].*)@$1@;
287 print FTP "put $f $ff\n";
293 die "Don't know how to handle this URL scheme";
300 $s->Test if $s->{"do_test"};
301 $s->MakePatch if $s->{"do_patch"};
302 $s->Upload if $s->{"do_upload"};