comparison lib-src/rcs2log @ 15911:c9a152ad9c5a

Use ISO 8601 date format, with time zone appended if change-log-time-zone-rule is non-nil, instead of traditional Unix date format. (datearg): When computing default from ChangeLog, handle ISO format dates in addition to old-fashioned dates from Emacs 19.31 and earlier. Don't worry about hh:mm:ss since the resolution is now by day. Use emtpy datearg, not empty rlog_options, to decide whether to pass "$datearg" option to $rlog. (logTZ): New variable, set to TZ specified by change-log-time-zone-rule. (month_data): Remove `mo'; no longer needed. (rlog_options): Use -zLT for localltime output, if `rlog' supports it. (extractTZ): Use UTC if the zone is t. Match `revision' line of rlog output more accurately. Add -c, -v options.
author Erik Naggum <erik@naggum.no>
date Sat, 24 Aug 1996 21:11:14 +0000
parents 80562f089595
children ab395798ed22
comparison
equal deleted inserted replaced
15910:8cd4f2fd5525 15911:c9a152ad9c5a
10 # Clump together log entries that start with `{topic} ', 10 # Clump together log entries that start with `{topic} ',
11 # where `topic' contains neither white space nor `}'. 11 # where `topic' contains neither white space nor `}'.
12 12
13 # Author: Paul Eggert <eggert@twinsun.com> 13 # Author: Paul Eggert <eggert@twinsun.com>
14 14
15 # $Id: rcs2log,v 1.27 1996/01/15 01:17:56 eggert Exp kwzh $ 15 # $Id: rcs2log,v 1.28 1996/07/20 18:08:03 kwzh Exp erik $
16 16
17 # Copyright 1992, 1993, 1994, 1995, 1996 Free Software Foundation, Inc. 17 # Copyright 1992, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
18 18
19 # This program is free software; you can redistribute it and/or modify 19 # This program is free software; you can redistribute it and/or modify
20 # it under the terms of the GNU General Public License as published by 20 # it under the terms of the GNU General Public License as published by
21 # the Free Software Foundation; either version 2, or (at your option) 21 # the Free Software Foundation; either version 2, or (at your option)
22 # any later version. 22 # any later version.
23 # 23 #
24 # This program is distributed in the hope that it will be useful, 24 # This program is distributed in the hope that it will be useful,
25 # but WITHOUT ANY WARRANTY; without even the implied warranty of 25 # but WITHOUT ANY WARRANTY; without even the implied warranty of
26 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 26 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 # GNU General Public License for more details. 27 # GNU General Public License for more details.
28 # 28 #
29 # You should have received a copy of the GNU General Public License 29 # You should have received a copy of the GNU General Public License
30 # along with GNU Emacs; see the file COPYING. If not, write to the 30 # along with GNU Emacs; see the file COPYING. If not, write to the
31 # Free Software Foundation, Inc., 59 Temple Place - Suite 330, 31 # Free Software Foundation, Inc., 59 Temple Place - Suite 330,
32 # Boston, MA 02111-1307, USA. 32 # Boston, MA 02111-1307, USA.
33 33
38 # Parse options. 38 # Parse options.
39 39
40 # defaults 40 # defaults
41 : ${AWK=awk} 41 : ${AWK=awk}
42 : ${TMPDIR=/tmp} 42 : ${TMPDIR=/tmp}
43 changelog=ChangeLog # change log file name
44 datearg= # rlog date option
43 hostname= # name of local host (if empty, will deduce it later) 45 hostname= # name of local host (if empty, will deduce it later)
44 indent=8 # indent of log line 46 indent=8 # indent of log line
45 length=79 # suggested max width of log line 47 length=79 # suggested max width of log line
46 logins= # login names for people we know fullnames and mailaddrs of 48 logins= # login names for people we know fullnames and mailaddrs of
47 loginFullnameMailaddrs= # login<tab>fullname<tab>mailaddr triplets 49 loginFullnameMailaddrs= # login<tab>fullname<tab>mailaddr triplets
50 logTZ= # time zone for log dates (if empty, use local time)
48 recursive= # t if we want recursive rlog 51 recursive= # t if we want recursive rlog
52 revision= # t if we want revision numbers
49 rlog_options= # options to pass to rlog 53 rlog_options= # options to pass to rlog
50 tabwidth=8 # width of horizontal tab 54 tabwidth=8 # width of horizontal tab
51 55
52 while : 56 while :
53 do 57 do
54 case $1 in 58 case $1 in
59 -c) changelog=${2?}; shift;;
55 -i) indent=${2?}; shift;; 60 -i) indent=${2?}; shift;;
56 -h) hostname=${2?}; shift;; 61 -h) hostname=${2?}; shift;;
57 -l) length=${2?}; shift;; 62 -l) length=${2?}; shift;;
58 -[nu]) # -n is obsolescent; it is replaced by -u. 63 -[nu]) # -n is obsolescent; it is replaced by -u.
59 case $1 in 64 case $1 in
91 logins=$logins$nl$login 96 logins=$logins$nl$login
92 ;; 97 ;;
93 -r) rlog_options=$rlog_options$nl${2?}; shift;; 98 -r) rlog_options=$rlog_options$nl${2?}; shift;;
94 -R) recursive=t;; 99 -R) recursive=t;;
95 -t) tabwidth=${2?}; shift;; 100 -t) tabwidth=${2?}; shift;;
101 -v) revision=t;;
96 -*) echo >&2 "$0: usage: $0 [options] [file ...] 102 -*) echo >&2 "$0: usage: $0 [options] [file ...]
97 Options: 103 Options:
98 [-h hostname] [-i indent] [-l length] [-R] [-r rlog_option] 104 [-c changelog] [-h hostname] [-i indent] [-l length] [-R]
99 [-t tabwidth] [-u 'login<TAB>fullname<TAB>mailaddr']..." 105 [-r rlog_option] [-t tabwidth] [-v]
106 [-u 'login<TAB>fullname<TAB>mailaddr']..."
100 exit 1;; 107 exit 1;;
101 *) break 108 *) break
102 esac 109 esac
103 shift 110 shift
104 done 111 done
106 month_data=' 113 month_data='
107 m[0]="Jan"; m[1]="Feb"; m[2]="Mar" 114 m[0]="Jan"; m[1]="Feb"; m[2]="Mar"
108 m[3]="Apr"; m[4]="May"; m[5]="Jun" 115 m[3]="Apr"; m[4]="May"; m[5]="Jun"
109 m[6]="Jul"; m[7]="Aug"; m[8]="Sep" 116 m[6]="Jul"; m[7]="Aug"; m[8]="Sep"
110 m[9]="Oct"; m[10]="Nov"; m[11]="Dec" 117 m[9]="Oct"; m[10]="Nov"; m[11]="Dec"
111
112 # days in non-leap year thus far, indexed by month (0-12)
113 mo[0]=0; mo[1]=31; mo[2]=59; mo[3]=90
114 mo[4]=120; mo[5]=151; mo[6]=181; mo[7]=212
115 mo[8]=243; mo[9]=273; mo[10]=304; mo[11]=334
116 mo[12]=365
117 ' 118 '
118 119
119 120
120 # Put rlog output into $rlogout. 121 # Put rlog output into $rlogout.
121 122
122 # If no rlog options are given, 123 # If no rlog options are given,
123 # log the revisions checked in since the first ChangeLog entry. 124 # log the revisions checked in since the first ChangeLog entry.
125 # Since ChangeLog is only by date, some of these revisions may be duplicates of
126 # what's already in ChangeLog; it's the user's responsibility to remove them.
124 case $rlog_options in 127 case $rlog_options in
125 '') 128 '')
126 date=1970 129 date=1970
127 if test -s ChangeLog 130 if test -s "$changelog"
128 then 131 then
129 # Add 1 to seconds to avoid duplicating most recent log.
130 e=' 132 e='
133 /^[0-9]+-[0-9][0-9]-[0-9][0-9]/{
134 # ISO 8601 date
135 print $1
136 exit
137 }
131 /^... ... [ 0-9][0-9] [ 0-9][0-9]:[0-9][0-9]:[0-9][0-9] [0-9]+ /{ 138 /^... ... [ 0-9][0-9] [ 0-9][0-9]:[0-9][0-9]:[0-9][0-9] [0-9]+ /{
139 # old-fashioned date and time (Emacs 19.31 and earlier)
132 '"$month_data"' 140 '"$month_data"'
133 year = $5 141 year = $5
134 for (i=0; i<=11; i++) if (m[i] == $2) break 142 for (i=0; i<=11; i++) if (m[i] == $2) break
135 dd = $3 143 dd = $3
136 hh = substr($0,12,2) 144 printf "%d-%02d-%02d\n", year, i+1, dd
137 mm = substr($0,15,2)
138 ss = substr($0,18,2)
139 ss++
140 if (ss == 60) {
141 ss = 0
142 mm++
143 if (mm == 60) {
144 mm = 0
145 hh++
146 if (hh == 24) {
147 hh = 0
148 dd++
149 monthdays = mo[i+1] - mo[i]
150 if (i == 1 && year%4 == 0 && (year%100 != 0 || year%400 == 0)) monthdays++
151 if (dd == monthdays + 1) {
152 dd = 1
153 i++
154 if (i == 12) {
155 i = 0
156 year++
157 }
158 }
159 }
160 }
161 }
162 # Output comma instead of space to avoid CVS 1.5 bug.
163 printf "%d/%02d/%02d,%02d:%02d:%02d\n", year,i+1,dd,hh,mm,ss
164 exit 145 exit
165 } 146 }
166 ' 147 '
167 d=`$AWK "$e" <ChangeLog` || exit 148 d=`$AWK "$e" <"$changelog"` || exit
168 case $d in 149 case $d in
169 ?*) date=$d 150 ?*) date=$d
170 esac 151 esac
171 fi 152 fi
172 datearg="-d>$date" 153 datearg="-d>$date"
173 esac 154 esac
155
156 # Use rlog's -zLT option, if rlog supports it.
157 case `rlog -zLT 2>&1` in
158 *'unknown option'*) ;;
159 *) rlog_options=-zLT$nl$rlog_options
160 esac
161
162 # Use TZ specified by ChangeLog local variable, if any.
163 if test -s "$changelog"
164 then
165 extractTZ='
166 /^.*change-log-time-zone-rule['"$tab"' ]*:['"$tab"' ]*"\([^"]*\)".*/{
167 s//\1/; p; q
168 }
169 /^.*change-log-time-zone-rule['"$tab"' ]*:['"$tab"' ]*t.*/{
170 s//UTC0/; p; q
171 }
172 '
173 logTZ=`tail "$changelog" | sed -n "$extractTZ"`
174 case $logTZ in
175 ?*) TZ=$logTZ; export TZ
176 esac
177 fi
174 178
175 # If CVS is in use, examine its repository, not the normal RCS files. 179 # If CVS is in use, examine its repository, not the normal RCS files.
176 if test ! -f CVS/Repository 180 if test ! -f CVS/Repository
177 then 181 then
178 rlog=rlog 182 rlog=rlog
243 llogout=$TMPDIR/rcs2log$$l 247 llogout=$TMPDIR/rcs2log$$l
244 rlogout=$TMPDIR/rcs2log$$r 248 rlogout=$TMPDIR/rcs2log$$r
245 trap exit 1 2 13 15 249 trap exit 1 2 13 15
246 trap "rm -f $llogout $rlogout; exit 1" 0 250 trap "rm -f $llogout $rlogout; exit 1" 0
247 251
248 case $rlog_options in 252 case $datearg in
249 ?*) $rlog $rlog_options ${1+"$@"} >$rlogout;; 253 ?*) $rlog $rlog_options "$datearg" ${1+"$@"} >$rlogout;;
250 '') $rlog "$datearg" ${1+"$@"} >$rlogout 254 '') $rlog $rlog_options ${1+"$@"} >$rlogout
251 esac || exit 255 esac || exit
252 256
253 257
254 # Get the full name of each author the logs mention, and set initialize_fullname 258 # Get the full name of each author the logs mention, and set initialize_fullname
255 # to awk code that initializes the `fullname' awk associative array. 259 # to awk code that initializes the `fullname' awk associative array.
411 sep = indent_string 415 sep = indent_string
412 Log = substr(Log, i+1) 416 Log = substr(Log, i+1)
413 } 417 }
414 }' 418 }'
415 419
420 # Pattern to match the `revision' line of rlog output.
421 rlog_revision_pattern='^revision [0-9]+\.[0-9]+(\.[0-9]+\.[0-9]+)*(['"$tab"' ]+locked by: [^'"$tab"' $,.0-9:;@]*[^'"$tab"' $,:;@][^'"$tab"' $,.0-9:;@]*;)?['"$tab"' ]*$'
422
416 case $hostname in 423 case $hostname in
417 '') 424 '')
418 hostname=`( 425 hostname=`(
419 hostname || uname -n || uuname -l || cat /etc/whoami 426 hostname || uname -n || uuname -l || cat /etc/whoami
420 ) 2>/dev/null` || { 427 ) 2>/dev/null` || {
448 } 455 }
449 if (filename ~ /,v$/) { 456 if (filename ~ /,v$/) {
450 filename = substr(filename, 1, length(filename) - 2) 457 filename = substr(filename, 1, length(filename) - 2)
451 } 458 }
452 } 459 }
460 rev = "?"
453 } 461 }
454 /^Working file:/ { if (repository == "") filename = $3 } 462 /^Working file:/ { if (repository == "") filename = $3 }
455 /^date: /, /^(-----------*|===========*)$/ { 463 /'"$rlog_revision_pattern"'/, /^(-----------*|===========*)$/ {
456 if ($0 ~ /^branches: /) { next } 464 if ($0 ~ /'"$rlog_revision_pattern"'/) {
465 rev = $2
466 next
467 }
457 if ($0 ~ /^date: [0-9][- +\/0-9:]*;/) { 468 if ($0 ~ /^date: [0-9][- +\/0-9:]*;/) {
458 date = $2 469 date = $2
459 if (date ~ /-/) { 470 if (date ~ /\//) {
460 # An ISO format date. Replace all "-"s with "/"s. 471 # This is a traditional RCS format date YYYY/MM/DD.
472 # Replace "/"s with "-"s to get ISO format.
461 newdate = "" 473 newdate = ""
462 while ((i = index(date, "-")) != 0) { 474 while ((i = index(date, "/")) != 0) {
463 newdate = newdate substr(date, 1, i-1) "/" 475 newdate = newdate substr(date, 1, i-1) "-"
464 date = substr(date, i+1) 476 date = substr(date, i+1)
465 } 477 }
466 date = newdate date 478 date = newdate date
467 } 479 }
468 # Ignore any time zone; ChangeLog has no room for it. 480 time = substr($3, 1, length($3) - 1)
469 time = substr($3, 1, 8)
470 author = substr($5, 1, length($5)-1) 481 author = substr($5, 1, length($5)-1)
471 printf "%s %s %s %s %c", filename, date, time, author, 13 482 printf "%s %s %s %s %s %c", filename, rev, date, time, author, 13
483 rev = "?"
472 next 484 next
473 } 485 }
486 if ($0 ~ /^branches: /) { next }
474 if ($0 ~ /^(-----------*|===========*)$/) { print ""; next } 487 if ($0 ~ /^(-----------*|===========*)$/) { print ""; next }
475 printf "%s%c", $0, 13 488 printf "%s%c", $0, 13
476 } 489 }
477 ' | 490 ' |
478 491
479 # Now each line is of the form 492 # Now each line is of the form
480 # FILENAME YYYY/MM/DD HH:MM:SS AUTHOR \rLOG 493 # FILENAME REVISION YYYY-MM-DD HH:MM:SS[+-TIMEZONE] AUTHOR \rLOG
481 # where \r stands for a carriage return, 494 # where \r stands for a carriage return,
482 # and each line of the log is terminated by \r instead of \n. 495 # and each line of the log is terminated by \r instead of \n.
483 # Sort the log entries, first by date+time (in reverse order), 496 # Sort the log entries, first by date+time (in reverse order),
484 # then by author, then by log entry, and finally by file name (just in case). 497 # then by author, then by log entry, and finally by file name and revision
485 sort +1 -3r +3 +0 | 498 # (just in case).
499 sort +2 -4r +4 +0 |
486 500
487 # Finally, reformat the sorted log entries. 501 # Finally, reformat the sorted log entries.
488 $AWK ' 502 $AWK '
489 BEGIN { 503 BEGIN {
504 logTZ = "'"$logTZ"'"
505 revision = "'"$revision"'"
506
490 # Some awk variants do not understand "\r" or "\013", so we have to 507 # Some awk variants do not understand "\r" or "\013", so we have to
491 # put a carriage return directly in the file. 508 # put a carriage return directly in the file.
492 CR=" 509 CR="
493 " # <-- There is a single CR between the " chars here. 510 " # <-- There is a single CR between the " chars here.
494 511
502 if (0 < '"$tabwidth"') 519 if (0 < '"$tabwidth"')
503 for (; '"$tabwidth"' <= i; i -= '"$tabwidth"') 520 for (; '"$tabwidth"' <= i; i -= '"$tabwidth"')
504 indent_string = indent_string "\t" 521 indent_string = indent_string "\t"
505 while (1 <= i--) 522 while (1 <= i--)
506 indent_string = indent_string " " 523 indent_string = indent_string " "
507
508 # Set up date conversion tables.
509 # RCS uses a nice, clean, sortable format,
510 # but ChangeLog wants the traditional, ugly ctime format.
511
512 # January 1, 0 AD (Gregorian) was Saturday = 6
513 EPOCH_WEEKDAY = 6
514 # Of course, there was no 0 AD, but the algorithm works anyway.
515
516 w[0]="Sun"; w[1]="Mon"; w[2]="Tue"; w[3]="Wed"
517 w[4]="Thu"; w[5]="Fri"; w[6]="Sat"
518
519 '"$month_data"'
520 } 524 }
521 525
522 { 526 {
523 newlog = substr($0, 1 + index($0, CR)) 527 newlog = substr($0, 1 + index($0, CR))
524 528
525 # Ignore log entries prefixed by "#". 529 # Ignore log entries prefixed by "#".
526 if (newlog ~ /^#/) { next } 530 if (newlog ~ /^#/) { next }
527 531
528 if (Log != newlog || date != $2 || author != $4) { 532 if (Log != newlog || date != $3 || author != $5) {
529 533
530 # The previous log and this log differ. 534 # The previous log and this log differ.
531 535
532 # Print the old log. 536 # Print the old log.
533 if (date != "") '"$printlogline"' 537 if (date != "") '"$printlogline"'
554 if (files != "") 558 if (files != "")
555 for (i in filesknown) 559 for (i in filesknown)
556 filesknown[i] = 0 560 filesknown[i] = 0
557 files = "" 561 files = ""
558 } 562 }
559 if (date != $2 || author != $4) { 563 if (date != $3 || author != $5) {
560 # The previous date+author and this date+author differ. 564 # The previous date+author and this date+author differ.
561 # Print the new one. 565 # Print the new one.
562 date = $2 566 date = $3
563 author = $4 567 time = $4
564 568 author = $5
565 # Convert nice RCS date like "1992/01/03 00:03:44" 569
566 # into ugly ctime date like "Fri Jan 3 00:03:44 1992". 570 zone = ""
567 # Calculate day of week from Gregorian calendar. 571 if (logTZ && ((i = index(time, "-")) || (i = index(time, "+"))))
568 i = index($2, "/") 572 zone = " " substr(time, i)
569 year = substr($2, 1, i-1) + 0 573
570 monthday = substr($2, i+1) 574 # Print "date[ timezone] fullname <email address>".
571 i = index(monthday, "/")
572 month = substr(monthday, 1, i-1) + 0
573 day = substr(monthday, i+1) + 0
574 leap = 0
575 if (2 < month && year%4 == 0 && (year%100 != 0 || year%400 == 0)) leap = 1
576 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
577
578 # Print "date fullname (email address)".
579 # Get fullname and email address from associative arrays; 575 # Get fullname and email address from associative arrays;
580 # default to author and author@hostname if not in arrays. 576 # default to author and author@hostname if not in arrays.
581 if (fullname[author]) 577 if (fullname[author])
582 auth = fullname[author] 578 auth = fullname[author]
583 else 579 else
584 auth = author 580 auth = author
585 printf "%s %s %2d %s %d %s ", w[days_since_Sunday_before_epoch%7], m[month-1], day, $3, year, auth 581 printf "%s%s %s ", date, zone, auth
586 if (mailaddr[author]) 582 if (mailaddr[author])
587 printf "<%s>\n\n", mailaddr[author] 583 printf "<%s>\n\n", mailaddr[author]
588 else 584 else
589 printf "<%s@%s>\n\n", author, "'"$hostname"'" 585 printf "<%s@%s>\n\n", author, "'"$hostname"'"
590 } 586 }
591 if (! filesknown[$1]) { 587 if (! filesknown[$1]) {
592 filesknown[$1] = 1 588 filesknown[$1] = 1
593 if (files == "") files = " " $1 589 if (files == "") files = " " $1
594 else files = files ", " $1 590 else files = files ", " $1
591 if (revision && $2 != "?") files = files " " $2
595 } 592 }
596 } 593 }
597 END { 594 END {
598 # Print the last log. 595 # Print the last log.
599 if (date != "") { 596 if (date != "") {
605 602
606 603
607 # Exit successfully. 604 # Exit successfully.
608 605
609 exec rm -f $llogout $rlogout 606 exec rm -f $llogout $rlogout
607
608 # Local Variables:
609 # tab-width:4
610 # End: