diff options
Diffstat (limited to 'pat')
-rw-r--r-- | pat/Jmakefile | 62 | ||||
-rwxr-xr-x | pat/Makefile.SH | 297 | ||||
-rw-r--r-- | pat/README | 120 | ||||
-rwxr-xr-x | pat/pat.SH | 154 | ||||
-rw-r--r-- | pat/pat.man | 513 | ||||
-rwxr-xr-x | pat/patbase.SH | 122 | ||||
-rw-r--r-- | pat/patchlevel.h | 34 | ||||
-rwxr-xr-x | pat/patcil.SH | 541 | ||||
-rwxr-xr-x | pat/patclean.SH | 185 | ||||
-rwxr-xr-x | pat/patcol.SH | 235 | ||||
-rwxr-xr-x | pat/patdiff.SH | 236 | ||||
-rwxr-xr-x | pat/patftp.SH | 118 | ||||
-rwxr-xr-x | pat/patindex.SH | 66 | ||||
-rwxr-xr-x | pat/patlog.SH | 388 | ||||
-rwxr-xr-x | pat/patmake.SH | 411 | ||||
-rwxr-xr-x | pat/patname.SH | 175 | ||||
-rwxr-xr-x | pat/patnotify.SH | 232 | ||||
-rwxr-xr-x | pat/patpost.SH | 179 | ||||
-rwxr-xr-x | pat/patsend.SH | 218 | ||||
-rwxr-xr-x | pat/patsnap.SH | 124 |
20 files changed, 4410 insertions, 0 deletions
diff --git a/pat/Jmakefile b/pat/Jmakefile new file mode 100644 index 0000000..ee31e68 --- /dev/null +++ b/pat/Jmakefile @@ -0,0 +1,62 @@ +/* + * Jmakefile for patching tools. + */ + +;# $Id$ +;# +;# Copyright (c) 1991-1997, 2004-2006, Raphael Manfredi +;# +;# You may redistribute only under the terms of the Artistic Licence, +;# as specified in the README file that comes with the distribution. +;# You may reuse parts of this distribution only within the terms of +;# that same Artistic Licence; a copy of which may be found at the root +;# of the source tree for dist 4.0. +;# +;# $Log: Jmakefile,v $ +;# Revision 3.0.1.3 1995/07/24 09:57:21 ram +;# patch56: was missing an entry for the patlog program +;# +;# Revision 3.0.1.2 1994/01/24 13:42:48 ram +;# patch16: added dependency generation stage +;# +;# Revision 3.0.1.1 1993/08/24 12:09:05 ram +;# patch3: added patnotify and patsnap +;# +;# Revision 3.0 1993/08/18 12:10:32 ram +;# Baseline for dist 3.0 netwide release. +;# + +/* BASE is used to give the extensions for pat* files. Usually, '//' can be + * used to specify a null expansion pattern, but some of those new smart cpp + * now think it's a up-to-end-of-line comment--why do they do that to us? + */ +BASE = /^^/ cil base diff make clean col name ftp send \ + index post notify snap log + +/* PAT is derived from BASE and is the list of all the files to produce */ +PAT = \ +|expand f!$(BASE)! + pat!f \ +-expand \\ + +NoManPages() /* There is a single man page for all tools */ +SimpleShellScriptTarget($(PAT)) + +InstallMultipleFlags($(PAT),$(SCRIPTDIR),-m 555) +InstallManPage(pat,$(MANSRC)) + +PATSH = \ +|expand f!$(PAT)! + !f.SH \ +-expand \\ + +depend:: local_depend +local_depend:: + ($(SED) '/^# DO NOT DELETE/q' Makefile && \ + grep '^\$$grep' $(PATSH) | \ + $(SED) -e "s/^.*' \([^ ]*\) >>\([^ ]*\)/\2: \1/" \ + ) > Makefile.new + cp Makefile Makefile.bak + cp Makefile.new Makefile + $(RM) Makefile.new + diff --git a/pat/Makefile.SH b/pat/Makefile.SH new file mode 100755 index 0000000..8fbb905 --- /dev/null +++ b/pat/Makefile.SH @@ -0,0 +1,297 @@ +: Makefile.SH generated from Jmake.tmpl and Jmakefile [jmake 3.5-43] +: $X-Id: Jmake.tmpl 47 2010-11-28 22:23:13Z rmanfredi $ + +case $CONFIG in +'') + if test -f config.sh; then TOP=.; + elif test -f ../config.sh; then TOP=..; + elif test -f ../../config.sh; then TOP=../..; + elif test -f ../../../config.sh; then TOP=../../..; + elif test -f ../../../../config.sh; then TOP=../../../..; + else + echo "Can't find config.sh."; exit 1 + fi + . $TOP/config.sh + ;; +esac +case "$0" in +*/*) cd `expr X$0 : 'X\(.*\)/'` ;; +esac +CURRENT=pat +DIR=`echo $CURRENT/ | sed -e 's/\.\///g'` +echo "Extracting ${DIR}Makefile (with variable substitutions)" + +INSTALL=`echo $install | sed -e 's,\./i,\$(TOP)/i,'` +INSTALLDIR=`echo $installdir | sed -e 's,\./i,\$(TOP)/i,'` +DATE=`date` + +$spitshell >Makefile <<!GROK!THIS! +######################################################################## +# Makefile generated from Makefile.SH on $DATE + +SHELL = /bin/sh +JMAKE = jmake +TOP = .. +CURRENT = $CURRENT +DIR = $DIR +INSTALL = $INSTALL +INSTALLDIR = $INSTALLDIR + +######################################################################## +# Parameters set by Configure -- edit config.sh if changes are needed + +CTAGS = ctags +JCPPFLAGS = $cppflags +L = $manext +MANSRC = $installmansrc +MV = $mv +RM = $rm -f +SCRIPTDIR = $installscript +SED = $sed + +!GROK!THIS! +$spitshell >>Makefile <<'!NO!SUBS!' +######################################################################## +# Jmake rules for building libraries, programs, scripts, and data files +# $X-Id: Jmake.rules 18 2006-12-27 10:35:09Z rmanfredi $ + +######################################################################## +# Start of Jmakefile + +# $X-Id: Jmakefile 48 2010-11-28 23:05:09Z rmanfredi $ +# +# Copyright (c) 1991-1997, 2004-2006, Raphael Manfredi +# +# You may redistribute only under the terms of the Artistic Licence, +# as specified in the README file that comes with the distribution. +# You may reuse parts of this distribution only within the terms of +# that same Artistic Licence; a copy of which may be found at the root +# of the source tree for dist 4.0. +# +# $X-Log: Jmakefile,v $ +# Revision 3.0.1.3 1995/07/24 09:57:21 ram +# patch56: was missing an entry for the patlog program +# +# Revision 3.0.1.2 1994/01/24 13:42:48 ram +# patch16: added dependency generation stage +# +# Revision 3.0.1.1 1993/08/24 12:09:05 ram +# patch3: added patnotify and patsnap +# +# Revision 3.0 1993/08/18 12:10:32 ram +# Baseline for dist 3.0 netwide release. +# + +BASE = // cil base diff make clean col name ftp send \ + index post notify snap log + +PAT = \ + pat \ + patcil \ + patbase \ + patdiff \ + patmake \ + patclean \ + patcol \ + patname \ + patftp \ + patsend \ + patindex \ + patpost \ + patnotify \ + patsnap \ + patlog + +all:: $(PAT) + +local_realclean:: + $(RM) $(PAT) + +pat: pat.SH + /bin/sh pat.SH + +patcil: patcil.SH + /bin/sh patcil.SH + +patbase: patbase.SH + /bin/sh patbase.SH + +patdiff: patdiff.SH + /bin/sh patdiff.SH + +patmake: patmake.SH + /bin/sh patmake.SH + +patclean: patclean.SH + /bin/sh patclean.SH + +patcol: patcol.SH + /bin/sh patcol.SH + +patname: patname.SH + /bin/sh patname.SH + +patftp: patftp.SH + /bin/sh patftp.SH + +patsend: patsend.SH + /bin/sh patsend.SH + +patindex: patindex.SH + /bin/sh patindex.SH + +patpost: patpost.SH + /bin/sh patpost.SH + +patnotify: patnotify.SH + /bin/sh patnotify.SH + +patsnap: patsnap.SH + /bin/sh patsnap.SH + +patlog: patlog.SH + /bin/sh patlog.SH + + +local_install:: $(PAT) + @case '${MFLAGS}' in *[i]*) set +e;; esac; \ + (set -x; test -d $(INSTALL_PREFIX)$(SCRIPTDIR) || \ + $(INSTALLDIR) $(INSTALL_PREFIX)$(SCRIPTDIR)); \ + for i in $(PAT); do \ + (set -x; $(INSTALL) -c -m 555 \ + $$i $(INSTALL_PREFIX)$(SCRIPTDIR)) || exit 1;\ + done + +local_deinstall:: + @case '${MFLAGS}' in *[i]*) set +e;; esac; \ + for i in $(PAT); do \ + (set -x; $(RM) $(INSTALL_PREFIX)$(SCRIPTDIR)/$$i); \ + done + +local_install.man:: pat.man + @case '${MFLAGS}' in *[i]*) set +e;; esac; \ + (set -x; test -d $(INSTALL_PREFIX)$(MANSRC) || \ + $(INSTALLDIR) $(INSTALL_PREFIX)$(MANSRC)); \ + $(INSTALL) -c -m 444 pat.man $(INSTALL_PREFIX)$(MANSRC)/pat.$(L) + +local_deinstall.man:: + $(RM) $(INSTALL_PREFIX)$(MANSRC)/pat.$(L) + +PATSH = \ + pat.SH \ + patcil.SH \ + patbase.SH \ + patdiff.SH \ + patmake.SH \ + patclean.SH \ + patcol.SH \ + patname.SH \ + patftp.SH \ + patsend.SH \ + patindex.SH \ + patpost.SH \ + patnotify.SH \ + patsnap.SH \ + patlog.SH + +depend:: local_depend +local_depend:: + ($(SED) '/^# DO NOT DELETE/q' Makefile && \ + grep '^\$$grep' $(PATSH) | \ + $(SED) -e "s/^.*' \([^ ]*\) >>\([^ ]*\)/\2: \1/" \ + ) > Makefile.new + cp Makefile Makefile.bak + cp Makefile.new Makefile + $(RM) Makefile.new + +######################################################################## +# Common rules for all Makefiles -- do not edit + +all:: + +clean: local_clean +realclean: local_realclean +clobber: local_clobber + +local_clean:: + if test -f core; then $(RM) core; fi + $(RM) *~ *.o + +local_realclean:: local_clean + +local_clobber:: local_realclean + $(RM) Makefile config.sh + +install:: local_install +install.man:: maybe_install.man +deinstall:: local_deinstall +deinstall.man:: maybe_deinstall.man + +install.man-yes: local_install.man +install.man-no: +deinstall.man-yes: local_deinstall.man +deinstall.man-no: + +!NO!SUBS! +case "$installmansrc" in +'') man=no;; +*) man=yes;; +esac +$spitshell >>Makefile <<!GROK!THIS! +maybe_install.man: install.man-$man +maybe_deinstall.man: deinstall.man-$man +!GROK!THIS! +$spitshell >>Makefile <<'!NO!SUBS!' + +Makefile.SH: Jmakefile + -@if test -f $(TOP)/.package; then \ + if test -f Makefile.SH; then \ + echo " $(RM) Makefile.SH~; $(MV) Makefile.SH Makefile.SH~"; \ + $(RM) Makefile.SH~; $(MV) Makefile.SH Makefile.SH~; \ + fi; \ + echo " $(JMAKE) -DTOPDIR=$(TOP) -DCURDIR=$(CURRENT)" ; \ + $(JMAKE) -DTOPDIR=$(TOP) -DCURDIR=$(CURRENT) ; \ + else touch $@; fi + +Makefile: Makefile.SH + /bin/sh Makefile.SH + +tags:: + $(CTAGS) -w *.[ch] + $(CTAGS) -xw *.[ch] > tags + +local_clobber:: + $(RM) tags + +depend:: + +######################################################################## +# Empty rules for directories with no sub-directories -- do not edit + +local_install:: + @echo "install in $(CURRENT) done." + +local_deinstall:: + @echo "deinstall in $(CURRENT) done." + +local_install.man:: + @echo "install.man in $(CURRENT) done." + +local_deinstall.man:: + @echo "deinstall.man in $(CURRENT) done." + +Makefiles:: + +Makefiles.SH:: + +######################################################################## +# Dependencies generated by make depend +# DO NOT DELETE THIS LINE -- make depend relies on it + +# Put nothing here or make depend will gobble it up +.FORCE_DEPEND:: + @echo "You must run 'make depend' in $(TOP) first."; exit 1 +!NO!SUBS! +chmod 644 Makefile +$eunicefix Makefile + diff --git a/pat/README b/pat/README new file mode 100644 index 0000000..20e15ec --- /dev/null +++ b/pat/README @@ -0,0 +1,120 @@ +This is the root directory for pat tools. + +This directory contains an automatic patch generator. You must have RCS +to use this. You must also have run packinit in the top level directory +of your package to create a .package file. + +When you've modified a file in your package, the pat program is used to +control the whole process. The other programs can be called by hand, but +usually needn't be. Run pat from the top level directory of your package. + +The pat, patcil, patdiff, and patbase programs take a list of filenames as +arguments. Alternately, a -a means all files listed in MANIFEST. + +Patcil will create an RCS directory if necessary. However, it may not check in +things which require special initializaton properly. For example, if you +want to check in a shell script, you'd better make your RCS directory yourself +and then say + + rcs -i -c'# ' blurfl.xsh + +before running pat or patcil. Otherwise the RCS log may not be commented +properly. Unless of course you are using a standard extension (like .c for +a C file) or have placed the proper comments in front of the $Log marker +within the file itself--patcil will then correctly guess the type of +comment required. + +Patdiff will create a bugs directory in your top level directory, and will want +to find a patchlevel.h file in that same directory. Everything is done from +that top level directory--don't put any patchlevel.h or bugs directories in +your subdirectories. Each subdirectory has its own RCS directory though. + +Patpost, patsend and patftp may be used to post to Usenet, mail to someone, +or copy patches to your ftp directory. They take a destination and a list +of patches to process. + +Those pat tools are an hopefully enhanced version of the tools that +came with Larry Wall's dist 2.0. There are however a few new scripts: + + - patclean, which checks in the mods and removes the working files. + - patcol, which restores the files removed by a patclean. + - patname, which sets a symbolic version number. + +Here is the way I am using the pat tools... + +First, I set up a MANIFEST.new file. If you are converting an existing +distribution to use dist, the manifake script will convert a MANIFEST +into a MANIFEST.new (removing the possible archive number column). + +Then I run packinit to modify the version number and set up things +correctly. The package is then ready to be placed under pat control. +I make sure the file patchlevel.h is correctly set and I run: + + patcil -f -a -s + touch patchlevel.h + find . -name "*~" -exec /bin/rm -f {} \; -print + +There is a prototypical patchlevel.h file in this directory, so you +might want to have a look at it. + +[If you are planning on using the mailagent to send the patches (and sort +your mail -- that's its primary goal now), the you must make sure +the patchelevel.h file is locatated in the root directory of your package. +The mailagent program is available separately, and was posted on the +comp.sources.misc newsgroup] + +Now everything is ready. The distribution is frozen, the bugs directory +has been created. I issue a makedist -v to create the distribution kits. +Eventually I set up the mailagent so that people can request for the +distribution automatically. If I want to create a directory containing +the lattest sources (to be able to `kit' them to someone using the kit +program -- posted to comp.sources.unix), I use: + + makedist -c <package>-<version>@<patchlevel> + +for instance, for dist 2.9 at PL26 + + makedist -c dist-2.9@26 + +which I can then send to people directly with kit (which is NOT part +of this release). + +As I receive patches or find some bugs, I edit the files and make the +modifications. When I want to issue an official patch, I run: + + pat -n + +and one or more patches are issued. You can compress the patches in the +bugs subdirectory, since the mailpatch program knows about that. Also +patindex will correctly uncompress them. + +When I need to clean up the distribution directory, I use: + + patclean -a + +which checks in every changes and removes the working files. The whole +set of working files can then be restored by: + + patcol -a + +Sometimes, I made a couple of modification and I don't want to issue +a patch right now. I then run: + + patcil -a + +which checks in the changes. You can run this as many times as you want, +because patcil will skip unchanged file and remembers the last time you +issued a patch. + +If you are still using RCS 4.3, be sure you use makedist and not your +own shell archiver, as the $Locker symbol has an annoying expansion +which makes patch to fail when applyed. I'm not sure this was correctly +fixed with RCS 5.5 as I am not using it yet for various reasons. + +In any case, if you are using the copyright expansion feature (i.e. the +stuffing of the COPYRIGHT token surrounded by '@' -- can't do it here +or it will get expanded...), then you must use makedist to make sure +the copyright is properly written in all your files. Distributing files +with an un-expanded COPYRIGHT token in them would be a disaster, since +the patching system will also expand them before building a patch and +some of your hunks may not apply correctly. diff --git a/pat/pat.SH b/pat/pat.SH new file mode 100755 index 0000000..5723f26 --- /dev/null +++ b/pat/pat.SH @@ -0,0 +1,154 @@ +case $CONFIG in +'') + if test -f config.sh; then TOP=.; + elif test -f ../config.sh; then TOP=..; + elif test -f ../../config.sh; then TOP=../..; + elif test -f ../../../config.sh; then TOP=../../..; + elif test -f ../../../../config.sh; then TOP=../../../..; + else + echo "Can't find config.sh."; exit 1 + fi + . $TOP/config.sh + ;; +esac +case "$0" in +*/*) cd `expr X$0 : 'X\(.*\)/'` ;; +esac +echo "Extracting pat/pat (with variable substitutions)" +cat >pat <<!GROK!THIS! +$startperl + eval 'exec perl -S \$0 \${1+"\$@"}' + if \$running_under_some_shell; + +# $Id$ +# +# Copyright (c) 1991-1997, 2004-2006, Raphael Manfredi +# +# You may redistribute only under the terms of the Artistic Licence, +# as specified in the README file that comes with the distribution. +# You may reuse parts of this distribution only within the terms of +# that same Artistic Licence; a copy of which may be found at the root +# of the source tree for dist 4.0. +# +# Original Author: Larry Wall <lwall@netlabs.com> +# +# $Log: pat.SH,v $ +# Revision 3.0.1.5 1994/10/29 16:37:53 ram +# patch36: now unlinks all the files created by patlog in bugs +# +# Revision 3.0.1.4 1994/01/24 14:29:17 ram +# patch16: added ~/.dist_profile awareness +# +# Revision 3.0.1.3 1993/08/25 14:04:35 ram +# patch6: removal of patch temporary files did not work with gaps +# +# Revision 3.0.1.2 1993/08/24 12:14:39 ram +# patch3: now removes older patch temporary files within bugs +# +# Revision 3.0.1.1 1993/08/19 06:42:31 ram +# patch1: leading config.sh searching was not aborting properly +# +# Revision 3.0 1993/08/18 12:10:36 ram +# Baseline for dist 3.0 netwide release. +# + +\$version = '$VERSION'; +\$patchlevel = '$PATCHLEVEL'; +!GROK!THIS! +cat >>pat <<'!NO!SUBS!' + +$progname = &profile; # Read ~/.dist_profile +require 'getopts.pl'; +&usage unless $#ARGV >= 0; +&usage unless &Getopts("ahmnV"); + +if ($opt_V) { + print STDERR "$progname $version PL$patchlevel\n"; + exit 0; +} elsif ($opt_h) { + &usage; +} + +&readpackage; + +if (-f 'patchlevel.h') { + open(PL,"patchlevel.h") || die "$progname: can't open patchlevel.h: $!\n"; + while (<PL>) { + $bnum = $1 if /^#define\s+PATCHLEVEL\s+(\d+)/; + } + die "$progname: malformed patchlevel.h file.\n" if $bnum eq ''; + ++$bnum; +} else { + $bnum=1; +} + +if ($opt_n) { + &newer; # Look for files newer than patchlevel.h +} elsif ($opt_a) { + open(MANI,"MANIFEST.new") || die "No MANIFEST.new found.\n"; + @ARGV = (); + while (<MANI>) { + s|^\./||; + next if m|^patchlevel.h|; # This file is built by hand + chop; + ($_) = split(' '); + next if -d; + push(@ARGV,$_); + } + close MANI; +} elsif ($opt_m) { + open(MODS,"bugs/.mods$bnum") || die "$progname: no modification found.\n"; + @ARGV = (); + while (<MODS>) { + next if m|^patchlevel.h$|; # This file is built by hand + chop; + ($_) = split(' '); + push(@ARGV,$_); + } + close MODS; +} + +# Remove older patch temporary files + +@patlist = &patseq($bnum - 1); +foreach $cpat (@patlist) { + unlink <bugs/*.$cpat bugs/.logs$cpat bugs/.mods$cpat bugs/.xlog$cpat>; + unlink <bugs/.pri$cpat bugs/.subj$cpat bugs/.clog$cpat bugs/.rlog$cpat>; +} + +# Since we're about to launch other pat exectuables, disable ~/.dist_profile +# to protect them if they added some weird switches we don't need... + +$ENV{'DIST'} = '/dev/null'; # Disable ~/.dist_profile + +system 'perl', '-S', 'patcil', '-p', @ARGV; + +# Update MANIFEST if necessary, then patcil it. + +if (-f 'MANIFEST' && `diff MANIFEST.new MANIFEST 2>/dev/null` ne '') { + system 'cp', 'MANIFEST.new', 'MANIFEST'; + system 'perl', '-S', 'patcil', '-p', 'MANIFEST'; + push(@ARGV, 'MANIFEST'); +} + +system 'perl', '-S', 'patdiff', @ARGV; +system 'perl', '-S', 'patmake'; + +sub usage { + print STDERR "Usage: $progname [-ahmnV] [filelist]\n"; + print STDERR " -a : all the files in MANIFEST.new\n"; + print STDERR " -h : print this message and exit\n"; + print STDERR " -m : all the modified files (which have been patciled)\n"; + print STDERR " -n : all the files newer than patchlevel.h\n"; + print STDERR " -V : print version number and exit\n"; + exit 1; +} + +!NO!SUBS! +$grep -v '^;#' ../pl/newer.pl >>pat +$grep -v '^;#' ../pl/package.pl >>pat +$grep -v '^;#' ../pl/patseq.pl >>pat +$grep -v '^;#' ../pl/tilde.pl >>pat +$grep -v '^;#' ../pl/profile.pl >>pat +chmod +x pat +$eunicefix pat diff --git a/pat/pat.man b/pat/pat.man new file mode 100644 index 0000000..67a97b5 --- /dev/null +++ b/pat/pat.man @@ -0,0 +1,513 @@ +.rn '' }` +''' $Id$ +''' +''' Copyright (c) 1991-1997, 2004-2006, Raphael Manfredi +''' +''' You may redistribute only under the terms of the Artistic Licence, +''' as specified in the README file that comes with the distribution. +''' You may reuse parts of this distribution only within the terms of +''' that same Artistic Licence; a copy of which may be found at the root +''' of the source tree for dist 4.0. +''' +''' $Log: pat.man,v $ +''' Revision 3.0.1.7 1997/02/28 16:32:45 ram +''' patch61: documents contents of the message sent by patnotify +''' +''' Revision 3.0.1.6 1995/09/25 09:20:41 ram +''' patch59: new -i option for patsend to add extra instructions +''' +''' Revision 3.0.1.5 1995/05/12 12:25:28 ram +''' patch54: updated my e-mail address +''' +''' Revision 3.0.1.4 1994/10/29 16:38:31 ram +''' patch36: documents new patlog script and the files it uses +''' patch36: the RCS layer section has been extended slightly +''' +''' Revision 3.0.1.3 1993/08/27 14:40:19 ram +''' patch7: random cleanup +''' +''' Revision 3.0.1.2 1993/08/25 14:05:02 ram +''' patch6: new -q option for patsend and patnotify +''' +''' Revision 3.0.1.1 1993/08/24 12:15:42 ram +''' patch3: added patnotify and patsnap +''' patch3: patcol has a new -S option +''' patch3: the users file built by mailagent is now listed under FILES +''' +''' Revision 3.0 1993/08/18 12:10:37 ram +''' Baseline for dist 3.0 netwide release. +''' +.de Sh +.br +.ne 5 +.PP +\fB\\$1\fR +.PP +.. +.de Sp +.if t .sp .5v +.if n .sp +.. +''' +''' Set up \*(-- to give an unbreakable dash; +''' string Tr holds user defined translation string. +''' +.ie n \{\ +.tr \(*W-\*(Tr +.ds -- \(*W- +.if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +.if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +.ds L" "" +.ds R" "" +.ds L' ' +.ds R' ' +'br\} +.el\{\ +.ds -- \(em\| +.tr \*(Tr +.ds L" `` +.ds R" '' +.ds L' ` +.ds R' ' +'br\} +.TH PAT 1 ram +.SH NAME +pat \- patch generator tools +.SH SYNOPSIS +.B pat +[ +.B \-ahmnV +] [ +.I filelist +] +.br +.B patcil +[ +.B \-abfhnpqsV +] [ +.I filelist +] +.br +.B patdiff +[ +.B \-ahnV +] [ +.I filelist +] +.br +.B patbase +[ +.B \-ahV +] [ +.I filelist +] +.br +.B patlog +[ +.B \-hnruV +] +.br +.B patmake +[ +.B \-hV +] +.br +.B patsend +[ +.B \-hiquV +] [ +.I patchlist +] [ +.I recipients +] +.br +.B patnotify +[ +.B \-hquV +] [ +.I recipients +] +.br +.B patpost +[ +.B \-hrV +] +.I patchlist +.I newsgroups +.br +.B patftp +[ +.B \-hV +] [ +.I patchlist +] +.br +.B patname +[ +.B \-ahnmV +] +.B \-v +.I version +[ +.I filelist +] +.br +.B patsnap +[ +.B \-ahV +] [ +.B \-o +.I snapshot +] [ +.I filelist +] +.br +.B patcol +[ +.B \-achnmsCV +] [ +.B \-d +.I directory +] [ +.B \-f +.I mani +] [ +.B \-S +.I snap +] [ +.I filelist +] +.br +.B patclean +[ +.B \-ahnmV +] [ +.I filelist +] +.br +.B patindex +.SH DESCRIPTION +.I Pat +and its associated programs generate patches for any package that has been +stored under RCS. +These programs hide many of the details of RCS that get in your way when +constructing and maintaining a package. +All you need to do to create a new patch is to edit your files, run pat, +and furnish some descriptions to RCS and in the generated patch file. +Details such as how to initialize a new RCS file, what the comment string should +be, how create a new branch, +how to deal with subdirectories, how to do diffs and how to +organize the patch file are handled automatically. +.PP +Before using any of the pat programs you must initialize your package by +running packinit in the top-level directory of your package. +This produces a .package file that all of the dist programs make use of. +.PP +In any of the programs that want a filelist, if you specify +.B \-a +instead, +all files in MANIFEST.new will be processed. +In any of the programs that want a patchlist, a null patchlist means the +current patch. +You may use hyphens, commas and spaces to delimit patch numbers. +If the right side of a hyphen is the null string, the current patchlevel +is assumed as the maximum value. All the programs invoked with \fB\-h\fR +will print a small usage message with the meaning of each available options. +The \fB\-V\fR option gives the current version number. +.PP +Pat itself is a wrapper program that calls patcil, patdiff, and patmake. +Usually you can just invoke pat and ignore all the others. +Pat will update the MANIFEST file, if necessary (it will be an +exact copy of the MANIFEST.new file, provided that a MANIFEST already +existed), eventually calling patcil on it. +.PP +If you specify +.B \-n +instead of a filelist, pat will find all files that are +newer than patchlevel.h, put you into an editor to trim down the list, +then use that file list. +If every file of the list is removed, \fIpat\fR will be aborted. +.PP +.I Patcil +is used to do a ci -l on any listed files. +(It is assumed that you always want to keep your files checked out.) +In addition to the +.B \-a +switch, there is a +.B \-b +switch which does a quick checkin of +a set of files. +Instead of calling rcs on each file, it calls rcs on the whole list of +files. +This is useful for checking in a trunk revision. +When you are checking in a new trunk revision you might also want to use +the +.B \-s +flag which will strip out old RCS Log entries from the previous revision +so that you can start over fresh. +You probably should also use a +.B \-f +which is passed through to the ci to force unchanged files to be checked in. +To check in a new trunk revision, I say +.nf + + patcil -s -f -a + +.fi +.PP +Patcil will ask for the log entry instead of letting ci do it, and has a little +prompter built in that lets you manipulate the message in various ways. +Type h for a listing of what you can do. +One of the nicest things is that you can pop up into an editor, optionally +with a diff listing of the changes since the last patch, in case you've +forgotten what you changed. +If you type a CR as the first thing, it includes the +previous log message. +Exit the prompter with a CR. +.PP +There are two different ways to use patcil. +You can either call patcil yourself, or let pat call it for you. +It doesn't matter how many times you call patcil before running pat, since +patdiff knows what the last patch base is to compare with. +Patcil can be called in any of your directories; the other programs must +be called in your top-level directory (or in bugs, when meaningful). +.PP +When you are creating a new file at a given patchlevel, you must patcil it +with the +.B \-p +option. Otherwise, it will simply be checked-in as +a new trunk revision. The name of the file will be added to the MANIFEST.new +if it does not already appear in it. If the name is found along with a +description, that description will be passed through to rcs to properly +initialize the RCS file. +.PP +.I Patbase +can be used to reset the patch base to the current version when +you've scrapped the previous patch sequence and are making a new distribution +kit. +What it really does is an rcs -Nlastpat:REV, where REV is the current +revision. +If patdiff blows up and you want to set the patch base back to some previous +version, you have to call rcs -Nlastpat:REV yourself. +.PP +.I Patdiff +actually does the diffs that go into the patch, comparing whatever +version -Nlastpat points to with the most recently checked in version. +It then updates -Nlastpat to point to the current version. +It leaves the diff sitting in the bugs subdirectory for patmake to pick up. +It can either use rcsdiff, or a diff command of your choice specified when +you run packinit, in case your diff is better than rcsdiff. +.PP +.I Patlog +is invoked by \fIpatmake\fR usually, to update the \fIChangeLog\fR file +(or whatever name that file has been given when you ran \fIpackinit\fR). +It will gather log messages and launch an editor for you to make the +necessary updates. +If you have configured your package to also include RCS logs +in the \fIChangeLog\fR, another editor session will be launched for those +too. Finally, a final log is built as a candidate entry for \fIChangeLog\fR, +which you may also modify as you wish. +.PP +When you don't have configured a \fIChangeLog\fR file, \fIpatlog\fR will only +gather the information it needs to pass on to \fIpatmake\fR and will exit. +If you wish to call it yourself, you must do that after a least one +sucessfull \fIpatdiff\fR run. I recommend using the \fB\-n\fR option the +first time, and then use the \fB\-u\fR option along with \fB\-n\fR on +subsequent runs to recreate files only when needed. The \fB\-r\fR option +(which supersedes \fB\-u\fR) prevents \fIpatlog\fR from recreating an +existing file, even if it is out of date. +.PP +.I Patlog +will call \fIpatcil\fR and \fIpatdiff\fR on your \fIChangeLog\fR file +(after having stuffed the candidate log entry you edited at the top of the +file), unless prevented to do so by the \fB\-n\fR option. This means the +issued patch will update \fIChangeLog\fR with current patch information, as +you would expect it. +.PP +.I Patmake +combines all the pieces of the patch into one file and invokes +an editor so you can add the subject and description. +It throws all your log messages in as Subjects and as Description, under +the assumption +that it's easier to delete what you don't want than to remember everything +you did. +You'll also want to expand each item in the Description so they don't just +repeat the Subject lines. If you have a \fIChangeLog\fR file, this must have +been done already, or your \fIChangeLog\fR will not accurately represent +what is described in the patch, given that it has already been updated +when \fIpatmake\fR puts together all the pieces (see the note +about \fIpatlog\fR above). +.PP +Big patches will be split in order to keep size of each patch to a reasonable +size. This is handled automatically, so you don't have to bother with it. +The priority of each patch is merely intuited by \fIpatmake\fR, given the +assumption that small changes have a great priority. +.PP +Patsend, patpost and patftp are used to distribute your patches to the world. +.I Patsend +mails a set of patches to a set of recipients. The \fB\-u\fR switch adds all +the currently registered users who have asked for patches to be mailed to +them, as well as the recipients specified while running \fIpackinit\fR. +The \fB\-i\fR switch includes information with the patch about how the user +may deregister themselves so they do not receive future patches automatically; +this is also the default when the \fB\-u\fR switch is used. +.I Patpost +posts a set of patches to a set of newsgroups. +.I Patftp +merely copies the patch into your public ftp directory. +.PP +.I Patnotify +simply notifies users that a new patch has been released so that +they can retrieve it by themselves from an archive site or via e-mail if they +are interested. The \fB\-u\fR switch can be used to include all the currently +registered users who have asked for such a notification. The message includes +the patch priority and description, as well as instructions on how to +automatically request the patch (which will work only if you +have \fImailagent\fR installed). +.PP +Both \fIpatsend\fR and \fIpatnotify\fR let you edit the address list before +actually sending anything, unless you add the \fB\-q\fR option. +.PP +.I Patname +can be used to tag a set of files with a symbolic name (specified with +\fB\-v\fR). This will set the name for the most recent revision of each +file. +.PP +.I Patsnap +will get a snapshot of your release by creating a SNAPSHOT file (name can be +changed via \fB\-o\fR) listing the file names and the latest RCS revision +number for that file. Such snapshots can be used to identify the release +at some random patchlevel and then later be able to retrieve it by feeding +the snapshot file to \fIpatcol\fR. +.PP +.I Patcol +will check out a locked version of a file, eventually in an alternate +directory (specified with \fB\-d\fR, thus mirroring the distribution tree). +All the files which have no RCS counterpart (e.g. patchlevel.h) will be +simply copied by patcol. This is used by makedist to fake the distribution +before making the kits. By default, patcol will not do the copyright expansion +processing, but clients like \fImakedist\fR force it by using its \fB\-C\fR +option. Alternatively, you may force copying of the checked-out version +into a directory by using the \fB\-c\fR switch in conjunction with \fB\-d\fR +(or that former switch is simply ignored). +.PP +.I Patcol +can also take its file list from a SNAPSHOT file via the \fB\-S\fR switch, in +which case it will check out the files using the RCS version specified by the +snapshot file, such as one created by \fIpatsnap\fR. You may instead specify +\fB-a\fR, \fB\-m\fR or \fB\-n\fR to respectively use all the files in +MANIFEST.new, all the modified files (the one which have been \fIpatcil\fRed), +or all the files newer than \fIpatchlevel.h\fR. +.PP +.I Patclean +will remove the working files after having checked in all the +changes. You may restores your working files by using patcol. +.PP +.I Patindex +may be used from the top level directory or within the \fIbugs\fR directory. +It will list all the patches and their \fISubject:\fR lines. This program +knows about compressed patches and will decompress them while producing +the listing. +''' +''' R C S L a y e r +''' +.SH RCS LAYER +This section describes the RCS layer, in case something in the tools breaks, +so that you may fix your RCS files and restart the operation. +.PP +All the patch tools get the main RCS trunk revision number out of your +\&\fI.package\fR files, say it's 2.5. Then, at the time you ran \fIpackinit\fR, +you have chosen a branch for patches, usually number 1, which means all your +modifications will be stored on the 2.5.1 RCS branch. The tools will create +the branch for you when the time comes. +.PP +Each last released revision is tagged with an RCS \fIlastpat\fR symbol. When +the patch is built by \fIpatdiff\fR, the lattest version on the 2.5.1 branch +is compared with the one tagged as \fIlastpat\fR. This is why you may safely +issue more than one \fIpatcil\fR beffore issuing the patch and still have +it all worked out. Of course \fIpatdiff\fR will move the \fIlastpat\fR +tag to the lattest branch revision after processing a given file. +.PP +All the log messages and the modified files are kept in your \fIbugs\fR +directory, in hidden files (name starting with a dot). Those logs will be +collected when the patch is issued and the modified files are used by +\&\fIpat\fR's \fB\-m\fR switch. +.PP +.I Patdiff +collects its patch hunks under the \fIbugs\fR directory, in files +terminating with a \fI.nn\fR extension, where \fInn\fR represents the +current patch level + 1. (Which is going to be the next patchlevel when the +patch will be made by \fIpatmake\fR, unless it is too big to fit in one +file). +.PP +.I Patlog +prepares a set of files for \fIpatmake\fR: the \fI.clog\fR file collects +the information that will go under the Description: section within the +patch, and \fI.xlog\fR ones collect the \fIChangeLog\fR candidate entry. +Finally, \fI.rlog\fR files store the RCS information that is to be included +in the \fIChangeLog\fR, if requested. Note that the topmost three lines +are garbage and are ignored by all the tools handling those files. +.PP +In order to start up a new baseline (i.e. to change the RCS trunk revision +number), you need to rerun \fIpackinit\fR and change that number. Then issue +a new \fIpatcil\fR, probably with the \fB\-s\fR, \fB\-a\fR and \fB\-f\fR +options... +.SH FILES +.PD 0 +.TP 15 +bugs/*.[0-9]+ +Diffs for each file, gathered by \fIpatmake\fR to create a patch +.TP +bugs/patch* +Issued patches (can be compressed with \fIcompress\fR only) +.TP +bugs/.clog[0-9]+ +Description to be filled into the patch (or the first part if the patch is +split into several parts). +.TP +bugs/.logs[0-9]+ +Log messages for that patch +.TP +bugs/.mods[0-9]+ +Files modified in that patch (checked in with \fIpatcil\fR) +.TP +bugs/.pri[0-9]+ +The priority of the next patch, computed +by \fIpatlog\fR for \fIpatmake\fR's perusal. +.TP +bugs/.rlog[0-9]+ +The RCS logs computed by \fIpatlog\fR. +.TP +bugs/.subj[0-9]+ +The Subject: lines for the next patch, computed +by \fIpatlog\fR for \fIpatmake\fR's perusal. +.TP +bugs/.xlog[0-9]+ +The candidate entry for \fIChangeLog\fR. +.TP +users +File filled in by \fImailagent\fR's "@SH package" command, normally +issued by Configure, recording some of the users who kindly registered +themselves. +.PD +.SH ENVIRONMENT +.PD 0 +.TP 15 +PAGER +Which pager to use in patcil (overrides default) +.TP +EDITOR +What editor should be used (overrides default) +.TP +VISUAL +Same role as EDITOR but this one is checked first +.PD +.SH SEE ALSO +makedist(1), metaconfig(1). +.SH BUGS +Most of this should be built into RCS. +.SH AUTHORS +Larry Wall (version 2.0). +.br +Raphael Manfredi <Raphael.Manfredi@pobox.com>. +.rn }` '' diff --git a/pat/patbase.SH b/pat/patbase.SH new file mode 100755 index 0000000..e96ec55 --- /dev/null +++ b/pat/patbase.SH @@ -0,0 +1,122 @@ +case $CONFIG in +'') + if test -f config.sh; then TOP=.; + elif test -f ../config.sh; then TOP=..; + elif test -f ../../config.sh; then TOP=../..; + elif test -f ../../../config.sh; then TOP=../../..; + elif test -f ../../../../config.sh; then TOP=../../../..; + else + echo "Can't find config.sh."; exit 1 + fi + . $TOP/config.sh + ;; +esac +case "$0" in +*/*) cd `expr X$0 : 'X\(.*\)/'` ;; +esac +echo "Extracting pat/patbase (with variable substitutions)" +cat >patbase <<!GROK!THIS! +$startperl + eval 'exec perl -S \$0 \${1+"\$@"}' + if \$running_under_some_shell; + +# $Id$ +# +# Copyright (c) 1991-1997, 2004-2006, Raphael Manfredi +# +# You may redistribute only under the terms of the Artistic Licence, +# as specified in the README file that comes with the distribution. +# You may reuse parts of this distribution only within the terms of +# that same Artistic Licence; a copy of which may be found at the root +# of the source tree for dist 4.0. +# +# Original Author: Larry Wall <lwall@netlabs.com> +# +# $Log: patbase.SH,v $ +# Revision 3.0.1.3 1994/01/24 14:29:24 ram +# patch16: added ~/.dist_profile awareness +# +# Revision 3.0.1.2 1993/08/24 12:15:58 ram +# patch3: random cleanup +# +# Revision 3.0.1.1 1993/08/19 06:42:32 ram +# patch1: leading config.sh searching was not aborting properly +# +# Revision 3.0 1993/08/18 12:10:38 ram +# Baseline for dist 3.0 netwide release. +# + +\$version = '$VERSION'; +\$patchlevel = '$PATCHLEVEL'; +!GROK!THIS! +cat >>patbase <<'!NO!SUBS!' + +$progname = &profile; # My name + +require 'getopts.pl'; +&usage unless $#ARGV >= 0; +&usage unless &Getopts("ahV"); + +if ($opt_V) { + print STDERR "$progname $version PL$patchlevel\n"; + exit 0; +} elsif ($opt_h) { + &usage; +} + +&readpackage; + +$RCSEXT = ',v' unless $RCSEXT; +$TOPDIR = ''; # We are at the top-level directory + +if ($opt_a) { + open(MANI,"MANIFEST.new") || die "No MANIFEST.new found.\n"; + @ARGV = (); + while (<MANI>) { + chop; + s|^\./||; + next if m|^patchlevel.h|; # Special file + ($_) = split(' '); + next if -d; + push(@ARGV,$_); + } + close MANI; +} + +foreach $file (@ARGV) { + $files = &rcsargs($file); + @files = split(' ',$files); + $revs=0; + $rlog = `rlog -r$baserev -r$revbranch $files 2>&1`; + ($revs) = ($rlog =~ /selected revisions: (\d+)/); + if (!$revs) { + print "$progname: $file has never been checked in--checking in...\n"; + system 'perl', '-S', 'patcil', $file; + } + elsif ($revs == 1) { + print "Last revision for $file is $baserev.\n"; + system 'rcs', "-Nlastpat:$baserev", @files; + } + else { + ($lastrev) = ($rlog =~ /revision $revbranch\.(\d+)/); + print "Last revision for $file is $revbranch.$lastrev.\n"; + system 'rcs', "-Nlastpat:$revbranch.$lastrev", @files; + } +} + +sub usage { + print STDERR "Usage: $progname [-ahV] [filelist]\n"; + print STDERR " -a : all the files in MANIFEST.new\n"; + print STDERR " -h : print this message and exit\n"; + print STDERR " -V : print version number and exit\n"; + exit 1; +} + +!NO!SUBS! +$grep -v '^;#' ../pl/package.pl >>patbase +$grep -v '^;#' ../pl/rcsargs.pl >>patbase +$grep -v '^;#' ../pl/comment.pl >>patbase +$grep -v '^;#' ../pl/tilde.pl >>patbase +$grep -v '^;#' ../pl/profile.pl >>patbase +chmod +x patbase +$eunicefix patbase diff --git a/pat/patchlevel.h b/pat/patchlevel.h new file mode 100644 index 0000000..66b289a --- /dev/null +++ b/pat/patchlevel.h @@ -0,0 +1,34 @@ +/* + * This is a prototypical patchlevel.h file. Only the line defining + * the PATCHLEVEL symbol is taken into account when patching, so be + * sure to make changes to this file ONLY when you start a new release + * and, of course, before running patcil... + * + * This file must appear in your MANIFEST.new, but it will never be + * checked in by the pat tools. It is automatically updated when a new + * patch is issued. + * + * When using the '-n' option in some pat* scripts, this file is + * taken as a timestamp. So it is best to avoid manual editing unless + * you know what you are doing. + */ + +/* + * $Id$ + * + * Copyright (c) 1991-1997, 2004-2006, Raphael Manfredi + * + * You may redistribute only under the terms of the Artistic Licence, + * as specified in the README file that comes with the distribution. + * You may reuse parts of this distribution only within the terms of + * that same Artistic Licence; a copy of which may be found at the root + * of the source tree for dist 4.0. + * + * $Log: patchlevel.h,v $ + * Revision 3.0 1993/08/18 12:10:39 ram + * Baseline for dist 3.0 netwide release. + * + */ + +#define VERSION 3.0 /* For instance */ +#define PATCHLEVEL 0 /* This line is a mandatory */ diff --git a/pat/patcil.SH b/pat/patcil.SH new file mode 100755 index 0000000..642bac2 --- /dev/null +++ b/pat/patcil.SH @@ -0,0 +1,541 @@ +case $CONFIG in +'') + if test -f config.sh; then TOP=.; + elif test -f ../config.sh; then TOP=..; + elif test -f ../../config.sh; then TOP=../..; + elif test -f ../../../config.sh; then TOP=../../..; + elif test -f ../../../../config.sh; then TOP=../../../..; + else + echo "Can't find config.sh."; exit 1 + fi + . $TOP/config.sh + ;; +esac +case "$0" in +*/*) cd `expr X$0 : 'X\(.*\)/'` ;; +esac +echo "Extracting pat/patcil (with variable substitutions)" +$cat >patcil <<!GROK!THIS! +$startperl + eval 'exec perl -S \$0 \${1+"\$@"}' + if \$running_under_some_shell; + +# $Id$ +# +# Copyright (c) 1991-1997, 2004-2006, Raphael Manfredi +# +# You may redistribute only under the terms of the Artistic Licence, +# as specified in the README file that comes with the distribution. +# You may reuse parts of this distribution only within the terms of +# that same Artistic Licence; a copy of which may be found at the root +# of the source tree for dist 4.0. +# +# Original Author: Larry Wall <lwall@netlabs.com> +# +# $Log: patcil.SH,v $ +# Revision 3.0.1.4 1994/10/29 16:42:12 ram +# patch36: now honors the VISUAL and EDITOR environment variables +# patch36: newer RCS programs chop trailing spaces in log messages +# patch36: separated V/E and v/e commands +# patch36: new 'v' command to edit the file being patcil'ed +# patch36: added hook for 'V' command (not implemented yet) +# +# Revision 3.0.1.3 1994/01/24 14:30:04 ram +# patch16: now prefix error messages with program's name +# patch16: added ~/.dist_profile awareness +# +# Revision 3.0.1.2 1993/08/25 14:05:35 ram +# patch6: moved geteditor to ../pl/editor.pl +# +# Revision 3.0.1.1 1993/08/19 06:42:33 ram +# patch1: leading config.sh searching was not aborting properly +# +# Revision 3.0 1993/08/18 12:10:40 ram +# Baseline for dist 3.0 netwide release. +# + +\$defeditor = '$defeditor'; +\$pager = '$pager'; +\$version = '$VERSION'; +\$patchlevel = '$PATCHLEVEL'; +!GROK!THIS! +cat >>patcil <<'!NO!SUBS!' + +$progname = &profile; # Read ~/.dist_profile +require 'getopts.pl'; +&usage unless $#ARGV >= 0; +&usage unless &Getopts("abfhnpqsV"); + +if ($opt_V) { + print STDERR "$progname $version PL$patchlevel\n"; + exit 0; +} elsif ($opt_h) { + &usage; +} + +$RCSEXT = ',v' unless $RCSEXT; +$PAGER = $ENV{'PAGER'} || "$pager"; +$EDITOR = &geteditor; + +system 'mkdir', 'RCS' unless -d 'RCS'; + +chop($pwd = `pwd`) unless -f '.package'; +until (-f '.package') { + die "$progname: no .package file! Run packinit.\n" unless $pwd; + chdir '..' || die "Can't cd .."; + $pwd =~ s|(.*)/(.*)|$1|; + $prefix = $2 . '/' . $prefix; +} +if ($prefix) { + for (@ARGV) { + s/^/$prefix/ unless m|^[-/]|; + } +} + +# We now are at the top level + +&readpackage; + +if (-f 'patchlevel.h') { + open(PL,"patchlevel.h") || die "$progname: can't open patchlevel.h: $!\n"; + while (<PL>) { + $bnum = $1 if /^#define\s+PATCHLEVEL\s+(\d+)/; + } + die "$progname: malformed patchlevel.h file.\n" if $bnum eq ''; + ++$bnum; +} else { + $bnum=1; +} + +system 'mkdir', 'bugs' unless -d 'bugs'; +open(LOGS,">>bugs/.logs$bnum"); # Remember logs for patmake +open(MODS,">>bugs/.mods$bnum"); # Remember modified files + +push(@sw,'-q') if $opt_q; +push(@sw,'-f') if $opt_f; + +if ($opt_a) { + open(MANI,"MANIFEST.new") || die "$progname: can't read MANIFEST.new: $!\n"; + @ARGV = (); + while (<MANI>) { + chop; + s|^\./||; + next if m|^patchlevel.h|; # Special file + ($_) = split(' '); + next if -d; + push(@ARGV,$_); + } + close MANI; +} elsif ($opt_n) { + &newer; +} + +@filelist = @ARGV; + +sub CLEANUP { + print "$progname: Warning: restore $ARGV\n"; + exit 1; +} + +if ($opt_s) { + open(TTY,">/dev/tty"); + select(TTY); + $| = 1; + select(stdout); + $SIG{'INT'} = 'CLEANUP'; + while (<>) { + if (/^(.*)\$Log[:\$]/) { + $comment = $1; + $comment =~ s/\s+$//; # Newer RCS chop spaces on emtpy lines + $len = length($comment); + print; + $lastnl = 1; + logline: while (<>) { + $c = substr($_,0,$len); + last logline unless $c eq $comment; + $_ = substr($_,$len,999); + if ($lastnl) { + unless (/^\s*Revision\s+\d/) { + $_ = $comment . $_; + last logline; + } + $lastnl = 0; + } else { + $lastnl = 1 if /^\s*$/; + } + } + } + } + continue { + print; + if ($ARGV ne $oldargv) { + print TTY "$progname: stripping $ARGV...\n"; + $oldargv = $ARGV; + } + } + $SIG{'INT'} = 'DEFAULT'; + close TTY; +} + +if ($opt_b) { + $flist = &rcsargs(@filelist); + @flist=split(' ',$flist); + system 'rcs', '-u', @flist; + system 'rcs', "-l$revbranch", @flist; + system 'ci', '-l', "-r$revbranch", @sw, @flist; + exit 0; +} + +open(MANI,"MANIFEST.new") || die "$progname: can't open MANIFEST.new: $!\n"; +while (<MANI>) { + # Find how many spaces the user wants before comments + $space || /(\S+\s+)\S+/ && ($space = length($1)); + ($file,$file_comment) = m|(\S+)\s+(.*)|; + $inmani{$file} = 1; # File is listed in MANIFEST + $comment{$file} = $file_comment; # Save comments +} +close MANI; +$space = 29 unless $space; # Default value + +file: foreach $file (@filelist) { + $files = &rcsargs($file); + @files = split(' ',$files); + $file = $files[1] if $file =~ /\.$RCSEXT$/; + unless ($inmani{$file}) { + print "$file does not appear to be in your MANIFEST.new--add? [y] "; + $ans = <stdin>; + if ($ans !~ /^n/i) { + print "MANIFEST.new comment? "; + $file_comment = <stdin>; + chop($file_comment); + $spacenum = $space - length($file); + $blank = " "; + $blank = " " x $spacenum unless $spacenum < 1; + `echo '${file}${blank}$file_comment' >>MANIFEST.new`; + if (-f 'MANIFEST') { + print "(Also adding file to your MANIFEST)\n"; + # Add a (new) at the end, so the two manifests will + # differ and thus manifest will get patched correctly. + `echo '${file}${blank}$file_comment (new)' >>MANIFEST`; + print MODS "MANIFEST\n"; + } + } else { + $file_comment = ""; # No file, no comment + } + } + $is_first = 0; # Suppose this is not the first cil + $revs = 0; # Makes revs a numeric variable + $rlog = `rlog -r$baserev -r$revbranch $files 2>&1`; + ($total) = ($rlog =~ /total revisions: (\d+)/); + ($revs) = ($rlog =~ /selected revisions: (\d+)/); + $comment = &rcscomment($file); + if (!$revs) { + if ($total) { + if ($rlog !~ /locks:\s*;/) { + system 'rcs', '-u', @files; # unlock branch + } + # New trunck revision + system 'rcs', '-l', @files; # lock trunk + } + else { + $file_comment = $comment{$file} if $inmani{$file}; + if ($comment ne '') { + &feed($file_comment, 'rcs', '-i', "-c$comment", @files); + } else { + &feed($file_comment, 'rcs', '-i', @files); + } + } + if ($opt_p) { # check in null as trunk revision + rename($file, "$file.xxx"); + `cp /dev/null $file` unless -f $file; + &cil_col("empty\n", $baserev); + system 'rcs', "-Nlastpat:$baserev", @files; + rename("$file.xxx", $file); + $mess = &getlog($file); + next file if $mess eq 'nope'; + system 'rcs', '-u', @files; # Unlock trunck + &feed($mess, 'ci', "-l$revbranch", @sw, @files) unless $?; + } else { + $is_first = 1; # This is the first cil + $mess = &getlog($file); + next file if $mess eq 'nope'; + &cil_col($mess, $baserev); + system 'rcs', "-Nlastpat:$baserev", @files; + } + } else { + if (!$opt_f) { + if ($revs == 1) { + $delta = `rcsdiff -r$baserev $files 2>/dev/null`; + } else { + $delta = `rcsdiff -r$revbranch $files 2>/dev/null`; + } + if ($delta eq '') { # No change in file + print "$progname: no changes in $file since last patcil.\n"; + next; # Skip file + } + } + if ($revs == 1) { + $mess = &getlog($file); + next file if $mess eq 'nope'; + &cil_cil($mess, $revbranch); + } else { + $mess = &getlog($file); + next file if $mess eq 'nope'; + &cil_col($mess, $revbranch); + } + } +} + +# Used for the first revisions on a branch +sub cil_cil { + local($mess) = shift(@_); + local($rev) = shift(@_); + if (&feed($mess, 'ci', @sw, "-l$rev", @files)) { + print "$progname: unlocking and trying again...\n"; + system 'rcs', '-u', @files; + &feed($mess, 'ci', @sw, "-l$rev", @files) unless $?; + } +} + +# Run a ci -l on the file. If this fails, try to lock the file first. +# If this fails again, try again with a separate checkout. +sub cil_col { + local($mess) = shift(@_); + local($rev) = shift(@_); + if (&feed($mess, 'ci', @sw, "-l$rev", @files)) { + print "$progname: locking and trying again...\n"; + if ($rev =~ /\d+\.\d+\.\d+/) { + system 'rcs', "-l$rev", @files; # Lock branch + } else { + system 'rcs', '-l', @files; # Lock trunck + } + if (&feed($mess, 'ci', @sw, "-l$rev", @files)) { + print "$progname: trying again with separate checkout...\n"; + if (&feed($mess, 'ci', @sw, "-r$rev", @files)) { + system 'rcs', "-u$rev", @files unless $?; + system 'co', "-l$rev", @files unless $?; + } else { + print "$progname: sorry, giving up...\n"; + } + } + } +} + +sub feed { + local($mess) = shift(@_); + open(FORK,"|-") || exec @_; + print FORK $mess; + close FORK; + $?; +} + +sub getlog { + local($file) = @_; + local($mess) = ''; + local($prefix) = "patch$bnum: "; + local($prompt) = $comment; + local($len); + $prompt = '>> ' unless $prompt; + $prefix = '' if $is_first; + print "Type log message for $file (finish with ., CR for previous):\n"; + try: for (;;) { + line: for (print "$prompt$prefix";;print "$prompt$prefix") { + if ($always) { + print "\n"; + $line = ''; + } else { + $line = <stdin>; + } + if ($line =~ /^\.?$/) { + if ($mess) { + last line; + } else { + $line = 'p'; + } + } + if ($line =~ /^[h?]$/) { + print " +CR or . Terminate log message. +!<cmd> Start command in a subshell. +D Print out diff listing since last patch. +N Give name of the current file. +E Call editor for log message with a diff listing. +V Call editor for file with a context diff added to HISTORY. +X Extract HISTORY and append it to current log message. +a Always use this message. +d Print out diff listing since last patcil. +f Forget message I have so far. +h or ? This help message. +l List what I have so far. +n Forget this file; go to next file if any. +p Append previous message. +r Print out the rlog for this file. +e Call editor for log message. +v Call editor for file. +x Toggle patch# prefix. + +"; + next line; + } + if ($line =~ /^!(.*)$/) { + $_ = $1; + $_ = ($ENV{'SHELL'} || "/bin/sh") if $1 eq ''; + system $_; + next line; + } + if ($line =~ /^E$/) { + $mess .= "\n" . `rcsdiff -c -rlastpat $files`; + } + if ($line =~ /^e$/) { + $mess = &edit($mess); + next line; + } + if ($line =~ /^V$/) { + ######## FIXME ######### + # Will do something like: + # &add_history($file, `rcsdiff -c -rlastpat $files`); + # HISTORY + # Extract or add this. Create it if not already there. + # $Log + # $EndLog <<-- stops HISTORY and COPYRIGHT lookup + ######################## + print "HISTORY processing not implemented yet.\n"; + print "(You have to use 'E' to get old 'V' processing).\n"; + next line; + } + if ($line =~ /^v$/) { + system $EDITOR, $file; + next line; + } + if ($line =~ /^r$/) { + system "rlog $files | $PAGER"; + next line; + } + if ($line =~ /^D$/) { + if ($revs == 0) { + print "Sorry. There is no revision for this file yet.\n"; + } else { + system "rcsdiff -c -rlastpat $files | $PAGER"; + } + next line; + } + if ($line =~ /^d$/) { + if ($revs == 0) { + print "Sorry. There is no revision for this file yet.\n"; + } + elsif ($revs == 1) { + system "rcsdiff -c -r$baserev $files | $PAGER"; + } else { + system "rcsdiff -c -r$revbranch $files | $PAGER"; + } + next line; + } + if ($line =~ /^N$/) { + print "Typing log message for $file.\n"; + next line; + } + if ($line =~ /^f$/) { + $mess = ''; + next line; + } + if ($line =~ /^a$/) { + $always++ if $mess || $prevmess; + next line; + } + if ($line =~ /^n$/) { + $mess = 'nope'; + last line; + } + if ($line =~ /^l$/) { + foreach $line (split(/\n/,$mess)) { + print $prompt,$line,"\n"; + } + next line; + } + if ($line =~ /^p$/) { + $mess .= $prevmess; + foreach $line (split(/\n/,$prevmess)) { + print $prompt,$line,"\n"; + } + next line; + } + if ($line =~ /^X$/) { + foreach $line (split(/\n/, &xtract_history($file))) { + $mess .= $prompt . $line . "\n"; + print $prompt,$line,"\n"; + } + next line; + } + if ($line =~ /^x$/) { + $prefix = $prefix ? '' : "patch$bnum: "; + next line; + } + $mess .= $prefix . $line; + $len = length($comment . $prefix . $line); + if ($len > 80) { + print "(Warning: last line longer than 80 chars)\n"; + } elsif ($len > 72) { # In case of vi with line numbers + print "(Warning: last line longer than 72 chars)\n"; + } + if (length($mess) > 511) { + print "You'll have to trim to less than 512 chars...\n"; + sleep(3); + $mess = &edit($mess); + } + } + $mess = $prevmess if $mess eq ''; + if (!$mess) { + print "No previous message, try again.\n"; + next try; + } + if (length($mess) > 511) { + print "Sorry, that's too long; RCS won't take it. Try again...\n"; + next try; + } + last try; + } + unless ($is_first) { + print LOGS $mess unless $mess eq 'nope'; + print MODS "$file\n"; + } + $prevmess = $mess unless $mess eq 'nope'; + $mess; # Returned value +} + +sub edit { + local($text) = join("\n", @_); + open(TMP,">/tmp/cil$$") || die "Can't create /tmp/cil$$"; + print TMP $text; + close TMP; + system $EDITOR, "/tmp/cil$$"; + $text = `cat /tmp/cil$$`; + unlink "/tmp/cil$$"; + $text; +} + +sub usage { + print STDERR <<EOM; +Usage: $progname [-abfhnpqsV] [filelist] + -a : all the files in MANIFEST.new + -b : batch mode + -f : force check in (passed through to ci) + -h : print this message and exit + -n : all the files newer than patchlevel.h + -p : patching mode (null trunk revision if new file) + -q : ask rcs to be quiet + -s : strip log messages + -V : print version number and exit +EOM + exit 1; +} + +!NO!SUBS! +$grep -v '^;#' ../pl/newer.pl >>patcil +$grep -v '^;#' ../pl/package.pl >>patcil +$grep -v '^;#' ../pl/rcsargs.pl >>patcil +$grep -v '^;#' ../pl/comment.pl >>patcil +$grep -v '^;#' ../pl/editor.pl >>patcil +$grep -v '^;#' ../pl/tilde.pl >>patcil +$grep -v '^;#' ../pl/profile.pl >>patcil +chmod +x patcil +$eunicefix patcil diff --git a/pat/patclean.SH b/pat/patclean.SH new file mode 100755 index 0000000..363e480 --- /dev/null +++ b/pat/patclean.SH @@ -0,0 +1,185 @@ +case $CONFIG in +'') + if test -f config.sh; then TOP=.; + elif test -f ../config.sh; then TOP=..; + elif test -f ../../config.sh; then TOP=../..; + elif test -f ../../../config.sh; then TOP=../../..; + elif test -f ../../../../config.sh; then TOP=../../../..; + else + echo "Can't find config.sh."; exit 1 + fi + . $TOP/config.sh + ;; +esac +case "$0" in +*/*) cd `expr X$0 : 'X\(.*\)/'` ;; +esac +echo "Extracting pat/patclean (with variable substitutions)" +cat >patclean <<!GROK!THIS! +$startperl + eval 'exec perl -S \$0 \${1+"\$@"}' + if \$running_under_some_shell; + +# $Id$ +# +# Copyright (c) 1991-1997, 2004-2006, Raphael Manfredi +# +# You may redistribute only under the terms of the Artistic Licence, +# as specified in the README file that comes with the distribution. +# You may reuse parts of this distribution only within the terms of +# that same Artistic Licence; a copy of which may be found at the root +# of the source tree for dist 4.0. +# +# $Log: patclean.SH,v $ +# Revision 3.0.1.2 1994/01/24 14:30:17 ram +# patch16: now prefix error messages with program's name +# patch16: added ~/.dist_profile awareness +# +# Revision 3.0.1.1 1993/08/19 06:42:33 ram +# patch1: leading config.sh searching was not aborting properly +# +# Revision 3.0 1993/08/18 12:10:41 ram +# Baseline for dist 3.0 netwide release. +# + +\$version = '$VERSION'; +\$patchlevel = '$PATCHLEVEL'; +!GROK!THIS! +cat >>patclean <<'!NO!SUBS!' + +$RCSEXT = ',v' unless $RCSEXT; + +$progname = &profile; # Read ~/.dist_profile +require 'getopts.pl'; +&usage unless $#ARGV >= 0; +&usage unless &Getopts("ahnmV"); + +if ($opt_V) { + print STDERR "$progname $version PL$patchlevel\n"; + exit 0; +} elsif ($opt_h) { + &usage; +} + +$RCSEXT = ',v' unless $RCSEXT; +$ENV{'DIST'} = '/dev/null'; # Disable ~/.dist_profile + +chop($pwd = `pwd`) unless -f '.package'; +until (-f '.package') { + die "$progname: no .package file! Run packinit.\n" unless $pwd; + chdir '..' || die "$progname: can't cd ..: $!\n"; + $pwd =~ s|(.*)/(.*)|$1|; + $prefix = $2 . '/' . $prefix; +} +if ($prefix) { + for (@ARGV) { + s/^/$prefix/ unless m|^[-/]|; + } +} + +# We now are at the top level + +&readpackage; + +if ($opt_n) { + &newer; # Look for files newer than patchlevel.h +} elsif ($opt_a) { + open(MANI,"MANIFEST.new") || die "$progname: can't read MANIFEST.new: $!\n"; + @ARGV = (); + while (<MANI>) { + s|^\./||; + next if m|^patchlevel.h|; # This file is built by hand + chop; + ($_) = split(' '); + next if -d; + push(@ARGV,$_); + } + close MANI; +} elsif ($opt_m) { + open(MODS,"bugs/.mods$bnum") || die "$progname: no modification found.\n"; + @ARGV = (); + while (<MODS>) { + next if m|^patchlevel.h$|; # This file is built by hand + chop; + ($_) = split(' '); + push(@ARGV,$_); + } + close MODS; +} + +# Set a temporary file for check outs +$TMPFILE = "/tmp/cl$$.tmp"; + +# Now loop over each file specified, doing a 'rcsclean' +foreach $file (@ARGV) { + if (-f $file) { + $files = &rcsargs($file); + @files = split(' ', $files); + $rlog = `rlog -rlastpat- $files 2>&1`; + ($revs) = ($rlog =~ /selected revisions: (\d+)/); + if (!$revs) { + print "$progname: $file has never been checked in--checking in...\n"; + system 'perl', '-S', 'patcil', '-p', $file; + $revs = 2; # At least null trunk + new fresh revision + } + # Look whether there is a branch + if ($revs == 1) { + $rlog = `rlog -r$revbranch $files 2>&1`; + ($revs) = ($rlog =~ /selected revisions: (\d+)/); + $revs++; # add the base revision + } + # We must only give the name of the RCS revision file, i.e. $files[1] + if ($revs == 1) { + system "co -q -p$baserev $files[1] > $TMPFILE"; + } else { + system "co -q -p$revbranch $files[1] > $TMPFILE"; + } + if ($? == 0) { + system 'cmp', '-s', $file, $TMPFILE; + if ($? == 0) { + unlink $file; + print "$progname: $file removed.\n"; + } else { + # Check in file and make sure all was ok + system 'perl', '-S', 'patcil', '-p', $file; + system "co -q -p$revbranch $files[1] > $TMPFILE"; + if ($? == 0) { + system 'cmp', '-s', $file, $TMPFILE; + if ($? == 0) { + unlink $file; + print "$progname: $file removed.\n"; + } else { + print "$progname: $file NOT removed.\n"; + } + } else { + print "$progname: could not check out--$file NOT removed.\n"; + } + } + } else { + print "$progname: no revision--$file NOT removed.\n"; + } + } +} + +unlink "$TMPFILE"; + +sub usage { + print STDERR <<EOM; +Usage: $progname [-ahnmV] [filelist] + -a : all the files in MANIFEST.new + -h : print this message and exit + -n : all the files newer than patchlevel.h + -m : all the modified files (which have been patciled) + -V : print version number and exit +EOM + exit 1; +} + +!NO!SUBS! +$grep -v '^;#' ../pl/newer.pl >>patclean +$grep -v '^;#' ../pl/package.pl >>patclean +$grep -v '^;#' ../pl/rcsargs.pl >>patclean +$grep -v '^;#' ../pl/tilde.pl >>patclean +$grep -v '^;#' ../pl/profile.pl >>patclean +chmod +x patclean +$eunicefix patclean diff --git a/pat/patcol.SH b/pat/patcol.SH new file mode 100755 index 0000000..61c9310 --- /dev/null +++ b/pat/patcol.SH @@ -0,0 +1,235 @@ +case $CONFIG in +'') + if test -f config.sh; then TOP=.; + elif test -f ../config.sh; then TOP=..; + elif test -f ../../config.sh; then TOP=../..; + elif test -f ../../../config.sh; then TOP=../../..; + elif test -f ../../../../config.sh; then TOP=../../../..; + else + echo "Can't find config.sh."; exit 1 + fi + . $TOP/config.sh + ;; +esac +case "$0" in +*/*) cd `expr X$0 : 'X\(.*\)/'` ;; +esac +echo "Extracting pat/patcol (with variable substitutions)" +cat >patcol <<!GROK!THIS! +$startperl + eval 'exec perl -S \$0 \${1+"\$@"}' + if \$running_under_some_shell; + +# $Id$ +# +# Copyright (c) 1991-1997, 2004-2006, Raphael Manfredi +# +# You may redistribute only under the terms of the Artistic Licence, +# as specified in the README file that comes with the distribution. +# You may reuse parts of this distribution only within the terms of +# that same Artistic Licence; a copy of which may be found at the root +# of the source tree for dist 4.0. +# +# $Log: patcol.SH,v $ +# Revision 3.0.1.3 1994/01/24 14:30:25 ram +# patch16: now prefix error messages with program's name +# patch16: added ~/.dist_profile awareness +# +# Revision 3.0.1.2 1993/08/24 12:16:30 ram +# patch3: new -S option for snapshot check-outs +# +# Revision 3.0.1.1 1993/08/19 06:42:34 ram +# patch1: leading config.sh searching was not aborting properly +# +# Revision 3.0 1993/08/18 12:10:42 ram +# Baseline for dist 3.0 netwide release. +# + +\$version = '$VERSION'; +\$patchlevel = '$PATCHLEVEL'; +!GROK!THIS! +cat >>patcol <<'!NO!SUBS!' + +$progname = &profile; # Read ~/.dist_profile +require 'getopts.pl'; +&usage unless $#ARGV >= 0; +&usage unless &Getopts("acd:f:hnmsCRS:V"); + +if ($opt_V) { + print STDERR "$progname $version PL$patchlevel\n"; + exit 0; +} elsif ($opt_h) { + &usage; +} + +$RCSEXT = ',v' unless $RCSEXT; +$NEWMANI = 'MANIFEST.new' unless $NEWMANI = $opt_f; + +chop($pwd = `pwd`) unless -f '.package'; +until (-f '.package') { + die "$progname: no .package file! Run packinit.\n" unless $pwd; + chdir '..' || die "$progname: can't cd ..: $!"; + $pwd =~ s|(.*)/(.*)|$1|; + $prefix = $2 . '/' . $prefix; +} +if ($prefix) { + for (@ARGV) { + s/^/$prefix/ unless m|^[-/]|; + } +} + +# We now are at the top level + +&readpackage; +undef $opt_C unless -f $copyright; +©right'init($copyright) if $opt_C; +&makedir($opt_d) if $opt_d; + +undef $opt_c unless $opt_d; # Disable -c if not -d +undef $opt_R unless $opt_d; # Disable -R if not -d +push(@sw, '-q') if $opt_s; # Let RCS work quietly + +if ($opt_n) { + &newer; # Look for files newer than patchlevel.h +} elsif ($opt_a) { + open(MANI, $NEWMANI) || die "No $NEWMANI found.\n"; + @ARGV = (); + while (<MANI>) { + s|^\./||; + next if m|^patchlevel.h| && !$opt_d; # This file is built by hand + chop; + ($_) = split(' '); + next if -d; + push(@ARGV,$_); + } + close MANI; +} elsif ($opt_m) { + open(MODS,"bugs/.mods$bnum") || die "$progname: no modification found.\n"; + @ARGV = (); + while (<MODS>) { + next if m|^patchlevel.h$|; # This file is built by hand + chop; + ($_) = split(' '); + next if -d; + push(@ARGV,$_); + } + close MODS; +} elsif ($opt_S) { + &readsnapshot($opt_S); + foreach $file (sort keys %Snap) { + push(@ARGV, $file); + } +} + +# Now loop over each file specified, doing a 'co -l' +foreach $file (@ARGV) { + if ($opt_c && -f $file) { + ©_file($file, $opt_d); + next; + } + # Continue only if file does not exist or option -d was used. + if (! -f $file || $opt_d) { + $files = &rcsargs($file); + @files = split(' ', $files); + if ($opt_S && ($rev = $Snap{$file}) ne '') { # Use snapshot file + &col($rev); + next; + } + $rlog = `rlog -rlastpat- $files 2>&1`; + ($revs) = ($rlog =~ /selected revisions: (\d+)/); + if (!$revs) { + if ($opt_d) { + ©_file($file, $opt_d); + } else { + print STDERR "$progname: $file has never been checked in\n"; + } + } else { + # Look whether there is a branch + if ($revs == 1) { + $rlog = `rlog -r$revbranch $files 2>&1`; + ($revs) = ($rlog =~ /selected revisions: (\d+)/); + $revs++; # add the base revision (trunk) + } + if ($revs == 1) { + &col($baserev); + } else { + &col($revbranch); + } + } + + } +} + +# Run co -l on @files, unlock file if it fails and retry. +# If '-d' option was used, we check out in the specified +# directory, after having made all the necessary directories +# in the path name (which should be relative to the top). +sub col { + local($rev) = shift; # Revision to be checked out. + if (! $opt_d) { + if (system 'co', "-l$rev", @sw, @files) { + print "$progname: unlocking and trying again...\n" unless $opt_s; + system 'rcs', '-u', @sw, @files; + system 'co', "-l$rev", @sw, @files unless $?; + } + } else { + local($name) = $files[0]; # First element is file name + $_ = $name; + s|(.*)/.*|\1| && &makedir("$opt_d/$_"); + if ($opt_C) { + ©right'expand("co -p @sw -r$rev $files[1]", "$opt_d/$name"); + } else { + system "co -p -r$rev @sw $files[1] > $opt_d/$name"; + } + system 'perl', '-pi', '-e', 's|Lock[e]r:.*\$|\$|;', "$opt_d/$name" + if $opt_R; + # If RCS file has x bits set, add them on new file + -x $files[1] && chmod(0755, "$opt_d/$name"); + } +} + +# Copy file into directory, eventually performing copyright expansion... +sub copy_file { + local($file, $dir) = @_; + local($base) = $file =~ m|^(.*)/.*|; + &makedir("$dir/$base"); + if ($opt_C) { + ©right'expand("cat $file", "$dir/$file"); + } else { + system 'cp', "$file", "$dir/$file"; + } + system 'perl', '-pi', '-e', 's|Lock[e]r:.*\$|\$|;', "$dir/$file" if $opt_R; + -x $file && chmod(0755, "$dir/$file"); + print "$progname: $file has been copied\n" unless $opt_s; +} + +sub usage { + print STDERR <<EOM; +Usage: $progname [-achnmsCRV] [-d directory] [-f mani] [-S snap] [filelist] + -a : all the files in MANIFEST.new (see also -f) + -c : copy files if checked-out copy exists (only when -d) + -d : check out (or copy) in the specified directory + -f : use supplied file instead of MANIFEST.new + -h : print this message and exit + -n : all the files newer than patchlevel.h + -m : all the modified files (which have been patciled) + -s : silent mode + -C : perform copyright expansion on checked out (or copied) file + -R : strip out RCS \$Locker marker from checked-out file (only when -d) + -S : use snapshot file to determine file list and RCS revisions + -V : print version number and exit +EOM + exit 1; +} + +!NO!SUBS! +$grep -v '^;#' ../pl/newer.pl >>patcol +$grep -v '^;#' ../pl/package.pl >>patcol +$grep -v '^;#' ../pl/rcsargs.pl >>patcol +$grep -v '^;#' ../pl/copyright.pl >>patcol +$grep -v '^;#' ../pl/makedir.pl >>patcol +$grep -v '^;#' ../pl/snapshot.pl >>patcol +$grep -v '^;#' ../pl/tilde.pl >>patcol +$grep -v '^;#' ../pl/profile.pl >>patcol +chmod +x patcol +$eunicefix patcol diff --git a/pat/patdiff.SH b/pat/patdiff.SH new file mode 100755 index 0000000..0c74c9a --- /dev/null +++ b/pat/patdiff.SH @@ -0,0 +1,236 @@ +case $CONFIG in +'') + if test -f config.sh; then TOP=.; + elif test -f ../config.sh; then TOP=..; + elif test -f ../../config.sh; then TOP=../..; + elif test -f ../../../config.sh; then TOP=../../..; + elif test -f ../../../../config.sh; then TOP=../../../..; + else + echo "Can't find config.sh."; exit 1 + fi + . $TOP/config.sh + ;; +esac +case "$0" in +*/*) cd `expr X$0 : 'X\(.*\)/'` ;; +esac +echo "Extracting pat/patdiff (with variable substitutions)" +cat >patdiff <<!GROK!THIS! +$startperl + eval 'exec perl -S \$0 \${1+"\$@"}' + if \$running_under_some_shell; + +# $Id$ +# +# Copyright (c) 1991-1997, 2004-2006, Raphael Manfredi +# +# You may redistribute only under the terms of the Artistic Licence, +# as specified in the README file that comes with the distribution. +# You may reuse parts of this distribution only within the terms of +# that same Artistic Licence; a copy of which may be found at the root +# of the source tree for dist 4.0. +# +# Original Author: Larry Wall <lwall@netlabs.com> +# +# $Log: patdiff.SH,v $ +# Revision 3.0.1.2 1994/01/24 14:30:36 ram +# patch16: now prefix error messages with program's name +# patch16: added ~/.dist_profile awareness +# +# Revision 3.0.1.1 1993/08/19 06:42:35 ram +# patch1: leading config.sh searching was not aborting properly +# +# Revision 3.0 1993/08/18 12:10:43 ram +# Baseline for dist 3.0 netwide release. +# + +\$version = '$VERSION'; +\$patchlevel = '$PATCHLEVEL'; +!GROK!THIS! +cat >>patdiff <<'!NO!SUBS!' + +$RCSEXT = ',v' unless $RCSEXT; +$TOPDIR = ''; # We are at top-level directory + +$progname = &profile; # Read ~/.dist_profile +require 'getopts.pl'; +&usage unless $#ARGV >= 0; +&usage unless &Getopts("ahnV"); + +if ($opt_V) { + print STDERR "$progname $version PL$patchlevel\n"; + exit 0; +} elsif ($opt_h) { + &usage; +} + +&readpackage; +©right'init($copyright) if -f $copyright; + +system 'mkdir', 'bugs' unless -d 'bugs'; + +if (-f 'patchlevel.h') { + open(PL,"patchlevel.h") || die "$progname: can't open patchlevel.h: $!\n"; + while (<PL>) { + $bnum = $1 if /^#define\s+PATCHLEVEL\s+(\d+)/; + } + die "$progname: malformed patchlevel.h file.\n" if $bnum eq ''; + ++$bnum; +} else { + $bnum=1; +} + +if ($opt_a) { + open(MANI,"MANIFEST.new") || die "$progname: can't read MANIFEST.new: $!\n"; + @ARGV = (); + while (<MANI>) { + chop; + ($_) = split(' '); + next if -d; + push(@ARGV,$_); + } + close MANI; +} + +foreach $file (@ARGV) { + next if ($file =~ /^patchlevel.h$/); # Skip patchlevel.h + if (! -f $file) { + print "$progname: $file not found.\n"; + next; + } + $files = &rcsargs($file); + @files = split(' ',$files); + $new=''; + $revs=0; + $rlog = `rlog -rlastpat- $files 2>&1`; + ($lastpat) = ($rlog =~ /lastpat: ([\d.]+)/); + ($revs) = ($rlog =~ /selected revisions: (\d+)/); + if (!$revs) { + print "$progname: no cil has been done on $file.\n" ;; + } elsif ($revs == 1) { + ($base) = ($rlog =~ /.*\nrevision\s+(\S+)/); + ($a,$b,$c,$d) = split(/\./,$base); + if ($d ne '') { + if (!$opt_n) { + print + "$progname: no changes in $file since last patch. (Did you cil it?)\n"; + next; # Skip file with no changes + } else { + $new='foo'; + } + } else { + $revs=0; + $rlog = `rlog -r$revbranch- $files 2>&1`; + ($revs) = ($rlog =~ /selected revisions: (\d+)/); + if (!$revs) { + print + "$progname: no changes in $file since base version. (Did you cil it?)\n"; + next; # Skip file with no changes + } else { + ($new) = ($rlog =~ /\nrevision\s*(\d+\.\d+\.\d+\.\d+)/); + } + } + } else { + ($new) = ($rlog =~ /\nrevision\s*(\d+\.\d+\.\d+\.\d+)/); + } + if ($new ne '') { + ($fname = $file) =~ s|.*/||; + $fname = substr($fname, 0, 11); # For filsystems with short names + open(PATCH,">>bugs/$fname.$bnum") || die "Can't make patch"; + print PATCH "\nIndex: $file\n"; + open(CO,"co -p -rlastpat $files 2>/dev/null |"); + while (<CO>) { + if (/\$Header/ || /\$Id/) { + print PATCH "Prereq: $lastpat\n"; + last; + } + } + close CO; + if (!$opt_n) { + if ($mydiff eq '') { + open(DIFF,"rcsdiff -c -rlastpat -r$new $files |") || + die "$progname: can't fork rcsdiff: $!\n"; + while (<DIFF>) { + if ($. == 1) {s|\*\*\* \S+ |*** $file.old |;} + if ($. == 2) {s|--- \S+ |--- $file |;} + s|Lock[e]r:.*\$|\$|; # Use [e] to make it safe on itself + print PATCH; + } + close DIFF; + system 'rcs', "-Nlastpat:$new", @files; + } else { + ©right'expand("co -p -rlastpat $file", "/tmp/pdo$$"); + ©right'expand("co -p -r$new $file", "/tmp/pdn$$"); + open(DIFF, "$mydiff /tmp/pdo$$ /tmp/pdn$$ |") || + die "Can't run $mydiff"; + while (<DIFF>) { # Contextual or unified diff + if ($. == 1) { + s|\*\*\* \S+ |*** $file.old | || + s|--- \S+ |--- $file.old |; + } + if ($. == 2) { + s|--- \S+ |--- $file | || + s|\+\+\+ \S+ |+++ $file |; + } + s|Lock[e]r:.*\$|\$|; # Remove locker mark + print PATCH; + } + close DIFF; + system 'rcs', "-Nlastpat:$new", @files; + unlink "/tmp/pdn$$", "/tmp/pdo$$"; + } + } else { + if ($mydiff eq '') { + open(DIFF,"rcsdiff -c -rlastpat $files |") || + die "Can't run rcsdiff"; + while (<DIFF>) { + if ($. == 1) {s|\*\*\* \S+ |*** $file.old |;} + if ($. == 2) {s|--- \S+ |--- $file |;} + s|Lock[e]r:.*\$|\$|; # Remove locker mark + print PATCH; + } + close DIFF; + } else { + system "co -p -rlastpat $files >/tmp/pdo$$"; + system "cp $file /tmp/pdn$$"; + open(DIFF, "$mydiff /tmp/pdo$$ /tmp/pdn$$ |") || + die "$progname: can't fork $mydiff: $!\n"; + while (<DIFF>) { + # Contextual or unified diff + if ($. == 1) { + s|\*\*\* \S+ |*** $file.old |; + s|--- \S+ |--- $file.old |; + } + if ($. == 2) { + s|--- \S+ |--- $file |; + s|\+\+\+ \S+ |+++ $file |; + } + s|Lock[e]r:.*\$|\$|; # Remove locker mark + print PATCH; + } + close DIFF; + unlink "/tmp/pdn$$", "/tmp/pdo$$"; + } + } + } +} + +sub usage { + print STDERR <<EOM; +Usage: $progname [-ahnV] [filelist] + -a : all the files in MANIFEST.new + -h : print this message and exit + -n : non update mode + -V : print version number and exit +EOM + exit 1; +} + +!NO!SUBS! +$grep -v '^;#' ../pl/package.pl >>patdiff +$grep -v '^;#' ../pl/rcsargs.pl >>patdiff +$grep -v '^;#' ../pl/copyright.pl >>patdiff +$grep -v '^;#' ../pl/tilde.pl >>patdiff +$grep -v '^;#' ../pl/profile.pl >>patdiff +chmod +x patdiff +$eunicefix patdiff diff --git a/pat/patftp.SH b/pat/patftp.SH new file mode 100755 index 0000000..d14fd46 --- /dev/null +++ b/pat/patftp.SH @@ -0,0 +1,118 @@ +case $CONFIG in +'') + if test -f config.sh; then TOP=.; + elif test -f ../config.sh; then TOP=..; + elif test -f ../../config.sh; then TOP=../..; + elif test -f ../../../config.sh; then TOP=../../..; + elif test -f ../../../../config.sh; then TOP=../../../..; + else + echo "Can't find config.sh."; exit 1 + fi + . $TOP/config.sh + ;; +esac +case "$0" in +*/*) cd `expr X$0 : 'X\(.*\)/'` ;; +esac +echo "Extracting pat/patftp (with variable substitutions)" +cat >patftp <<!GROK!THIS! +$startperl + eval 'exec perl -S \$0 \${1+"\$@"}' + if \$running_under_some_shell; + +# $Id$ +# +# Copyright (c) 1991-1997, 2004-2006, Raphael Manfredi +# +# You may redistribute only under the terms of the Artistic Licence, +# as specified in the README file that comes with the distribution. +# You may reuse parts of this distribution only within the terms of +# that same Artistic Licence; a copy of which may be found at the root +# of the source tree for dist 4.0. +# +# Original Author: Larry Wall <lwall@netlabs.com> +# +# $Log: patftp.SH,v $ +# Revision 3.0.1.3 1994/01/24 14:30:43 ram +# patch16: now prefix error messages with program's name +# patch16: added ~/.dist_profile awareness +# +# Revision 3.0.1.2 1993/08/24 12:16:57 ram +# patch3: removed useless orgname variable +# +# Revision 3.0.1.1 1993/08/19 06:42:36 ram +# patch1: leading config.sh searching was not aborting properly +# +# Revision 3.0 1993/08/18 12:10:44 ram +# Baseline for dist 3.0 netwide release. +# + +\$version = '$VERSION'; +\$patchlevel = '$PATCHLEVEL'; +!GROK!THIS! +cat >>patftp <<'!NO!SUBS!' + +$progname = &profile; # Read ~/.dist_profile +require 'getopts.pl'; +&usage unless &Getopts("hV"); + +if ($opt_V) { + print STDERR "$progname $version PL$patchlevel\n"; + exit 0; +} elsif ($opt_h) { + &usage; +} + +$RCSEXT = ',v' unless $RCSEXT; +chdir '..' if -d '../bugs'; + +&readpackage; + +if ($#ARGV < 0) { + open(PL,"patchlevel.h") || die "$progname: can't open patchlevel.h: $!\n"; + while (<PL>) { + $argv = $1 if /^#define\s+PATCHLEVEL\s+(\d+)/; + } + close PL; + die "$progname: malformed patchlevel.h file.\n" if $argv eq ''; + @ARGV = $argv; +} else { + for (@ARGV) { + s/^patch//; + } + $argv = &rangeargs(@ARGV); + @ARGV = split(' ',$argv); +} + +if ($#ARGV < 0) { + print STDERR "$progname: no patches specified.\n"; + &usage; +} elsif ($#ARGV) { + print "$progname: copying $package $baserev patches $argv to $ftpdir...\n"; +} else { + print "$progname: copying $package $baserev patch $argv to $ftpdir...\n"; +} + +chdir 'bugs' || die "$progname: can't cd to bugs: $!\n"; + +until ($#ARGV < 0) { + $patnum = shift; + `cp patch$patnum $ftpdir`; +} + +sub usage { + print STDERR <<EOM; +Usage: $progname [-hV] patchlist + -h : print this message and exit + -V : print version number and exit +EOM + exit 1; +} + +!NO!SUBS! +$grep -v '^;#' ../pl/package.pl >>patftp +$grep -v '^;#' ../pl/rangeargs.pl >>patftp +$grep -v '^;#' ../pl/tilde.pl >>patftp +$grep -v '^;#' ../pl/profile.pl >>patftp +chmod +x patftp +$eunicefix patftp diff --git a/pat/patindex.SH b/pat/patindex.SH new file mode 100755 index 0000000..83e175b --- /dev/null +++ b/pat/patindex.SH @@ -0,0 +1,66 @@ +case $CONFIG in +'') + if test -f config.sh; then TOP=.; + elif test -f ../config.sh; then TOP=..; + elif test -f ../../config.sh; then TOP=../..; + elif test -f ../../../config.sh; then TOP=../../..; + elif test -f ../../../../config.sh; then TOP=../../../..; + else + echo "Can't find config.sh."; exit 1 + fi + . $TOP/config.sh + ;; +esac +case "$0" in +*/*) cd `expr X$0 : 'X\(.*\)/'` ;; +esac +echo "Extracting pat/patindex (with variable substitutions)" +$spitshell >patindex <<!GROK!THIS! +$startsh + +# $Id$ +# +# Copyright (c) 1991-1997, 2004-2006, Raphael Manfredi +# +# You may redistribute only under the terms of the Artistic Licence, +# as specified in the README file that comes with the distribution. +# You may reuse parts of this distribution only within the terms of +# that same Artistic Licence; a copy of which may be found at the root +# of the source tree for dist 4.0. +# +# Original Author: Larry Wall <lwall@netlabs.com> +# +# $Log: patindex.SH,v $ +# Revision 3.0.1.1 1993/08/19 06:42:37 ram +# patch1: leading config.sh searching was not aborting properly +# +# Revision 3.0 1993/08/18 12:10:44 ram +# Baseline for dist 3.0 netwide release. +# + +zcat='$zcat' +test='$test' +sed='$sed' +grep='$grep' + +!GROK!THIS! +$spitshell >>patindex <<'!NO!SUBS!' +if test -d bugs; then + cd bugs +fi +for i in patch? patch??; do + if $test -f $i; then + echo "=== $i ===" + $grep '^Subject: ' $i | $sed 's/^patch\(.*\):Subject/\1/' + fi +done +for i in patch?.Z patch??.Z; do + if $test -f $i; then + name=`echo $i | $sed "s|\.Z$||"` + echo "=== $name ===" + $zcat $i | $grep '^Subject: ' | $sed 's/^patch\(.*\):Subject/\1/' + fi +done +!NO!SUBS! +chmod 755 patindex +$eunicefix patindex diff --git a/pat/patlog.SH b/pat/patlog.SH new file mode 100755 index 0000000..1588af4 --- /dev/null +++ b/pat/patlog.SH @@ -0,0 +1,388 @@ +case $CONFIG in +'') + if test -f config.sh; then TOP=.; + elif test -f ../config.sh; then TOP=..; + elif test -f ../../config.sh; then TOP=../..; + elif test -f ../../../config.sh; then TOP=../../..; + elif test -f ../../../../config.sh; then TOP=../../../..; + else + echo "Can't find config.sh."; exit 1 + fi + . $TOP/config.sh + ;; +esac +case "$0" in +*/*) cd `expr X$0 : 'X\(.*\)/'` ;; +esac +echo "Extracting pat/patlog (with variable substitutions)" +cat >patlog <<!GROK!THIS! +$startperl + eval 'exec perl -S \$0 \${1+"\$@"}' + if \$running_under_some_shell; + +# $Id$ +# +# Copyright (c) 1991-1997, 2004-2006, Raphael Manfredi +# +# You may redistribute only under the terms of the Artistic Licence, +# as specified in the README file that comes with the distribution. +# You may reuse parts of this distribution only within the terms of +# that same Artistic Licence; a copy of which may be found at the root +# of the source tree for dist 4.0. +# +# $Log: patlog.SH,v $ +# Revision 3.0.1.2 1997/02/28 16:33:03 ram +# patch61: typo fix +# +# Revision 3.0.1.1 1994/10/29 16:42:26 ram +# patch36: created +# + +\$defeditor='$defeditor'; +\$version = '$VERSION'; +\$patchlevel = '$PATCHLEVEL'; +!GROK!THIS! +cat >>patlog <<'!NO!SUBS!' + +$progname = &profile; # Read ~/.dist_profile +require 'getopts.pl'; +&usage unless &Getopts("hnruV"); + +if ($opt_V) { + print STDERR "$progname $version PL$patchlevel\n"; + exit 0; +} elsif ($opt_h) { + &usage; +} + +&readpackage; + +if (-f 'patchlevel.h') { + open(PL,"patchlevel.h") || die "$progname: can't open patchlevel.h: $!\n"; + while (<PL>) { + if (/^#define\s+PATCHLEVEL\s+(\d+)/) { + $last = $1; + $patchline = $.; # Record PATCHLEVEL line + } + } + die "$progname: malformed patchlevel.h file.\n" if $last eq ''; + $bnum = $last + 1; +} +else { + $patchline = 1; + $bnum = 1; + $last = ''; +} + +chdir 'bugs' if -d 'bugs'; + +die "$progname: patch #$bnum already exists.\n" if -f "patch$bnum"; + +@patlist=<*.$bnum>; +die "$progname: no diff files for patch #$bnum.\n" if + $patlist[0] =~ /^\*/ || $patlist[0] eq ''; + +# Set up a proper editor, for later perusal +$editor = $ENV{'VISUAL'}; +$editor = $ENV{'EDITOR'} unless $editor; +$editor = $defeditor unless $editor; +$editor = 'vi' unless $editor; + +# The following used to be done in patmake. Only we do not really need to +# compute the subject lines for the generated patch here, we do it nonetheless +# to avoid code duplication in patmake. + +if (-s ".logs$bnum") { + $logs = ''; + open(LOGS,".logs$bnum"); + while (<LOGS>) { + unless ($logseen{$_}) { + $logs .= $_; + $logseen{$_}++; + $logsnum++; # One more log + } + } + close LOGS; + $subj = $logs; + $logs =~ s/^patch\d+:\s*/\t/gm; + $logs =~ s/\n/\n\n/gm; + $subj =~ s/^patch\d+:\s*/Subject: /gm; +} else { + $subj = "Subject: \n"; +} + +# Try to guess the priority of the patch +if (-s ".mods$bnum") { + open(MODS, ".mods$bnum"); + while (<MODS>) { + chop; + unless ($fileseen{$_}) { + $fileseen{$_}++; + $modsnum++; # One more modified file + } + } + close MODS; +} +$modsnum++ unless $modsnum; # Avoid divisions by zero +$mean = $logsnum / $modsnum; +if ($mean > 0.7 && $mean < 1.3) { + $priority = "MEDIUM"; +} elsif ($mean <= 0.7) { + $priority = "HIGH"; # Small changes +} else { + $priority = "LOW"; # Big changes +} + +# Save priority for patmake +open(PRIORITY, ">.pri$bnum") || die "$progname: can't create .pri$bnum: $!\n"; +print PRIORITY $priority, "\n"; +close PRIORITY; + +# Save subject lines for patmake +open(SUBJECTS, ">.subj$bnum") || die "$progname: can't create .subj$bnum: $!\n"; +print SUBJECTS $subj; +close SUBJECTS; + +# +# Generate description file, then edit it so that the user may fixup things. +# + +unless (($opt_r && -f ".clog$bnum") || ($opt_u && &uptodate(".clog$bnum"))) { + open(CHANGES, ">.clog$bnum") || + die "$progname: can't create .clog$bnum: $!\n"; + print CHANGES <<EOM; +Edition of the Description section for patch #$bnum. +Please leave those three lines here, they will be removed automatically. +------------------------------------------------------------------------ +EOM + print CHANGES $logs; + close CHANGES; +} + +# If they don't want to maintain a ChangeLog file, that's it. They'll get +# the old behaviour where the description is edited directly from within +# the generated patch. + +exit(0) if $changelog =~ /^\s*$/; + +system $editor, ".clog$bnum"; + +# +# Generate RCS log file. +# + +if ($changercs) { + unless ( + ($opt_r && -f ".rlog$bnum") || ($opt_u && &uptodate(".rlog$bnum")) + ) { + &buildlogs; + open(RCS, ">.rlog$bnum") || + die "$progname: can't create .rlog$bnum: $!\n"; + print RCS <<EOM; +Edition of the RCS log section for $changelog (patch #$bnum). +Please leave those three lines here, they will be removed automatically. +------------------------------------------------------------------------ +EOM + foreach $key (sort keys %rcslog) { + print RCS &format('* ' . $rcslog{$key}), "\n"; + } + close RCS; + } + system $editor, ".rlog$bnum"; +} + +# +# Final logfile entry generation +# + +chop($date=`date`); + +unless ( + ($opt_r && -f ".xlog$bnum") || + ($opt_u && &uptodate(".xlog$bnum") && !&newertmp) +) { + open(LOG, ">.xlog$bnum") || die "$progname: can't create .xlog$bnum: $!\n"; + print LOG <<EOM; +Edition of the $changelog entry for patch #$bnum. +Please leave those three lines here, they will be removed automatically. +------------------------------------------------------------------------ +EOM + print LOG "$date $maintname <$maintloc>\n\n"; + print LOG ". Description:\n\n"; + &addlog(".clog$bnum"); + if ($changercs) { + print LOG ". Files changed:\n\n"; + &addlog(".rlog$bnum"); + } + close LOG; +} +system $editor, ".xlog$bnum"; +exit(0) if $opt_n; + +# +# Changelog file update, checking in and diff computation. +# + +print "$progname: updating $changelog...\n"; + +chdir('..') || die "$progname: can't go back to ..: $!\n"; +if (-f $changelog) { + rename($changelog, "$changelog.bak") || + die "$progname: can't rename $changelog into $changelog.bak: $!\n"; +} + +open(LOG, ">$changelog") || die "$progname: can't create $changelog: $!\n"; +&addlog("bugs/.xlog$bnum"); +if (-f "$changelog.bak") { + open(OLOG, "$changelog.bak") || + die "$progname: can't open $changelog.bak: $!\n"; + print LOG while <OLOG>; + close OLOG; +} +close LOG; + +print "$progname: checking in $changelog and computing diff...\n"; + +# It is safe to run a patcil and a patdiff now, since the Changelog file has +# been updated anyway: any log done while checking that file in will not +# appear in the patch log nor the Changelog. + +system 'perl', '-S', 'patcil', '-p', $changelog; +system 'perl', '-S', 'patdiff', $changelog; + +exit 0; # All done. + +# Returns true if .clog and .rlog (it it exists) are newer than .xlog. +sub newertmp { + return 1 unless -f ".xlog$bnum"; # To force regeneration + return 1 if &newer(".clog$bnum", ".xlog$bnum") || + (!$changercs || &newer(".rlog$bnum", ".xlog$bnum")); + 0; +} + +# Returns true if $file is newer than the reference file $ref. +sub newer { + local($file, $ref) = @_; + (stat($file))[9] >= (stat($ref))[9]; +} + +# Retursn true if $file is up-to-date with respect to .logs and .mods. +sub uptodate { + local($file) = @_; + return 0 unless -f $file; # Cannot be up-to-date if missing + &newer($file, ".logs$bnum") && &newer($file, ".mods$bnum"); +} + +# Add file to the LOG descriptor, skipping the first three lines of that file. +sub addlog { + local($file) = @_; + open(FILE, $file) || die "$progname: can't reopen $file: $!\n"; + $_ = <FILE>; $_ = <FILE>; $_ = <FILE>; + print LOG while <FILE>; + close FILE; +} + +# Build RCS logs, for each file listed in the %fileseen array, into %rcslog. +# Common RCS log messages are grouped under the same entry. +sub buildlogs { + local($log); + local(@files); + local($first); + local(%invertedlog); + foreach $file (keys %fileseen) { + $log = &rcslog($file); + next if $log eq ''; + $invertedlog{$log} .= "$file "; + } + foreach $log (keys %invertedlog) { + @files = split(' ', $invertedlog{$log}); + $first = (sort @files)[0]; + $rcslog{$first} = join(', ', @files) . ': ' . $log; + } +} + +# Grab log for a given file by parsing its $Log section. Only comments +# relevant to the patch are kept. This relies on the presence of the patchxx: +# leading string in front of each comment. +# If not sufficient (because people don't use patchxx prefixes), then we'll +# need a more sophisticated algorithm parsing revisions lines to see where we +# left of at the last patch. +sub rcslog { + local($file) = @_; + open(FILE, "../$file") || warn "$me: can't open $file: $!\n"; + local($_); + local($comment, $len); + local($pcomment) = "patch$bnum:"; + local($plen) = length($pcomment); + local($c); + local($lastnl) = 1; + local($kept); # Relevant part of the RCS comment which is kept + file: while (<FILE>) { + if (/^(.*)\$Log[:\$]/) { + $comment = $1; + $comment =~ s/\s+$//; # Newer RCS chop spaces on emtpy lines + $len = length($comment); + while (<FILE>) { + $c = substr($_, 0, $len); + last file unless $c eq $comment; + $_ = substr($_, $len, 9_999); + if ($lastnl) { + last file unless /^\s*Revision\s+\d/; + $lastnl = 0; + } elsif (/^\s*$/) { + $lastnl = 1; + } else { + s/^\s*//; # Older RCS will have space here + $c = substr($_, 0, $plen); + last file unless $c eq $pcomment; + # Comment for that patch is kept after space cleanup + $_ = substr($_, $plen, 9_999); + s/^\s*//; + s/\s*$//; + $_ .= '.' unless /\.$/; + s/^(.)/\U$1/; # Ensure upper-cased to start sentence + s/^/ / if $kept; + $kept .= $_; # Will be reformatted later on + } + } + } + } + close FILE; + $kept; +} + +# Format line to fit in 80 columns (70 + 8 for the added leading tabs). +# Rudimentary parsing to break lines after a , or a space. +sub format { + local($_) = @_; + local($tmp); + local($msg); + while (length($_) > 70) { + $tmp = substr($_, 0, 70); + $tmp =~ s/^(.*)([,\s]).*/$1/; + $msg .= "\t$tmp" . ($2 eq ',' ? ',' : '') . "\n"; + $_ = substr($_, length($tmp), 9_999); + $_ =~ s/^\s+//; + } + $msg .= "\t$_\n"; + $msg; +} + +sub usage { + print STDERR <<EOM; +Usage: $progname [-hnruV] + -h : print this message and exit. + -n : not-really mode: force re-edit, but stop after updating. + -r : reuse existing change file candidate entries (supersedes -u). + -u : update mode, recreate files only when out of date. + -V : print version number and exit. +EOM + exit 1; +} + +!NO!SUBS! +$grep -v '^;#' ../pl/package.pl >>patlog +$grep -v '^;#' ../pl/tilde.pl >>patlog +$grep -v '^;#' ../pl/profile.pl >>patlog +chmod +x patlog +$eunicefix patlog diff --git a/pat/patmake.SH b/pat/patmake.SH new file mode 100755 index 0000000..6a122c3 --- /dev/null +++ b/pat/patmake.SH @@ -0,0 +1,411 @@ +case $CONFIG in +'') + if test -f config.sh; then TOP=.; + elif test -f ../config.sh; then TOP=..; + elif test -f ../../config.sh; then TOP=../..; + elif test -f ../../../config.sh; then TOP=../../..; + elif test -f ../../../../config.sh; then TOP=../../../..; + else + echo "Can't find config.sh."; exit 1 + fi + . $TOP/config.sh + ;; +esac +case "$0" in +*/*) cd `expr X$0 : 'X\(.*\)/'` ;; +esac +echo "Extracting pat/patmake (with variable substitutions)" +cat >patmake <<!GROK!THIS! +$startperl + eval 'exec perl -S \$0 \${1+"\$@"}' + if \$running_under_some_shell; + +# $Id$ +# +# Copyright (c) 1991-1997, 2004-2006, Raphael Manfredi +# +# You may redistribute only under the terms of the Artistic Licence, +# as specified in the README file that comes with the distribution. +# You may reuse parts of this distribution only within the terms of +# that same Artistic Licence; a copy of which may be found at the root +# of the source tree for dist 4.0. +# +# Original Author: Larry Wall <lwall@netlabs.com> +# Contribution by: Graham Stoney <greyham@research.canon.oz.au> +# +# $Log: patmake.SH,v $ +# Revision 3.0.1.5 1995/09/25 09:21:19 ram +# patch59: now calls patsend with -i to add more instructions +# +# Revision 3.0.1.4 1994/10/29 16:43:09 ram +# patch36: a lot of setup is now performed by patlog +# patch36: added various escapes in strings for perl5 support +# +# Revision 3.0.1.3 1994/01/24 14:30:55 ram +# patch16: now prefix error messages with program's name +# patch16: added ~/.dist_profile awareness +# +# Revision 3.0.1.2 1993/08/24 12:18:59 ram +# patch3: now asks for patch mailing/posting after all patches edited +# patch3: patch release notification is done via new patnotify +# patch3: random cleanup, removed old RCS logs +# +# Revision 3.0.1.1 1993/08/19 06:42:38 ram +# patch1: leading config.sh searching was not aborting properly +# +# Revision 3.0 1993/08/18 12:10:45 ram +# Baseline for dist 3.0 netwide release. +# + +\$defeditor='$defeditor'; +\$version = '$VERSION'; +\$patchlevel = '$PATCHLEVEL'; +\$mailer = '$mailer'; +!GROK!THIS! +cat >>patmake <<'!NO!SUBS!' + +$progname = &profile; # Read ~/.dist_profile +require 'getopts.pl'; +&usage unless &Getopts("hV"); + +if ($opt_V) { + print STDERR "$progname $version PL$patchlevel\n"; + exit 0; +} elsif ($opt_h) { + &usage; +} + +&readpackage; +&readusers; + +$FILEOVERHEAD = 40; # Name of files, Index, Prereq +$MAXPATSIZE = 50000; # Maximum allowed size for a patch +$PATOVERHEAD = 2500; # Litterature +$FIRST_PAT = 3000; # Give space for first patch (descriptions) + +if (-f 'patchlevel.h') { + open(PL,"patchlevel.h") || die "$progname: can't open patchlevel.h: $!\n"; + while (<PL>) { + if (/^#define\s+PATCHLEVEL\s+(\d+)/) { + $last = $1; + $patchline = $.; # Record PATCHLEVEL line + } + } + die "$progname: malformed patchlevel.h file.\n" if $last eq ''; + $bnum = $last + 1; +} +else { + $patchline = 1; + $bnum = 1; + $last = ''; +} + +@ARGV = <[Mm]akefile*>; +$mf = ''; +if ($#ARGV > 0) { + while (<>) { + $mf .= $_ if /^[a-z.]+\s*:/; # Rules in makefile + } +} +$after = ''; +$after .= "\t\tConfigure -ders\n" if -f 'Configure'; +$after .= "\t\tmake depend\n" if $mf =~ /^depend:/m; +$after .= "\t\tmake\n" if $mf; +$after .= "\t\tmake test\n" if $mf =~ /^test:/m; +$after .= "\t\tmake install\n" if $mf =~ /^install:/m; +$after .= "\t\tmake install.man\n" if $mf =~ /^install\.man:/m; + +chdir 'bugs' if -d 'bugs'; +die "$progname: patch #$bnum already exists.\n" if -f "patch$bnum"; + +@patlist=<*.$bnum>; +die "$progname: no diff files for patch #$bnum.\n" if + $patlist[0] =~ /^\*/ || $patlist[0] eq ''; + +# Whether they asked for a changelog file or not, call patlog. +# This will create at least the .pri and .subj and .clog files that we need. +# If a changelog file is needed, it will update it and create the necessary +# patch before we go on and put all those patches together. +# Note that we make use of the '-r' option, in case they have already +# run patlog themselves and made the necessary adjustments. Since -r supersedes +# -u, it's safe to allow ~/.dist_profile processing anyway. + +chdir '..' if -d '../bugs'; +system 'perl', '-S', 'patlog', '-r'; # Must be called from top-level dir +chdir 'bugs' if -d 'bugs'; + +@patlist=<*.$bnum>; # Reget it, in case Changes.xx appeared due to patlog + +# Look for size of each diff file +for (@patlist) { + ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime, + $blksize,$blocks) = stat($_); + $size{$_} = $size; +} + +# Sort the array, biggest sizes first +sub revnum { $size{$a} < $size{$b} ? 1 : $size{$a} > $size{$b} ? -1 : 0; } +@patlist = sort revnum @patlist; + +# Put files in a patch +for (@patlist) { + $i=1; + # Find the patch in which the current file can go + # Divide size by 15 to count the 3 spaces added in front of each line + while (($newtot = int($tot[$i] + $size{$_} + $size{$_}/15 + $FILEOVERHEAD)) > + $MAXPATSIZE-$PATOVERHEAD-($i == 1 ? $FIRST_PAT : 0) && $tot[$i]) { + $i++; + } + # Adding $_ to patch $i giving $newtot bytes + $tot[$i] = $newtot; # Update size of kit $i + $list[$i] .= " $_"; # Add file to the kit $i +} + +$numpat = $#list; # Number of patches to generate + +if ($numpat > 1) { + print "$progname: Warning: generating $numpat patches.\n"; + sleep(1); +} + +$hah = " (hah!)" if $bnum == 1; +$patbase = $bnum; # First patch generated + +open(PRIORITY, ".pri$bnum"); +chop($priority = <PRIORITY>); +close PRIORITY; +$priority = 'LOW' unless $priority; + +for ($i = 1; $i <= $numpat; $i++) { # For all patches... + open(PATCH,">patch$bnum") || die "Can't create patch #$bnum"; + chop($date=`date`); + print PATCH +"System: $package version $baserev +Patch #: $bnum +"; + print PATCH "Priority: $priority\n" unless $priority eq ''; + # Print subjects only for first patch + if ($i == 1) { + open(SUBJECTS, ".subj$bnum"); + print PATCH while <SUBJECTS>; + close SUBJECTS; + } else { + print PATCH "Subject: patch #$patbase, continued\n"; + } + print PATCH +"Date: $date +From: $maintname <$maintloc> + +Description: +"; + # Print description and repeat-by only for first patch + if ($i == 1) { + open(LOGS, ".clog$bnum"); + $_ = <LOGS>; $_ = <LOGS>; $_ = <LOGS>; # Skip first three lines + print PATCH while <LOGS>; + close LOGS; + print PATCH "Repeat-By: \n"; + } else { + print PATCH "\tSee patch #$patbase.\n\n"; + } + print PATCH +" +Fix: From rn, say \"| patch -p -N -d DIR\", where DIR is your $package source + directory. Outside of rn, say \"cd DIR; patch -p -N <thisarticle\". + If you don't have the patch program, apply the following by hand, + or get patch (version 2.0, latest patchlevel). + + After patching: +"; + # Do $after only after last patch + if ($i == $numpat) { + print PATCH $after; + } else { + printf PATCH +"\t\t*** DO NOTHING--INSTALL ALL PATCHES UP THROUGH #%d FIRST ***\n", +$patbase + $numpat - 1; + } + print PATCH " + If patch indicates that patchlevel is the wrong version, you may need + to apply one or more previous patches, or the patch may already + have been applied. See the patchlevel.h file to find out what has or + has not been applied. In any event, don't continue with the patch. + + If you are missing previous patches$hah they can be obtained from me: + + $maintname <$maintloc> + +"; + if ($mailagent ne 'false') { + print PATCH +" If you send a mail message of the following form it will greatly speed + processing: + + Subject: Command + \@SH mailpatch PATH $package $baserev LIST + ^ note the c + + where PATH is a return path FROM ME TO YOU either in Internet notation, + or in bang notation from some well-known host, and LIST is the number + of one or more patches you need, separated by spaces, commas, and/or + hyphens. Saying 35- says everything from 35 to the end. + + To get some more detailed instructions, send me the following mail: + + Subject: Command + \@SH mailhelp PATH + +"; + } + if ($ftpsite) { + print PATCH +" You can also get the patches via anonymous FTP from + $ftpsite. +"; + } + # Print patchlevel at the top of each patch + print PATCH " +Index: patchlevel.h +"; + if ($last eq '') { + `echo "#define PATCHLEVEL 1" >patchlevel.h`; + `cp /dev/null patchlevel.h.null`; + print PATCH `diff -c patchlevel.h.null patchlevel.h`; + unlink 'patchlevel.h', 'patchlevel.h.null'; + } + else { + print PATCH +"Prereq: $last +${patchline}c${patchline} +< #define PATCHLEVEL $last +--- +> #define PATCHLEVEL $bnum +"; + } + $last = $bnum; # Update last patch + push(@patset, $bnum); # Record set of generated patch(es) + + @ARGV = split(' ', $list[$i]); + while (<>) { print PATCH; } + print PATCH "\n*** End of Patch $bnum ***\n"; + close PATCH; + + # Update patchlevel.h file + $editor = $ENV{'VISUAL'}; + $editor = $ENV{'EDITOR'} unless $editor; + $editor = $defeditor unless $editor; + $editor = 'vi' unless $editor; + system $editor, "patch$bnum"; + if (-s "patch$bnum") { + system 'chmod', '-w', "patch$bnum"; # Protect newly created patch + chdir '..'; + `echo "#define PATCHLEVEL 0" >patchlevel.h` unless -f 'patchlevel.h'; + open(PL,"patchlevel.h") || + die "$progname: can't open patchlevel.h: $!\n"; + open(PLN,">patchlevel.h+") || + die "$progname: can't create new patchlevel.h: $!\n"; + while (<PL>) { + if (/^#define\s+PATCHLEVEL\s+(\d+)/) { + $bnum = $1; + $bnum++; # Update patch level + print PLN "#define PATCHLEVEL $bnum\n"; + } else { + print PLN; # Simply copy other lines + } + } + close PLN; + close PL; + `mv -f patchlevel.h+ patchlevel.h`; + die "$progname: malformed patchlevel.h file.\n" if $bnum eq ''; + } else { + unlink "patch$bnum"; + die "$progname: aborted.\n"; + } + + chdir 'bugs' || die "$progname: cannot cd to bugs: $!\n"; + + # Find priority for next patch in loop + $priority=''; + open(PATCH, "patch$bnum") || die "Cannot re-open patch #$bnum !\n"; + while (<PATCH>) { + /^Priority:\s*(\S+)\s*$/ && ($priority = $1); + } + close PATCH; + + $bnum++; # For next patch in loop +} + +utime time, time, 'patchlevel.h'; # Reset timestamp on patchlevel + +if (@patset == 1) { + $bnum = pop(@patset); + $patch = "patch #$bnum"; +} else { + $bmin = shift(@patset); + $bmax = pop(@patset); + $bnum = "$bmin-$bmax"; + $patch = "patches #$bmin thru #$bmax"; +} + +# Post generated patches +if ($newsgroups) { + print "\nDo you wish to post $patch to $newsgroups? [y] "; + $ans = <stdin>; + system 'patpost', $bnum unless $ans =~ /^n/i; +} + +# Mail generated patches +if ($recipients) { + print "\n"; + if (0 == ($recipients =~ tr/ //)) { + print "Do you wish to send $patch to $recipients? [y] "; + } else { + print "The following people are on the recipient list:\n\n"; + foreach $addr (split(' ', $recipients)) { + print "\t$addr\n"; + } + print "\nDo you wish to send $patch to them? [y] "; + } + $ans = <stdin>; + system 'patsend', '-i', $bnum, $recipients unless $ans =~ /^n/i; +} + +# Copy patches to FTP directory +if ($ftpdir) { + print "\nDo you wish to copy $patch to $ftpdir? [y] "; + $ans = <stdin>; + system 'patftp', $bnum unless $ans =~ /^n/i; +} + +# Notify people about it. +if ($notify) { + print "\n"; + if (0 == ($notify =~ tr/ //)) { + print "Do you wish to notify $notify? [y] "; + } else { + print "The following people are on the notify list:\n\n"; + foreach $addr (split(' ', $notify)) { + print "\t$addr\n"; + } + print "\nDo you wish to notify them? [y] "; + } + $ans = <STDIN>; + system 'patnotify', $notify unless $ans =~ /^n/i; +} + +sub usage { + print STDERR <<EOM; +Usage: $progname [-hV] + -h : print this message and exit + -V : print version number and exit +EOM + exit 1; +} + +!NO!SUBS! +$grep -v '^;#' ../pl/package.pl >>patmake +$grep -v '^;#' ../pl/users.pl >>patmake +$grep -v '^;#' ../pl/tilde.pl >>patmake +$grep -v '^;#' ../pl/profile.pl >>patmake +chmod +x patmake +$eunicefix patmake diff --git a/pat/patname.SH b/pat/patname.SH new file mode 100755 index 0000000..8f99b1a --- /dev/null +++ b/pat/patname.SH @@ -0,0 +1,175 @@ +case $CONFIG in +'') + if test -f config.sh; then TOP=.; + elif test -f ../config.sh; then TOP=..; + elif test -f ../../config.sh; then TOP=../..; + elif test -f ../../../config.sh; then TOP=../../..; + elif test -f ../../../../config.sh; then TOP=../../../..; + else + echo "Can't find config.sh."; exit 1 + fi + . $TOP/config.sh + ;; +esac +case "$0" in +*/*) cd `expr X$0 : 'X\(.*\)/'` ;; +esac +echo "Extracting pat/patname (with variable substitutions)" +cat >patname <<!GROK!THIS! +$startperl + eval 'exec perl -S \$0 \${1+"\$@"}' + if \$running_under_some_shell; + +# $Id$ +# +# Copyright (c) 1991-1997, 2004-2006, Raphael Manfredi +# +# You may redistribute only under the terms of the Artistic Licence, +# as specified in the README file that comes with the distribution. +# You may reuse parts of this distribution only within the terms of +# that same Artistic Licence; a copy of which may be found at the root +# of the source tree for dist 4.0. +# +# $Log: patname.SH,v $ +# Revision 3.0.1.2 1994/01/24 14:31:02 ram +# patch16: now prefix error messages with program's name +# patch16: added ~/.dist_profile awareness +# +# Revision 3.0.1.1 1993/08/19 06:42:40 ram +# patch1: leading config.sh searching was not aborting properly +# +# Revision 3.0 1993/08/18 12:10:46 ram +# Baseline for dist 3.0 netwide release. +# + +\$version = '$VERSION'; +\$patchlevel = '$PATCHLEVEL'; +!GROK!THIS! +cat >>patname <<'!NO!SUBS!' + +$progname = &profile; # Read ~/.dist_profile +require 'getopts.pl'; +&usage unless $#ARGV >= 0; +&usage() unless &Getopts("ahnmv:V"); + +if ($opt_V) { + print STDERR "$progname $version PL$patchlevel\n"; + exit 0; +} elsif ($opt_h) { + &usage; +} + +$RCSEXT = ',v' unless $RCSEXT; +$ENV{'DIST'} = '/dev/null'; # Disable ~/.dist_profile + +chop($pwd = `pwd`) unless -f '.package'; +until (-f '.package') { + die "$progname: no .package file! Run packinit.\n" unless $pwd; + chdir '..' || die "$progname: can't cd ..: $!\n"; + $pwd =~ s|(.*)/(.*)|$1|; + $prefix = $2 . '/' . $prefix; +} +if ($prefix) { + for (@ARGV) { + s/^/$prefix/ unless m|^[-/]|; + } +} + +# We now are at the top level + +&readpackage; + +unless ($opt_v) { + print STDERR "$progname: version number must be specified using -v.\n"; + &usage; +} + +if ($opt_n) { + &newer; # Look for files newer than patchlevel.h +} elsif ($opt_a) { + open(MANI,"MANIFEST.new") || die "$progname: can't read MANIFEST.new: $!\n"; + @ARGV = (); + while (<MANI>) { + s|^\./||; + next if m|^patchlevel.h|; # This file is built by hand + chop; + ($_) = split(' '); + next if -d; + push(@ARGV,$_); + } + close MANI; +} elsif ($opt_m) { + open(MODS,"bugs/.mods$bnum") || die "$progname: no modification found.\n"; + @ARGV = (); + while (<MODS>) { + next if m|^patchlevel.h$|; # This file is built by hand + chop; + ($_) = split(' '); + push(@ARGV,$_); + } + close MODS; +} + +# Now loop over each file specified, doing a 'rcsfreeze' +foreach $file (@ARGV) { + $files = &rcsargs($file); + @files = split(' ', $files); + $rlog = `rlog -rlastpat- $files 2>&1`; + ($revs) = ($rlog =~ /selected revisions: (\d+)/); + if (!$revs) { + print "$progname: $file has never been checked in--checking in...\n"; + system 'perl', '-S', 'patcil', '-p', $file; + $revs = 2; # At least null trunk + new fresh revision + } + # Look whether there is a branch + if ($revs == 1) { + $rlog = `rlog -r$revbranch $files 2>&1`; + ($revs) = ($rlog =~ /selected revisions: (\d+)/); + $revs++; # add the base revision + } + # If working file exists, make sure latest version was checked in + if (-f $file) { + if ($revs == 1) { + $delta = `rcsdiff -r$baserev $files 2>/dev/null`; + } else { + $delta = `rcsdiff -r$revbranch $files 2>/dev/null`; + } + if ($delta ne '') { + # File changed; check it in. + system 'perl', '-S', 'patcil', '-p', $file; + if ($revs > 1) { + # Have to re-run rlog after a new ci + $rlog = `rlog -r$revbranch $files 2>&1`; + } + } + } + # Now assign symbolic revision number + if ($revs == 1) { + system 'rcs', "-N$opt_v:$baserev", @files; + } else { + ($lastrev) = ($rlog =~ /revision $revbranch\.(\d+)/); + system 'rcs', "-N$opt_v:$revbranch.$lastrev", @files; + } +} + +sub usage { + print STDERR <<EOM; +Usage: $progname [-ahnmV] -v version [filelist] + -a : all the files in MANIFEST.new + -h : print this message and exit + -n : all the files newer than patchlevel.h + -m : all the modified files (which have been patciled) + -v : set version number (mandatory) + -V : print version number and exit +EOM + exit 1; +} + +!NO!SUBS! +$grep -v '^;#' ../pl/newer.pl >>patname +$grep -v '^;#' ../pl/package.pl >>patname +$grep -v '^;#' ../pl/rcsargs.pl >>patname +$grep -v '^;#' ../pl/tilde.pl >>patname +$grep -v '^;#' ../pl/profile.pl >>patname +chmod +x patname +$eunicefix patname diff --git a/pat/patnotify.SH b/pat/patnotify.SH new file mode 100755 index 0000000..5d1307e --- /dev/null +++ b/pat/patnotify.SH @@ -0,0 +1,232 @@ +case $CONFIG in +'') + if test -f config.sh; then TOP=.; + elif test -f ../config.sh; then TOP=..; + elif test -f ../../config.sh; then TOP=../..; + elif test -f ../../../config.sh; then TOP=../../..; + elif test -f ../../../../config.sh; then TOP=../../../..; + else + echo "Can't find config.sh."; exit 1 + fi + . $TOP/config.sh + ;; +esac +case "$0" in +*/*) cd `expr X$0 : 'X\(.*\)/'` ;; +esac +echo "Extracting pat/patnotify (with variable substitutions)" +cat >patnotify <<!GROK!THIS! +$startperl + eval 'exec perl -S \$0 \${1+"\$@"}' + if \$running_under_some_shell; + +# $Id$ +# +# Copyright (c) 1991-1997, 2004-2006, Raphael Manfredi +# +# You may redistribute only under the terms of the Artistic Licence, +# as specified in the README file that comes with the distribution. +# You may reuse parts of this distribution only within the terms of +# that same Artistic Licence; a copy of which may be found at the root +# of the source tree for dist 4.0. +# +# $Log: patnotify.SH,v $ +# Revision 3.0.1.9 1997/02/28 16:33:35 ram +# patch61: let them know the patch priority and description +# +# Revision 3.0.1.8 1995/09/25 09:21:43 ram +# patch59: now tells users how to directly request for mailed patches +# +# Revision 3.0.1.7 1994/10/29 16:43:19 ram +# patch36: added various escapes in strings for perl5 support +# +# Revision 3.0.1.6 1994/06/20 07:11:47 ram +# patch30: patnotify now includes the e-mail address for requests +# +# Revision 3.0.1.5 1994/01/24 14:31:48 ram +# patch16: now prefix error messages with program's name +# patch16: don't feed mailer with more than 50 addresses at a time +# patch16: added ~/.dist_profile awareness +# +# Revision 3.0.1.4 1993/08/27 14:40:42 ram +# patch7: two files were wrongly appended to patsend instead +# +# Revision 3.0.1.3 1993/08/25 14:07:43 ram +# patch6: now asks for recipient list edition by default +# patch6: new -q option to suppress that +# +# Revision 3.0.1.2 1993/08/24 12:48:03 ram +# patch5: fixed fatal typo in here document +# +# Revision 3.0.1.1 1993/08/24 12:19:11 ram +# patch3: created +# + +\$defeditor='$defeditor'; +\$version = '$VERSION'; +\$patchlevel = '$PATCHLEVEL'; +\$mailer = '$mailer'; +!GROK!THIS! +cat >>patnotify <<'!NO!SUBS!' + +$progname = &profile; # Read ~/.dist_profile +require 'getopts.pl'; +&usage unless &Getopts("hquV"); + +if ($opt_V) { + print STDERR "$progname $version PL$patchlevel\n"; + exit 0; +} elsif ($opt_h) { + &usage; +} + +chdir '..' if -d '../bugs'; + +&readpackage; +&readusers if $opt_u; + +$dest = join(' ', @ARGV); +$dest .= " $notify" if $opt_u; + +&usage unless $dest; + +# Offer to edit the address list unless -q +unless ($opt_q) { + select((select(STDOUT), $| = 1)[0]); + print "Do you wish to edit the address list? [y] "; + $ans = <STDIN>; + unless ($ans =~ /^n/i) { + @to = split(' ', $dest); + &listedit(*to); + $dest = join(' ', @to); + } +} + +if (-f 'patchlevel.h') { + open(PL,"patchlevel.h") || die "$progname: can't open patchlevel.h: $!\n"; + while (<PL>) { + if (/^#define\s+PATCHLEVEL\s+(\d+)/) { + $last = $1; + } + } + die "$progname: malformed patchlevel.h file.\n" if $last eq ''; +} else { + die "$progname: no patchlevel.h.\n"; +} + +@patches = &patseq($last); # Compute patches sequence +$lastpat = pop(@patches); + +warn "$progname: missing last .logs and .mods files\n" if $lastpat eq ''; + +$missing = $last - $lastpat + 1; +$these = $missing == 1 ? 'this' : 'these'; +$patches = $missing == 1 ? 'patch' : 'patches'; +$through = $missing == 1 ? $lastpat : "$lastpat thru " . ($lastpat+$missing-1); +$have = $missing == 1 ? 'has' : 'have'; +$patlist = "$lastpat-"; # They'll get everything up to the end + +($Patches = $patches) =~ s/^p/P/; +$opt = ($mailer =~ /sendmail/) ? '-odq' : ''; + +chdir 'bugs' || die "$progname: can't cd to bugs: $!\n"; + +# Find out priority of last patch set +$priority = 'UNKNOWN'; +open(PATCH, "patch$lastpat") || + die "$progname: can't open patch #$lastpat: $!\n"; +while (<PATCH>) { + /^Priority:\s*(\S+)\s*$/ && ($priority = $1); +} +close PATCH; + +# Look for the .clog<patch #> description and prepare the patch description +# for inclusion in the notification, so that they can figure out whether +# they really need that patch set. + +if (-f ".clog$lastpat") { + open(LOGS, ".clog$lastpat") || + die "$progname: can't open .clog$lastpat: $!\n"; + $_ = <LOGS> . <LOGS> . <LOGS>; # Skip first three lines + $clog = ''; + while (<LOGS>) { + $clog .= $_; + } + close LOGS; +} else { + warn "$progname: missing last .clog file in bugs directory\n"; +} + +print "$progname: sending notification of $missing new $patches to $dest...\n"; + +fork && exit; + +# I hate broken mailers! Bust it up into smaller groups of people... +@dest = split(' ', $dest); +while (@smalldest = splice(@dest, 0, 50)) { + $to = join(', ', @smalldest); # Sensible To: for sendmail + $smalldest = join(' ', @smalldest); + + open(MAILER, "|$mailer $opt $smalldest") || + die "$progname: can't fork $mailer: $!\n"; + print MAILER +"To: $to +Subject: $Patches $through for $package version $baserev $have been released. +Precedence: bulk +X-Mailer: dist [version $version PL$patchlevel] + +This is just a quick note to let you know that $package version $baserev +has been recently upgraded and that $patches $through $have been released. + +If you are actively using $package, I strongly suggest you upgrade by +applying $these $patches, whose priority is $priority. + +You can fetch $these $patches automatically by sending me the following mail: + + Subject: Command + \@SH mailpatch - $package $baserev $patlist + ^ note the c + +And if you wish to have future patches mailed directly to you, you can add: + + \@SH package - $package $baserev - mailpatches + +If you are not interested in receiving any information about future patches, +please send me the following mail: + + Subject: Command + \@SH package - $package $baserev +"; + print MAILER +" +Following is the $patches description: + +$clog" if $clog; + print MAILER +" +-- $progname speaking for $maintname <$maintloc>. +"; + close MAILER; +} + +sub usage { + print STDERR <<EOH; +Usage: $progname [-hquV] [recipients] + -h : print this message and exit + -q : quick mode, do not offer to edit recipient list + -u : add all to-be-notified users + -V : print version number and exit +EOH + exit 1; +} + +!NO!SUBS! +$grep -v '^;#' ../pl/package.pl >>patnotify +$grep -v '^;#' ../pl/users.pl >>patnotify +$grep -v '^;#' ../pl/patseq.pl >>patnotify +$grep -v '^;#' ../pl/editor.pl >>patnotify +$grep -v '^;#' ../pl/listedit.pl >>patnotify +$grep -v '^;#' ../pl/tilde.pl >>patnotify +$grep -v '^;#' ../pl/profile.pl >>patnotify +chmod +x patnotify +$eunicefix patnotify diff --git a/pat/patpost.SH b/pat/patpost.SH new file mode 100755 index 0000000..7aafd8c --- /dev/null +++ b/pat/patpost.SH @@ -0,0 +1,179 @@ +case $CONFIG in +'') + if test -f config.sh; then TOP=.; + elif test -f ../config.sh; then TOP=..; + elif test -f ../../config.sh; then TOP=../..; + elif test -f ../../../config.sh; then TOP=../../..; + elif test -f ../../../../config.sh; then TOP=../../../..; + else + echo "Can't find config.sh."; exit 1 + fi + . $TOP/config.sh + ;; +esac +case "$0" in +*/*) cd `expr X$0 : 'X\(.*\)/'` ;; +esac +echo "Extracting pat/patpost (with variable substitutions)" +cat >patpost <<!GROK!THIS! +$startperl + eval 'exec perl -S \$0 \${1+"\$@"}' + if \$running_under_some_shell; + +# $Id$ +# +# Copyright (c) 1991-1997, 2004-2006, Raphael Manfredi +# +# You may redistribute only under the terms of the Artistic Licence, +# as specified in the README file that comes with the distribution. +# You may reuse parts of this distribution only within the terms of +# that same Artistic Licence; a copy of which may be found at the root +# of the source tree for dist 4.0. +# +# Original Author: Larry Wall <lwall@netlabs.com> +# +# $Log: patpost.SH,v $ +# Revision 3.0.1.4 1995/05/12 12:25:58 ram +# patch54: added explicit From: header line pointing to the maintainer +# +# Revision 3.0.1.3 1994/01/24 14:32:09 ram +# patch16: now prefix error messages with program's name +# patch16: added ~/.dist_profile awareness +# +# Revision 3.0.1.2 1993/08/24 12:19:48 ram +# patch3: added ~name expansion for orgname +# patch3: random cleanup +# +# Revision 3.0.1.1 1993/08/19 06:42:41 ram +# patch1: leading config.sh searching was not aborting properly +# +# Revision 3.0 1993/08/18 12:10:47 ram +# Baseline for dist 3.0 netwide release. +# + +\$inews='${inews-/usr/lib/news/inews}'; +\$orgname='$orgname'; +\$version = '$VERSION'; +\$patchlevel = '$PATCHLEVEL'; +!GROK!THIS! + +cat >>patpost <<'!NO!SUBS!' + +$progname = &profile; # Read ~/.dist_profile +require 'getopts.pl'; +&usage unless $#ARGV >= 0; +&usage unless &Getopts("hrV"); + +if ($opt_V) { + print STDERR "$progname $version PL$patchlevel\n"; + exit 0; +} elsif ($opt_h) { + &usage; +} + +$RCSEXT = ',v' unless $RCSEXT; +if ($inews eq 'inews') { + $inews = '/usr/lib/news/inews' if -f '/usr/lib/news/inews'; +} + +chdir '..' if -d '../bugs'; + +&readpackage; + +$orgname = &tilda_expand($orgname); +chop($orgname = `cat $orgname`) if $orgname =~ m|^/|; + +if ($opt_r) { + $repost = ' (REPOST)'; +} + +while ($_ = shift) { + if (/^(patch)?[1-9][\d\-]*$/) { + s/^patch//; + push(@argv,$_); + } else { + push(@newsgroups,$_); + } +} +$newsgroups = join(',',@newsgroups) unless $#newsgroups < 0; +&usage unless $newsgroups; + +@ARGV = @argv; +open(PL,"patchlevel.h") || die "$progname: can't open patchlevel.h: $!\n"; +while (<PL>) { + $maxnum = $1 if /^#define\s+PATCHLEVEL\s+(\d+)/; +} +close PL; +die "$progname: malformed patchlevel.h file.\n" if $maxnum eq ''; + +if ($#ARGV < 0) { + @patseq = &patseq($maxnum); + $lastpat = pop(@patseq); + $argv = &rangeargs("$lastpat-$maxnum"); +} +else { + $argv = &rangeargs(@ARGV); +} + +@ARGV = split(' ',$argv); +$argv =~ s/ $//; + +if ($#ARGV < 0) { + print STDERR "$progname: no patches specified.\n"; + &usage; +} elsif ($#ARGV) { + print + "$progname: posting $package $baserev patches $argv to $newsgroups...\n"; +} else { + print + "$progname: posting $package $baserev patch $argv to $newsgroups...\n"; +} + +chdir 'bugs' || die "$progname: can't cd to bugs: $!\n"; + +fork && exit; + +until ($#ARGV < 0) { + $patnum = shift; + open(PATCH,"patch$patnum") || + die "$progname: can't open patch$patnum: $!\n"; + open(XHEAD,"|$inews -h") || die "$progname: can't fork $inews: $!\n"; + print XHEAD +"From: $maintloc ($maintname) +Newsgroups: $newsgroups +Subject: $package $baserev patch #$patnum$repost +Summary: This is an official patch for $package $baserev. Please apply it. +Expires: +References: +Sender: +Distribution: +Organization: $orgname +Keywords: + +"; + while (<PATCH>) { + print XHEAD; + } + close PATCH; + close XHEAD; + die "$progname: could not post patch$patnum.\n" if $?; +} + +sub usage { + print STDERR <<EOM; +Usage: $progname [-hrV] patchlist newsgroups + -h : print this message and exit + -r : signals a repost + -V : print version number and exit +EOM + exit 1; +} + +!NO!SUBS! +$grep -v '^;#' ../pl/package.pl >>patpost +$grep -v '^;#' ../pl/rangeargs.pl >>patpost +$grep -v '^;#' ../pl/patseq.pl >>patpost +$grep -v '^;#' ../pl/tilde.pl >>patpost +$grep -v '^;#' ../pl/profile.pl >>patpost +chmod +x patpost +$eunicefix patpost diff --git a/pat/patsend.SH b/pat/patsend.SH new file mode 100755 index 0000000..0fe7f42 --- /dev/null +++ b/pat/patsend.SH @@ -0,0 +1,218 @@ +case $CONFIG in +'') + if test -f config.sh; then TOP=.; + elif test -f ../config.sh; then TOP=..; + elif test -f ../../config.sh; then TOP=../..; + elif test -f ../../../config.sh; then TOP=../../..; + elif test -f ../../../../config.sh; then TOP=../../../..; + else + echo "Can't find config.sh."; exit 1 + fi + . $TOP/config.sh + ;; +esac +case "$0" in +*/*) cd `expr X$0 : 'X\(.*\)/'` ;; +esac +echo "Extracting pat/patsend (with variable substitutions)" +cat >patsend <<!GROK!THIS! +$startperl + eval 'exec perl -S \$0 \${1+"\$@"}' + if \$running_under_some_shell; + +# $Id$ +# +# Copyright (c) 1991-1997, 2004-2006, Raphael Manfredi +# +# You may redistribute only under the terms of the Artistic Licence, +# as specified in the README file that comes with the distribution. +# You may reuse parts of this distribution only within the terms of +# that same Artistic Licence; a copy of which may be found at the root +# of the source tree for dist 4.0. +# +# Original Author: Larry Wall <lwall@netlabs.com> +# +# $Log: patsend.SH,v $ +# Revision 3.0.1.6 1995/09/25 09:22:02 ram +# patch59: new -i option to add more instructions for end-users +# +# Revision 3.0.1.5 1994/01/24 14:32:46 ram +# patch16: now prefix error messages with program's name +# patch16: don't feed mailer with more than 50 addresses at a time +# patch16: added ~/.dist_profile awareness +# +# Revision 3.0.1.4 1993/08/25 14:08:01 ram +# patch6: now asks for recipient list edition by default +# patch6: new -q option to suppress that +# +# Revision 3.0.1.3 1993/08/24 12:21:59 ram +# patch3: new -u option +# patch3: added Precedence and X-Mailer headers in mail message +# patch3: added ~name expansion for orgname +# +# Revision 3.0.1.2 1993/08/19 07:10:19 ram +# patch3: was not correctly writing the To: header field +# +# Revision 3.0.1.1 1993/08/19 06:42:42 ram +# patch1: leading config.sh searching was not aborting properly +# +# Revision 3.0 1993/08/18 12:10:49 ram +# Baseline for dist 3.0 netwide release. +# + +\$orgname='$orgname'; +\$mailer='$mailer'; +\$version = '$VERSION'; +\$patchlevel = '$PATCHLEVEL'; +!GROK!THIS! +cat >>patsend <<'!NO!SUBS!' + +$progname = &profile; # Read ~/.dist_profile +require 'getopts.pl'; +&usage unless &Getopts("hiquV"); + +if ($opt_V) { + print STDERR "$progname $version PL$patchlevel\n"; + exit 0; +} elsif ($opt_h) { + &usage; +} + +chdir '..' if -d '../bugs'; + +&readpackage; +&readusers if $opt_u; + +$orgname = &tilda_expand($orgname); +chop($orgname = `cat $orgname`) if $orgname =~ m|^/|; + +while ($_ = shift) { + if (/^(patch)?[1-9][\d,-]*$/) { + s/^patch//; + push(@argv,$_); + } else { + push(@dest,$_); + } +} +$dest = join(' ',@dest); +$dest .= " $recipients" if $opt_u; +&usage unless $dest; + +# Offer to edit the address list unless -q +unless ($opt_q) { + select((select(STDOUT), $| = 1)[0]); + print "Do you wish to edit the address list? [y] "; + $ans = <STDIN>; + unless ($ans =~ /^n/i) { + @to = split(' ', $dest); + &listedit(*to); + $dest = join(' ', @to); + } +} + +$to = join(', ', split(' ', $dest)); +@ARGV = @argv; + +open(PL,"patchlevel.h") || die "$progname: can't open patchlevel.h: $!\n"; +while (<PL>) { + $maxnum = $1 if /^#define\s+PATCHLEVEL\s+(\d+)/; +} +close PL; +die "$progname: malformed patchlevel.h file.\n" if $maxnum eq ''; + +if ($#ARGV < 0) { + @patseq = &patseq($maxnum); + $lastpat = pop(@patseq); + $argv = &rangeargs("$lastpat-$maxnum"); +} else { + $argv = &rangeargs(@ARGV); +} + +@ARGV = split(' ',$argv); +$argv =~ s/ $//; + +if ($#ARGV < 0) { + print STDERR "$progname: no patches specified.\n"; + &usage; +} elsif ($#ARGV) { + print "$progname: sending $package $baserev patches $argv to $dest...\n"; +} else { + print "$progname: sending $package $baserev patch $argv to $dest...\n"; +} + +chdir 'bugs' || die "$progname: can't cd to bugs: $!\n"; + +fork && exit; + +$opt = '-odq' if $mailer =~ /sendmail/; + +until ($#ARGV < 0) { + $patnum = shift; + + # I hate broken mailers! Bust it up into smaller groups of people... + @dest = split(' ', $dest); + while (@smalldest = splice(@dest, 0, 50)) { + $to = join(', ', @smalldest); # Sensible To: for sendmail + $smalldest = join(' ', @smalldest); + + open(MAILER, "|$mailer $opt $smalldest") || + die "$progname: can't fork $mailer: $!\n"; + print MAILER +"To: $to +Subject: $package $baserev patch #$patnum +Precedence: bulk +X-Mailer: dist [version $version PL$patchlevel] +Organization: $orgname + +"; + print MAILER +"$package version $baserev has been recently upgraded with the following patch, +which is being mailed directly to you as you requested when running Configure. + +If you are not interested in having future patches mailed directly to you, +please send me the following mail: + + Subject: Command + \@SH package - $package $baserev + +-- $progname speaking for $maintname <$maintloc>. + +" if ($opt_i || $opt_u); + print MAILER +"[The latest patch for $package version $baserev is #$maxnum.] + +"; + open(PATCH,"patch$patnum") || + die "$progname: can't open patch$patnum: $!\n"; + while (<PATCH>) { + print MAILER; + } + close PATCH; + close MAILER; + die "$progname: could not mail patch$patnum.\n" if $?; + } +} + +sub usage { + print STDERR <<EOM; +Usage: $progname [-hiquV] [patchlist] [recipients] + -h : print this message and exit + -i : include information on how to stop receiving future patches + -q : quick mode, do not offer to edit recipient list + -u : add all to-be-mailed users + -V : print version number and exit +EOM + exit 1; +} + +!NO!SUBS! +$grep -v '^;#' ../pl/package.pl >>patsend +$grep -v '^;#' ../pl/rangeargs.pl >>patsend +$grep -v '^;#' ../pl/users.pl >>patsend +$grep -v '^;#' ../pl/patseq.pl >>patsend +$grep -v '^;#' ../pl/tilde.pl >>patsend +$grep -v '^;#' ../pl/editor.pl >>patsend +$grep -v '^;#' ../pl/listedit.pl >>patsend +$grep -v '^;#' ../pl/profile.pl >>patsend +chmod +x patsend +$eunicefix patsend diff --git a/pat/patsnap.SH b/pat/patsnap.SH new file mode 100755 index 0000000..18cbdb5 --- /dev/null +++ b/pat/patsnap.SH @@ -0,0 +1,124 @@ +case $CONFIG in +'') + if test -f config.sh; then TOP=.; + elif test -f ../config.sh; then TOP=..; + elif test -f ../../config.sh; then TOP=../..; + elif test -f ../../../config.sh; then TOP=../../..; + elif test -f ../../../../config.sh; then TOP=../../../..; + else + echo "Can't find config.sh."; exit 1 + fi + . $TOP/config.sh + ;; +esac +case "$0" in +*/*) cd `expr X$0 : 'X\(.*\)/'` ;; +esac +echo "Extracting pat/patsnap (with variable substitutions)" +cat >patsnap <<!GROK!THIS! +$startperl + eval 'exec perl -S \$0 \${1+"\$@"}' + if \$running_under_some_shell; + +# $Id$ +# +# Copyright (c) 1991-1997, 2004-2006, Raphael Manfredi +# +# You may redistribute only under the terms of the Artistic Licence, +# as specified in the README file that comes with the distribution. +# You may reuse parts of this distribution only within the terms of +# that same Artistic Licence; a copy of which may be found at the root +# of the source tree for dist 4.0. +# +# $Log: patsnap.SH,v $ +# Revision 3.0.1.2 1994/01/24 14:33:08 ram +# patch16: now prefix error messages with program's name +# patch16: added ~/.dist_profile awareness +# +# Revision 3.0.1.1 1993/08/24 12:22:08 ram +# patch3: created +# + +\$version = '$VERSION'; +\$patchlevel = '$PATCHLEVEL'; +!GROK!THIS! +cat >>patsnap <<'!NO!SUBS!' + +$progname = &profile; # Read ~/.dist_profile +require 'getopts.pl'; +&usage unless $#ARGV >= 0; +&usage unless &Getopts("aho:V"); + +$SNAPSHOT = 'SNAPSHOT'; # Default snapshot file name + +if ($opt_V) { + print STDERR "$progname $version PL$patchlevel\n"; + exit 0; +} elsif ($opt_h) { + &usage; +} + +&readpackage; + +$RCSEXT = ',v' unless $RCSEXT; +$TOPDIR = ''; # We are at the top-level directory +$SNAPSHOT = $opt_o if $opt_o; + +if ($opt_a) { + open(MANI,"MANIFEST.new") || die "$progname: can't read MANIFEST.new: $!\n"; + @ARGV = (); + while (<MANI>) { + chop; + s|^\./||; + next if m|^patchlevel.h|; # Special file + ($_) = split(' '); + next if -d; + push(@ARGV,$_); + } + close MANI; +} + +open(SNAPSHOT, ">$SNAPSHOT") || die "$progname: can't create $SNAPSHOT: $!\n"; + +foreach $file (@ARGV) { + $files = &rcsargs($file); + @files = split(' ',$files); + $revs=0; + $rlog = `rlog -r$baserev -r$revbranch $files 2>&1`; + ($revs) = ($rlog =~ /selected revisions: (\d+)/); + if (!$revs) { + print "$progname: $file has never been checked in--skipping\n"; + next; + } + elsif ($revs == 1) { + print "$progname: last revision for $file is $baserev.\n"; + print SNAPSHOT "$file\t$baserev\n"; + } + else { + ($lastrev) = ($rlog =~ /revision $revbranch\.(\d+)/); + print "$progname: last revision for $file is $revbranch.$lastrev.\n"; + print SNAPSHOT "$file\t$revbranch.$lastrev\n"; + } +} + +close SNAPSHOT; + +sub usage { + print STDERR <<EOM; +Usage: $progname [-ahV] [-o snapshot] [filelist] + -a : all the files in MANIFEST.new + -h : print this message and exit + -o : specify snapshot file output (default $SNAPSHOT) + -V : print version number and exit +EOM + exit 1; +} + +!NO!SUBS! +$grep -v '^;#' ../pl/package.pl >>patsnap +$grep -v '^;#' ../pl/rcsargs.pl >>patsnap +$grep -v '^;#' ../pl/comment.pl >>patsnap +$grep -v '^;#' ../pl/tilde.pl >>patsnap +$grep -v '^;#' ../pl/profile.pl >>patsnap +chmod +x patsnap +$eunicefix patsnap |