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 < # # $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!' use File::Temp qw/ tempfile tempdir /; $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 () { $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 () { 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 () { # 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 = ; if ($ans !~ /^n/i) { print "MANIFEST.new comment? "; $file_comment = ; 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 = ; } if ($line =~ /^\.?$/) { if ($mess) { last line; } else { $line = 'p'; } } if ($line =~ /^[h?]$/) { print " CR or . Terminate log message. ! 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", @_); my $tmp = File::Temp->new(); print $tmp $text; close $tmp; system $EDITOR, "$tmp"; $text = `cat "$tmp"`; unlink "$tmp"; $text; } sub usage { print STDERR <>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