#!/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
 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  ... .
#	   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 
 block.
#
html_quote()
{
	sed -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 "
\n" }
#      function sp(n) {for (i=0;i%3d %s \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%%3d %%s \\n\", n, NR, $0}\n"
	printf "function bl() {printf \"%%3d %%s\\n\", NR, $0}\n"
}
/^/	{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%%3d %%s \\n\", n, NR, $0}\n"
	printf "function wlb(n) {printf \"%%3d %%s\\n\", n, NR, $0}\n"
	printf "function bl() {printf \"%%3d %%s\\n\", NR, $0}\n"
}
/^/	{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 ""
echo " Sdiff $TNAME "
echo ""
echo ""
echo "
"

strip_unchanged /tmp/$$.file1.html

echo "
"

strip_unchanged /tmp/$$.file2.html

echo "
" 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 Framed Sdiff for $TNAME <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> 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
" 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
" } ' $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 "\n
'

nawk '
function ia() {
	printf "", anc++;
}
BEGIN {
	anc=0;
	inblock=1;
	ia();
}
NF == 0 || /^--- EOF ---";
	for(i=0;i<8;i++) printf "\n\n\n\n\n\n\n\n\n\n";
}
' $1

print '
\n' } #################################### 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 Anchor Navigation
Diff navigation:
EOF } #################################### diff_to_html() { TNAME=$1 DIFFTYPE=$2 html_quote | nawk ' BEGIN {printf "'$DIFFTYPE'diff '$TNAME'
\n"}
/^-------/	{ printf "

%s

\n", $0; next } /^\*\*\*\*/ { printf "
\n"; next} /^\*\*\*/ { printf "%s\n", $0 ; next} /^---/ { printf "%s\n", $0 ; next} /^\+/ {printf "%s\n", $0; next} /^!/ {printf "%s\n", $0; next} /^-/ {printf "%s\n", $0; next} {printf "%s\n", $0; next} END {printf "
\n"} ' } #################################### source_to_html() { WHICH=$1 TNAME=$2 html_quote | nawk ' BEGIN {printf "'"$WHICH $TNAME"'
\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 "
    " sccs prs -l -r$sid1 $cfile 2>/dev/null | html_quote | sed -e 's|[0-9]\{5,\}|&|g' \ -e 's|\([A-Z]\{1,2\}ARC\)[ /]\([0-9]\{4\}/[0-9]\{3\}\)|\1 \2|g'| nawk '/^COMMENTS:/ {p=1; printf "
  • "; continue} NF == 0 { continue } /^D / {p=0} {if (p==0) continue; print $0 "
    "}' echo "
" 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 "
"
	nawk '
	$1 == "'$1'" {
		do getline ; while (NF > 0)
		getline
		while (NF > 0) { print ; getline }
		exit
	}' < $WXFILE | html_quote |
	sed -e 's|[0-9]\{5,\}|&|g' \
	    -e 's|\([A-Z]\{1,2\}ARC\)[ /]\([0-9]\{4\}/[0-9]\{3\}\)|\1 \2|g'
	echo "
" } ##################################### # 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 " echo " webrev -" echo " webrev -w []" 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 "" echo '' echo "${CWS##*/}" echo "

${CWS##*/}

" echo "

" echo "Parent workspace is $PWS
" echo "Child workspace is $CWS
" printCI $TOTL $TINS $TDEL $TCHG $TUNC echo "


" echo "" 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=" (was $PP)" 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 "

" else echo "
" fi echo echo PD=$D # If there's a diffs file, make diffs links if [ -f $F.cdiff.html ]; then echo "Cdiffs" echo "Udiffs" if [ -x $WDIFF ]; then echo "Wdiffs" fi echo "Sdiffs" if [[ $WEBREV_FRAMES == 'yes' ]]; then print "Frames" 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 "Old" else echo "---" fi # If there's an new file, make the link if [ -f $F.html ]; then echo "New" else echo "---" fi echo "$P$OLDNAME

" # Insert delta comments if [ "$WXFILE" ]; then wxcomments $P else deltacomments $PP $P fi # Add additional comments comment echo "" # Add count of changes. if [ -f $F.count ]; then echo "

" cat $F.count echo "
" rm $F.count fi done echo "
" echo echo echo "


" echo "This code review page prepared with webrev (vers $WEBREV_UPDATED) on `date`." echo "" echo "" exec 1<&- # Close FD 1. exec 1<&3 # dup FD 3 to restore stdout. exec 3<&- # close FD 3. print "\n$WDIR created."