📄 rcs2log
字号:
set x $loginFullnameMailaddr login=$2 fullname=$3 mailaddr=$4 initialize_fullname="$initialize_fullname fullname[\"$login\"] = \"$fullname\"" initialize_mailaddr="$initialize_mailaddr mailaddr[\"$login\"] = \"$mailaddr\"" done IFS=$oldIFSesaccase $llogout in?*) sort -u -o $llogout <<EOF || exit$loginsEOFesacoutput_authors='/^date: / { 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 ~ /^[^;]*;$/) { print substr($5, 1, length($5)-1) }}'authors=` $AWK "$output_authors" <$rlogout | case $llogout in '') sort -u;; ?*) sort -u | comm -23 - $llogout esac`case $authors in?*) cat >$llogout <<EOF || exit$authorsEOF initialize_author_script='s/["\\]/\\&/g; s/.*/author[\"&\"] = 1/' initialize_author=`sed -e "$initialize_author_script" <$llogout` awkscript=' BEGIN { alphabet = "abcdefghijklmnopqrstuvwxyz" ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" '"$initialize_author"' } { if (author[$1]) { fullname = $5 if (fullname ~ /[0-9]+-[^(]*\([0-9]+\)$/) { # Remove the junk from fullnames like "0000-Admin(0000)". fullname = substr(fullname, index(fullname, "-") + 1) fullname = substr(fullname, 1, index(fullname, "(") - 1) } if (fullname ~ /,[^ ]/) { # Some sites put comma-separated junk after the fullname. # Remove it, but leave "Bill Gates, Jr" alone. fullname = substr(fullname, 1, index(fullname, ",") - 1) } 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) } # Quote quotes and backslashes properly in full names. # Do not use gsub; traditional awk lacks it. quoted = "" rest = fullname for (;;) { p = index(rest, "\\") q = index(rest, "\"") if (p) { if (q && q<p) p = q } else { if (!q) break p = q } quoted = quoted substr(rest, 1, p-1) "\\" substr(rest, p, 1) rest = substr(rest, p+1) } printf "fullname[\"%s\"] = \"%s%s\"\n", $1, quoted, rest author[$1] = 0 } } ' initialize_fullname=` { (getent passwd $authors) || ( cat /etc/passwd for author in $authors do NIS_PATH= nismatch $author passwd.org_dir done ypmatch $authors passwd ) } 2>/dev/null | $AWK -F: "$awkscript" `$initialize_fullnameesac# 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 \001).# `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, SOH)) sep = "\n" indent_string # Print the label. printf "%s*%s:", indent_string, files # Print each line of the log, transliterating \001 to \n. while ((i = index(Log, SOH)) != 0) { logline = substr(Log, 1, i-1) if (logline ~ /[^'"$tab"' ]/) { printf "%s%s\n", sep, logline } else { print "" } sep = indent_string Log = substr(Log, i+1) }}'# Pattern to match the `revision' line of rlog output.rlog_revision_pattern='^revision [0-9]+\.[0-9]+(\.[0-9]+\.[0-9]+)*(['"$tab"' ]+locked by: [^'"$tab"' $,.0-9:;@]*[^'"$tab"' $,:;@][^'"$tab"' $,.0-9:;@]*;)?['"$tab"' ]*$'case $hostname in'') hostname=`( hostname || uname -n || uuname -l || cat /etc/whoami ) 2>/dev/null` || { echo >&2 "$0: cannot deduce hostname" exit 1 } case $hostname in *.*) ;; *) domainname=`(domainname) 2>/dev/null` && case $domainname in *.*) hostname=$hostname.$domainname esac esacesac# Process the rlog output, generating ChangeLog style entries.# First, reformat the rlog output so that each line contains one log entry.# Transliterate \n to \001 so that multiline entries fit on a single line.# Discard irrelevant rlog output.$AWK <$rlogout ' BEGIN { repository = "'"$repository"'" } /^RCS file:/ { if (repository != "") { filename = $3 if (substr(filename, 1, length(repository) + 1) == repository "/") { filename = substr(filename, length(repository) + 2) } if (filename ~ /,v$/) { filename = substr(filename, 1, length(filename) - 2) } if (filename ~ /(^|\/)Attic\/[^\/]*$/) { i = length(filename) while (substr(filename, i, 1) != "/") i-- filename = substr(filename, 1, i - 6) substr(filename, i + 1) } } rev = "?" } /^Working file:/ { if (repository == "") filename = $3 } /'"$rlog_revision_pattern"'/, /^(-----------*|===========*)$/ { line = $0 if (line ~ /'"$rlog_revision_pattern"'/) { rev = $2 next } if (line ~ /^date: [0-9][- +\/0-9:]*;/) { date = $2 if (date ~ /\//) { # This is a traditional RCS format date YYYY/MM/DD. # Replace "/"s with "-"s to get ISO format. newdate = "" while ((i = index(date, "/")) != 0) { newdate = newdate substr(date, 1, i-1) "-" date = substr(date, i+1) } date = newdate date } time = substr($3, 1, length($3) - 1) author = substr($5, 1, length($5)-1) printf "%s %s %s %s %s %c", filename, rev, date, time, author, 1 rev = "?" next } if (line ~ /^branches: /) { next } if (line ~ /^(-----------*|===========*)$/) { print ""; next } if (line == "Initial revision" || line ~ /^file .+ was initially added on branch .+\.$/) { line = "New file." } printf "%s%c", line, 1 }' |# Now each line is of the form# FILENAME REVISION YYYY-MM-DD HH:MM:SS[+-TIMEZONE] AUTHOR \001LOG# where \001 stands for a carriage return,# and each line of the log is terminated by \001 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 and revision# (just in case).sort +2 -4r +4 +0 |# Finally, reformat the sorted log entries.$AWK ' BEGIN { logTZ = "'"$logTZ"'" revision = "'"$revision"'" # Some awk variants do not understand "\001", so we have to # put the char directly in the file. SOH="" # <-- There is a single SOH (octal code 001) here. # Initialize the fullname and mailaddr associative arrays. '"$initialize_fullname"' '"$initialize_mailaddr"' # 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 " " } { newlog = substr($0, 1 + index($0, SOH)) # Ignore log entries prefixed by "#". if (newlog ~ /^#/) { next } if (Log != newlog || date != $3 || author != $5) { # 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 ~ /^\{[^'"$tab"' }]*}['"$tab"' ]/) { i = index(newlog, "}") newclumpname = substr(newlog, 1, i) while (substr(newlog, i+1) ~ /^['"$tab"' ]/) 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 != $3 || author != $5) { # The previous date+author and this date+author differ. # Print the new one. date = $3 time = $4 author = $5 zone = "" if (logTZ && ((i = index(time, "-")) || (i = index(time, "+")))) zone = " " substr(time, i) # Print "date[ timezone] fullname <email address>". # Get fullname and email address from associative arrays; # default to author and author@hostname if not in arrays. if (fullname[author]) auth = fullname[author] else auth = author printf "%s%s %s ", date, zone, auth if (mailaddr[author]) printf "<%s>\n\n", mailaddr[author] else printf "<%s@%s>\n\n", author, "'"$hostname"'" } if (! filesknown[$1]) { filesknown[$1] = 1 if (files == "") files = " " $1 else files = files ", " $1 if (revision && $2 != "?") files = files " " $2 } } END { # Print the last log. if (date != "") { '"$printlogline"' printf "\n" } }' &&# Exit successfully.exec rm -f $llogout $rlogout# Local Variables:# tab-width:4# End:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -