diff options
author | stevel@tonic-gate <none@none> | 2005-06-14 00:00:00 -0700 |
---|---|---|
committer | stevel@tonic-gate <none@none> | 2005-06-14 00:00:00 -0700 |
commit | 7c478bd95313f5f23a4c958a745db2134aa03244 (patch) | |
tree | c871e58545497667cbb4b0a4f2daf204743e1fe7 /usr/src/tools/scripts/webrev.sh | |
download | illumos-joyent-7c478bd95313f5f23a4c958a745db2134aa03244.tar.gz |
OpenSolaris Launch
Diffstat (limited to 'usr/src/tools/scripts/webrev.sh')
-rw-r--r-- | usr/src/tools/scripts/webrev.sh | 1617 |
1 files changed, 1617 insertions, 0 deletions
diff --git a/usr/src/tools/scripts/webrev.sh b/usr/src/tools/scripts/webrev.sh new file mode 100644 index 0000000000..78008e121d --- /dev/null +++ b/usr/src/tools/scripts/webrev.sh @@ -0,0 +1,1617 @@ +#!/usr/bin/ksh -p +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (the "License"). You may not use this file except in compliance +# with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# ident "%Z%%M% %I% %E% SMI" +# +# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# This script takes a file list and a workspace +# and builds a set of html files suitable for doing +# a code review of source changes via a web page. +# +# Here's how you use it: +# +# $ webrev file.list +# +# Alternatively, just run "webrev -l" and it'll extract +# a file list from the output of "putback -n" that will +# include any files updated, created, or currently sccs +# checked out. The script creates a "webrev" directory +# in the workspace directory that contains all the generated +# html files. It also stashes a copy of the file list in +# there. +# +# +# 1) If you run "webrev -l" it'll extract a file list from +# the output of "putback -n" that will include any files +# updated, created, or currently checked out. This is +# the easiest way to use webrev. If you use the "-l" +# option to generate the file list then skip to step (4). +# Note: if the workspace is large (e.g. all of Solaris usr/src +# then this might take a while. You can run "webrev -l -f flp" +# to have webrev extract a file list from the output of +# "putback -n -f flp". +# +# The file list created by "webrev -l" is stashed in the +# webrev directory as "file.list". +# +# If you would like more control over the file list then +# create a file containing a list of all the files to +# be included in your review with paths relative to your +# workspace directory, e.g. +# +# usr/src/uts/common/fs/nfs/nfs_subr.c +# usr/src/uts/common/fs/nfs/nfs_export.c +# usr/src/cmd/fs.d/nfs/mountd/mountd.c +# : +# +# Include the paths of any files added, deleted, or modified. +# You can keep this list of files in the webrev directory +# that the script creates in your workspace directory +# (CODEMGR_WS). +# +# 2) The script needs to be able locate your workspace and +# its parent. If you have already activated your workspace +# with the "ws" command then the script will use the +# CODEMGR_WS environment variable. If you are not working +# within a workspace activation, then you'll need to set +# the environment variable within the file list, e.g. +# +# CODEMGR_WS=/home/brent/myws +# +# usr/src/uts/common/fs/nfs/nfs_subr.c +# usr/src/uts/common/fs/nfs/nfs_export.c +# usr/src/cmd/fs.d/nfs/mountd/mountd.c +# : +# +# If you would like to compare against some other workspace +# that is not the parent, then you can set the CODEMGR_PARENT +# environment variable in the file list, e.g. +# +# CODEMGR_WS=/home/brent/myws +# CODEMGR_PARENT=/ws/on297-gate +# +# usr/src/uts/common/fs/nfs/nfs_subr.c +# usr/src/uts/common/fs/nfs/nfs_export.c +# usr/src/cmd/fs.d/nfs/mountd/mountd.c +# : +# +# 3) Run this script with the name of the file containing +# the file list as an argument, e.g. +# +# $ webrev file.list +# +# If you supply "-" as the name of the file, then stdin +# will be used. +# +# If you use the "-w" flag, i.e. "webrev -w file.list" +# then webrev will assume the file list is in the format +# expected by the "wx" package: pathname lines alternating +# with SCCS comment lines separated by blank lines, e.g. +# +# usr/src/uts/common/fs/nfs/nfs_subr.c +# +# 1206578 Fix spelling error in comment +# +# usr/src/uts/common/fs/nfs/nfs_export.c +# +# 4039272 cstyle fixes +# +# usr/src/cmd/fs.d/nfs/mountd/mountd.c +# +# 1927634 mountd daemon doesn't handle expletives +# +# Embedded bug ids (any sequence of 5 or more digits) +# will be converted to a URL (see URL environment variable +# below). +# +# 4) For each file in the list, the script will compare it +# with the version in the parent workspace (CODEMGR_PARENT) +# and generate context and side-by-side diffs (sdiffs) as +# HTML files as well as HTML renderings of the old and new +# files with prepended line numbers for easy cross-checking +# with diffs. +# +# The HTML files will have additional formatting to +# color code the source lines: +# +# unchanged : black +# removed : brown +# changed : blue +# new : bold blue +# +# +# 5) Webrev will create a directory $CODEMGR_WS/webrev +# and create the HTML files in a hierarchy beneath +# this directory. Links to these HTML files will be +# built into an index.html file in the "webrev" directory. +# If you would like the "webrev" directory to appear +# somewhere other than $CODEMGR_WS, then set the WDIR +# environment variable, e.g. +# +# WDIR=/tmp webrev -l +# +# Each file will be listed on a line with a link to +# its Cdiffs, Udiffs, Sdiffs, Old, and New versions. A blank +# line will be inserted between filenames that do not exist +# within the same directory as a grouping aid. +# SCCS comments for each delta will be included +# automatically. Bug numbers (any sequence of 5 or more +# digits) in the comment will be replaced by a URL to +# your local bug server. You may need to modify the URL +# below: +# + if [[ -z $WEBREV_BUGURL ]]; then + URL='http://monaco.sfbay.sun.com/detail.jsp?cr=' + else + URL="$WEBREV_BUGURL" + fi +# +# Likewise, ARC cases will be replaced by a URL starting with: +# + URL2="http://sac.eng.sun.com/" +# +# As a review aid, you can add value to the index +# file by including text that explains the changes in front +# of the links for each file. You might also add links +# to the one-pager, project plan, or other documents +# helpful to the reviewer. +# +# 6) View the index.html file with your web browser to +# verify that its what you want your reviewers to see. +# The browser must support HTML tables and colored fonts. +# Then send an Email invitation to your reviewers including +# the URL to the index.html file in your workspace. If you +# use an "http:" URL then you can omit the "index.html" +# filename, e.g. +# +# To: bob, jane, wendy +# Subject: Please review fix for bug 1234576 +# +# I'd be grateful if would review my bugfix. +# All the relevant information can be obtained +# with the following URL: +# +# http://jurassic.eng/home/brent/myws/webrev +# +# Thanks +# Brent +# +############### +# +# Acknowledgements to Rob Thurlow, Mike Eisler, Lin Ling, +# Rod Evans, Mike Kupfer, Greg Onufer, Glenn Skinner, +# Oleg Larin, David Robinson, Matthew Cross, David L. Paktor, +# Neal Gafter, John Beck, Darren Moffat, Norm Shulman, Bill Watson, +# Pedro Rubio and Bill Shannon for valuable feedback and insight in +# building this script. +# +# Have fun! +# Brent Callaghan 11/28/96 +############### +# +# Change Log +# +# 3/28/97 Add support for specifying stdin as a "-" argument. +# +# 6/15/97 Fix to allow file overwrite for users who set "noclobber" +# +# 8/19/97 Fix illegal "&" escape sequences (from Greg Onufer) +# +# 10/29/97 Create all HTML files under a "webrev" directory +# Add -bw flags to "sdiff" +# +# 3/9/98 Improvements to better handle Java code. +# Fix for quoting of code in <pre> blocks. +# Fix some color bugs. SCCS fix with not +# getting appropriate parent version depending +# on whether child version is checked out or +# not (from Bill Shannon). +# +# 3/13/98 Added code from Bill Shannon's "spc" script +# To add SCCS comments automatically to index.html. +# +# 3/18/98 Added -l option to generate file list automatically. +# +# 4/4/98 Added -w option to support Bonwick's wx package +# active file list which can included pending +# SCCS comments. +# Reorganized layout of index file so that SCCS comments +# now come after the file diffs line. This looks much +# better. Also, reduced the text point size in diffs +# so that more source code can be viewed. +# +# 3/6/98 Handle files in the root directory of the workspace. +# +# 10/15/98 Fix minor bugs in sdiff color coding. +# Replace long runs of unchanged lines in sdiff +# by a horiz rule. +# Link bugids in SCCS & wx comments to web page via URL. +# Bracket HTML page with <html> ... </html>. +# Add HTML comment to index file to help in placing +# change comments. +# +# 10/22/98 Fixed a bug affecting wx comments output. +# File names in index file are now bold. +# Basename of child workspace is used as the title. +# +# 12/22/98 Allow user to specify WDIR target directory for +# "webrev" directory. +# +# 2/8/99 Allow file comparison with a parent that is not +# a workspace - just a raw directory hierarchy of +# files created by a workspace snapshot tool like +# freezept (from Matthew Cross). +# +# 3/18/99 Allow the -l option to extract values for +# CODEMGR_WS and for CODEMGR_PARENT if they +# are not already defined. Play the file list +# out through stdout once it's created +# (from David L. Paktor). +# +# 3/18/99 Correctly handle the case where no changes are found +# +# 4/7/99 Handle case of relative name for -w filename. +# +# 8/20/99 Fix handling of file.list +# +# 10/25/99 Additions or deletions to the beginning of a file +# caused the lines to go out of synch. Added new +# code to handle this case. Thanks to Glenn Skinner +# for reporting the bug. +# +# 4/21/00 Added date of webrev run to last line of index page +# (suggestion by David Robinson) +# +# 8/2/00 Changed "sort" to "sort -u" to eliminate +# duplicates in putback output. Thanks to +# Bill Shannon. +# +# 11/21/00 Added filenames to the HTML page titles. +# (suggestion by David Robinson) +# +# 11/21/00 Fixed a problem with lost sccs comments in a +# new file. Also added a default for the -w wxfile +# flag. Thanks to Darren Moffat for these. +# +# 11/22/00 Fix to detect and handle renames correctly. +# +# 1/17/01 Allow the use of a file list program (flp) to +# be specified as an argument to -l. For example: +# "webrev -l -f ~/aux.flp". An flp is a program +# that generates a file list. Thanks to Norm Shulman. +# +# 2/1/01 Invoke context diff from CDIFFCMD environment +# variable. This allows an alternative diff +# command line to be invoked if set in the environment. +# Thanks to John Beck (a fan of udiff). +# +# 2/2/01 Change "sort -k1,1" to "sort -k 1,1" +# Bugfix from Neal Gafter +# +# 4/27/01 Added webrev script date to index page +# Suggestion from John Beck +# +# 4/27/01 Protect HTML sensitive characters in SCCS +# delta comments. Bug reported by Pedro Rubio +# +# 7/24/01 Modify page title to be workspace name - suggestion +# from Bill Watson. +# +# Following variable is set to SCCS delta date 20YY/MM/DD. +# Note this will have to be changed in 2100 or when SCCS has support for +# 4 digit years; whichever is the sooner! +# + WEBREV_UPDATED=20%E% +# +############### + +REMOVED_COLOR=brown +CHANGED_COLOR=blue +NEW_COLOR=blue + +# +# Make a piece of source code safe for display in an HTML <pre> block. +# +html_quote() +{ + sed -e "s/&/\&/g" -e "s/</\</g" -e "s/>/\>/g" "$@" | expand +} + +sdiff_to_html() +{ +# +# This function takes two files as arguments, obtains their diff, +# and processes the diff output to present the files as an HTML +# document with the files displayed side-by-side, differences +# shown in color. +# +# This HTML generated by this function assumes that the browser +# can handle HTML 3.0 tables and colored text as implemented +# in Netscape 2.0. The output is "wide" so it will be necessary +# to widen the browser window when viewing the output. +# +# The function takes two files as arguments +# and the HTML will be delivered on stdout, e.g. +# +# $ sdiff_html prog.c- prog.c > prog.diffs.html +# +# In addition if WEBREV_FRAMES == 'yes' then framed_sdiff() is called +# which creates $2.frames.html in the webrev tree. +# +# FYI: This function is rather unusual in its use of awk. +# The initial diff run produces conventional diff output +# showing changed lines mixed with editing codes. The +# changes lines are ignored - we're interested in the +# editing codes, e.g. +# +# 8c8 +# 57a61 +# 63c66,76 +# 68,93d80 +# 106d90 +# 108,110d91 +# +# These editing codes are parsed by the awk script and used to +# generate another awk script that generates HTML, e.g the +# above lines would turn into something like this: +# +# BEGIN { printf "<pre>\n" } +# function sp(n) {for (i=0;i<n;i++)printf "\n"} +# function wl(n) {printf "<FONT COLOR=%s>%3d %s </FONT>\n", n, NR, $0} +# NR==8 {wl("#7A7ADD");next} +# NR==54 {wl("#7A7ADD");sp(3);next} +# NR==56 {wl("#7A7ADD");next} +# NR==57 {wl("black");printf "\n"; next} +# : : +# +# This script is then run on the original source file to generate +# the HTML that corresponds to the source file. +# +# The two HTML files are then combined into a single piece of +# HTML that uses an HTML table construct to present the files +# side by side. You'll notice that the changes are color-coded: +# +# black - unchanged lines +# blue - changed lines +# bold blue - new lines +# brown - deleted lines +# +# Blank lines are inserted in each file to keep unchanged +# lines in sync (side-by-side). This format is familiar +# to users of sdiff(1) or Teamware's filemerge tool. + +diff -b $1 $2 > /tmp/$$.diffs + +# +# Now we have the diffs, generate the HTML for the old file. +# + +TNAME=$2 + +nawk ' +BEGIN { + printf "function sp(n) {for (i=0;i<n;i++)printf \"\\n\"}\n" + printf "function wl(n) {printf \"<FONT COLOR=%%s>%%3d %%s </FONT>\\n\", n, NR, $0}\n" + printf "function bl() {printf \"%%3d %%s\\n\", NR, $0}\n" +} +/^</ {next} +/^>/ {next} +/^---/ {next} +{ + split($1, a, /[cad]/) ; + if (index($1, "a")) { + if (a[1] == 0) { + n = split(a[2], r, /,/); + if (n == 1) + printf "BEGIN\t\t{sp(1)}\n" + else + printf "BEGIN\t\t{sp(%d)}\n",\ + (r[2] - r[1]) + 1 + next + } + + printf "NR==%s\t\t{", a[1] + n = split(a[2], r, /,/); + s = r[1]; + if (n == 1) + printf "bl();printf \"\\n\"; next}\n" + else { + n = r[2] - r[1] + printf "bl();sp(%d);next}\n",\ + (r[2] - r[1]) + 1 + } + next + } + if (index($1, "d")) { + n = split(a[1], r, /,/); + n1 = r[1] + n2 = r[2] + if (n == 1) + printf "NR==%s\t\t{wl(\"'$REMOVED_COLOR'\") ; next}\n" , n1 + else + printf "NR==%s,NR==%s\t{wl(\"'$REMOVED_COLOR'\") ; next}\n" , n1, n2 + next + } + if (index($1, "c")) { + n = split(a[1], r, /,/); + n1 = r[1] + n2 = r[2] + final = n2 + d1 = 0 + if (n == 1) + printf "NR==%s\t\t{wl(\"'$CHANGED_COLOR'\");" , n1 + else { + d1 = n2 - n1 + printf "NR==%s,NR==%s\t{wl(\"'$CHANGED_COLOR'\");" , n1, n2 + } + m = split(a[2], r, /,/); + n1 = r[1] + n2 = r[2] + if (m > 1) { + d2 = n2 - n1 + if (d2 > d1) { + if (n > 1) printf "if (NR==%d)", final + printf "sp(%d);", d2 - d1 + } + } + printf "next}\n" ; + + next + } +} +END { printf "{printf \"%%3d %%s\\n\", NR, $0 }\n" } +' /tmp/$$.diffs > /tmp/$$.file1 + +html_quote $1 | nawk -f /tmp/$$.file1 > /tmp/$$.file1.html + +# +# Now generate the HTML for the new file +# + +nawk ' +BEGIN { + printf "function sp(n) {for (i=0;i<n;i++)printf \"\\n\"}\n" + printf "function wl(n) {printf \"<FONT COLOR=%%s>%%3d %%s </FONT>\\n\", n, NR, $0}\n" + printf "function wlb(n) {printf \"<FONT COLOR=%%s><b>%%3d %%s</b></FONT>\\n\", n, NR, $0}\n" + printf "function bl() {printf \"%%3d %%s\\n\", NR, $0}\n" +} +/^</ {next} +/^>/ {next} +/^---/ {next} +{ + split($1, a, /[cad]/) ; + if (index($1, "d")) { + if (a[2] == 0) { + n = split(a[1], r, /,/); + if (n == 1) + printf "BEGIN\t\t{sp(1)}\n" + else + printf "BEGIN\t\t{sp(%d)}\n",\ + (r[2] - r[1]) + 1 + next + } + + printf "NR==%s\t\t{", a[2] + n = split(a[1], r, /,/); + s = r[1]; + if (n == 1) + printf "bl();printf \"\\n\"; next}\n" + else { + n = r[2] - r[1] + printf "bl();sp(%d);next}\n",\ + (r[2] - r[1]) + 1 + } + next + } + if (index($1, "a")) { + n = split(a[2], r, /,/); + n1 = r[1] + n2 = r[2] + if (n == 1) + printf "NR==%s\t\t{wlb(\"'$NEW_COLOR'\") ; next}\n" , n1 + else + printf "NR==%s,NR==%s\t{wlb(\"'$NEW_COLOR'\") ; next}\n" , n1, n2 + next + } + if (index($1, "c")) { + n = split(a[2], r, /,/); + n1 = r[1] + n2 = r[2] + final = n2 + d2 = 0; + if (n == 1) { + final = n1 + printf "NR==%s\t\t{wl(\"'$CHANGED_COLOR'\");" , n1 + } else { + d2 = n2 - n1 + printf "NR==%s,NR==%s\t{wl(\"'$CHANGED_COLOR'\");" , n1, n2 + } + m = split(a[1], r, /,/); + n1 = r[1] + n2 = r[2] + if (m > 1) { + d1 = n2 - n1 + if (d1 > d2) { + if (n > 1) printf "if (NR==%d)", final + printf "sp(%d);", d1 - d2 + } + } + printf "next}\n" ; + next + } +} +END { printf "{printf \"%%3d %%s\\n\", NR, $0 }\n" } +' /tmp/$$.diffs > /tmp/$$.file2 + +html_quote $2 | nawk -f /tmp/$$.file2 > /tmp/$$.file2.html + +# Now combine into a table + +echo "<body bgcolor=#EEEEEE>" +echo "<title> Sdiff $TNAME </title>" +echo "<table><tr valign=top>" +echo "<td><pre>" + +strip_unchanged /tmp/$$.file1.html + +echo "</pre></td><td><pre>" + +strip_unchanged /tmp/$$.file2.html + +echo "</pre></td>" +echo "</tr></table>" + +if [[ $WEBREV_FRAMES == 'yes' ]]; then + framed_sdiff $TNAME /tmp/$$.file1.html /tmp/$$.file2.html +fi + +} + +#################################### + +function framed_sdiff +{ +# Expects html files created by sdiff_to_html which it then augments +# with HTML navigation anchors. +# +# NOTE: We rely on standard usage of $TNAME and $WDIR/$DIR. +# + typeset TNAME=$1 + typeset file1=$2 + typeset file2=$3 + typeset RTOP + # Make the rhs/lhs files and output the frameset file. + insert_anchors $file1 > $WDIR/$DIR/$TNAME.lhs.html + insert_anchors $file2 > $WDIR/$DIR/$TNAME.rhs.html + # Enable html files to access WDIR via a relative path. + RTOP=$(relative_cws) + cat > $WDIR/$DIR/$TNAME.frames.html <<-EOF + <html><head> + <title>Framed Sdiff for $TNAME</title> + </head> + <FRAMESET ROWS="*,50"> + <FRAMESET COLS="50%,50%"> + <FRAME SRC="$TNAME.lhs.html" SCROLLING="auto" NAME="lhs"> + <FRAME SRC="$TNAME.rhs.html" SCROLLING="auto" NAME="rhs"> + </FRAMESET> + <FRAME SRC="${RTOP}ancnav.html" SCROLLING="no" MARGINWIDTH="0" + MARGINHEIGHT="0"> + <NOFRAMES> + <P>Alas FRAMES webrev requires that your browser supports FRAMES + and has the feature enabled. + <a href="index.html">Return to webrev index</a>.</p> + </NOFRAMES> + </FRAMESET> + </html> + EOF +} + +#################################### + +strip_unchanged() +{ +# Removes chunks of sdiff documents that have not +# changed. This makes it easier for a code reviewer +# to find the bits that have changed. +# +# Deleted lines of text are replaced by an +# horizontal rule. Some identical lines are +# retained before and after the changed lines +# to provide some context. The number of these +# lines is controlled by the variable C in the +# nawk script below. +# +# The script detects changed lines as any line +# that has a "FONT COLOR=" string embedded (unchanged +# lines use the default color and have no FONT directive). +# Blank lines (without a sequence number) are also detected +# since they flag lines that have been inserted or deleted. + +nawk ' + +BEGIN { C = c = 20 } +NF == 0 || /FONT COLOR=/ { + if (c > C) { + c -= C + inx = 0 + if (c > C) { + print "\n<hr>" + inx = c % C + c = C + } + + for (i = 0; i < c; i++) + print ln[(inx + i) % C] + } + c = 0; + print + next +} +{ if (c >= C) { + ln[c % C] = $0 + c++; + next; + } + c++; + print +} +END { if (c > (C * 2)) print "\n<hr>" } + +' $1 +} +#################################### + +function insert_anchors +{ +# Flag blocks of difference with sequentially numbered invisible +# anchors. These are used to drive the WEBREV_FRAMES version of the +# sdiffs output. +# +# NOTE: Anchor zero flags the top of the file irrespective of changes, +# an additional anchor is also appended to flag the bottom. +# +# The script detects changed lines as any line that has a "<FONT +# COLOR=" string embedded (unchanged lines use the default color and +# have no FONT directive). Blank lines (without a sequence number) +# are also detected since they flag lines that have been inserted or +# deleted. +# +# In addition, here is a good place to top and tail the document for +# use in its parent frame. We add a lot of blank lines to tackily +# assist the last anchors to have an effect on the screen. + +print '<html>\n<body bgcolor="#EEEEEE">\n<pre>' + +nawk ' +function ia() { + printf "<A NAME=\"%d\"></A>", anc++; +} +BEGIN { + anc=0; + inblock=1; + ia(); +} +NF == 0 || /^<FONT COLOR=/ { + if (inblock == 0) { + ia(); + inblock=1; + } + print; + next; +} +{ + inblock=0; + print; +} +END { + ia(); + print "<center><font color=\"red\"><b>--- EOF ---</b></font></center>"; + for(i=0;i<8;i++) printf "\n\n\n\n\n\n\n\n\n\n"; +} +' $1 + +print '</pre>\n</html>' +} + +#################################### + +function relative_cws +{ +# +# Print a relative return path from PWD to CWS. for example if +# PWD=/ws/onnv-gate/usr/src/tools/scripts and CWS=/ws/onnv-gate this +# function would print "../../../../". +# +# In the event that CWS is not in PWD a warning is printed to stderr, +# WDIR is returned and thus the resulting webrev is not relocatable. +# + typeset cur="${PWD##$CWS(/)}" ret + if [[ $PWD == $cur ]]; then # Should never happen. + print -u2 "\nWarning: relative_cws: \"$PWD\" not relative to \"$CWS\"." + print -u2 "Check input paths. Framed webrev will not be relocatable!" + print $WDIR + else + while [[ -n ${cur} ]] + do + cur=${cur%%*(/)*([!/])} + ret="../$ret" + done + print $ret + fi +} + +#################################### + +function frame_navigation +{ +# Output anchor navigation file for framed sdiffs. +cat << \EOF +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<html><head><title>Anchor Navigation</title> +<meta http-equiv="Content-Script-Type" content="text/javascript"> +<meta http-equiv="Content-Type" content="text/html"> + <style> + div.button td { background: #900;} + div.button a { color: white } + div.button a:hover { background: black; color: white } + </style> + <script language="JavaScript"> +<!-- +var anc=0; +var myInt; +var scrolling=0; +var sfactor; +var scount=10; + +function scrollByPix() { + if (scount<=0) { + sfactor*=1.2; + scount=10; + } + parent.lhs.scrollBy(0,sfactor); + parent.rhs.scrollBy(0,sfactor); + scount--; +} + +function scrollByAnc(num) { + if (num < 0) { + anc=0; + num=0; + } + if (num >= parent.lhs.document.anchors.length) { + anc=parent.lhs.document.anchors.length - 1; + num=anc; + } + parent.lhs.location.replace(parent.lhs.location.pathname + "#" + num); + parent.rhs.location.replace(parent.rhs.location.pathname + "#" + num); + anc=num; + if (num <= 0) { + document.diff.sync.value="BOF"; + } else if (num < parent.lhs.document.anchors.length - 1) { + document.diff.sync.value=num; + } else { + document.diff.sync.value="EOF"; + } + // Scroll back a little to expose previous lines. + parent.lhs.scrollBy(0,-30); + parent.rhs.scrollBy(0,-30); +} + +function stopScroll() { + if (scrolling==1) { + clearInterval(myInt); + scrolling=0; + } +} + +function startScroll() { + stopScroll(); + scrolling=1; + myInt=setInterval("scrollByPix()",10); +} + +function handlePress(b) { + switch (b) { + case 1 : + scrollByAnc(-1); + break; + case 2 : + scrollByAnc(anc-1); + break; + case 3 : + sfactor=-3; + startScroll(); + break; + case 4 : + sfactor=3; + startScroll(); + break; + case 5 : + scrollByAnc(anc+1); + break; + case 6 : + scrollByAnc(parent.lhs.document.anchors.length); + break; + } +} + +function handleRelease(b) { + stopScroll(); +} + +function ValidateDiffNum(){ + i=Number(document.diff.sync.value); + if (isNaN(i)) { + document.diff.sync.value=anc; + } else { + scrollByAnc(i); + } + return false; +} + +//--> + </script> + </head> + <body> + <noscript lang="javascript"> + <center> + <p><big>Framed Navigation controls require Javascript</big><br> + Either this browser is incompatable or javascript is not enabled</p> + </center> + </noscript> + <table width="100%" border="0" align="center"> + <tr><th valign="middle" width="25%"><i>Diff navigation:</i></th> + <td align="centre" valign="top" width="50%"> + <div class="button"> + <table border="0" cellpadding="2" align="center"><tr> + <td align="center" valign="left"> + <a onMouseDown="handlePress(1);return true;" + onMouseUp="handleRelease(1);return true;" + onMouseOut="handleRelease(1);return true;" + onClick="return false;" + title="Go to Beginning Of file">BOF</a></td> + <td align="center" valign="middle"> + <a onMouseDown="handlePress(3);return true;" + onMouseUp="handleRelease(3);return true;" + onMouseOut="handleRelease(3);return true;" + title="Scroll Up: Press and Hold to accelerate" + onClick="return false;">Scroll frames Up</a></td> + <td align="center" valign="right"> + <a onMouseDown="handlePress(2);return true;" + onMouseUp="handleRelease(2);return true;" + onMouseOut="handleRelease(2);return true;" + title="Go to previous Diff" + onClick="return false;">Prev Diff</a> + </td></tr> + <tr> + <td align="center" valign="left"> + <a onMouseDown="handlePress(6);return true;" + onMouseUp="handleRelease(6);return true;" + onMouseOut="handleRelease(6);return true;" + onClick="return false;" + title="Go to End Of File">EOF</a></td> + <td align="center" valign="middle"> + <a onMouseDown="handlePress(4);return true;" + onMouseUp="handleRelease(4);return true;" + onMouseOut="handleRelease(4);return true;" + title="Scroll Down: Press and Hold to accelerate" + onClick="return false;">Scroll frames Down</a></td> + <td align="center" valign="right"> + <a onMouseDown="handlePress(5);return true;" + onMouseUp="handleRelease(5);return true;" + onMouseOut="handleRelease(5);return true;" + title="Go to next Diff" + onClick="return false;">Next Diff</a></td> + </tr></table> + </dev> + </TD> + <th valign="middle" width="25%"> + <form name="diff" onsubmit="return ValidateDiffNum();"> + <input name="sync" value="BOF" size="8" type="text"> + </form> + </th> + </TR> + </table> + </body> +</html> +EOF +} + +#################################### + +diff_to_html() +{ +TNAME=$1 +DIFFTYPE=$2 + +html_quote | nawk ' +BEGIN {printf "<body bgcolor=\"#EEEEEE\"><title>'$DIFFTYPE'diff '$TNAME'</title><pre>\n"} +/^-------/ { printf "<center><h1>%s</h1></center>\n", $0; next } +/^\*\*\*\*/ { printf "<hr>\n"; next} +/^\*\*\*/ { printf "<FONT COLOR=\"red\" SIZE=+1><b>%s</b></FONT>\n", $0 ; next} +/^---/ { printf "<FONT COLOR=\"green\" SIZE=+1><b>%s</b></FONT>\n", $0 ; next} +/^\+/ {printf "<FONT COLOR=\"'$NEW_COLOR'\"><b>%s</b></FONT>\n", $0; next} +/^!/ {printf "<FONT COLOR=\"'$CHANGED_COLOR'\">%s</FONT>\n", $0; next} +/^-/ {printf "<FONT COLOR=\"'$REMOVED_COLOR'\">%s</FONT>\n", $0; next} + {printf "<FONT COLOR=\"black\">%s</FONT>\n", $0; next} +END {printf "</pre></FONT></body>\n"} +' +} + +#################################### + +source_to_html() +{ +WHICH=$1 +TNAME=$2 + +html_quote | nawk ' +BEGIN {printf "<body bgcolor=\"#EEEEEE\"><title>'"$WHICH $TNAME"'</title><pre>\n"} + {line += 1 ; printf "%3d %s\n", line, $0 } +' +} + +#################################### +# Find the first delta in the child that's not in the parent. +# Get the newest delta from the parent, get all deltas from the +# child starting with that delta, and then get all info starting +# with the second oldest delta in that list (the first delta +# unique to the child). +# +# This code adapted from Bill Shannon's "spc" script + +deltacomments() +{ +pfile=$PWS/$1 +cfile=$CWS/$2 + +if [ -f $pfile ]; then + psid=$(sccs prs -d:I: $pfile 2>/dev/null) +else + psid=1.1 +fi + +set -A sids $(sccs prs -l -r$psid -d:I: $cfile 2>/dev/null) +N=${#sids[@]} + +if [[ $N -ge 2 ]]; then + sid1=${sids[$((N-2))]} # Gets 2nd to last sid + + echo "<ul>" + sccs prs -l -r$sid1 $cfile 2>/dev/null | + html_quote | + sed -e 's|[0-9]\{5,\}|<a href='$URL'&>&</a>|g' \ + -e 's|\([A-Z]\{1,2\}ARC\)[ /]\([0-9]\{4\}/[0-9]\{3\}\)|<a href='$URL2'\1/\2>\1 \2</a>|g'| + nawk '/^COMMENTS:/ {p=1; printf "<li>"; continue} + NF == 0 { continue } + /^D / {p=0} + {if (p==0) continue; print $0 "<br>"}' + echo "</ul>" +fi +} + +#################################### +# Given the pathname of a file, find its location +# in a "wx" active file list and print the following +# sccs comment. Embedded bugids (sequence of 5 or +# more digits) are turned into URLs. + +wxcomments() +{ + + echo "<blockquote><pre>" + nawk ' + $1 == "'$1'" { + do getline ; while (NF > 0) + getline + while (NF > 0) { print ; getline } + exit + }' < $WXFILE | html_quote | + sed -e 's|[0-9]\{5,\}|<a href='$URL'&>&</a>|g' \ + -e 's|\([A-Z]\{1,2\}ARC\)[ /]\([0-9]\{4\}/[0-9]\{3\}\)|<a href='$URL2'\1/\2>\1 \2</a>|g' + echo "</pre></blockquote>" +} + +##################################### +# Calculate number of changes. +# + +function difflines +{ + integer tot chg del ins unc err + typeset filename + + diff -e $1 $2 | eval $( nawk ' + ## Change range of lines: N,Nc + /^[0-9]*,[0-9]*c$/ { + n=split(substr($1,1,length($1)-1), counts, ","); + if (n != 2) { + error=2 + exit; + } + ## 3,5c means lines 3 , 4 and 5 are changed, a total of 3 lines. + ## following would be 5 - 3 = 2! Hence +1 for correction. + r=(counts[2]-counts[1])+1; + ## Now count replacement lines: each represents a change instead + ## of a delete, so increment c and decrement r. + while (getline != /^\.$/) { + c++; + r--; + } + ## If there were more replacement lines than original lines, + ## then r will be negative; in this case there are no deletions, + ## but there are r changes that should be counted as adds, and + ## since r is negative, subtract it from a and add it to c. + if (r < 0) { + a-=r; + c+=r; + } + ## If there were more original lines than replacement lines, then + ## r will be positive; in this case, increment d by that much. + if (r > 0) { + d+=r; + } + next; + } + + ## Change lines: Nc + /^[0-9].*c$/ { + ## The first line is a replacement; any more are additions. + if (getline != /^\.$/) { + c++; + while (getline != /^\.$/) a++; + } + next; + } + + ## Add lines: both Na and N,Na + /^[0-9].*a$/ { + while (getline != /^\.$/) a++; + next; + } + + ## Delete range of lines: N,Nd + /^[0-9]*,[0-9]*d$/ { + n=split(substr($1,1,length($1)-1), counts, ","); + if (n != 2) { + error=2 + exit; + } + ## 3,5d means lines 3 , 4 and 5 are deleted, a total of 3 lines. + ## following would be 5 - 3 = 2! Hence +1 for correction. + r=(counts[2]-counts[1])+1; + d+=r; + next; + } + + ## Delete line: Nd + ## For example 10d says line 10 is deleted. + /^[0-9]*d$/ {d++; next} + + ## Should not get here! + { + error=1; + exit; + } + + ## Finish off - print results + END{ + printf("tot=%d;chg=%d;del=%d;ins=%d;err=%d\n", + (c+d+a), c, d, a, error); + }' ) + + # End of nawk, Check to see if any trouble occurred. + if (( $? > 0 || err > 0 )); then + print "Unexpected Error occurred reading \`diff -e $1 $2\`: \$?=$?, err=" $err + else + # Accumulate totals + (( TOTL += tot )) + (( TCHG += chg )) + (( TDEL += del )) + (( TINS += ins )) + # Calculate unchanged lines + wc -l $1 | read unc filename + if (( unc > 0 )); then + (( unc -= del + chg )) + (( TUNC += unc )) + fi + # print summary + printCI $tot $ins $del $chg $unc + fi +} + +##################################### +# Print out Code Inspection figures similar to sccs-prt(1) format. +# +function printCI +{ + integer tot=$1 ins=$2 del=$3 chg=$4 unc=$5 + typeset str + if (( tot == 1 )); then + str="line" + else + str="lines" + fi + printf "%d %s changed : %d/%d/%d/%d %s\n" \ + $tot $str $ins $del $chg $unc "(inserted/deleted/modified/unchanged)" +} + +##################################### +# +# Start Here +# +##################################### + +trap "rm -f /tmp/$$.* ; exit" 0 1 2 3 15 + +set +o noclobber + +WDIFF=${WDIFF:-/ws/onnv-gate/public/bin/wdiff} + +FLIST=$1 + +# By default enable frame diff. +WEBREV_FRAMES=${WEBREV_FRAMES:-yes} + +# Declare global total counters. +integer TOTL TINS TDEL TCHG TUNC + +if [ "$FLIST" = "-" ]; then + FLIST=/tmp/$$.flist + cat > $FLIST +fi + +# If the -l flag is given instead of the name of +# a file list, then generate the file list by +# extracting file names from a putback -n. +# Some names may come from the "update/create" +# messages and others from the "currently checked out" +# warning. Renames are detected here too. +# Extract values for CODEMGR_WS and CODEMGR_PARENT +# from the output of the putback -n as well, but remove +# them if they are already defined. + +if [ "$FLIST" = "-l" ]; then + + FLIST=/tmp/$$.filelist + print "Generating file list ...\c" + + putback -n $2 $3 2>&1 | + awk '/^update:|^create:/{print $2} + /^Parent workspace:/{printf("CODEMGR_PARENT=%s\n",$3)} \ + /^Child workspace:/{printf("CODEMGR_WS=%s\n",$3)} \ + /^The following files/{p=1 ; continue} + /^rename/{old=$3} + $1 == "to:"{print $2, old} + /^"/ {continue} + NF == 0 {p=0 ; continue} + {if (p==1) print $1}' | + sort -r -k 1,1 -u | sort > $FLIST + + print " Done\n" +fi + +# If the -w flag is given then assume the file +# list is in Bonwick's "wx" command format, i.e. +# pathname lines alternating with SCCS comment +# lines with blank lines as separators. +# Use the SCCS comments later in building +# the index.html file. + +if [ "$FLIST" = "-w" ]; then + shift + WXFILE=$1 + + # If the wx file pathname is relative + # then make it absolute because the + # webrev does a "cd" later on. + # + # If no wx file pathname is given, then + # it defaults to "wx/active" in the + # workspace directory. + + if [ -z "${WXFILE}" ]; then + WXFILE=${CODEMGR_WS}/wx/active + elif [ ${WXFILE%%/*} ]; then + WXFILE=$PWD/$WXFILE + fi + + FLIST=/tmp/$$.filelist + nawk '{ c = 1; print; + while (getline) { + if (NF == 0) { c = -c; continue } + if (c > 0) print + } + }' $WXFILE > $FLIST +fi + +if [ ! -f $FLIST ]; then + echo "$FLIST: no such file" + + echo "Usage: webrev <file>" + echo " webrev -" + echo " webrev -w [<wx file>]" + echo " webrev -l [-f flp]" + exit 1 +fi + + +# Remove workspace variables from the flist +# file if they're already set in the environment. +# We want the environment variables to take +# precedence over any set in the file list. + +if [ "$CODEMGR_WS" != "" ]; then + egrep -v '^CODEMGR_WS=' $FLIST > $FLIST.$$ + mv $FLIST.$$ $FLIST +fi +if [ "$CODEMGR_PARENT" != "" ]; then + egrep -v '^CODEMGR_PARENT=' $FLIST > $FLIST.$$ + mv $FLIST.$$ $FLIST +fi + + +# Now do an "eval" to set env variables that +# are listed in the file list. + +eval `sed -e "s/#.*$//" $FLIST | grep = ` + + +if [ "$CODEMGR_WS" = "" ]; then + echo "CODEMGR_WS not set." + echo "Activate a workspace or set in $FLIST" + exit 1 +fi + +if [ ! -d $CODEMGR_WS ]; then + echo "$CODEMGR_WS: no such workspace" + exit 1 +fi + +# Observe true directory name of CODEMGR_WS, as used later in webrev title. +CODEMGR_WS=$(cd $CODEMGR_WS;print $PWD) + +if [ "$CODEMGR_PARENT" = "" ]; then + CODEMGR_PARENT=`workspace parent` +fi + +if [ ! -d $CODEMGR_PARENT ]; then + echo "$CODEMGR_PARENT: no such parent workspace" + exit 1 +fi + +echo +echo CODEMGR_WS=$CODEMGR_WS +echo CODEMGR_PARENT=$CODEMGR_PARENT +echo + +CWS=$CODEMGR_WS +PWS=$CODEMGR_PARENT +WDIR=${WDIR:-$CWS}/webrev +if [ ${WDIR%%/*} ]; then + WDIR=$PWD/$WDIR +fi +if [ ! -d $WDIR ]; then + mkdir $WDIR +fi + +# Save the file list in the webrev dir + +if [ ! $FLIST -ef $WDIR/file.list ]; then + cp $FLIST $WDIR/file.list +fi + +# Remove comments, blank lines and env variables from the file list + +sed -e "s/#.*$//" -e "/=/d" -e "/^[ ]*$/d" $FLIST | + +# ... and read lines from the cleaned-up file list + +while read LINE +do + set - $LINE + P=$1 + + # Normally, each line in the file list is + # just a pathname of a file that has + # been modified or created in the child. + # A file that is renamed in the child workspace + # has two names on the line: new name followed + # by the old name. + + if [ $# = 2 ]; then + PP=$2 # old filename + OLDNAME=" (was $PP)" + PDIR=${PP%/*} + if [ "$PDIR" == "$PP" ]; then + PDIR="." # File at root of workspace + fi + + PF=${PP##*/} + + DIR=${P%/*} + if [ "$DIR" == "$P" ]; then + DIR="." # File at root of workspace + fi + + F=${P##*/} + else + OLDNAME="" + DIR=${P%/*} + if [ "$DIR" == "$P" ]; then + DIR="." # File at root of workspace + fi + + F=${P##*/} + + PP=$P + PDIR=$DIR + PF=$F + fi + + + + if [ ! -d $CWS/$DIR ]; then + echo " $CWS/$DIR: no such directory" + continue + fi + + print " $P$OLDNAME\n\t\c" + + # Make the webrev mirror directory if necessary + + if [ ! -d $WDIR/$DIR ]; then + mkdir -p $WDIR/$DIR + fi + + # cd to the directory so the names are short + + cd $CWS/$DIR + + # If the child's version doesn't exist then + # get a readonly copy. + + if [ ! -f $F -a -f SCCS/s.$F ]; then + sccs get -s $F + fi + + # Get the parent's version of the file. First see + # whether the child's version is checked out and + # get the parent's version with keywords expanded + # or unexpanded as appropriate. + + if [ -f $PWS/$PDIR/SCCS/s.$PF -o -f $PWS/$PDIR/SCCS/p.$PF ]; then + if [ -f SCCS/p.$F ]; then + sccs get -s -p -k $PWS/$PDIR/$PF > $WDIR/$DIR/$F- + else + sccs get -s -p $PWS/$PDIR/$PF > $WDIR/$DIR/$F- + fi + else + if [ -f $PWS/$PDIR/$PF ]; then + # Parent is not a real workspace, but just a raw + # directory tree - use the file that's there as + # the old file. + + cp $PWS/$PDIR/$PF $WDIR/$DIR/$F- + fi + fi + + if [ ! -f $F -a ! -f $WDIR/$DIR/$F- ]; then + echo "*** Error: file not in parent or child" + continue + fi + + # If we have old and new versions of the file + # then run the appropriate diffs. + + if [ -f $F -a -f $WDIR/$DIR/$F- ]; then + ${CDIFFCMD:-diff -b -C 5} $WDIR/$DIR/$F- $F > $WDIR/$DIR/$F.cdiff + diff_to_html $F "C" < $WDIR/$DIR/$F.cdiff > $WDIR/$DIR/$F.cdiff.html + print " cdiffs\c" + + ${UDIFFCMD:-diff -b -U 5} $WDIR/$DIR/$F- $F > $WDIR/$DIR/$F.udiff + diff_to_html $F "U" < $WDIR/$DIR/$F.udiff > $WDIR/$DIR/$F.udiff.html + print " udiffs\c" + + if [[ -x $WDIFF ]]; then + $WDIFF -t "Wdiff $DIR/$F" $WDIR/$DIR/$F- $F > $WDIR/$DIR/$F.wdiff.html + print " wdiffs\c" + fi + + sdiff_to_html $WDIR/$DIR/$F- $F > $WDIR/$DIR/$F.sdiff.html + print " sdiffs\c" + + if [[ $WEBREV_FRAMES == 'yes' ]]; then + print " frames\c" + fi + + rm -f $WDIR/$DIR/$F.cdiff $WDIR/$DIR/$F.udiff + + difflines $WDIR/$DIR/$F- $F > $WDIR/$DIR/$F.count + elif [ -f $F ]; then + # new file: count added lines + difflines /dev/null $F > $WDIR/$DIR/$F.count + elif [ -f $WDIR/$DIR/$F- ]; then + # old file: count deleted lines + difflines $WDIR/$DIR/$F- /dev/null > $WDIR/$DIR/$F.count + fi + + if [ -f $WDIR/$DIR/$F- ]; then + source_to_html Old $PF < $WDIR/$DIR/$F- > $WDIR/$DIR/$F-.html + rm -f $WDIR/$DIR/$F- + print " old\c" + fi + + if [ -f $F ]; then + source_to_html New $F < $F > $WDIR/$DIR/$F.html + print " new\c" + fi + + echo +done + +if [[ $WEBREV_FRAMES == 'yes' ]]; then + frame_navigation > $WDIR/ancnav.html +fi + +# Now build the index.html file that contains +# links to the source files and their diffs. + +cd $CWS + +# Save total changed lines for Code Inspection. +echo "$TOTL" > $WDIR/TotalChangedLines + +INDEXFILE=$WDIR/index.html +exec 3<&1 # duplicate stdout to FD3. +exec 1<&- # Close stdout. +exec > $INDEXFILE # Open stdout to index file. + +echo "<html>" +echo '<body bgcolor="#EEEEEE">' +echo "<title>${CWS##*/}</title>" +echo "<center><h1>${CWS##*/}</h1></center>" +echo "<p>" +echo "Parent workspace is $PWS <br>" +echo "Child workspace is $CWS <br>" +printCI $TOTL $TINS $TDEL $TCHG $TUNC +echo "<hr>" +echo "<code>" + +sed -e "s/#.*$//" -e "/=/d" -e "/^[ ]*$/d" $FLIST | + +# ... and read lines from the cleaned-up file list + +while read LINE +do + set - $LINE + P=$1 + + if [ $# = 2 ]; then + PP=$2 + OLDNAME=" <i>(was $PP)</i>" + else + PP=$P + OLDNAME="" + fi + + # Avoid processing the same file twice. + # It's possible for renamed files to + # appear twice in the file list + + F=$WDIR/$P + + # Group files in + # the same directory + + D=${F%/*} + if [ "$D" != "$PD" ]; then + echo "<p>" + else + echo "<br>" + fi + echo + echo + PD=$D + + # If there's a diffs file, make diffs links + + if [ -f $F.cdiff.html ]; then + echo "<a href=$P.cdiff.html>Cdiffs</a>" + echo "<a href=$P.udiff.html>Udiffs</a>" + + if [ -x $WDIFF ]; then + echo "<a href=$P.wdiff.html>Wdiffs</a>" + fi + + echo "<a href=$P.sdiff.html>Sdiffs</a>" + + if [[ $WEBREV_FRAMES == 'yes' ]]; then + print "<a href=\"$P.frames.html\">Frames</a>" + fi + else + echo "------ ------ ------" + + if [ -x $WDIFF ]; then + echo " ------" + fi + + if [[ $WEBREV_FRAMES == 'yes' ]]; then + print " ------" + fi + fi + + # If there's an old file, make the link + + if [ -f $F-.html ]; then + echo "<a href=$P-.html>Old</a>" + else + echo "---" + fi + + # If there's an new file, make the link + + if [ -f $F.html ]; then + echo "<a href=$P.html>New</a>" + else + echo "---" + fi + echo "<b>$P</b>$OLDNAME<p>" + + # Insert delta comments + + if [ "$WXFILE" ]; then + wxcomments $P + else + deltacomments $PP $P + fi + + # Add additional comments comment + + echo "<!-- Add comments to explain changes in $P here -->" + + # Add count of changes. + + if [ -f $F.count ]; then + echo "<blockquote>" + cat $F.count + echo "</blockquote>" + rm $F.count + fi +done + +echo "</code>" +echo +echo +echo "<P><HR><FONT SIZE=2>" +echo "This code review page prepared with <b>webrev</b> (vers $WEBREV_UPDATED) on `date`." +echo "</FONT>" +echo "</html>" + +exec 1<&- # Close FD 1. +exec 1<&3 # dup FD 3 to restore stdout. +exec 3<&- # close FD 3. + +print "\n$WDIR created." |