webrev.sh revision daaffb314aae330855b7faea7a653244767ed744
168N/A# The contents of this file are subject to the terms of the 168N/A# Common Development and Distribution License (the "License"). 168N/A# You may not use this file except in compliance with the License. 168N/A# See the License for the specific language governing permissions 168N/A# and limitations under the License. 168N/A# When distributing Covered Code, include this CDDL HEADER in each 168N/A# If applicable, add the following below this CDDL HEADER, with the 168N/A# fields enclosed by brackets "[]" replaced with your own identifying 168N/A# information: Portions Copyright [yyyy] [name of copyright owner] 5636N/A# ident "%Z%%M% %I% %E% SMI" 5680N/A# Copyright 2006 Sun Microsystems, Inc. All rights reserved. 6018N/A# Use is subject to license terms. 168N/A# This script takes a file list and a workspace and builds a set of html files 168N/A# suitable for doing a code review of source changes via a web page. 6407N/A# Documentation is available via the manual page, webrev.1, or just 586N/A# Acknowledgements to contributors to webrev are listed in the webrev(1) 6018N/A# The following variable is set to SCCS delta date 20YY/MM/DD. 1258N/A# Note this will have to be changed in 2100 or when SCCS has support for 168N/A# 4 digit years; whichever is the sooner! 168N/A<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 168N/A<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" 168N/ASTDHEAD=
'<meta http-equiv="cache-control" content="no-cache" /> 5636N/A<meta http-equiv="Pragma" content="no-cache" /> 5636N/A<meta http-equiv="Expires" content="-1" /> 1589N/A Note to customizers: the body of the webrev is IDed as SUNWwebrev 6018N/A mechanism available in some browsers. 6018N/A For example, to have all "removed" information be red instead of 6018N/A border-top: 1px solid #aaa; 1589N/A border-bottom: 1px solid #aaa; 4867N/Aa:hover { background-color: #ffcc99; } 6018N/Apre { font-size: 0.8em; font-family: courier, monospace; } 3817N/Ahr { border: none 0; border-top: 1px solid #aaa; height: 1px; } 6018N/A# UDiffs need a slightly different CSS rule for 'new' items (we don't 3817N/A# want them to be bolded as we do in cdiffs or sdiffs). 3817N/A# input_cmd | html_quote | output_cmd # html_quote filename | output_cmd # Make a piece of source code safe for display in an HTML <pre> block. sed -e "s/&/\&/g" -e "s/</\</g" -e "s/>/\>/g" "$@" | expand # input_cmd | bug2url | output_cmd # Scan for bugids and insert <a> links to the relevent bug database. sed -e 's|[0-9]\{5,\}|<a href=\"'$BUGURL'&\">&</a>|g' # input_cmd | sac2url | output_cmd # Scan for ARC cases and insert <a> links to the relevent SAC database. # This is slightly complicated because inside the SWAN, SAC cases are # referenced as 2006/123 (without labelling the ARC). sed -e 's|\([A-Z]\{1,2\}ARC\)[ /]\([0-9]\{4\}\)/\([0-9]\{3\}\)|<a href=\"'$SACURL'\1/\2/\3\">\1 \2/\3</a>|g' sed -e 's|\([A-Z]\{1,2\}ARC\)[ /]\([0-9]\{4\}\)/\([0-9]\{3\}\)|<a href=\"'$SACURL'/\2/\3\">\1 \2/\3</a>|g' # strip_unchanged <infile> | output_cmd # 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 a 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 "<span class=" # string embedded (unchanged lines have no particular class and are not # part of a <span>). Blank lines (without a sequence number) are also # detected since they flag lines that have been inserted or deleted. NF == 0 || /span class=/ { print "\n</pre><hr /><pre>" END { if (c > (C * 2)) print "\n</pre><hr />" } # 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. It also # takes a delta comment, rendered as an HTML snippet, as the third # argument. The function takes two files as arguments, then the name of # file, the path, and the comment. The HTML will be delivered on stdout, # 1234567</a> my bugid' > <file>.html # 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 changed lines are ignored - we're interested in # the editing codes, e.g. # 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>%4d %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 # 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. # Now we have the diffs, generate the HTML for the old file. printf "function sp(n) {for (i=0;i<n;i++)printf \"\\n\"}\n" printf "function removed() " printf "{printf \"<span class=\\\"removed\\\">%%4d %%s</span>\\n\", NR, $0}\n" printf "function changed() " printf "{printf \"<span class=\\\"changed\\\">%%4d %%s</span>\\n\", NR, $0}\n" printf "function bl() {printf \"%%4d %%s\\n\", NR, $0}\n" printf "BEGIN\t\t{sp(1)}\n" printf "BEGIN\t\t{sp(%d)}\n",\ printf "NR==%s\t\t{", a[1] printf "bl();printf \"\\n\"; next}\n" printf "bl();sp(%d);next}\n",\ printf "NR==%s\t\t{removed(); next}\n" , n1 printf "NR==%s,NR==%s\t{removed(); next}\n" , n1, n2 printf "NR==%s\t\t{changed();" , n1 printf "NR==%s,NR==%s\t{changed();" , n1, n2 if (n > 1) printf "if (NR==%d)", final printf "sp(%d);", d2 - d1 END { printf "{printf \"%%4d %%s\\n\", NR, $0 }\n" } # Now generate the HTML for the new file printf "function sp(n) {for (i=0;i<n;i++)printf \"\\n\"}\n" printf "{printf \"<span class=\\\"new\\\">%%4d %%s</span>\\n\", NR, $0}\n" printf "function changed() " printf "{printf \"<span class=\\\"changed\\\">%%4d %%s</span>\\n\", NR, $0}\n" printf "function bl() {printf \"%%4d %%s\\n\", NR, $0}\n" printf "BEGIN\t\t{sp(1)}\n" printf "BEGIN\t\t{sp(%d)}\n",\ printf "NR==%s\t\t{", a[2] printf "bl();printf \"\\n\"; next}\n" printf "bl();sp(%d);next}\n",\ printf "NR==%s\t\t{new() ; next}\n" , n1 printf "NR==%s,NR==%s\t{new() ; next}\n" , n1, n2 printf "NR==%s\t\t{changed();" , n1 printf "NR==%s,NR==%s\t{changed();" , n1, n2 if (n > 1) printf "if (NR==%d)", final printf "sp(%d);", d1 - d2 END { printf "{printf \"%%4d %%s\\n\", NR, $0 }\n" } # Post-process the HTML files by running them back through nawk # Now combine into a valid HTML file and side-by-side into a table print "</head><body id=\"SUNWwebrev\">" print "<a class=\"print\" href=\"javascript:print()\">Print this page</a>" print "<table><tr valign=\"top\">" print "</pre></td><td><pre>" # framed_sdiff <filename> <filepath> <lhsfile> <rhsfile> <comment> # Expects lefthand and righthand side html files created by sdiff_to_html. # We use insert_anchors() to augment those with HTML navigation anchors, # and then emit the main frame. Content is placed into: # NOTE: We rely on standard usage of $WDIR and $DIR. # Enable html files to access WDIR via a relative path. # Make the rhs/lhs files and output the frameset file. <script type="text/javascript" src="$RTOP/ancnav.js" /> <body id="SUNWwebrev" onkeypress="keypress(event);"> <pre>$comments</pre><hr /> cp $WDIR/$DIR/$TNAME.lhs.html $WDIR/$DIR/$TNAME.rhs.html insert_anchors $lhsfile >> $WDIR/$DIR/$TNAME.lhs.html insert_anchors $rhsfile >> $WDIR/$DIR/$TNAME.rhs.html print $close >> $WDIR/$DIR/$TNAME.lhs.html print $close >> $WDIR/$DIR/$TNAME.rhs.html print "$FRAMEHTML<head>$STDHEAD" > $WDIR/$DIR/$TNAME.frames.html print "<title>$WNAME Framed-Sdiff " \ "$TPATH/$TNAME</title> </head>" >> $WDIR/$DIR/$TNAME.frames.html cat >> $WDIR/$DIR/$TNAME.frames.html <<-EOF <frameset cols="50%,50%"> <frame src="$TNAME.lhs.html" scrolling="auto" name="lhs" /> <frame src="$TNAME.rhs.html" scrolling="auto" name="rhs" /> <frame src="$RTOP/ancnav.html" scrolling="no" marginwidth="0" marginheight="0" name="nav" /> Alas 'frames' webrev requires that your browser supports frames and has the feature enabled. # Merge codereview output files to a single conforming postscript file, by: # - removing all extraneous headers/trailers # - making the page numbers right # - removing pages devoid of contents which confuse some cat > /tmp/$$.crmerge.pl << \EOF print scalar(<>); # %!PS-Adobe--- print "%%Orientation: Landscape\n"; next if (/^%%Pages:\s*\d+/); if ($pno == 0 || $page =~ /\)S/) { # Header or single page containing text print "%%Page: ? $pno\n" if ($pno > 0); # Skip from %%Trailer of one document to Endprolog $doprint = 0 if (/^%%Trailer/); $page .= $_ if ($doprint); print "%%Page: ? $pno\n"; print "%%Trailer\n%%Pages: $pno\n"; # input_cmd | insert_anchors | output_cmd # Flag blocks of difference with sequentially numbered invisible # anchors. These are used to drive the frames version of the # 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 "<span # class=" string embedded (unchanged lines have no class set and are # not part of a <span>. Blank lines (without a sequence number) # are also detected since they flag lines that have been inserted or # This should be able to be a singleton <a /> but that # seems to trigger a bug in firefox a:hover rule processing printf "<a name=\"%d\" id=\"anc%d\"></a>", anc, anc++; NF == 0 || /^<span class=/ { printf "<b style=\"font-size: large; color: red\">"; for(i=0;i<8;i++) printf "\n\n\n\n\n\n\n\n\n\n"; printf "<form name=\"eof\">"; printf "<input name=\"value\" value=\"%d\" type=\"hidden\" />", # Print a relative return path from $1 to $2. For example if # this function would print "../../../../". # In the event that $1 is not in $2 a warning is printed to stderr, # and $2 is returned-- the result of this is that the resulting webrev typeset cur="${1##$2?(/)}" if [[ $2 == $cur ]]; then # Should never happen. print -u2 "\nWarning: relative_dir: \"$1\" not relative " print -u2 "to \"$2\". Check input paths. Framed webrev " print -u2 "will not be relocatable!" # Emit javascript for frame navigation // on each side, so we pluck from the left. // this must be: val >= maxval myInt=setInterval("scrollByPix()",10); function handlePress(b) { scrollToAnc(getAncValue() - 1); scrollToAnc(getAncValue() + 1); function handleRelease(b) { } else if (keychar == "j" || keychar == " ") { function ValidateDiffNum(){ # Output anchor navigation file for framed sdiffs. function frame_navigation print "$HTML<head>$STDHEAD" <title>Anchor Navigation</title> <meta http-equiv="Content-Type" content="text/html"> div.button td { padding-left: 5px; padding-right: 5px; background-color: #eee; text-align: center; border: 1px #444 outset; cursor: pointer; } onkeypress="keypress(event);"> <noscript lang="javascript"> <p><big>Framed Navigation controls require Javascript</big><br /> Either this browser is incompatable or javascript is not enabled</p> <table width="100%" border="0" align="center"> <td valign="middle" width="25%">Diff navigation: Use 'j' and 'k' for next and previous diffs; or use buttons <td align="center" valign="top" width="50%"> <table border="0" align="center"> <a onMouseDown="handlePress(1);return true;" onMouseUp="handleRelease(1);return true;" onMouseOut="handleRelease(1);return true;" title="Go to Beginning Of file">BOF</a></td> <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 Up</a></td> <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> <a onMouseDown="handlePress(6);return true;" onMouseUp="handleRelease(6);return true;" onMouseOut="handleRelease(6);return true;" title="Go to End Of File">EOF</a></td> <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 Down</a></td> <a onMouseDown="handlePress(5);return true;" onMouseUp="handleRelease(5);return true;" onMouseOut="handleRelease(5);return true;" onClick="return false;">Next Diff</a></td> <th valign="middle" width="25%"> <form action="" name="diff" onsubmit="return ValidateDiffNum();"> <input name="display" value="BOF" size="8" type="text" /> <input name="real" value="0" size="8" type="hidden" /> # diff_to_html <filename> <filepath> { U | C } <comment> # Processes the output of diff to produce an HTML file representing either # context or unified diffs. print "$HTML<head>$STDHEAD" print "<title>$WNAME ${DIFFTYPE}diff $TPATH</title>" if [[ $DIFFTYPE == "U" ]]; then <a class="print" href="javascript:print()">Print this page</a> /^-------/ { printf "<center><h1>%s</h1></center>\n", $0; next } /^\@\@.*\@\@$/ { printf "</pre><hr /><pre>\n"; printf "<span class=\"newmarker\">%s</span>\n", $0; /^\*\*\*/ { printf "<hr /><span class=\"oldmarker\">%s</span>\n", $0; /^---/ { printf "<span class=\"newmarker\">%s</span>\n", $0; /^\+/ {printf "<span class=\"new\">%s</span>\n", $0; next} /^!/ {printf "<span class=\"changed\">%s</span>\n", $0; next} /^-/ {printf "<span class=\"removed\">%s</span>\n", $0; next} print "</pre></body></html>\n" # source_to_html { new | old } <filename> # Process a plain vanilla source file to transform it into an HTML file. print "$HTML<head>$STDHEAD" print "<title>$WHICH $TNAME</title>" print "<body id=\"SUNWwebrev\">" print "</pre></body></html>" # teamwarecomments {text|html} parent-file child-file # 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 /^COMMENTS:/ {p=1; continue} /^D [0-9]+\.[0-9]+/ {printf "--- %s ---\n", $2; p=0; } {if (p==0) continue; print $0 }' sid1=${sids[$((N-2))]} # Gets 2nd to last sid if [[ $fmt == "text" ]]; then # wxcomments {text|html} filepath # Given the pathname of a file, find its location in a "wx" active file # list and print the following sccs comment. Output is either text or # HTML; if the latter, embedded bugids (sequence of 5 or more digits) are do getline ; while (NF > 0) while (NF > 0) { print ; getline } if [[ $fmt == "text" ]]; then # getcomments {text|html} filepath parentpath # Fetch the comments depending on what SCM mode we're in. # printCI <total-changed> <inserted> <deleted> <modified> <unchanged> # Print out Code Inspection figures similar to sccs-prt(1) format. printf '%d %s changed: %d ins; %d del; %d mod; %d unchg\n' \ # difflines <oldfile> <newfile> # Calculate and emit number of added, removed, modified and unchanged lines, # and total lines changed, the sum of added + removed + modified. # Change range of lines: N,Nc n=split(substr($1,1,length($1)-1), counts, ","); # 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 != /^\.$/) { # 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 there were more original lines than replacement lines, then # r will be positive; in this case, increment d by that much. # The first line is a replacement; any more are additions. while (getline != /^\.$/) a++; # Add lines: both Na and N,Na while (getline != /^\.$/) a++; # Delete range of lines: N,Nd n=split(substr($1,1,length($1)-1), counts, ","); # 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; # Delete line: Nd. For example 10d says line 10 is deleted. # Finish off - print results printf("tot=%d;mod=%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 # Calculate unchanged lines print "<span class=\"lineschanged\">" # Sets up webrev to source its information from a wx-formatted file. # Sets the global 'wxfile' variable. # If the wx file pathname is relative then make it absolute # because the webrev does a "cd" later on. if (NF == 0) { c = -c; continue } # flist_from_teamware [ <args-to-putback-n> ] # 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. "valid teamware workspace" print " File list from: 'putback -n $parent_args $*' ... \c" /^update:|^create:/ {print $2} /^Parent workspace:/ {printf("CODEMGR_PARENT=%s\n",$3)} /^Child workspace:/ {printf("CODEMGR_WS=%s\n",$3)} /^The following files are currently checked out/ {p = 1; continue} $1 == "to:" {print $2, old} # Use "eval" to set env variables that are listed in the file # list. Then copy those into our local versions of those # variables if they have not been set already. # Check to see if CODEMGR_PARENT is set in the flist file. # We dynamically test the SCM type; this allows future extensions to # If CODEMGR_WS is specified in the flist file, we assume teamware. # The presence of $CODEMGR_WS and a Codemgr_wsdata directory # is our clue that this is a teamware workspace. print 'Usage:\twebrev [common-options] webrev [common-options] ( <file> | - ) webrev [common-options] -w <wx file> webrev [common-options] -l [arguments to 'putback'] -O: Print bugids/arc cases suitable for OpenSolaris. -i <filename>: Include <filename> in the index.html file. -o <outdir>: Output webrev to specified directory. -p <compare-against>: Use specified parent wkspc or basis for comparison -w <wxfile>: Use specified wx active file. WDIR: Control the output directory. WEBREV_BUGURL: Control the URL prefix for bugids. WEBREV_SACURL: Control the URL prefix for ARC cases. Teamware: CODEMGR_WS: Workspace location. Teamware: CODEMGR_PARENT: Parent workspace location. # Main program starts here trap "rm -f /tmp/$$.* ; exit" 0 1 2 3 15 print -u2 "Warning: wdiff not found!" # Declare global total counters. while getopts "i:o:p:lwO" opt # If -l has been specified, we need to abort further options # processing, because subsequent arguments are going to be # arguments to 'putback -n'. # If this manually set as the parent, and it appears to be an earlier webrev, # then note that fact and set the parent to the raw_files/new subdirectory. print -u2 "$1: no such file or not readable" # Before we go on to further consider -l and -w, work out which SCM we think print -u2 "Unable to determine SCM type currently in use." print -u2 "For teamware: webrev looks for \$CODEMGR_WS either in" print -u2 " the environment or in the file list." # 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 # If the -w 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 [[ -z $wxfile ]] && print -u2 "wx file not specified, and could not " \ "be auto-detected (check \$CODEMGR_WS)" && exit 1 print -u2 " File list from: wx 'active' file '$wxfile' ... \c" print -u2 "Warning: unused arguments: $*" # Parent (internally $codemgr_parent) and workspace ($codemgr_ws) can # be set in a number of ways, in decreasing precedence: # 1) on the command line (only for the parent) # 2) in the user environment # 4) automatically based on the workspace (only for the parent) # Here is case (2): the user environment # If we're in auto-detect mode and we haven't already gotten the file # list, then see if we can get it by probing for wx. print -u2 "Warning: wx not found!" # We need to use wx list -w so that we get renamed files, etc. # but only if a wx active file exists-- otherwise wx will # hang asking us to initialize our wx information. print -u2 " File list from: 'wx list -w' ... \c" # If by hook or by crook we've gotten a file list by now (perhaps # from the command line), eval it to extract environment variables from # Continuing step (3): If we still have no file list, we'll try to get # Observe true directory name of CODEMGR_WS, as used later in # (4) If we still don't have a value for codemgr_parent, get it # Reset CODEMGR_WS to make sure teamware commands are happy. # If the user didn't specify a -i option, check to see if there is a # webrev-info file in the workspace directory. # $INCLUDE_FILE may be a relative path, and the script alters # PWD, so we just stash a copy in /tmp. # Name of the webrev, derived from the workspace name; in the # future this could potentially be an option. if [[ ! -d $WDIR ]]; then # Summarize what we're going to do. print "Compare against: $PWS" print " Output to: $WDIR" # Save the file list in the webrev dir # Bug IDs will be replaced by a URL. Order of precedence # is: default location, $WEBREV_BUGURL, the -O flag. # Likewise, ARC cases will be replaced by a URL. Order of precedence # is: default, $WEBREV_SACURL, the -O flag. # Note that -O also triggers different substitution behavior for # Clean up the file list: Remove comments, blank lines and env variables. # First pass through the files: generate the per-file webrev HTML-files. # 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. PDIR="." # File at root of workspace if [[ $DIR == $P ]]; then DIR="." # File at root of workspace if [[ "$DIR" == "$P" ]]; then DIR="." # File at root of workspace # Make the webrev mirror directory if necessary # cd to the directory so the names are short # If we're in OpenSolaris mode, we enforce a minor policy: # help to make sure the reviewer doesn't accidentally publish print "*** Omitting closed source for OpenSolaris" \ # We stash old and new files into parallel directories in /tmp # and do our diffs there. This makes it possible to generate # clean looking diffs which don't have absolute paths present. # If the child's version doesn't exist then if [[ ! -f $F && -f SCCS/s.$F ]]; then # Snag new version of file. # 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 SCCS/p.$F ]; then # Parent is not a real workspace, but just a raw # directory tree - use the file that's there as print "*** Error: file not in parent or child" if [[ $? == 0 && $rename == 1 ]]; then # If we have old and new versions of the file then run the appropriate # diffs. This is complicated by a couple of factors: # - renames must be handled specially: we emit a 'remove' # - new files and deleted files must be handled specially # - Solaris patch(1m) can't cope with file creation # (and hence renames) as of this writing. # - To make matters worse, gnu patch doesn't interpret the # output of Solaris diff properly when it comes to # adds and deletes. We need to do some "cleansing" # [to add a file] @@ -1,0 +X,Y @@ --> @@ -0,0 +X,Y @@ # [to del a file] @@ -X,Y +1,0 @@ --> @@ -X,Y +0,0 @@ # Tack the patch we just made onto the accumulated patch for the # renamed file: may also have differences # new file: count added lines # old file: count deleted lines # Now we generate the postscript for this file. We generate diffs # only in the event that there is delta, or the file is new (it seems # tree-killing to print out the contents of deleted files). print " ${B}Generating PDF: ${NB}\c" # links to the source files and their diffs. # Save total changed lines for Code Inspection. exec 3<&1 # duplicate stdout to FD3. exec 1<&- # Close stdout. print "<body id=\"SUNWwebrev\">" print "<div class=\"summary\">" print "<h2>Code Review for $WNAME</h2>" # Figure out the username and gcos name. To maintain compatibility # with passwd(4), we must support '&' substitutions. print "<tr><th>Prepared by:</th>" print "<tr><th>Workspace:</th><td>$CWS</td></tr>" print "<tr><th>Compare against:</th><td>" print "<tr><th>Summary of changes:</th><td>" print "<tr><th>Patch of changes:</th><td>" print "<tr><th>Printable review:</th><td>" print "<tr><th>Author comments:</th><td><div>" # Second pass through the files: generate the rest of the index file if [[ $DIR == $P ]]; then DIR="." # File at root of workspace # Avoid processing the same file twice. # It's possible for renamed files to # appear twice in the file list # If there's a diffs file, make diffs links print " ------ ------ ------" # If there's an old file, make the link print "<a href=\"$P-.html\">Old</a>" # If there's an new file, make the link print "<a href=\"$P.html\">New</a>" print "<a href=\"$P.patch\">Patch</a>" print " <i>Closed source: omitted from" \ print "<blockquote><pre>" # Add additional comments comment print "<!-- Add comments to explain changes in $P here -->" print "<p style=\"font-size: small\">" print "This code review page was prepared using <b>$0</b>" print "OpenSolaris</a> project. The latest version may be obtained" exec 1<&3 # dup FD 3 to restore stdout.