diff options
Diffstat (limited to 'gnu/usr.bin/cvs/contrib/rcs2log')
| -rw-r--r-- | gnu/usr.bin/cvs/contrib/rcs2log | 326 |
1 files changed, 326 insertions, 0 deletions
diff --git a/gnu/usr.bin/cvs/contrib/rcs2log b/gnu/usr.bin/cvs/contrib/rcs2log new file mode 100644 index 000000000000..d7900025b851 --- /dev/null +++ b/gnu/usr.bin/cvs/contrib/rcs2log @@ -0,0 +1,326 @@ +#!/bin/sh + +# RCS to ChangeLog generator + +# Generate a change log prefix from RCS/* and the existing ChangeLog (if any). +# Output the new prefix to standard output. +# You can edit this prefix by hand, and then prepend it to ChangeLog. + +# Ignore log entries that start with `#'. +# Clump together log entries that start with `{topic} ', +# where `topic' contains neither white space nor `}'. + +# Author: Paul Eggert <eggert@twinsun.com> + +# OrigId: rcs2log,v 1.9 1993/01/15 05:33:29 eggert Exp + +# Copyright 1992, 1993 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; see the file COPYING. If not, write to +# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + + +# Parse options. + +# defaults +indent=8 # indent of log line +length=79 # suggested max width of log line +tabwidth=8 # width of horizontal tab + +while : +do + case $1 in + -i) indent=${2?};; + -l) length=${2?};; + -t) tabwidth=${2?};; + -*) echo >&2 "$0: usage: $0 [-i indent] [-l length] [-t tabwidth] [file ...]" + exit 1;; + *) break + esac + shift; shift +done + + +# Log into $rlogout the revisions checked in since the first ChangeLog entry. + +date=1970 +if test -s ChangeLog +then + # Add 1 to seconds to avoid duplicating most recent log. + # It's a good thing `rlog' doesn't mind a time ending in `:60'. + e=' + /^... ... [ 0-9][0-9] [ 0-9][0-9]:[0-9][0-9]:[0-9][0-9] [0-9]+ /{ + printf "%s%02d %s\n", substr($0,1,17), substr($0,18,2)+1, $5 + exit + } + ' + d=`awk "$e" <ChangeLog` || exit + case $d in + ?*) date=$d + esac +fi +datearg="-d>$date" + +rlogout=/tmp/chg$$ +trap exit 1 2 13 15 +trap 'rm -f $rlogout; exit 1' 0 + +case $# in +0) set RCS/* +esac + +rlog "$datearg" "$@" >$rlogout || exit + + +# Get the full name of each author the logs mention, and set initialize_fullname +# to awk code that initializes the `fullname' awk associative array. +# Warning: foreign authors (i.e. not known in the passwd file) are mishandled; +# you have to fix the resulting output by hand. + +initialize_fullname= +authors=` + sed -n 's|^date: *[0-9]*/[0-9][0-9]/[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9]; *author: *\([^; ]*\).*|\1|p' <$rlogout | + sort -u +` +case $authors in +?*) + initialize_author= + for author in $authors + do + initialize_author="$initialize_author + author[\"$author\"] = 1 + " + done + + awkscript=' + BEGIN { + alphabet = "abcdefghijklmnopqrstuvwxyz" + ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + '"$initialize_author"' + } + { + if (author[$1]) { + fullname = $5 + abbr = index(fullname, "&") + if (abbr) { + a = substr($1, 1, 1) + A = a + i = index(alphabet, a) + if (i) A = substr(ALPHABET, i, 1) + fullname = substr(fullname, 1, abbr-1) A substr($1, 2) substr(fullname, abbr+1) + } + printf "fullname[\"%s\"] = \"%s\"\n", $1, fullname + author[$1] = 0 + } + } + ' + + initialize_fullname=` + (cat /etc/passwd; ypmatch $authors passwd) 2>/dev/null | + awk -F: "$awkscript" + ` +esac + + +# Function to print a single log line. +# We don't use awk functions, to stay compatible with old awk versions. +# `Log' is the log message (with \n replaced by \r). +# `files' contains the affected files. +printlogline='{ + + # Following the GNU coding standards, rewrite + # * file: (function): comment + # to + # * file (function): comment + if (Log ~ /^\([^)]*\): /) { + i = index(Log, ")") + files = files " " substr(Log, 1, i) + Log = substr(Log, i+3) + } + + # If "label: comment" is too long, break the line after the ":". + sep = " " + if ('"$length"' <= '"$indent"' + 1 + length(files) + index(Log, "\r")) sep = "\n" indent_string + + # Print the label. + printf "%s*%s:", indent_string, files + + # Print each line of the log, transliterating \r to \n. + while ((i = index(Log, "\r")) != 0) { + printf "%s%s\n", sep, substr(Log, 1, i-1) + sep = indent_string + Log = substr(Log, i+1) + } +}' + +hostname=`( + hostname || cat /etc/whoami || uuname -l || uname -n +) 2>/dev/null` || { + echo >&2 "$0: cannot deduce hostname" + exit 1 +} + + +# Process the rlog output, generating ChangeLog style entries. + +# First, reformat the rlog output so that each line contains one log entry. +# Transliterate \n to \r so that multiline entries fit on a single line. +# Discard irrelevant rlog output. +awk <$rlogout ' + /^Working file:/ { filename = $3 } + /^date: /, /^(-----------*|===========*)$/ { + if ($0 ~ /^branches: /) { next } + if ($0 ~ /^date: [0-9][ /0-9:]*;/) { + time = substr($3, 1, length($3)-1) + author = substr($5, 1, length($5)-1) + printf "%s %s %s %s \r", filename, $2, time, author + next + } + if ($0 ~ /^(-----------*|===========*)$/) { print ""; next } + printf "%s\r", $0 + } +' | + +# Now each line is of the form +# FILENAME YYYY/MM/DD HH:MM:SS AUTHOR \rLOG +# where \r stands for a carriage return, +# and each line of the log is terminated by \r instead of \n. +# Sort the log entries, first by date+time (in reverse order), +# then by author, then by log entry, and finally by file name (just in case). +sort +1 -3r +3 +0 | + +# Finally, reformat the sorted log entries. +awk ' + BEGIN { + + # Initialize the fullname associative array. + '"$initialize_fullname"' + + # Initialize indent string. + indent_string = "" + i = '"$indent"' + if (0 < '"$tabwidth"') + for (; '"$tabwidth"' <= i; i -= '"$tabwidth"') + indent_string = indent_string "\t" + while (1 <= i--) + indent_string = indent_string " " + + # Set up date conversion tables. + # RCS uses a nice, clean, sortable format, + # but ChangeLog wants the traditional, ugly ctime format. + + # January 1, 0 AD (Gregorian) was Saturday = 6 + EPOCH_WEEKDAY = 6 + # Of course, there was no 0 AD, but the algorithm works anyway. + + w[0]="Sun"; w[1]="Mon"; w[2]="Tue"; w[3]="Wed" + w[4]="Thu"; w[5]="Fri"; w[6]="Sat" + + m[0]="Jan"; m[1]="Feb"; m[2]="Mar" + m[3]="Apr"; m[4]="May"; m[5]="Jun" + m[6]="Jul"; m[7]="Aug"; m[8]="Sep" + m[9]="Oct"; m[10]="Nov"; m[11]="Dec" + + # days in non-leap year thus far, indexed by month (0-12) + mo[0]=0; mo[1]=31; mo[2]=59; mo[3]=90 + mo[4]=120; mo[5]=151; mo[6]=181; mo[7]=212 + mo[8]=243; mo[9]=273; mo[10]=304; mo[11]=334 + mo[12]=365 + } + + { + newlog = substr($0, 1 + index($0, "\r")) + + # Ignore log entries prefixed by "#". + if (newlog ~ /^#/) { next } + + if (Log != newlog || date != $2 || author != $4) { + + # The previous log and this log differ. + + # Print the old log. + if (date != "") '"$printlogline"' + + # Logs that begin with "{clumpname} " should be grouped together, + # and the clumpname should be removed. + # Extract the new clumpname from the log header, + # and use it to decide whether to output a blank line. + newclumpname = "" + sep = "\n" + if (date == "") sep = "" + if (newlog ~ /^{[^ }]*}[ ]/) { + i = index(newlog, "}") + newclumpname = substr(newlog, 1, i) + while (substr(newlog, i+1) ~ /^[ ]/) i++ + newlog = substr(newlog, i+1) + if (clumpname == newclumpname) sep = "" + } + printf sep + clumpname = newclumpname + + # Get ready for the next log. + Log = newlog + if (files != "") + for (i in filesknown) + filesknown[i] = 0 + files = "" + } + if (date != $2 || author != $4) { + # The previous date+author and this date+author differ. + # Print the new one. + date = $2 + author = $4 + + # Convert nice RCS date like "1992/01/03 00:03:44" + # into ugly ctime date like "Fri Jan 3 00:03:44 1992". + # Calculate day of week from Gregorian calendar. + i = index($2, "/") + year = substr($2, 1, i-1) + 0 + monthday = substr($2, i+1) + i = index(monthday, "/") + month = substr(monthday, 1, i-1) + 0 + day = substr(monthday, i+1) + 0 + leap = 0 + if (2 < month && year%4 == 0 && (year%100 != 0 || year%400 == 0)) leap = 1 + days_since_Sunday_before_epoch = EPOCH_WEEKDAY + year * 365 + int((year + 3) / 4) - int((year + 99) / 100) + int((year + 399) / 400) + mo[month-1] + leap + day - 1 + + # Print "date fullname (email address)" if the fullname is known; + # print "date author" otherwise. + # Get the fullname from the associative array. + # The email address is just author@thishostname. + printf "%s %s %2d %s %d ", w[days_since_Sunday_before_epoch%7], m[month-1], day, $3, year + if (fullname[author]) + printf "%s (%s@%s)\n\n", fullname[author], author, "'"$hostname"'" + else + printf "%s\n\n", author + } + if (! filesknown[$1]) { + filesknown[$1] = 1 + if (files == "") files = " " $1 + else files = files ", " $1 + } + } + END { + # Print the last log. + if (date != "") { + '"$printlogline"' + printf "\n" + } + } +' && + + +# Exit successfully. + +exec rm -f $rlogout |
