1#! /bin/sh 2# $MirOS: src/gnu/usr.bin/cvs/contrib/rcs2log.sh,v 1.6 2011/05/06 22:44:59 tg Exp $ 3 4# Copyright (C) 1995-2005 The Free Software Foundation, Inc. 5 6# This program is free software; you can redistribute it and/or modify 7# it under the terms of the GNU General Public License as published by 8# the Free Software Foundation; either version 2, or (at your option) 9# any later version. 10# 11# This program is distributed in the hope that it will be useful, 12# but WITHOUT ANY WARRANTY; without even the implied warranty of 13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14# GNU General Public License for more details. 15 16# RCS to ChangeLog generator 17 18# Generate a change log prefix from RCS files (perhaps in the CVS repository) 19# and the ChangeLog (if any). 20# Output the new prefix to standard output. 21# You can edit this prefix by hand, and then prepend it to ChangeLog. 22 23# Ignore log entries that start with `#'. 24# Clump together log entries that start with `{topic} ', 25# where `topic' contains neither white space nor `}'. 26 27Help='The default FILEs are the files registered under the working directory. 28Options: 29 30 -c CHANGELOG Output a change log prefix to CHANGELOG (default ChangeLog). 31 -h HOSTNAME Use HOSTNAME in change log entries (default current host). 32 -i INDENT Indent change log lines by INDENT spaces (default 8). 33 -l LENGTH Try to limit log lines to LENGTH characters (default 79). 34 -L FILE Use rlog-format FILE for source of logs. 35 -n Obsolete, use -u instead (whose syntax differs). 36 -R If no FILEs are given and RCS is used, recurse through working directory. 37 -r OPTION Pass OPTION to subsidiary log command. 38 -t TABWIDTH Tab stops are every TABWIDTH characters (default 8). 39 -u "LOGIN<tab>FULLNAME<tab>MAILADDR" Assume LOGIN has FULLNAME and MAILADDR. 40 -v Append RCS revision to file names in log lines. 41 --help Output help. 42 --version Output version number. 43 44Report bugs to <bug-gnu-emacs@gnu.org>.' 45 46Id='$Id: rcs2log,v 1.48 2001/09/05 23:07:46 eggert Exp $' 47 48# Copyright 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2001, 2003 49# Free Software Foundation, Inc. 50 51# This program is free software; you can redistribute it and/or modify 52# it under the terms of the GNU General Public License as published by 53# the Free Software Foundation; either version 2, or (at your option) 54# any later version. 55# 56# This program is distributed in the hope that it will be useful, 57# but WITHOUT ANY WARRANTY; without even the implied warranty of 58# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 59# GNU General Public License for more details. 60# 61# You should have received a copy of the GNU General Public License 62# along with this program; see the file COPYING. If not, write to the 63# Free Software Foundation, Inc., 59 Temple Place - Suite 330, 64# Boston, MA 02111-1307, USA. 65 66Copyright='Copyright 1992-2003 Free Software Foundation, Inc. 67This program comes with NO WARRANTY, to the extent permitted by law. 68You may redistribute copies of this program 69under the terms of the GNU General Public License. 70For more information about these matters, see the files named COPYING. 71Author: Paul Eggert <eggert@twinsun.com>' 72 73# functions 74@MKTEMP_SH_FUNCTION@ 75 76# Use the traditional C locale. 77LANG=C 78LANGUAGE=C 79LC_ALL=C 80LC_COLLATE=C 81LC_CTYPE=C 82LC_MESSAGES=C 83LC_NUMERIC=C 84LC_TIME=C 85export LANG LANGUAGE LC_ALL LC_COLLATE LC_CTYPE LC_MESSAGES LC_NUMERIC LC_TIME 86 87# These variables each contain a single ASCII character. 88# Unfortunately, there's no portable way of writing these characters 89# in older Unix implementations, other than putting them directly into 90# this text file. 91SOH='' # SOH, octal code 001 92tab=' ' 93nl=' 94' 95 96# Parse options. 97 98# defaults 99: ${MKTEMP="@MKTEMP@"} 100: ${AWK=awk} 101: ${TMPDIR=/tmp} 102 103changelog=ChangeLog # change log file name 104datearg= # rlog date option 105hostname= # name of local host (if empty, will deduce it later) 106indent=8 # indent of log line 107length=79 # suggested max width of log line 108logins= # login names for people we know fullnames and mailaddrs of 109loginFullnameMailaddrs= # login<tab>fullname<tab>mailaddr triplets 110logTZ= # time zone for log dates (if empty, use local time) 111recursive= # t if we want recursive rlog 112revision= # t if we want revision numbers 113rlog_options= # options to pass to rlog 114rlogfile= # log file to read from 115tabwidth=8 # width of horizontal tab 116 117while : 118do 119 case $1 in 120 -c) changelog=${2?}; shift;; 121 -i) indent=${2?}; shift;; 122 -h) hostname=${2?}; shift;; 123 -l) length=${2?}; shift;; 124 -L) rlogfile=${2?}; shift;; 125 -[nu]) # -n is obsolescent; it is replaced by -u. 126 case $1 in 127 -n) case ${2?}${3?}${4?} in 128 *"$tab"* | *"$nl"*) 129 echo >&2 "$0: -n '$2' '$3' '$4': tabs, newlines not allowed" 130 exit 1;; 131 esac 132 login=$2 133 lfm=$2$tab$3$tab$4 134 shift; shift; shift;; 135 -u) 136 # If $2 is not tab-separated, use colon for separator. 137 case ${2?} in 138 *"$nl"*) 139 echo >&2 "$0: -u '$2': newlines not allowed" 140 exit 1;; 141 *"$tab"*) 142 t=$tab;; 143 *) 144 t=':';; 145 esac 146 case $2 in 147 *"$t"*"$t"*"$t"*) 148 echo >&2 "$0: -u '$2': too many fields" 149 exit 1;; 150 *"$t"*"$t"*) 151 uf="[^$t]*$t" # An unselected field, followed by a separator. 152 sf="\\([^$t]*\\)" # The selected field. 153 login=`expr "X$2" : "X$sf"` 154 lfm="$login$tab"` 155 expr "X$2" : "$uf$sf" 156 `"$tab"` 157 expr "X$2" : "$uf$uf$sf" 158 `;; 159 *) 160 echo >&2 "$0: -u '$2': not enough fields" 161 exit 1;; 162 esac 163 shift;; 164 esac 165 case $logins in 166 '') logins=$login;; 167 ?*) logins=$logins$nl$login;; 168 esac 169 case $loginFullnameMailaddrs in 170 '') loginFullnameMailaddrs=$lfm;; 171 ?*) loginFullnameMailaddrs=$loginFullnameMailaddrs$nl$lfm;; 172 esac;; 173 -r) 174 case $rlog_options in 175 '') rlog_options=${2?};; 176 ?*) rlog_options=$rlog_options$nl${2?};; 177 esac 178 shift;; 179 -R) recursive=t;; 180 -t) tabwidth=${2?}; shift;; 181 -v) revision=t;; 182 --version) 183 set $Id 184 rcs2logVersion=$3 185 echo >&2 "rcs2log (GNU Emacs) $rcs2logVersion$nl$Copyright" 186 exit 0;; 187 -*) echo >&2 "Usage: $0 [OPTION]... [FILE ...]$nl$Help" 188 case $1 in 189 --help) exit 0;; 190 *) exit 1;; 191 esac;; 192 *) break;; 193 esac 194 shift 195done 196 197month_data=' 198 m[0]="Jan"; m[1]="Feb"; m[2]="Mar" 199 m[3]="Apr"; m[4]="May"; m[5]="Jun" 200 m[6]="Jul"; m[7]="Aug"; m[8]="Sep" 201 m[9]="Oct"; m[10]="Nov"; m[11]="Dec" 202' 203 204logdir=$($MKTEMP -d $TMPDIR/rcs2log.XXXXXXXXXX) 205test -n "$logdir" || exit 206llogout=$logdir/l 207trap exit 1 2 13 15 208trap "rm -fr $logdir 2>/dev/null" 0 209 210# If no rlog-format log file is given, generate one into $rlogfile. 211case $rlogfile in 212'') 213 rlogfile=$logdir/r 214 215 # If no rlog options are given, 216 # log the revisions checked in since the first ChangeLog entry. 217 # Since ChangeLog is only by date, some of these revisions may be duplicates of 218 # what's already in ChangeLog; it's the user's responsibility to remove them. 219 case $rlog_options in 220 '') 221 if test -s "$changelog" 222 then 223 e=' 224 /^[0-9]+-[0-9][0-9]-[0-9][0-9]/{ 225 # ISO 8601 date 226 print $1 227 exit 228 } 229 /^... ... [ 0-9][0-9] [ 0-9][0-9]:[0-9][0-9]:[0-9][0-9] [0-9]+ /{ 230 # old-fashioned date and time (Emacs 19.31 and earlier) 231 '"$month_data"' 232 year = $5 233 for (i=0; i<=11; i++) if (m[i] == $2) break 234 dd = $3 235 printf "%d-%02d-%02d\n", year, i+1, dd 236 exit 237 } 238 ' 239 d=`$AWK "$e" <"$changelog"` || exit 240 case $d in 241 ?*) datearg="-d>$d";; 242 esac 243 fi;; 244 esac 245 246 # Use TZ specified by ChangeLog local variable, if any. 247 if test -s "$changelog" 248 then 249 extractTZ=' 250 /^.*change-log-time-zone-rule['"$tab"' ]*:['"$tab"' ]*"\([^"]*\)".*/{ 251 s//\1/; p; q 252 } 253 /^.*change-log-time-zone-rule['"$tab"' ]*:['"$tab"' ]*t.*/{ 254 s//UTC0/; p; q 255 } 256 ' 257 logTZ=`tail "$changelog" | sed -n "$extractTZ"` 258 case $logTZ in 259 ?*) TZ=$logTZ; export TZ;; 260 esac 261 fi 262 263 # If CVS is in use, examine its repository, not the normal RCS files. 264 if test ! -f CVS/Repository 265 then 266 rlog=rlog 267 repository= 268 else 269 rlog='cvs -q log' 270 repository=`sed 1q <CVS/Repository` || exit 271 test ! -f CVS/Root || CVSROOT=`cat <CVS/Root` || exit 272 case $CVSROOT in 273 *:/*:/*) 274 echo >&2 "$0: $CVSROOT: CVSROOT has multiple ':/'s" 275 exit 1;; 276 *:/*) 277 # remote repository 278 pository=`expr "X$repository" : '.*:\(/.*\)'`;; 279 *) 280 # local repository 281 case $repository in 282 /*) ;; 283 *) repository=${CVSROOT?}/$repository;; 284 esac 285 if test ! -d "$repository" 286 then 287 echo >&2 "$0: $repository: bad repository (see CVS/Repository)" 288 exit 1 289 fi 290 pository=$repository;; 291 esac 292 293 # Ensure that $pository ends in exactly one slash. 294 while : 295 do 296 case $pository in 297 *//) pository=`expr "X$pository" : 'X\(.*\)/'`;; 298 */) break;; 299 *) pository=$pository/; break;; 300 esac 301 done 302 303 fi 304 305 # Use $rlog's -zLT option, if $rlog supports it. 306 case `$rlog -zLT 2>&1` in 307 *' option'*) ;; 308 *) 309 case $rlog_options in 310 '') rlog_options=-zLT;; 311 ?*) rlog_options=-zLT$nl$rlog_options;; 312 esac;; 313 esac 314 315 # With no arguments, examine all files under the RCS directory. 316 case $# in 317 0) 318 case $repository in 319 '') 320 oldIFS=$IFS 321 IFS=$nl 322 case $recursive in 323 t) 324 RCSdirs=`find . -name RCS -type d -print` 325 filesFromRCSfiles='s|,v$||; s|/RCS/|/|; s|^\./||' 326 files=` 327 { 328 case $RCSdirs in 329 ?*) find $RCSdirs \ 330 -type f \ 331 ! -name '*_' \ 332 ! -name ',*,' \ 333 ! -name '.*_' \ 334 ! -name .rcsfreeze.log \ 335 ! -name .rcsfreeze.ver \ 336 -print;; 337 esac 338 find . -name '*,v' -print 339 } | 340 sort -u | 341 sed "$filesFromRCSfiles" 342 `;; 343 *) 344 files= 345 for file in RCS/.* RCS/* .*,v *,v 346 do 347 case $file in 348 RCS/. | RCS/.. | RCS/,*, | RCS/*_) continue;; 349 RCS/.rcsfreeze.log | RCS/.rcsfreeze.ver) continue;; 350 RCS/.\* | RCS/\* | .\*,v | \*,v) test -f "$file" || continue;; 351 RCS/*,v | RCS/.*,v) ;; 352 RCS/* | RCS/.*) test -f "$file" || continue;; 353 esac 354 case $files in 355 '') files=$file;; 356 ?*) files=$files$nl$file;; 357 esac 358 done 359 case $files in 360 '') exit 0;; 361 esac;; 362 esac 363 set x $files 364 shift 365 IFS=$oldIFS;; 366 esac;; 367 esac 368 369 case $datearg in 370 ?*) $rlog $rlog_options "$datearg" ${1+"$@"} >$rlogfile;; 371 '') $rlog $rlog_options ${1+"$@"} >$rlogfile;; 372 esac || exit;; 373esac 374 375 376# Get the full name of each author the logs mention, and set initialize_fullname 377# to awk code that initializes the `fullname' awk associative array. 378# Warning: foreign authors (i.e. not known in the passwd file) are mishandled; 379# you have to fix the resulting output by hand. 380 381initialize_fullname= 382initialize_mailaddr= 383 384case $loginFullnameMailaddrs in 385?*) 386 case $loginFullnameMailaddrs in 387 *\"* | *\\*) 388 sed 's/["\\]/\\&/g' >$llogout <<EOF || exit 389$loginFullnameMailaddrs 390EOF 391 loginFullnameMailaddrs=`cat $llogout`;; 392 esac 393 394 oldIFS=$IFS 395 IFS=$nl 396 for loginFullnameMailaddr in $loginFullnameMailaddrs 397 do 398 IFS=$tab 399 set x $loginFullnameMailaddr 400 login=$2 401 fullname=$3 402 mailaddr=$4 403 initialize_fullname="$initialize_fullname 404 fullname[\"$login\"] = \"$fullname\"" 405 initialize_mailaddr="$initialize_mailaddr 406 mailaddr[\"$login\"] = \"$mailaddr\"" 407 done 408 IFS=$oldIFS;; 409esac 410 411case $logins in 412?*) 413 sort -u -o $llogout <<EOF 414$logins 415EOF 416 ;; 417'') 418 : ;; 419esac >$llogout || exit 420 421output_authors='/^date: / { 422 if ($2 ~ /^[0-9]*[-\/][0-9][0-9][-\/][0-9][0-9]$/ && $3 ~ /^[0-9][0-9]:[0-9][0-9]:[0-9][0-9][-+0-9:]*;$/ && $4 == "author:" && $5 ~ /^[^;]*;$/) { 423 print substr($5, 1, length($5)-1) 424 } 425}' 426authors=` 427 $AWK "$output_authors" <"$rlogfile" | sort -u | comm -23 - $llogout 428` 429case $authors in 430?*) 431 cat >$llogout <<EOF || exit 432$authors 433EOF 434 initialize_author_script='s/["\\]/\\&/g; s/.*/author[\"&\"] = 1/' 435 initialize_author=`sed -e "$initialize_author_script" <$llogout` 436 awkscript=' 437 BEGIN { 438 alphabet = "abcdefghijklmnopqrstuvwxyz" 439 ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 440 '"$initialize_author"' 441 } 442 { 443 if (author[$1]) { 444 fullname = $5 445 if (fullname ~ /[0-9]+-[^(]*\([0-9]+\)$/) { 446 # Remove the junk from fullnames like "0000-Admin(0000)". 447 fullname = substr(fullname, index(fullname, "-") + 1) 448 fullname = substr(fullname, 1, index(fullname, "(") - 1) 449 } 450 if (fullname ~ /,[^ ]/) { 451 # Some sites put comma-separated junk after the fullname. 452 # Remove it, but leave "Bill Gates, Jr" alone. 453 fullname = substr(fullname, 1, index(fullname, ",") - 1) 454 } 455 abbr = index(fullname, "&") 456 if (abbr) { 457 a = substr($1, 1, 1) 458 A = a 459 i = index(alphabet, a) 460 if (i) A = substr(ALPHABET, i, 1) 461 fullname = substr(fullname, 1, abbr-1) A substr($1, 2) substr(fullname, abbr+1) 462 } 463 464 # Quote quotes and backslashes properly in full names. 465 # Do not use gsub; traditional awk lacks it. 466 quoted = "" 467 rest = fullname 468 for (;;) { 469 p = index(rest, "\\") 470 q = index(rest, "\"") 471 if (p) { 472 if (q && q<p) p = q 473 } else { 474 if (!q) break 475 p = q 476 } 477 quoted = quoted substr(rest, 1, p-1) "\\" substr(rest, p, 1) 478 rest = substr(rest, p+1) 479 } 480 481 printf "fullname[\"%s\"] = \"%s%s\"\n", $1, quoted, rest 482 author[$1] = 0 483 } 484 } 485 ' 486 487 initialize_fullname=` 488 { 489 (getent passwd $authors) || 490 ( 491 cat /etc/passwd 492 for author in $authors 493 do NIS_PATH= nismatch $author passwd.org_dir 494 done 495 ypmatch $authors passwd 496 ) 497 } 2>/dev/null | 498 $AWK -F: "$awkscript" 499 `$initialize_fullname;; 500esac 501 502 503# Function to print a single log line. 504# We don't use awk functions, to stay compatible with old awk versions. 505# `Log' is the log message. 506# `files' contains the affected files. 507printlogline='{ 508 509 # Following the GNU coding standards, rewrite 510 # * file: (function): comment 511 # to 512 # * file (function): comment 513 if (Log ~ /^\([^)]*\): /) { 514 i = index(Log, ")") 515 filefunc = substr(Log, 1, i) 516 while ((j = index(filefunc, "\n"))) { 517 files = files " " substr(filefunc, 1, j-1) 518 filefunc = substr(filefunc, j+1) 519 } 520 files = files " " filefunc 521 Log = substr(Log, i+3) 522 } 523 524 # If "label: comment" is too long, break the line after the ":". 525 sep = " " 526 i = index(Log, "\n") 527 if ('"$length"' <= '"$indent"' + 1 + length(files) + i) sep = "\n" indent_string 528 529 # Print the label. 530 printf "%s*%s:", indent_string, files 531 532 # Print each line of the log. 533 while (i) { 534 logline = substr(Log, 1, i-1) 535 if (logline ~ /[^'"$tab"' ]/) { 536 printf "%s%s\n", sep, logline 537 } else { 538 print "" 539 } 540 sep = indent_string 541 Log = substr(Log, i+1) 542 i = index(Log, "\n") 543 } 544}' 545 546# Pattern to match the `revision' line of rlog output. 547rlog_revision_pattern='^revision [0-9]+\.[0-9]+(\.[0-9]+\.[0-9]+)*(['"$tab"' ]+locked by: [^'"$tab"' $,.0-9:;@]*[^'"$tab"' $,:;@][^'"$tab"' $,.0-9:;@]*;)?['"$tab"' ]*$' 548 549case $hostname in 550'') 551 hostname=`( 552 hostname || uname -n || uuname -l || cat /etc/whoami 553 ) 2>/dev/null` || { 554 echo >&2 "$0: cannot deduce hostname" 555 exit 1 556 } 557 558 case $hostname in 559 *.*) ;; 560 *) 561 domainname=`(domainname) 2>/dev/null` && 562 case $domainname in 563 *.*) hostname=$hostname.$domainname;; 564 esac;; 565 esac;; 566esac 567 568 569# Process the rlog output, generating ChangeLog style entries. 570 571# First, reformat the rlog output so that each line contains one log entry. 572# Transliterate \n to SOH so that multiline entries fit on a single line. 573# Discard irrelevant rlog output. 574$AWK ' 575 BEGIN { 576 pository = "'"$pository"'" 577 SOH="'"$SOH"'" 578 } 579 /^RCS file: / { 580 if (pository != "") { 581 filename = substr($0, 11) 582 if (substr(filename, 1, length(pository)) == pository) { 583 filename = substr(filename, length(pository) + 1) 584 } 585 if (filename ~ /,v$/) { 586 filename = substr(filename, 1, length(filename) - 2) 587 } 588 if (filename ~ /(^|\/)Attic\/[^\/]*$/) { 589 i = length(filename) 590 while (substr(filename, i, 1) != "/") i-- 591 filename = substr(filename, 1, i - 6) substr(filename, i + 1) 592 } 593 } 594 rev = "?" 595 } 596 /^Working file: / { if (repository == "") filename = substr($0, 15) } 597 /'"$rlog_revision_pattern"'/, /^(-----------*|===========*)$/ { 598 line = $0 599 if (line ~ /'"$rlog_revision_pattern"'/) { 600 rev = $2 601 next 602 } 603 if (line ~ /^date: [0-9][- +\/0-9:]*;/) { 604 date = $2 605 if (date ~ /\//) { 606 # This is a traditional RCS format date YYYY/MM/DD. 607 # Replace "/"s with "-"s to get ISO format. 608 newdate = "" 609 while ((i = index(date, "/")) != 0) { 610 newdate = newdate substr(date, 1, i-1) "-" 611 date = substr(date, i+1) 612 } 613 date = newdate date 614 } 615 time = substr($3, 1, length($3) - 1) 616 author = substr($5, 1, length($5)-1) 617 printf "%s%s%s%s%s%s%s%s%s%s", filename, SOH, rev, SOH, date, SOH, time, SOH, author, SOH 618 rev = "?" 619 next 620 } 621 if (line ~ /^branches: /) { next } 622 if (line ~ /^(-----------*|===========*)$/) { print ""; next } 623 if (line == "Initial revision" || line ~ /^file .+ was initially added on branch .+\.$/) { 624 line = "New file." 625 } 626 printf "%s%s", line, SOH 627 } 628' <"$rlogfile" | 629 630# Now each line is of the form 631# FILENAME@REVISION@YYYY-MM-DD@HH:MM:SS[+-TIMEZONE]@AUTHOR@LOG 632# where @ stands for an SOH (octal code 001), 633# and each line of LOG is terminated by SOH instead of \n. 634# Sort the log entries, first by date+time (in reverse order), 635# then by author, then by log entry, and finally by file name and revision 636# (just in case). 637sort -t"$SOH" -k 3,4r -k 5 -k 1 | 638 639# Finally, reformat the sorted log entries. 640$AWK -F"$SOH" ' 641 BEGIN { 642 logTZ = "'"$logTZ"'" 643 revision = "'"$revision"'" 644 645 # Initialize the fullname and mailaddr associative arrays. 646 '"$initialize_fullname"' 647 '"$initialize_mailaddr"' 648 649 # Initialize indent string. 650 indent_string = "" 651 i = '"$indent"' 652 if (0 < '"$tabwidth"') 653 for (; '"$tabwidth"' <= i; i -= '"$tabwidth"') 654 indent_string = indent_string "\t" 655 while (1 <= i--) 656 indent_string = indent_string " " 657 } 658 659 { 660 newlog = "" 661 for (i = 6; i < NF; i++) newlog = newlog $i "\n" 662 663 # Ignore log entries prefixed by "#". 664 if (newlog ~ /^#/) { next } 665 666 if (Log != newlog || date != $3 || author != $5) { 667 668 # The previous log and this log differ. 669 670 # Print the old log. 671 if (date != "") '"$printlogline"' 672 673 # Logs that begin with "{clumpname} " should be grouped together, 674 # and the clumpname should be removed. 675 # Extract the new clumpname from the log header, 676 # and use it to decide whether to output a blank line. 677 newclumpname = "" 678 sep = "\n" 679 if (date == "") sep = "" 680 if (newlog ~ /^\{[^'"$tab"' }]*}['"$tab"' ]/) { 681 i = index(newlog, "}") 682 newclumpname = substr(newlog, 1, i) 683 while (substr(newlog, i+1) ~ /^['"$tab"' ]/) i++ 684 newlog = substr(newlog, i+1) 685 if (clumpname == newclumpname) sep = "" 686 } 687 printf sep 688 clumpname = newclumpname 689 690 # Get ready for the next log. 691 Log = newlog 692 if (files != "") 693 for (i in filesknown) 694 filesknown[i] = 0 695 files = "" 696 } 697 if (date != $3 || author != $5) { 698 # The previous date+author and this date+author differ. 699 # Print the new one. 700 date = $3 701 time = $4 702 author = $5 703 704 zone = "" 705 if (logTZ && ((i = index(time, "-")) || (i = index(time, "+")))) 706 zone = " " substr(time, i) 707 708 # Print "date[ timezone] fullname <email address>". 709 # Get fullname and email address from associative arrays; 710 # default to author and author@hostname if not in arrays. 711 if (fullname[author]) 712 auth = fullname[author] 713 else 714 auth = author 715 printf "%s%s %s ", date, zone, auth 716 if (mailaddr[author]) 717 printf "<%s>\n\n", mailaddr[author] 718 else 719 printf "<%s@%s>\n\n", author, "'"$hostname"'" 720 } 721 if (! filesknown[$1]) { 722 filesknown[$1] = 1 723 if (files == "") files = " " $1 724 else files = files ", " $1 725 if (revision && $2 != "?") files = files " " $2 726 } 727 } 728 END { 729 # Print the last log. 730 if (date != "") { 731 '"$printlogline"' 732 printf "\n" 733 } 734 } 735' && 736 737 738# Exit successfully. 739 740exec rm -fr $logdir 741 742# Local Variables: 743# tab-width:4 744# End: 745