312N/A# The contents of this file are subject to the terms of the 312N/A# Common Development and Distribution License (the "License"). 312N/A# You may not use this file except in compliance with the License. 312N/A# See the License for the specific language governing permissions 312N/A# and limitations under the License. 312N/A# When distributing Covered Code, include this CDDL HEADER in each 312N/A# If applicable, add the following below this CDDL HEADER, with the 312N/A# fields enclosed by brackets "[]" replaced with your own identifying 312N/A# information: Portions Copyright [yyyy] [name of copyright owner] 607N/A# Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. 312N/A# Use is subject to license terms. 312N/A# This script takes a file list and a workspace and builds a set of html files 312N/A# suitable for doing a code review of source changes via a web page. 312N/A# Documentation is available via 'webrev -h'. 312N/A<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 312N/A<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" 312N/ASTDHEAD=
'<meta http-equiv="cache-control" content="no-cache" /> 312N/A<meta http-equiv="Pragma" content="no-cache" /> 312N/A<meta http-equiv="Expires" content="-1" /> 312N/A Note to customizers: the body of the webrev is IDed as SUNWwebrev 312N/A mechanism available in some browsers. 312N/A For example, to have all "removed" information be red instead of 312N/A background-color: #eeeeee; 312N/A border-top: 1px solid #aaa; 312N/A border-bottom: 1px solid #aaa; 312N/Apre { font-size: 0.8em; font-family: courier, monospace; } 312N/Ahr { border: none 0; border-top: 1px solid #aaa; height: 1px; } 312N/A# UDiffs need a slightly different CSS rule for 'new' items (we don't 312N/A# want them to be bolded as we do in cdiffs or sdiffs). 312N/A# input_cmd | html_quote | output_cmd 312N/A# html_quote filename | output_cmd 312N/A# Make a piece of source code safe for display in an HTML <pre> block. 312N/A sed -e "s/&/\&/g" -e "s/</\</g" -e "s/>/\>/g" "$@" | expand 312N/A# input_cmd | bug2url | output_cmd 312N/A# Scan for bugids and insert <a> links to the relevent bug database. 312N/A# input_cmd | sac2url | output_cmd 312N/A# Scan for ARC cases and insert <a> links to the relevent SAC database. 312N/A# This is slightly complicated because inside the SWAN, SAC cases are 312N/A# referenced as 2006/123 (without labelling the ARC). 312N/A 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' 312N/A sed -e 's|\([A-Z]\{1,2\}ARC\)[ /]\([0-9]\{4\}\)/\([0-9]\{3\}\)|<a href=\"'$SACURL'/\2/\3\">\1 \2/\3</a>|g' 312N/A# strip_unchanged <infile> | output_cmd 312N/A# Removes chunks of sdiff documents that have not changed. This makes it 312N/A# easier for a code reviewer to find the bits that have changed. 312N/A# Deleted lines of text are replaced by a horizontal rule. Some 312N/A# identical lines are retained before and after the changed lines to 312N/A# provide some context. The number of these lines is controlled by the 312N/A# variable C in the $AWK script below. 312N/A# The script detects changed lines as any line that has a "<span class=" 312N/A# string embedded (unchanged lines have no particular class and are not 312N/A# part of a <span>). Blank lines (without a sequence number) are also 312N/A# detected since they flag lines that have been inserted or deleted. 312N/A NF == 0 || /span class=/ { 312N/A print "\n</pre><hr></hr><pre>" 312N/A for (i = 0; i < c; i++) 312N/A print ln[(inx + i) % C] 312N/A END { if (c > (C * 2)) print "\n</pre><hr></hr>" } 312N/A# This function takes two files as arguments, obtains their diff, and 312N/A# processes the diff output to present the files as an HTML document with 312N/A# the files displayed side-by-side, differences shown in color. It also 312N/A# takes a delta comment, rendered as an HTML snippet, as the third 312N/A# argument. The function takes two files as arguments, then the name of 312N/A# file, the path, and the comment. The HTML will be delivered on stdout, 607N/A# JDK-1234567</a> my bugid' > <file>.html 312N/A# FYI: This function is rather unusual in its use of awk. The initial 312N/A# diff run produces conventional diff output showing changed lines mixed 312N/A# with editing codes. The changed lines are ignored - we're interested in 312N/A# These editing codes are parsed by the awk script and used to generate 312N/A# another awk script that generates HTML, e.g the above lines would turn 312N/A# into something like this: 312N/A# BEGIN { printf "<pre>\n" } 312N/A# function sp(n) {for (i=0;i<n;i++)printf "\n"} 312N/A# function wl(n) {printf "<font color=%s>%4d %s </font>\n", n, NR, $0} 312N/A# NR==8 {wl("#7A7ADD");next} 312N/A# NR==54 {wl("#7A7ADD");sp(3);next} 312N/A# NR==56 {wl("#7A7ADD");next} 312N/A# NR==57 {wl("black");printf "\n"; next} 312N/A# This script is then run on the original source file to generate the 312N/A# HTML that corresponds to the source file. 312N/A# The two HTML files are then combined into a single piece of HTML that 312N/A# uses an HTML table construct to present the files side by side. You'll 312N/A# notice that the changes are color-coded: 312N/A# black - unchanged lines 312N/A# Blank lines are inserted in each file to keep unchanged lines in sync 312N/A# (side-by-side). This format is familiar to users of sdiff(1) or 312N/A# Teamware's filemerge tool. 312N/A # Now we have the diffs, generate the HTML for the old file. 312N/A printf "function sp(n) {for (i=0;i<n;i++)printf \"\\n\"}\n" 312N/A printf "function removed() " 312N/A printf "{printf \"<span class=\\\"removed\\\">%%4d %%s</span>\\n\", NR, $0}\n" 312N/A printf "function changed() " 312N/A printf "{printf \"<span class=\\\"changed\\\">%%4d %%s</span>\\n\", NR, $0}\n" 312N/A printf "function bl() {printf \"%%4d %%s\\n\", NR, $0}\n" 312N/A split($1, a, /[cad]/) ; 312N/A n = split(a[2], r, /,/); 312N/A printf "BEGIN\t\t{sp(1)}\n" 312N/A printf "BEGIN\t\t{sp(%d)}\n",\ 312N/A printf "NR==%s\t\t{", a[1] 312N/A n = split(a[2], r, /,/); 312N/A printf "bl();printf \"\\n\"; next}\n" 312N/A printf "bl();sp(%d);next}\n",\ 312N/A n = split(a[1], r, /,/); 312N/A printf "NR==%s\t\t{removed(); next}\n" , n1 312N/A printf "NR==%s,NR==%s\t{removed(); next}\n" , n1, n2 312N/A n = split(a[1], r, /,/); 312N/A printf "NR==%s\t\t{changed();" , n1 312N/A printf "NR==%s,NR==%s\t{changed();" , n1, n2 312N/A m = split(a[2], r, /,/); 312N/A if (n > 1) printf "if (NR==%d)", final 312N/A printf "sp(%d);", d2 - d1 312N/A END { printf "{printf \"%%4d %%s\\n\", NR, $0 }\n" } 312N/A # Now generate the HTML for the new file 312N/A printf "function sp(n) {for (i=0;i<n;i++)printf \"\\n\"}\n" 312N/A printf "function new() " 312N/A printf "{printf \"<span class=\\\"new\\\">%%4d %%s</span>\\n\", NR, $0}\n" 312N/A printf "function changed() " 312N/A printf "{printf \"<span class=\\\"changed\\\">%%4d %%s</span>\\n\", NR, $0}\n" 312N/A printf "function bl() {printf \"%%4d %%s\\n\", NR, $0}\n" 312N/A split($1, a, /[cad]/) ; 312N/A n = split(a[1], r, /,/); 312N/A printf "BEGIN\t\t{sp(1)}\n" 312N/A printf "BEGIN\t\t{sp(%d)}\n",\ 312N/A printf "NR==%s\t\t{", a[2] 312N/A n = split(a[1], r, /,/); 312N/A printf "bl();printf \"\\n\"; next}\n" 312N/A printf "bl();sp(%d);next}\n",\ 312N/A n = split(a[2], r, /,/); 312N/A printf "NR==%s\t\t{new() ; next}\n" , n1 312N/A printf "NR==%s,NR==%s\t{new() ; next}\n" , n1, n2 312N/A n = split(a[2], r, /,/); 312N/A printf "NR==%s\t\t{changed();" , n1 312N/A printf "NR==%s,NR==%s\t{changed();" , n1, n2 312N/A m = split(a[1], r, /,/); 312N/A if (n > 1) printf "if (NR==%d)", final 312N/A printf "sp(%d);", d1 - d2 312N/A END { printf "{printf \"%%4d %%s\\n\", NR, $0 }\n" } 312N/A # Post-process the HTML files by running them back through $AWK 312N/A # Now combine into a valid HTML file and side-by-side into a table 312N/A print "</head><body id=\"SUNWwebrev\">" 312N/A print "<a class=\"print\" href=\"javascript:print()\">Print this page</a>" 312N/A print "<table><tr valign=\"top\">" 312N/A print "</pre></td><td><pre>" 312N/A# framed_sdiff <filename> <filepath> <lhsfile> <rhsfile> <comment> 312N/A# Expects lefthand and righthand side html files created by sdiff_to_html. 312N/A# We use insert_anchors() to augment those with HTML navigation anchors, 312N/A# and then emit the main frame. Content is placed into: 312N/A# NOTE: We rely on standard usage of $WDIR and $DIR. 312N/A # Enable html files to access WDIR via a relative path. 312N/A # Make the rhs/lhs files and output the frameset file. 312N/A <script type="text/javascript" src="$RTOP/ancnav.js"></script> 312N/A <body id="SUNWwebrev" onkeypress="keypress(event);"> 312N/A <pre>$comments</pre><hr></hr> 312N/A cp $WDIR/$DIR/$TNAME.lhs.html $WDIR/$DIR/$TNAME.rhs.html 312N/A insert_anchors $lhsfile >> $WDIR/$DIR/$TNAME.lhs.html 312N/A insert_anchors $rhsfile >> $WDIR/$DIR/$TNAME.rhs.html 312N/A print $close >> $WDIR/$DIR/$TNAME.lhs.html 312N/A print $close >> $WDIR/$DIR/$TNAME.rhs.html 312N/A print "$FRAMEHTML<head>$STDHEAD" > $WDIR/$DIR/$TNAME.frames.html 312N/A print "<title>$WNAME Framed-Sdiff " \ 312N/A "$TPATH/$TNAME</title> </head>" >> $WDIR/$DIR/$TNAME.frames.html 312N/A cat >> $WDIR/$DIR/$TNAME.frames.html <<-EOF 312N/A <frameset cols="50%,50%"> 312N/A <frame src="$TNAME.lhs.html" scrolling="auto" name="lhs" /> 312N/A <frame src="$TNAME.rhs.html" scrolling="auto" name="rhs" /> 312N/A <frame src="$RTOP/ancnav.html" scrolling="no" marginwidth="0" 312N/A marginheight="0" name="nav" /> 312N/A Alas 'frames' webrev requires that your browser supports frames 312N/A and has the feature enabled. 312N/A# Merge codereview output files to a single conforming postscript file, by: 312N/A# - removing all extraneous headers/trailers 312N/A# - making the page numbers right 312N/A# - removing pages devoid of contents which confuse some 312N/A cat > /tmp/$$.crmerge.pl << \EOF 312N/A print scalar(<>); # %!PS-Adobe--- 312N/A print "%%Orientation: Landscape\n"; 312N/A next if (/^%%Pages:\s*\d+/); 312N/A if ($pno == 0 || $page =~ /\)S/) { 312N/A # Header or single page containing text 312N/A print "%%Page: ? $pno\n" if ($pno > 0); 312N/A # Skip from %%Trailer of one document to Endprolog 312N/A $doprint = 0 if (/^%%Trailer/); 312N/A $page .= $_ if ($doprint); 312N/A print "%%Page: ? $pno\n"; 312N/A print "%%Trailer\n%%Pages: $pno\n"; 312N/A# input_cmd | insert_anchors | output_cmd 312N/A# Flag blocks of difference with sequentially numbered invisible 312N/A# anchors. These are used to drive the frames version of the 312N/A# NOTE: Anchor zero flags the top of the file irrespective of changes, 312N/A# an additional anchor is also appended to flag the bottom. 312N/A# The script detects changed lines as any line that has a "<span 312N/A# class=" string embedded (unchanged lines have no class set and are 312N/A# not part of a <span>. Blank lines (without a sequence number) 312N/A# are also detected since they flag lines that have been inserted or 312N/A # This should be able to be a singleton <a /> but that 312N/A # seems to trigger a bug in firefox a:hover rule processing 312N/A printf "<a name=\"%d\" id=\"anc%d\"></a>", anc, anc++; 312N/A NF == 0 || /^<span class=/ { 312N/A printf "<b style=\"font-size: large; color: red\">"; 312N/A printf "--- EOF ---</b>" 312N/A for(i=0;i<8;i++) printf "\n\n\n\n\n\n\n\n\n\n"; 312N/A printf "<form name=\"eof\">"; 312N/A printf "<input name=\"value\" value=\"%d\" type=\"hidden\" />", 312N/A# Print a relative return path from $1 to $2. For example if 312N/A# this function would print "../../../../". 312N/A# In the event that $1 is not in $2 a warning is printed to stderr, 312N/A# and $2 is returned-- the result of this is that the resulting webrev 312N/A print -u2 "\nWARNING: relative_dir: \"$1\" not relative " 312N/A print -u2 "to \"$2\". Check input paths. Framed webrev " 312N/A print -u2 "will not be relocatable!" 312N/A# Emit javascript for frame navigation 312N/A // on each side, so we pluck from the left. 312N/A // this must be: val >= maxval 312N/Afunction startScroll() { 312N/A myInt=setInterval("scrollByPix()",10); 312N/Afunction handlePress(b) { 312N/A scrollToAnc(getAncValue() - 1); 312N/A scrollToAnc(getAncValue() + 1); 312N/Afunction handleRelease(b) { 312N/A } else if (keychar == "j" || keychar == " ") { 312N/Afunction ValidateDiffNum(){ 312N/A# Output anchor navigation file for framed sdiffs. 312N/Afunction frame_navigation 312N/A print "$HTML<head>$STDHEAD" 312N/A<title>Anchor Navigation</title> 312N/A background-color: #eee; text-align: center; 312N/A border: 1px #444 outset; cursor: pointer; } 312N/A onkeypress="keypress(event);"> 312N/A <noscript lang="javascript"> 312N/A <p><big>Framed Navigation controls require Javascript</big><br /> 312N/A Either this browser is incompatable or javascript is not enabled</p> 312N/A <table width="100%" border="0" align="center"> 312N/A <td valign="middle" width="25%">Diff navigation: 312N/A Use 'j' and 'k' for next and previous diffs; or use buttons 312N/A <td align="center" valign="top" width="50%"> 312N/A <table border="0" align="center"> 312N/A <a onMouseDown="handlePress(1);return true;" 312N/A onMouseUp="handleRelease(1);return true;" 312N/A onMouseOut="handleRelease(1);return true;" 312N/A onClick="return false;" 312N/A title="Go to Beginning Of file">BOF</a></td> 312N/A <a onMouseDown="handlePress(3);return true;" 312N/A onMouseUp="handleRelease(3);return true;" 312N/A onMouseOut="handleRelease(3);return true;" 312N/A title="Scroll Up: Press and Hold to accelerate" 312N/A onClick="return false;">Scroll Up</a></td> 312N/A <a onMouseDown="handlePress(2);return true;" 312N/A onMouseUp="handleRelease(2);return true;" 312N/A onMouseOut="handleRelease(2);return true;" 312N/A title="Go to previous Diff" 312N/A onClick="return false;">Prev Diff</a> 312N/A <a onMouseDown="handlePress(6);return true;" 312N/A onMouseUp="handleRelease(6);return true;" 312N/A onMouseOut="handleRelease(6);return true;" 312N/A onClick="return false;" 312N/A title="Go to End Of File">EOF</a></td> 312N/A <a onMouseDown="handlePress(4);return true;" 312N/A onMouseUp="handleRelease(4);return true;" 312N/A onMouseOut="handleRelease(4);return true;" 312N/A title="Scroll Down: Press and Hold to accelerate" 312N/A onClick="return false;">Scroll Down</a></td> 312N/A <a onMouseDown="handlePress(5);return true;" 312N/A onMouseUp="handleRelease(5);return true;" 312N/A onMouseOut="handleRelease(5);return true;" 312N/A title="Go to next Diff" 312N/A onClick="return false;">Next Diff</a></td> 312N/A <th valign="middle" width="25%"> 312N/A <form action="" name="diff" onsubmit="return ValidateDiffNum();"> 312N/A <input name="display" value="BOF" size="8" type="text" /> 312N/A <input name="real" value="0" size="8" type="hidden" /> 312N/A# diff_to_html <filename> <filepath> { U | C } <comment> 312N/A# Processes the output of diff to produce an HTML file representing either 312N/A# context or unified diffs. 312N/A print "$HTML<head>$STDHEAD" 312N/A print "<title>$WNAME ${DIFFTYPE}diff $TPATH</title>" 312N/A if [[ $DIFFTYPE == "U" ]]; then 312N/A <a class="print" href="javascript:print()">Print this page</a> 312N/A /^-------/ { printf "<center><h1>%s</h1></center>\n", $0; next } 312N/A /^\*\*\*/ { printf "<hr /><span class=\"oldmarker\">%s</span>\n", $0; 312N/A /^---/ { printf "<span class=\"newmarker\">%s</span>\n", $0; 312N/A /^\+/ {printf "<span class=\"new\">%s</span>\n", $0; next} 312N/A /^!/ {printf "<span class=\"changed\">%s</span>\n", $0; next} 312N/A /^-/ {printf "<span class=\"removed\">%s</span>\n", $0; next} 312N/A print "</pre></body></html>\n" 312N/A# source_to_html { new | old } <filename> 312N/A# Process a plain vanilla source file to transform it into an HTML file. 312N/A print "$HTML<head>$STDHEAD" 312N/A print "<title>$WHICH $TNAME</title>" 312N/A print "<body id=\"SUNWwebrev\">" 312N/A print "</pre></body></html>" 312N/A# teamwarecomments {text|html} parent-file child-file 312N/A# newest delta from the parent, get all deltas from the child starting 312N/A# with that delta, and then get all info starting with the second oldest 312N/A# delta in that list (the first delta unique to the child). 312N/A# This code adapted from Bill Shannon's "spc" script 312N/A /^COMMENTS:/ {p=1; next} 312N/A /^D [0-9]+\.[0-9]+/ {printf "--- %s ---\n", $2; p=0; } 312N/A {if (p==0) next; print $0 }' 312N/A# wxcomments {text|html} filepath 312N/A# Given the pathname of a file, find its location in a "wx" active file 312N/A# list and print the following sccs comment. Output is either text or 312N/A# HTML; if the latter, embedded bugids (sequence of 5 or more digits) are 312N/A do getline ; while (NF > 0) 312N/A while (NF > 0) { print ; getline } 312N/A # If the output from 'hg status' is not empty, it means the file 312N/A # hasn't been committed, so don't fetch comments. 312N/A# getcomments {text|html} filepath parentpath 312N/A# Fetch the comments depending on what SCM mode we're in. 312N/A# printCI <total-changed> <inserted> <deleted> <modified> <unchanged> 312N/A# Print out Code Inspection figures similar to sccs-prt(1) format. 312N/A printf '%d %s changed: %d ins; %d del; %d mod; %d unchg' \ 312N/A# difflines <oldfile> <newfile> 312N/A# Calculate and emit number of added, removed, modified and unchanged lines, 312N/A# and total lines changed, the sum of added + removed + modified. 312N/A # Change range of lines: N,Nc 312N/A n=split(substr($1,1,length($1)-1), counts, ","); 312N/A # 3,5c means lines 3 , 4 and 5 are changed, a total of 3 lines. 312N/A # following would be 5 - 3 = 2! Hence +1 for correction. 312N/A r=(counts[2]-counts[1])+1; 312N/A # Now count replacement lines: each represents a change instead 312N/A # of a delete, so increment c and decrement r. 312N/A while (getline != /^\.$/) { 312N/A # If there were more replacement lines than original lines, 312N/A # then r will be negative; in this case there are no deletions, 312N/A # but there are r changes that should be counted as adds, and 312N/A # since r is negative, subtract it from a and add it to c. 312N/A # If there were more original lines than replacement lines, then 312N/A # r will be positive; in this case, increment d by that much. 312N/A # The first line is a replacement; any more are additions. 312N/A if (getline != /^\.$/) { 312N/A while (getline != /^\.$/) a++; 312N/A # Add lines: both Na and N,Na 312N/A while (getline != /^\.$/) a++; 312N/A # Delete range of lines: N,Nd 312N/A n=split(substr($1,1,length($1)-1), counts, ","); 312N/A # 3,5d means lines 3 , 4 and 5 are deleted, a total of 3 lines. 312N/A # following would be 5 - 3 = 2! Hence +1 for correction. 312N/A r=(counts[2]-counts[1])+1; 312N/A # Delete line: Nd. For example 10d says line 10 is deleted. 312N/A /^[0-9]*d$/ {d++; next} 312N/A # Finish off - print results 312N/A printf("tot=%d;mod=%d;del=%d;ins=%d;err=%d\n", 312N/A (c+d+a), c, d, a, error); 312N/A # End of $AWK, Check to see if any trouble occurred. 312N/A print "Unexpected Error occurred reading" \ 312N/A # Calculate unchanged lines 312N/A print "<span class=\"lineschanged\">\c" 312N/A# Sets up webrev to source its information from a wx-formatted file. 312N/A# Sets the global 'wxfile' variable. 312N/A # If the wx file pathname is relative then make it absolute 312N/A # because the webrev does a "cd" later on. 312N/A if (NF == 0) { c = -c; continue } 312N/A# flist_from_teamware [ <args-to-putback-n> ] 312N/A# Generate the file list by extracting file names from a putback -n. Some 312N/A# "currently checked out" warning. Renames are detected here too. Extract 312N/A# values for CODEMGR_WS and CODEMGR_PARENT from the output of the putback 312N/A# -n as well, but remove them if they are already defined. 312N/A "valid teamware workspace" 312N/A /^update:|^create:/ {print $2} 312N/A /^Parent workspace:/ {printf("CODEMGR_PARENT=%s\n",$3)} 312N/A /^Child workspace:/ {printf("CODEMGR_WS=%s\n",$3)} 312N/A /^The following files are currently checked out/ {p = 1; next} 312N/A $1 == "to:" {print $2, old} 312N/A /^\[.*\]$/ {tree=substr($1,2,length($1)-2); 312N/A if (revs[tree] == -1 || rev < revs[tree]) 312N/A END {for (tree in trees) 312N/A { rev=revs[trees[tree]]; 312N/A {printf("%s %d\n",trees[tree],rev-1)} 312N/A print " File list from hg foutgoing $PWS ..." 312N/A # hg commit hasn't been run see what is lying around 312N/A print "\n No outgoing, perhaps you haven't commited." 312N/A print " File list from hg fstatus -mard ...\c" 312N/A# Used when dealing with the result of 'hg foutgoing' 312N/A# When now go down the tree and generate the change list 312N/A # Then all the added files 312N/A # But some of these could have been "moved" or renamed ones 312N/A # so let's make sure we get the proper info 312N/A # hg status -aC will produce something like: 312N/A # The first and last are simple addition while the middle one 312N/A if [ $# -eq 2 -a "$1" == "A" ]; then 312N/A # forest extension is still being changed. For instance the output 312N/A # of fstatus used to no prepend the tree path to filenames, but 312N/A # this has changed recently. AWK code below does try to handle both 312N/A /^\[.*\]$/ {tree=substr($1,2,length($1)-2); next} 312N/A $1 != "" {n=index($1,tree); 312N/A { printf("%s/%s\n",tree,$1)} 312N/A # There is a bug in the output of fstatus -aC on recent versions: it 312N/A # inserts a space between the name of the tree and the filename of the 312N/A /^\[.*\]$/ {tree=substr($1,2,length($1)-2); next} 312N/A /^A .*/ {n=index($2,tree); 312N/A { printf("A %s/%s\n",tree,$2)} 607N/A { printf("A %s\n",$2)}; 312N/A /^ / {n=index($1,tree); 312N/A { printf("%s/%s\n",tree,$1)} 312N/A printf("%s/%s\n",tree,$2) 312N/A if [ $# -eq 2 -a "$1" == "A" ]; then 312N/A /^\[.*\]$/ {tree=substr($1,2,length($1)-2); next} 312N/A $1 != "" {n=index($1,tree); 312N/A { printf("%s/%s\n",tree,$1)} 312N/A# flist_from_mercurial $PWS 312N/A# Only local file based repositories are supported at present 312N/A# since even though we can determine the list from the parent finding 312N/A# the changes is harder. 312N/A# We first look for any outgoing files, this is for when the user has 312N/A# run hg commit. If we don't find any then we look with hg status. 312N/A# We need at least one of default-push or default paths set in .hg/hgrc 312N/A# If neither are set we don't know who to compare with. 312N/A# if [ "${PWS##ssh://}" != "$PWS" -o \ 312N/A# "${PWS##http://}" != "$PWS" -o \ 312N/A# "${PWS##https://}" != "$PWS" ]; then 312N/A# print "Remote Mercurial repositories not currently supported." 312N/A# print "Set default and/or default-push to a local repository" 312N/A # hg commit hasn't been run see what is lying around 312N/A print "\n No outgoing, perhaps you haven't commited." 312N/A # First let's list all the modified or deleted files 312N/A # Then all the added files 312N/A # But some of these could have been "moved" or renamed ones 312N/A # so let's make sure we get the proper info 312N/A # hg status -aC will produce something like: 312N/A # The first and last are simple addition while the middle one 312N/A if [ $# -eq 2 -a "$1" == "A" ]; then 312N/A # Use "eval" to set env variables that are listed in the file 312N/A # list. Then copy those into our local versions of those 312N/A # variables if they have not been set already. 312N/A # Check to see if CODEMGR_PARENT is set in the flist file. 312N/A# We dynamically test the SCM type; this allows future extensions to 312N/A # If CODEMGR_WS is specified in the flist file, we assume teamware. 312N/A # The presence of $CODEMGR_WS and a Codemgr_wsdata directory 312N/A # is our clue that this is a teamware workspace. 312N/A # Same if true if current directory has a Codemgr_wsdata sub-dir 312N/A # If the child's version doesn't exist then 312N/A # Snag new version of file. 312N/A # Get the parent's version of the file. First see whether the 312N/A # child's version is checked out and get the parent's version 312N/A # with keywords expanded or unexpanded as appropriate. 312N/A # Parent is not a real workspace, but just a raw 312N/A # directory tree - use the file that's there as 312N/A# Find the parent for $1 312N/A # No specific parent means previous changeset is parent 312N/A # Format is either of the following two: 312N/A # 548:16f1915bb5cd 547:ffaa4e775815 312N/A # new version of the file. 312N/A # Old version of the file. 312N/A # when specifying a workspace we have to provide 312N/A # It's a rename (or a move), so let's make sure we move 312N/A # to the right directory first, then restore it once done 312N/A print "Usage:\twebrev [common-options] 312N/A webrev [common-options] ( <file> | - ) 312N/A webrev [common-options] -w <wx file> 312N/A webrev [common-options] -l [arguments to 'putback'] 312N/A -v: Print the version of this tool. 312N/A -b: Do not ignore changes in the amount of white space. 312N/A -c <CR#>: Include link to CR (aka bugid) in the main page. 312N/A -o <outdir>: Output webrev to specified directory. 312N/A -p <compare-against>: Use specified parent wkspc or basis for comparison 312N/A -w <wxfile>: Use specified wx active file. 312N/A -u <username>: Use that username instead of 'guessing' one. 312N/A -m: Forces the use of Mercurial 312N/A -t: Forces the use of Teamware 312N/A -r rev: Compare against a specified revision 312N/A -N: Skip 'hg outgoing', use only 'hg status' 312N/A -f: Use the forest extension 312N/A WDIR: Control the output directory. 312N/A WEBREV_BUGURL: Control the URL prefix for bugids. 312N/A WEBREV_SACURL: Control the URL prefix for ARC cases. 312N/A Teamware: CODEMGR_WS: Workspace location. 312N/A Teamware: CODEMGR_PARENT: Parent workspace location. 312N/A# Main program starts here 312N/Atrap "rm -f /tmp/$$.* ; exit" 0 1 2 3 15 312N/A # Under windows mercurial outputs '\' instead of '/' 312N/A print -u2 "Error: No perl interpreter found. Exiting." 312N/A# These aren't fatal, but we want to note them to the user. 312N/A# We don't warn on the absence of 'wx' until later when we've 312N/A# determined that we actually need to try to invoke it. 312N/A# [[ ! -x $CODEREVIEW ]] && print -u2 "WARNING: codereview(1) not found." 312N/A# [[ ! -x $PS2PDF ]] && print -u2 "WARNING: ps2pdf(1) not found." 312N/A# [[ ! -x $WDIFF ]] && print -u2 "WARNING: wdiff not found." 312N/A# Declare global total counters. 312N/Awhile getopts "c:i:o:p:r:u:lmtwONvfb" opt 312N/A # If -l has been specified, we need to abort further options 312N/A # processing, because subsequent arguments are going to be 312N/A # arguments to 'putback -n'. 312N/A print "The -r <rev> flag is incompatible with the use of forests" 312N/A# If this manually set as the parent, and it appears to be an earlier webrev, 312N/A if [[ $1 == "-" ]]; then 312N/A print -u2 "$1: no such file or not readable" 312N/A# Before we go on to further consider -l and -w, work out which SCM we think 312N/A print -u2 "Unable to determine SCM type currently in use." 312N/A print -u2 "For teamware: webrev looks for \$CODEMGR_WS either in" 312N/A print -u2 " the environment or in the file list." 312N/A print -u2 "For mercurial: webrev runs 'hg root'." 312N/A # determine Workspace and parent workspace paths 312N/A # Let's try to expand it if it's an alias defined in [paths] 312N/A # OUTPWS is the parent repository to use when using 'hg outgoing' 312N/A # for forest we have to rely on properly set default and 312N/A # default-push because they can be different from the top one. 312N/A # unless of course it was explicitely speficied with -p 312N/A # Unfortunately mercurial is bugged and doesn't handle 312N/A # aliases correctly in 'hg path default' 312N/A # So let's do it ourselves. Sigh... 312N/A # Still empty, means no default-push 312N/A # Let's try to expand it if it's an alias defined in [paths] 312N/A # OUTPWS may contain username:password, let's make sure we remove the 312N/A # sensitive information before we print out anything in the HTML 312N/A # Remove everything between '://' and '@' 312N/A # 'default' means no particular branch, so let's cancel that 312N/A # If no "-N", always do "hg outgoing" against parent 312N/A # repository to determine list of outgoing revisions. 312N/A # If no "-r", choose revision to compare against by 312N/A # finding the latest revision not in the outgoing list. 312N/A # If skipping "hg outgoing" but still comparing against a 312N/A # specific revision (not the tip), set revision for comment 312N/A #Let's check if a merge is needed, if so, issue a warning 312N/A print "WARNING: parent rev is not tip. Maybe an update or merge is needed" 312N/A # If the -l flag is given instead of the name of a file list, 312N/A # then generate the file list by extracting file names from a 312N/A # If the -w is given then assume the file list is in Bonwick's "wx" 312N/A # command format, i.e. pathname lines alternating with SCCS comment 312N/A # lines with blank lines as separators. Use the SCCS comments later 312N/A [[ -z $wxfile ]] && print -u2 "wx file not specified, and could not " \ 312N/A "be auto-detected (check \$CODEMGR_WS)" && exit 1 312N/A print -u2 " File list from: standard input" 312N/A print -u2 "WARNING: unused arguments: $*" 312N/A # Parent (internally $codemgr_parent) and workspace ($codemgr_ws) can 312N/A # be set in a number of ways, in decreasing precedence: 312N/A # 1) on the command line (only for the parent) 312N/A # 2) in the user environment 312N/A # 4) automatically based on the workspace (only for the parent) 312N/A # Here is case (2): the user environment 312N/A # If we're in auto-detect mode and we haven't already gotten the file 312N/A # list, then see if we can get it by probing for wx. 312N/A print -u2 "WARNING: wx not found!" 312N/A # We need to use wx list -w so that we get renamed files, etc. 312N/A # but only if a wx active file exists-- otherwise wx will 312N/A # hang asking us to initialize our wx information. 312N/A print -u2 " File list from: 'wx list -w' ... \c" 312N/A # If by hook or by crook we've gotten a file list by now (perhaps 312N/A # from the command line), eval it to extract environment variables from 312N/A # it: This is step (3). 312N/A # Continuing step (3): If we still have no file list, we'll try to get 312N/A # Observe true directory name of CODEMGR_WS, as used later in 312N/A # (4) If we still don't have a value for codemgr_parent, get it 312N/A # Reset CODEMGR_WS to make sure teamware commands are happy. 312N/A# If the user didn't specify a -i option, check to see if there is a 312N/A# webrev-info file in the workspace directory. 312N/A # $INCLUDE_FILE may be a relative path, and the script alters 312N/A # PWD, so we just stash a copy in /tmp. 312N/A # If the output directory doesn't end with '/webrev' or '/webrev/' 312N/A # then add '/webrev'. This is for backward compatibility 312N/A# Name of the webrev, derived from the workspace name; in the 312N/A# future this could potentially be an option. 312N/A# Let's keep what's after the last '/' 312N/A# If WDIR doesn't start with '/' or 'x:' prepend the current dir 312N/A [[ $? != 0 ]] && exit 1 312N/A# Summarize what we're going to do. 312N/A# Save the file list in the webrev dir 312N/A# Bug IDs will be replaced by a URL. Order of precedence 312N/A# is: default location, $WEBREV_BUGURL, the -O flag. 312N/A# Likewise, ARC cases will be replaced by a URL. Order of precedence 312N/A# is: default, $WEBREV_SACURL, the -O flag. 312N/A# Note that -O also triggers different substitution behavior for 312N/A# SACURL. See sac2url(). 312N/A# Clean up the file list: Remove comments, blank lines and env variables. 312N/A# Clean up residual raw files 312N/A# Should we ignore changes in white spaces when generating diffs? 312N/A# First pass through the files: generate the per-file webrev HTML-files. 312N/A if [[ $1 == "Revision:" ]]; then 312N/A # Normally, each line in the file list is just a pathname of a 312N/A # file that has been modified or created in the child. A file 312N/A # that is renamed in the child workspace has two names on the 312N/A # line: new name followed by the old name. 312N/A # Make the webrev directory if necessary as it may have been 312N/A # removed because it was empty 312N/A # Make the webrev mirror directory if necessary 312N/A # cd to the directory so the names are short 312N/A # If we're in OpenSolaris mode, we enforce a minor policy: 312N/A # help to make sure the reviewer doesn't accidentally publish 312N/A print "*** Omitting closed source for OpenSolaris" \ 312N/A # We stash old and new files into parallel directories in /tmp 312N/A # and do our diffs there. This makes it possible to generate 312N/A # clean looking diffs which don't have absolute paths present. 312N/A print "*** Error: file not in parent or child" 783N/A # It's a JAR or ZIP file, let's do it differently 783N/A print "No access to jar, so can't produce diffs for jar or zip files" 312N/A print " wdiffs[fail]\c" 312N/A # renamed file: may also have differences 312N/A # new file: count added lines 312N/A # old file: count deleted lines 312N/A # If we have old and new versions of the file then run the 312N/A # appropriate diffs. This is complicated by a couple of factors: 312N/A # - renames must be handled specially: we emit a 'remove' 312N/A # diff and an 'add' diff 312N/A # - new files and deleted files must be handled specially 312N/A # - Solaris patch(1m) can't cope with file creation 312N/A # (and hence renames) as of this writing. 312N/A # - To make matters worse, gnu patch doesn't interpret the 312N/A # output of Solaris diff properly when it comes to 312N/A # adds and deletes. We need to do some "cleansing" 312N/A # [to add a file] @@ -1,0 +X,Y @@ --> @@ -0,0 +X,Y @@ 312N/A # [to del a file] @@ -X,Y +1,0 @@ --> @@ -X,Y +0,0 @@ 312N/A # Tack the patch we just made onto the accumulated patch for the 312N/A print " wdiffs[fail]\c" 312N/A # renamed file: may also have differences 312N/A # new file: count added lines 312N/A # old file: count deleted lines 312N/A # Now we generate the postscript for this file. We generate diffs 312N/A # only in the event that there is delta, or the file is new (it seems 312N/A # tree-killing to print out the contents of deleted files). 312N/A print " Generating PDF: \c" 312N/A# links to the source files and their diffs. 312N/A# Save total changed lines for Code Inspection. 312N/Aexec 3<&1 # duplicate stdout to FD3. 312N/Aexec 1<&- # Close stdout. 312N/Aprint "<body id=\"SUNWwebrev\">" 312N/Aprint "<div class=\"summary\">" 312N/A # Let's try to extract the user name from the .hgrc file 312N/A # Figure out the username and gcos name. To maintain compatibility 312N/A # with passwd(4), we must support '&' substitutions. 312N/A print "<tr><th>Prepared by:</th>" 312N/Aprint "<tr><th>Workspace:</th><td>$CWS</td></tr>" 312N/A print "<tr><th>Compare against:</th><td>" 312N/A print "<tr><th>Compare against:</th><td>" 312N/A print "<tr><th>Compare against version:</th><td>$OUTREV</td></tr>" 312N/Aprint "<tr><th>Summary of changes:</th><td>" 312N/A print "<tr><th>Patch of changes:</th><td>" 312N/A print "<tr><th>Printable review:</th><td>" 312N/A print "<tr><th>Author comments:</th><td><div>" 312N/A print "</div></td></tr>" 312N/A# Add links to referenced CRs, if any 312N/A# external URL has a <title> like: 312N/A# <title>Bug ID: 6641309 Wrong Cookie separator used in HttpURLConnection</title> 312N/A# while internal URL has <title> like: 607N/A# <title>[#JDK-6641309] Wrong Cookie separator used in HttpURLConnection</title> 607N/A #add "JDK-" to raw bug id for jbs links. 312N/A print "<tr><th>Bug id:</th><td>" 312N/Aprint "<tr><th>Legend:</th><td>" 312N/Aprint "<b>Modified file</b><br><font color=red><b>Deleted file</b></font><br><font color=green><b>New file</b></font></td></tr>" 312N/A# Second pass through the files: generate the rest of the index file 312N/A if [[ $1 == "Revision:" ]]; then 312N/A # Avoid processing the same file twice. 312N/A # It's possible for renamed files to 312N/A # appear twice in the file list 312N/A # If there's a diffs file, make diffs links 312N/A print " ------ ------ ------" 312N/A # If there's an old file, make the link 312N/A # If there's an new file, make the link 312N/A print "<font color=green><b>$P</b></font>" 312N/A print "<font color=red><b>$P</b></font>" 312N/A print " <i>Closed source: omitted from" \ 312N/A print "</p><blockquote>\c" 312N/A # Insert delta comments if any 312N/A # Add additional comments comment 312N/A print "<!-- Add comments to explain changes in $P here -->" 312N/A # Add count of changes. 312N/Aprint "<p style=\"font-size: small\">" 312N/Aprint "This code review page was prepared using <b>$0</b>" 312N/A # Let's generate a zip file for convenience 312N/Aexec 1<&3 # dup FD 3 to restore stdout.