head 1.1; access; symbols; locks; strict; comment @# @; 1.1 date 97.10.24.10.21.14; author alexis; state Exp; branches; next ; desc @@ 1.1 log @Initial revision @ text @#!/usr/bin/perl ############################################################################### # # MAKE RELEASE - A RELEASE MANAGEMENT SYSTEM # Copyright (C) 1997 Alexis Huxley # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # ############################################################################### ############################################################################### # # CONFIGURABLE THINGS # ############################################################################### # PERL 5 LIBRARY DIRECTORY # Where are you going to put those .pl files you should have just configured? # and if perl isn't going to be able to find find.pl, then add a colon and # the path to that here as well. $main::local_pl_dir = $ENV{'HOME'} . "/dev/common"; # This lists what should be done to what files. Ideally it should be moved # to an external file. # (V)erson control, (I)d/(N)one/(W)e/(O)ther, (Y)es ident/(N)o ident $MR_ZERO = 0x0000; $MR_VN = 0x0000; $MR_VW = 0x0001; $MR_VO = 0x0002; $MR_VI = 0x0004; $MR_VWY = $MR_VW | $MR_VI; $MR_VOY = $MR_VO | $MR_VI; $MR_VWN = $MR_VW ; $MR_VON = $MR_VO; # (R)elease, (S)ource/(B)inary/(A)ll/(N)either $MR_RN = 0x0000; $MR_RS = 0x0010; $MR_RB = 0x0020; $MR_RA = $MR_RS | $MR_RB; # (M)arker, (Y)es/(N)o $MR_MN = 0x0000; $MR_MY = 0x0040; # (C)ompile, (Y)es/(N)o $MR_CN = 0x0000; $MR_CY = 0x0080; # VerCntl Rels Marker Compile $file_ctrl_bits{'Makefile.defs'} = $MR_VWY | $MR_RA ; $file_ctrl_bits{'Makefile'} = $MR_VWY | $MR_RA ; $file_ctrl_bits{'cfg-examples/Makefile'} = $MR_VWY | $MR_RA ; $file_ctrl_bits{'cfg/Makefile'} = $MR_VWY | $MR_RA ; $file_ctrl_bits{'doc/Makefile'} = $MR_VWY | $MR_RA ; $file_ctrl_bits{'pppd/Makefile'} = $MR_VWY | $MR_RA ; $file_ctrl_bits{'scr-examples/Makefile'} = $MR_VWY | $MR_RA ; $file_ctrl_bits{'scr/Makefile'} = $MR_VWY | $MR_RA ; $file_ctrl_bits{'src/Makefile'} = $MR_VWY | $MR_RA ; $file_ctrl_bits{'init/Makefile'} = $MR_VWY | $MR_RA ; $file_ctrl_bits{'init/local-ppplc.in'} = $MR_VWY | $MR_RS | $MR_MY; $file_ctrl_bits{'init/local-ppplc'} = $MR_VN | $MR_RB | $MR_CY; $file_ctrl_bits{'scr-examples/getmail'} = $MR_VWY | $MR_RA | $MR_MY; $file_ctrl_bits{'scr-examples/getnews'} = $MR_VWY | $MR_RA | $MR_MY; $file_ctrl_bits{'scr-examples/sndmail'} = $MR_VWY | $MR_RA | $MR_MY; $file_ctrl_bits{'scr-examples/sndnews'} = $MR_VWY | $MR_RA | $MR_MY; $file_ctrl_bits{'cfg-examples/master.cfg'} = $MR_VWY | $MR_RA ; $file_ctrl_bits{'cfg/modems/courier.cfg'} = $MR_VWY | $MR_RA ; $file_ctrl_bits{'cfg/isps/demon.cfg'} = $MR_VWY | $MR_RA ; $file_ctrl_bits{'scr/qtest'} = $MR_VWY | $MR_RA | $MR_MY; $file_ctrl_bits{'pppd/ip-up'} = $MR_VWY | $MR_RA | $MR_MY; $file_ctrl_bits{'pppd/ip-down'} = $MR_VWY | $MR_RA | $MR_MY; $file_ctrl_bits{'scr/announce'} = $MR_VWY | $MR_RA | $MR_MY; $file_ctrl_bits{'scr/ppplcc.in'} = $MR_VWY | $MR_RS | $MR_MY; $file_ctrl_bits{'scr/ppplcc'} = $MR_VN | $MR_RB | $MR_CY; $file_ctrl_bits{'scr/xppplcc.in'} = $MR_VWY | $MR_RS | $MR_MY; $file_ctrl_bits{'scr/xppplcc'} = $MR_VN | $MR_RB | $MR_CY; $file_ctrl_bits{'pppd/options'} = $MR_VWN | $MR_RA ; $file_ctrl_bits{'src/sndmsg.c'} = $MR_VWY | $MR_RS ; $file_ctrl_bits{'src/ppplcd.c'} = $MR_VWY | $MR_RS ; $file_ctrl_bits{'src/ppplcd.h'} = $MR_VWY | $MR_RS ; $file_ctrl_bits{'src/ppplcd_mhf.c'} = $MR_VWY | $MR_RS ; $file_ctrl_bits{'src/ppplcd_utils.c'} = $MR_VWY | $MR_RS ; $file_ctrl_bits{'src/ppplcd_utils.h'} = $MR_VWY | $MR_RS ; $file_ctrl_bits{'src/ppplcd_ipc.c'} = $MR_VWY | $MR_RS ; $file_ctrl_bits{'src/ppplcd_ipc.h'} = $MR_VWY | $MR_RS ; $file_ctrl_bits{'src/ppplcd_cfg.c'} = $MR_VWY | $MR_RS ; $file_ctrl_bits{'src/ppplcd_cfg.h'} = $MR_VWY | $MR_RS ; $file_ctrl_bits{'src/ppplcd_msgids.c'} = $MR_VWY | $MR_RS ; $file_ctrl_bits{'src/ppplcd_msgids.h'} = $MR_VWY | $MR_RS ; $file_ctrl_bits{'src/patchlevel.c'} = $MR_VWY | $MR_RS | $MR_MY; $file_ctrl_bits{'src/patchlevel.h'} = $MR_VWY | $MR_RS ; $file_ctrl_bits{'src/ppplcd'} = $MR_VN | $MR_RB | $MR_CY ; $file_ctrl_bits{'src/sndmsg'} = $MR_VN | $MR_RB | $MR_CY ; ############################################################################### # # DON'T CHANGE ANYTHING BELOW HERE # ############################################################################### # Uses first for checking #use strict; #use FileHandle; # STDOUT->autoflush(1); # Progname ($main::progname = $0) =~ s/^.*\/([^\/]+)/$1/; # RCS version string $main::modvers{$main::progname} = "PATCHLEVEL_MARKER"; ($main::modvers{$main::progname} =~ /^P.*R$/) && ($main::modvers{$main::progname} = '$Id: make_release,v 1.4 1997/10/22 23:41:18 alexis Exp $') =~ s/^.*,v (\S+) .*$/$1/; # Modify include path $ENV{'LOCAL_PL_DIR'} && ($main::local_pl_dir = $ENV{'LOCAL_PL_DIR'}); push(@@INC,split(/:/, $main::local_pl_dir)); # Requires utils.pl version 1.15 at least require "utils.pl"; (($main::modvers{'utils.pl'} cmp "1.15") == -1) && (!$ENV{'IGNORE_PL_VERSIONS'}) && &utils::error("configuration error: wrong version of utils.pl"); # Program proper starts here $versions_in_releases_file = ".versions_in_releases"; $file_ctrl_bits{$versions_in_releases_file} = $MR_VWN; ############################################################################## # # ROUTINES TO PERFORM A SIMPLE OPERATION ON A SINGLE FILE # ############################################################################## sub gotmarker { my($file) = @@_; my($rc); open(MARKER_HANDLE, $file) || die; $rc = 0; while () { if (/PATCHLEVEL_MARKER/) { $rc = 1; } } close MARKER_HANDLE; return($rc); } sub usage { print "Usage: $main::progname [ -v | -d ]\n"; print " $main::progname -V\n"; exit(1); } sub main { my(@@ARGV) = @@_; while (defined($ARGV[0]) && $ARGV[0] =~ /^-/) { $_ = shift @@ARGV; if (/^-d(.*)/) { $utils::verboselevel = ($1 ? $1 : shift @@ARGV); } elsif (/^-v$/) { $utils::verboselevel = 3; } elsif (/^-V$/) { print "$main::progname version ", $main::modvers{$main::progname}, "\n"; exit 0; } else { &usage; } } &fix_missing_writable_marked; $new_release_id = &get_release_id; &mark_files; &make_source_release_files; &make_files; &make_binary_release_files; &clear_marked_files; # This is not actually necessary, but it's very confusing to run a # a binary which was saying 'version PATCHLEVEL_MARKER' before, and # run it again to see it saying something else afterwards. So we # remake stuff having got rid of the markers. &make_files; system("rm -f /tmp/$main::progname.$$.*"); } sub fix_missing_writable_marked { my ($file); &utils::info("fixing missing, writable and marked files"); foreach $file (sort keys(%file_ctrl_bits)) { $bits = $file_ctrl_bits{$file}; ($bits & $MR_RS) || next; (! -f $file && ($bits & $MR_VW) && &utils::info("$file: retrieving") && system("co $file > /dev/null 2>&1")); (! -f $file && &utils::error("$file: missing")); (-w $file && ($bits & $MR_VW) && &utils::info("$file: writable, investigating") && &coifnc($file) && &utils::error("$file: modified")); (($bits & $MR_MY) && !&gotmarker($file) && &utils::info("$file: clearing marker") && (system("co $file > /dev/null 2>&1") || !&gotmarker($file)) && &utils::error("$file: clear marker failed")); } } sub clear_marked_files() { my ($file); &utils::info("clearing marked files and tidying up"); foreach $file (sort keys(%file_ctrl_bits)) { $bits = $file_ctrl_bits{$file}; (($bits & $MR_MY) && !&gotmarker($file) && (system("co $file > /dev/null 2>&1") || !&gotmarker($file)) && &utils::error("$file: clear marker failed")); } } sub mark_files() { my ($file); &utils::info("marking files"); foreach $file (keys (%file_ctrl_bits)) { ($file_ctrl_bits{$file} & $MR_MY) || next; &utils::debug(5, "marking $file..."); system("perl -pi -e \"s/PATCHLEVEL_MARKER/$new_release_id/g\" $file"); } } sub make_files() { my ($file); foreach $file (sort keys(%file_ctrl_bits)) { $bits = $file_ctrl_bits{$file}; ($bits & $MR_CY) && system("make $file") && (! -f $file) && &utils::error("$file: make failed"); } } sub coifnc { my($file) = @@_; if (-w $file && `rcsdiff $file 2>/dev/null` eq "") { &utils::info("$file: unmodified, checking out again"); system("co -f $file 2>/dev/null"); } return(-w $file); } sub ident { my($file) = @@_; ( ! -f $file || ! -r $file ) && return(0); open(IDENT_HANDLE, $file) || return(0); while () { chop; if (/^.*,v ([0-9\.]+) .*$/) { close(IDENT_HANDLE); return($1); } } close(IDENT_HANDLE); return(0); } sub get_release_id { my ($new_release_id, $old_release_id, $id, $file); &utils::info("examining previous and current releases"); open(NEWVERIDS_HANDLE, ">/tmp/$main::progname.$$.newverids") || die; foreach $file ((sort(keys %file_ctrl_bits))) { $bits = $file_ctrl_bits{$file}; if ($bits & $MR_VI) { ($id = &ident($file)) == 0 && &utils::error("$file: ident failed"); print NEWVERIDS_HANDLE "ComponentId: $file $id\n"; } } close NEWVERIDS_HANDLE; open(OLDVERIDS_HANDLE, ">/tmp/$main::progname.$$.oldverids"); open(RELEASE_HANDLE, $versions_in_releases_file) || &utils::error("problem reading $versions_in_releases_file: $!"); while () { chop; (/^ComponentId: /) && print OLDVERIDS_HANDLE "$_\n"; (/^ReleaseId: (.*)/) && ($old_release_id = "$1"); } close OLDVERIDS_HANDLE; if (!$old_release_id) { $old_release_id = "0"; } close RELEASE_HANDLE; if (system("diff /tmp/$main::progname.$$.oldverids /tmp/$main::progname.$$.newverids > /dev/null")) { &question("old release id is $old_release_id, enter new release id:"); chop($new_release_id = ); (($old_release_id cmp $new_release_id) != -1 && &utils::error("release ids must rise")); system("co -l $versions_in_releases_file 2>/dev/null"); system("echo ReleaseId: $new_release_id > $versions_in_releases_file"); system("cat /tmp/$main::progname.$$.newverids >> $versions_in_releases_file"); system("ci -u -m\"Release $new_release_id (`date`)\" $versions_in_releases_file 2>/dev/null"); } else { $new_release_id = $old_release_id; } unlink("/tmp/$PROGNAME.$$.newverids"); unlink("/tmp/$PROGNAME.$$.oldverids"); return $new_release_id; } sub shell { &utils::info("now do what you will and exit"); system("PS1=\"$main::progname> \" /bin/sh"); print "\n"; } sub make_source_release_files { my ($file); ($stem = `pwd`) =~ s/^.*\/([^\/]+)/$1/; chop($stem); foreach $file (sort keys(%file_ctrl_bits)) { $bits = $file_ctrl_bits{$file}; ($bits & $MR_RS && push(@@make_source_release_files, "$stem-$new_release_id/$file")); } @@make_source_release_files || return(0); &utils::info("making source release $new_release_id"); symlink ".", "$stem-$new_release_id"; system("tar chf - " . join(' ', @@make_source_release_files) . " | gzip > $stem-$new_release_id.tar.gz"); unlink "$stem-$new_release_id"; } sub make_binary_release_files { my($file); ($stem = `pwd`) =~ s/^.*\/([^\/]+)/$1/; chop($stem); foreach $file (sort keys(%file_ctrl_bits)) { $bits = $file_ctrl_bits{$file}; ($bits & $MR_RB && push(@@make_binary_release_files, "$stem-$new_release_id/$file")); } @@make_binary_release_files || return(0); &utils::info("making binary release $new_release_id"); symlink ".", "$stem-$new_release_id"; system("tar chf - " . join(' ', @@make_binary_release_files) . " | gzip > $stem-$new_release_id-bin.tar.gz"); unlink "$stem-$new_release_id"; } sub question { my($question) = @@_; print "$main::progname: QUESTION: $question "; } ############################################################################### # # ENTRY POINT # ############################################################################### # Force a sensible umask, this should really do something like # newumask = 022 binary-ored with oldumask, but I can't remember # the umask syntax and the camel book is not around. umask 077; exit(&main(@@ARGV)); @