ohair@314: #!/bin/ksh -p ohair@314: # ohair@314: # CDDL HEADER START ohair@314: # ohair@314: # The contents of this file are subject to the terms of the ohair@314: # Common Development and Distribution License (the "License"). ohair@314: # You may not use this file except in compliance with the License. ohair@314: # ohair@314: # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE ohair@314: # or http://www.opensolaris.org/os/licensing. ohair@314: # See the License for the specific language governing permissions ohair@314: # and limitations under the License. ohair@314: # ohair@314: # When distributing Covered Code, include this CDDL HEADER in each ohair@314: # file and include the License file at usr/src/OPENSOLARIS.LICENSE. ohair@314: # If applicable, add the following below this CDDL HEADER, with the ohair@314: # fields enclosed by brackets "[]" replaced with your own identifying ohair@314: # information: Portions Copyright [yyyy] [name of copyright owner] ohair@314: # ohair@314: # CDDL HEADER END ohair@314: # mduigou@616: # Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. ohair@314: # Use is subject to license terms. ohair@314: # ohair@314: # This script takes a file list and a workspace and builds a set of html files ohair@314: # suitable for doing a code review of source changes via a web page. ohair@314: # Documentation is available via 'webrev -h'. ohair@314: # ohair@314: mduigou@851: WEBREV_UPDATED=25.0-hg+openjdk.java.net ohair@314: ohair@314: HTML=' ohair@314: ohair@314: \n' ohair@314: ohair@314: FRAMEHTML=' ohair@314: ohair@314: \n' ohair@314: mduigou@851: STDHEAD=' mduigou@851: ohair@314: ohair@314: ohair@314: ohair@314: ohair@314: ohair@314: ohair@314: ' ohair@314: ohair@314: # ohair@314: # UDiffs need a slightly different CSS rule for 'new' items (we don't ohair@314: # want them to be bolded as we do in cdiffs or sdiffs). ohair@314: # ohair@314: UDIFFCSS=' ohair@314: ohair@314: ' ohair@314: ohair@314: # ohair@314: # input_cmd | html_quote | output_cmd ohair@314: # or ohair@314: # html_quote filename | output_cmd ohair@314: # ohair@314: # Make a piece of source code safe for display in an HTML
 block.
ohair@314: #
ohair@314: html_quote()
ohair@314: {
mduigou@851: 	sed -e "s/&/\&/g" -e "s/&#\([x]*[0-9A-Fa-f]\{2,5\}\);/\&#\1;/g" -e "s//\>/g" "$@" | expand
mduigou@851: }
mduigou@851: 
mduigou@851: #
mduigou@851: # input_cmd | html_quote | output_cmd
mduigou@851: # or
mduigou@851: # html_dequote filename | output_cmd
mduigou@851: #
mduigou@851: # Replace HTML entities with literals
mduigou@851: #
mduigou@851: html_dequote()
mduigou@851: {
mduigou@851: 	sed -e "s/"/\"/g" -e "s/'/\'/g" -e "s/&/\&/g" -e "s/</<'/g" -e "s/>/>/g" "$@" | expand
ohair@314: }
ohair@314: 
ohair@314: #
ohair@314: # input_cmd | bug2url | output_cmd
ohair@314: #
ohair@314: # Scan for bugids and insert  links to the relevent bug database.
ohair@314: #
ohair@314: bug2url()
ohair@314: {
mduigou@616: 	sed -e 's|[0-9]\{5,\}|&|g'
ohair@314: }
ohair@314: 
ohair@314: #
ohair@314: # strip_unchanged  | output_cmd
ohair@314: #
ohair@314: # Removes chunks of sdiff documents that have not changed. This makes it
ohair@314: # easier for a code reviewer to find the bits that have changed.
ohair@314: #
ohair@314: # Deleted lines of text are replaced by a horizontal rule. Some
ohair@314: # identical lines are retained before and after the changed lines to
ohair@314: # provide some context.  The number of these lines is controlled by the
ohair@314: # variable C in the $AWK script below.
ohair@314: #
ohair@314: # The script detects changed lines as any line that has a "
"
ohair@314: 				inx = c % C
ohair@314: 				c = C
ohair@314: 			}
ohair@314: 
ohair@314: 			for (i = 0; i < c; i++)
ohair@314: 				print ln[(inx + i) % C]
ohair@314: 		}
ohair@314: 		c = 0;
ohair@314: 		print
ohair@314: 		next
ohair@314: 	}
ohair@314: 	{	if (c >= C) {
ohair@314: 			ln[c % C] = $0
ohair@314: 			c++;
ohair@314: 			next;
ohair@314: 		}
ohair@314: 		c++;
ohair@314: 		print
ohair@314: 	}
ohair@314: 	END	{ if (c > (C * 2)) print "\n

" } ohair@314: ohair@314: ' $1 ohair@314: } ohair@314: ohair@314: # ohair@314: # sdiff_to_html ohair@314: # ohair@314: # This function takes two files as arguments, obtains their diff, and ohair@314: # processes the diff output to present the files as an HTML document with ohair@314: # the files displayed side-by-side, differences shown in color. It also ohair@314: # takes a delta comment, rendered as an HTML snippet, as the third ohair@314: # argument. The function takes two files as arguments, then the name of ohair@314: # file, the path, and the comment. The HTML will be delivered on stdout, ohair@314: # e.g. ohair@314: # ohair@314: # $ sdiff_to_html old/usr/src/tools/scripts/webrev.sh \ ohair@314: # new/usr/src/tools/scripts/webrev.sh \ ohair@314: # webrev.sh usr/src/tools/scripts \ mduigou@792: # ' mduigou@616: # JDK-1234567 my bugid' > .html ohair@314: # ohair@314: # framed_sdiff() is then called which creates $2.frames.html ohair@314: # in the webrev tree. ohair@314: # ohair@314: # FYI: This function is rather unusual in its use of awk. The initial ohair@314: # diff run produces conventional diff output showing changed lines mixed ohair@314: # with editing codes. The changed lines are ignored - we're interested in ohair@314: # the editing codes, e.g. ohair@314: # ohair@314: # 8c8 ohair@314: # 57a61 ohair@314: # 63c66,76 ohair@314: # 68,93d80 ohair@314: # 106d90 ohair@314: # 108,110d91 ohair@314: # ohair@314: # These editing codes are parsed by the awk script and used to generate ohair@314: # another awk script that generates HTML, e.g the above lines would turn ohair@314: # into something like this: ohair@314: # ohair@314: # BEGIN { printf "
\n" }
ohair@314: #      function sp(n) {for (i=0;i%4d %s \n", n, NR, $0}
ohair@314: #      NR==8           {wl("#7A7ADD");next}
ohair@314: #      NR==54          {wl("#7A7ADD");sp(3);next}
ohair@314: #      NR==56          {wl("#7A7ADD");next}
ohair@314: #      NR==57          {wl("black");printf "\n"; next}
ohair@314: #        :               :
ohair@314: #
ohair@314: #  This script is then run on the original source file to generate the
ohair@314: #  HTML that corresponds to the source file.
ohair@314: #
ohair@314: #  The two HTML files are then combined into a single piece of HTML that
ohair@314: #  uses an HTML table construct to present the files side by side.  You'll
ohair@314: #  notice that the changes are color-coded:
ohair@314: #
ohair@314: #   black     - unchanged lines
ohair@314: #   blue      - changed lines
ohair@314: #   bold blue - new lines
ohair@314: #   brown     - deleted lines
ohair@314: #
ohair@314: #  Blank lines are inserted in each file to keep unchanged lines in sync
ohair@314: #  (side-by-side).  This format is familiar to users of sdiff(1) or
ohair@314: #  Teamware's filemerge tool.
ohair@314: #
ohair@314: sdiff_to_html()
ohair@314: {
ohair@314: 	diff -b $1 $2 > /tmp/$$.diffs
ohair@314: 
ohair@314: 	TNAME=$3
ohair@314: 	TPATH=$4
ohair@314: 	COMMENT=$5
ohair@314: 
ohair@314: 	#
ohair@314: 	#  Now we have the diffs, generate the HTML for the old file.
ohair@314: 	#
ohair@314: 	$AWK '
ohair@314: 	BEGIN	{
ohair@314: 		printf "function sp(n) {for (i=0;i%%4d %%s\\n\", NR, $0}\n"
ohair@314: 		printf "function changed() "
ohair@314: 		printf "{printf \"%%4d %%s\\n\", NR, $0}\n"
ohair@314: 		printf "function bl() {printf \"%%4d %%s\\n\", NR, $0}\n"
ohair@314: }
ohair@314: 	/^/	{next}
ohair@314: 	/^---/	{next}
ohair@314: 
ohair@314: 	{
ohair@314: 	split($1, a, /[cad]/) ;
ohair@314: 	if (index($1, "a")) {
ohair@314: 		if (a[1] == 0) {
ohair@314: 			n = split(a[2], r, /,/);
ohair@314: 			if (n == 1)
ohair@314: 				printf "BEGIN\t\t{sp(1)}\n"
ohair@314: 			else
ohair@314: 				printf "BEGIN\t\t{sp(%d)}\n",\
ohair@314: 				(r[2] - r[1]) + 1
ohair@314: 			next
ohair@314: 		}
ohair@314: 
ohair@314: 		printf "NR==%s\t\t{", a[1]
ohair@314: 		n = split(a[2], r, /,/);
ohair@314: 		s = r[1];
ohair@314: 		if (n == 1)
ohair@314: 			printf "bl();printf \"\\n\"; next}\n"
ohair@314: 		else {
ohair@314: 			n = r[2] - r[1]
ohair@314: 			printf "bl();sp(%d);next}\n",\
ohair@314: 			(r[2] - r[1]) + 1
ohair@314: 		}
ohair@314: 		next
ohair@314: 	}
ohair@314: 	if (index($1, "d")) {
ohair@314: 		n = split(a[1], r, /,/);
ohair@314: 		n1 = r[1]
ohair@314: 		n2 = r[2]
ohair@314: 		if (n == 1)
ohair@314: 			printf "NR==%s\t\t{removed(); next}\n" , n1
ohair@314: 		else
ohair@314: 			printf "NR==%s,NR==%s\t{removed(); next}\n" , n1, n2
ohair@314: 		next
ohair@314: 	}
ohair@314: 	if (index($1, "c")) {
ohair@314: 		n = split(a[1], r, /,/);
ohair@314: 		n1 = r[1]
ohair@314: 		n2 = r[2]
ohair@314: 		final = n2
ohair@314: 		d1 = 0
ohair@314: 		if (n == 1)
ohair@314: 			printf "NR==%s\t\t{changed();" , n1
ohair@314: 		else {
ohair@314: 			d1 = n2 - n1
ohair@314: 			printf "NR==%s,NR==%s\t{changed();" , n1, n2
ohair@314: 		}
ohair@314: 		m = split(a[2], r, /,/);
ohair@314: 		n1 = r[1]
ohair@314: 		n2 = r[2]
ohair@314: 		if (m > 1) {
ohair@314: 			d2  = n2 - n1
ohair@314: 			if (d2 > d1) {
ohair@314: 				if (n > 1) printf "if (NR==%d)", final
ohair@314: 				printf "sp(%d);", d2 - d1
ohair@314: 			}
ohair@314: 		}
ohair@314: 		printf "next}\n" ;
ohair@314: 
ohair@314: 		next
ohair@314: 	}
ohair@314: 	}
ohair@314: 
ohair@314: 	END	{ printf "{printf \"%%4d %%s\\n\", NR, $0 }\n" }
ohair@314: 	' /tmp/$$.diffs > /tmp/$$.file1
ohair@314: 
ohair@314: 	#
ohair@314: 	#  Now generate the HTML for the new file
ohair@314: 	#
ohair@314: 	$AWK '
ohair@314: 	BEGIN	{
ohair@314: 		printf "function sp(n) {for (i=0;i%%4d %%s\\n\", NR, $0}\n"
ohair@314: 		printf "function changed() "
ohair@314: 		printf "{printf \"%%4d %%s\\n\", NR, $0}\n"
ohair@314: 		printf "function bl() {printf \"%%4d %%s\\n\", NR, $0}\n"
ohair@314: 	}
ohair@314: 
ohair@314: 	/^/	{next}
ohair@314: 	/^---/	{next}
ohair@314: 
ohair@314: 	{
ohair@314: 	split($1, a, /[cad]/) ;
ohair@314: 	if (index($1, "d")) {
ohair@314: 		if (a[2] == 0) {
ohair@314: 			n = split(a[1], r, /,/);
ohair@314: 			if (n == 1)
ohair@314: 				printf "BEGIN\t\t{sp(1)}\n"
ohair@314: 			else
ohair@314: 				printf "BEGIN\t\t{sp(%d)}\n",\
ohair@314: 				(r[2] - r[1]) + 1
ohair@314: 			next
ohair@314: 		}
ohair@314: 
ohair@314: 		printf "NR==%s\t\t{", a[2]
ohair@314: 		n = split(a[1], r, /,/);
ohair@314: 		s = r[1];
ohair@314: 		if (n == 1)
ohair@314: 			printf "bl();printf \"\\n\"; next}\n"
ohair@314: 		else {
ohair@314: 			n = r[2] - r[1]
ohair@314: 			printf "bl();sp(%d);next}\n",\
ohair@314: 			(r[2] - r[1]) + 1
ohair@314: 		}
ohair@314: 		next
ohair@314: 	}
ohair@314: 	if (index($1, "a")) {
ohair@314: 		n = split(a[2], r, /,/);
ohair@314: 		n1 = r[1]
ohair@314: 		n2 = r[2]
ohair@314: 		if (n == 1)
ohair@314: 			printf "NR==%s\t\t{new() ; next}\n" , n1
ohair@314: 		else
ohair@314: 			printf "NR==%s,NR==%s\t{new() ; next}\n" , n1, n2
ohair@314: 		next
ohair@314: 	}
ohair@314: 	if (index($1, "c")) {
ohair@314: 		n = split(a[2], r, /,/);
ohair@314: 		n1 = r[1]
ohair@314: 		n2 = r[2]
ohair@314: 		final = n2
ohair@314: 		d2 = 0;
ohair@314: 		if (n == 1) {
ohair@314: 			final = n1
ohair@314: 			printf "NR==%s\t\t{changed();" , n1
ohair@314: 		} else {
ohair@314: 			d2 = n2 - n1
ohair@314: 			printf "NR==%s,NR==%s\t{changed();" , n1, n2
ohair@314: 		}
ohair@314: 		m = split(a[1], r, /,/);
ohair@314: 		n1 = r[1]
ohair@314: 		n2 = r[2]
ohair@314: 		if (m > 1) {
ohair@314: 			d1  = n2 - n1
ohair@314: 			if (d1 > d2) {
ohair@314: 				if (n > 1) printf "if (NR==%d)", final
ohair@314: 				printf "sp(%d);", d1 - d2
ohair@314: 			}
ohair@314: 		}
ohair@314: 		printf "next}\n" ;
ohair@314: 		next
ohair@314: 	}
ohair@314: 	}
ohair@314: 	END	{ printf "{printf \"%%4d %%s\\n\", NR, $0 }\n" }
ohair@314: 	' /tmp/$$.diffs > /tmp/$$.file2
ohair@314: 
ohair@314: 	#
ohair@314: 	# Post-process the HTML files by running them back through $AWK
ohair@314: 	#
ohair@314: 	html_quote < $1 | $AWK -f /tmp/$$.file1 > /tmp/$$.file1.html
ohair@314: 
ohair@314: 	html_quote < $2 | $AWK -f /tmp/$$.file2 > /tmp/$$.file2.html
ohair@314: 
ohair@314: 	#
ohair@314: 	# Now combine into a valid HTML file and side-by-side into a table
ohair@314: 	#
ohair@314: 	print "$HTML$STDHEAD"
ohair@314: 	print "$WNAME Sdiff $TPATH "
ohair@314: 	print ""
ohair@314: 	print "

$TPATH/$TNAME

" ohair@314: print "Print this page" ohair@314: print "
$COMMENT
\n" ohair@314: print "" ohair@314: print "" ohair@314: print "
"
ohair@314: 
ohair@314: 	strip_unchanged /tmp/$$.file1.html
ohair@314: 
ohair@314: 	print "
"
ohair@314: 
ohair@314: 	strip_unchanged /tmp/$$.file2.html
ohair@314: 
ohair@314: 	print "
" ohair@314: print "" ohair@314: ohair@314: framed_sdiff $TNAME $TPATH /tmp/$$.file1.html /tmp/$$.file2.html \ ohair@314: "$COMMENT" ohair@314: } ohair@314: ohair@314: ohair@314: # ohair@314: # framed_sdiff ohair@314: # ohair@314: # Expects lefthand and righthand side html files created by sdiff_to_html. ohair@314: # We use insert_anchors() to augment those with HTML navigation anchors, ohair@314: # and then emit the main frame. Content is placed into: ohair@314: # ohair@314: # $WDIR/DIR/$TNAME.lhs.html ohair@314: # $WDIR/DIR/$TNAME.rhs.html ohair@314: # $WDIR/DIR/$TNAME.frames.html ohair@314: # ohair@314: # NOTE: We rely on standard usage of $WDIR and $DIR. ohair@314: # ohair@314: function framed_sdiff ohair@314: { ohair@314: typeset TNAME=$1 ohair@314: typeset TPATH=$2 ohair@314: typeset lhsfile=$3 ohair@314: typeset rhsfile=$4 ohair@314: typeset comments=$5 ohair@314: typeset RTOP ohair@314: ohair@314: # Enable html files to access WDIR via a relative path. ohair@314: RTOP=$(relative_dir $TPATH $WDIR) ohair@314: ohair@314: # Make the rhs/lhs files and output the frameset file. ohair@314: print "$HTML$STDHEAD" > $WDIR/$DIR/$TNAME.lhs.html ohair@314: ohair@314: cat >> $WDIR/$DIR/$TNAME.lhs.html <<-EOF ohair@314: ohair@314: ohair@314: ohair@314: ohair@314:
$comments

ohair@314: EOF ohair@314: ohair@314: cp $WDIR/$DIR/$TNAME.lhs.html $WDIR/$DIR/$TNAME.rhs.html ohair@314: ohair@314: insert_anchors $lhsfile >> $WDIR/$DIR/$TNAME.lhs.html ohair@314: insert_anchors $rhsfile >> $WDIR/$DIR/$TNAME.rhs.html ohair@314: ohair@314: close='' ohair@314: ohair@314: print $close >> $WDIR/$DIR/$TNAME.lhs.html ohair@314: print $close >> $WDIR/$DIR/$TNAME.rhs.html ohair@314: ohair@314: print "$FRAMEHTML$STDHEAD" > $WDIR/$DIR/$TNAME.frames.html ohair@314: print "$WNAME Framed-Sdiff " \ ohair@314: "$TPATH/$TNAME " >> $WDIR/$DIR/$TNAME.frames.html ohair@314: cat >> $WDIR/$DIR/$TNAME.frames.html <<-EOF ohair@314: ohair@314: ohair@314: ohair@314: ohair@314: ohair@314: ohair@314: ohair@314: <body id="SUNWwebrev"> ohair@314: Alas 'frames' webrev requires that your browser supports frames ohair@314: and has the feature enabled. ohair@314: </body> ohair@314: ohair@314: ohair@314: ohair@314: EOF ohair@314: } ohair@314: ohair@314: ohair@314: # ohair@314: # fix_postscript ohair@314: # ohair@314: # Merge codereview output files to a single conforming postscript file, by: ohair@314: # - removing all extraneous headers/trailers ohair@314: # - making the page numbers right ohair@314: # - removing pages devoid of contents which confuse some ohair@314: # postscript readers. ohair@314: # ohair@314: # From Casper. ohair@314: # ohair@314: function fix_postscript ohair@314: { ohair@314: infile=$1 ohair@314: ohair@314: cat > /tmp/$$.crmerge.pl << \EOF ohair@314: ohair@314: print scalar(<>); # %!PS-Adobe--- ohair@314: print "%%Orientation: Landscape\n"; ohair@314: ohair@314: $pno = 0; ohair@314: $doprint = 1; ohair@314: ohair@314: $page = ""; ohair@314: ohair@314: while (<>) { ohair@314: next if (/^%%Pages:\s*\d+/); ohair@314: ohair@314: if (/^%%Page:/) { ohair@314: if ($pno == 0 || $page =~ /\)S/) { ohair@314: # Header or single page containing text ohair@314: print "%%Page: ? $pno\n" if ($pno > 0); ohair@314: print $page; ohair@314: $pno++; ohair@314: } else { ohair@314: # Empty page, skip it. ohair@314: } ohair@314: $page = ""; ohair@314: $doprint = 1; ohair@314: next; ohair@314: } ohair@314: ohair@314: # Skip from %%Trailer of one document to Endprolog ohair@314: # %%Page of the next ohair@314: $doprint = 0 if (/^%%Trailer/); ohair@314: $page .= $_ if ($doprint); ohair@314: } ohair@314: ohair@314: if ($page =~ /\)S/) { ohair@314: print "%%Page: ? $pno\n"; ohair@314: print $page; ohair@314: } else { ohair@314: $pno--; ohair@314: } ohair@314: print "%%Trailer\n%%Pages: $pno\n"; ohair@314: EOF ohair@314: ohair@314: $PERL /tmp/$$.crmerge.pl < $infile ohair@314: } ohair@314: ohair@314: ohair@314: # ohair@314: # input_cmd | insert_anchors | output_cmd ohair@314: # ohair@314: # Flag blocks of difference with sequentially numbered invisible ohair@314: # anchors. These are used to drive the frames version of the ohair@314: # sdiffs output. ohair@314: # ohair@314: # NOTE: Anchor zero flags the top of the file irrespective of changes, ohair@314: # an additional anchor is also appended to flag the bottom. ohair@314: # ohair@314: # The script detects changed lines as any line that has a "", anc, anc++; ohair@314: } ohair@314: ohair@314: BEGIN { ohair@314: anc=1; ohair@314: inblock=1; ohair@314: printf "
\n";
ohair@314: 	}
ohair@314: 	NF == 0 || /^";
ohair@314: 		printf "--- EOF ---"
ohair@314:         	for(i=0;i<8;i++) printf "\n\n\n\n\n\n\n\n\n\n";
ohair@314: 		printf "
" ohair@314: printf "
"; ohair@314: printf "", ohair@314: anc - 1; ohair@314: printf "
"; ohair@314: } ohair@314: ' $1 ohair@314: } ohair@314: ohair@314: ohair@314: # ohair@314: # relative_dir ohair@314: # ohair@314: # Print a relative return path from $1 to $2. For example if ohair@314: # $1=/tmp/myreview/raw_files/usr/src/tools/scripts and $2=/tmp/myreview, ohair@314: # this function would print "../../../../". ohair@314: # ohair@314: # In the event that $1 is not in $2 a warning is printed to stderr, ohair@314: # and $2 is returned-- the result of this is that the resulting webrev ohair@314: # is not relocatable. ohair@314: # ohair@314: function relative_dir ohair@314: { ohair@314: d1=$1 ohair@314: d2=$2 ohair@314: if [[ "$d1" == "." ]]; then ohair@314: print "." ohair@314: else ohair@314: typeset cur="${d1##$d2?(/)}" ohair@314: typeset ret="" ohair@314: if [[ $d2 == $cur ]]; then # Should never happen. ohair@314: # Should never happen. ohair@314: print -u2 "\nWARNING: relative_dir: \"$1\" not relative " ohair@314: print -u2 "to \"$2\". Check input paths. Framed webrev " ohair@314: print -u2 "will not be relocatable!" ohair@314: print $2 ohair@314: return ohair@314: fi ohair@314: ohair@314: while [[ -n ${cur} ]]; ohair@314: do ohair@314: cur=${cur%%*(/)*([!/])} ohair@314: if [[ -z $ret ]]; then ohair@314: ret=".." ohair@314: else ohair@314: ret="../$ret" ohair@314: fi ohair@314: done ohair@314: print $ret ohair@314: fi ohair@314: } ohair@314: ohair@314: ohair@314: # ohair@314: # frame_nav_js ohair@314: # ohair@314: # Emit javascript for frame navigation ohair@314: # ohair@314: function frame_nav_js ohair@314: { ohair@314: cat << \EOF ohair@314: var myInt; ohair@314: var scrolling=0; ohair@314: var sfactor = 3; ohair@314: var scount=10; ohair@314: ohair@314: function scrollByPix() { ohair@314: if (scount<=0) { ohair@314: sfactor*=1.2; ohair@314: scount=10; ohair@314: } ohair@314: parent.lhs.scrollBy(0,sfactor); ohair@314: parent.rhs.scrollBy(0,sfactor); ohair@314: scount--; ohair@314: } ohair@314: ohair@314: function scrollToAnc(num) { ohair@314: ohair@314: // Update the value of the anchor in the form which we use as ohair@314: // storage for this value. setAncValue() will take care of ohair@314: // correcting for overflow and underflow of the value and return ohair@314: // us the new value. ohair@314: num = setAncValue(num); ohair@314: ohair@314: // Set location and scroll back a little to expose previous ohair@314: // lines. ohair@314: // ohair@314: // Note that this could be improved: it is possible although ohair@314: // complex to compute the x and y position of an anchor, and to ohair@314: // scroll to that location directly. ohair@314: // ohair@314: parent.lhs.location.replace(parent.lhs.location.pathname + "#" + num); ohair@314: parent.rhs.location.replace(parent.rhs.location.pathname + "#" + num); ohair@314: ohair@314: parent.lhs.scrollBy(0,-30); ohair@314: parent.rhs.scrollBy(0,-30); ohair@314: } ohair@314: ohair@314: function getAncValue() ohair@314: { ohair@314: return (parseInt(parent.nav.document.diff.real.value)); ohair@314: } ohair@314: ohair@314: function setAncValue(val) ohair@314: { ohair@314: if (val <= 0) { ohair@314: val = 0; ohair@314: parent.nav.document.diff.real.value = val; ohair@314: parent.nav.document.diff.display.value = "BOF"; ohair@314: return (val); ohair@314: } ohair@314: ohair@314: // ohair@314: // The way we compute the max anchor value is to stash it ohair@314: // inline in the left and right hand side pages-- it's the same ohair@314: // on each side, so we pluck from the left. ohair@314: // ohair@314: maxval = parent.lhs.document.eof.value.value; ohair@314: if (val < maxval) { ohair@314: parent.nav.document.diff.real.value = val; ohair@314: parent.nav.document.diff.display.value = val.toString(); ohair@314: return (val); ohair@314: } ohair@314: ohair@314: // this must be: val >= maxval ohair@314: val = maxval; ohair@314: parent.nav.document.diff.real.value = val; ohair@314: parent.nav.document.diff.display.value = "EOF"; ohair@314: return (val); ohair@314: } ohair@314: ohair@314: function stopScroll() { ohair@314: if (scrolling==1) { ohair@314: clearInterval(myInt); ohair@314: scrolling=0; ohair@314: } ohair@314: } ohair@314: ohair@314: function startScroll() { ohair@314: stopScroll(); ohair@314: scrolling=1; ohair@314: myInt=setInterval("scrollByPix()",10); ohair@314: } ohair@314: ohair@314: function handlePress(b) { ohair@314: ohair@314: switch (b) { ohair@314: case 1 : ohair@314: scrollToAnc(-1); ohair@314: break; ohair@314: case 2 : ohair@314: scrollToAnc(getAncValue() - 1); ohair@314: break; ohair@314: case 3 : ohair@314: sfactor=-3; ohair@314: startScroll(); ohair@314: break; ohair@314: case 4 : ohair@314: sfactor=3; ohair@314: startScroll(); ohair@314: break; ohair@314: case 5 : ohair@314: scrollToAnc(getAncValue() + 1); ohair@314: break; ohair@314: case 6 : ohair@314: scrollToAnc(999999); ohair@314: break; ohair@314: } ohair@314: } ohair@314: ohair@314: function handleRelease(b) { ohair@314: stopScroll(); ohair@314: } ohair@314: ohair@314: function keypress(ev) { ohair@314: var keynum; ohair@314: var keychar; ohair@314: ohair@314: if (window.event) { // IE ohair@314: keynum = ev.keyCode; ohair@314: } else if (ev.which) { // non-IE ohair@314: keynum = ev.which; ohair@314: } ohair@314: ohair@314: keychar = String.fromCharCode(keynum); ohair@314: ohair@314: if (keychar == "k") { ohair@314: handlePress(2); ohair@314: return (0); ohair@314: } else if (keychar == "j" || keychar == " ") { ohair@314: handlePress(5); ohair@314: return (0); ohair@314: } ohair@314: return (1); ohair@314: } ohair@314: ohair@314: function ValidateDiffNum(){ ohair@314: val = parent.nav.document.diff.display.value; ohair@314: if (val == "EOF") { ohair@314: scrollToAnc(999999); ohair@314: return; ohair@314: } ohair@314: ohair@314: if (val == "BOF") { ohair@314: scrollToAnc(0); ohair@314: return; ohair@314: } ohair@314: ohair@314: i=parseInt(val); ohair@314: if (isNaN(i)) { ohair@314: parent.nav.document.diff.display.value = getAncValue(); ohair@314: } else { ohair@314: scrollToAnc(i); ohair@314: } ohair@314: return false; ohair@314: } ohair@314: ohair@314: EOF ohair@314: } ohair@314: ohair@314: # ohair@314: # frame_navigation ohair@314: # ohair@314: # Output anchor navigation file for framed sdiffs. ohair@314: # ohair@314: function frame_navigation ohair@314: { ohair@314: print "$HTML$STDHEAD" ohair@314: ohair@314: cat << \EOF ohair@314: Anchor Navigation ohair@314: ohair@314: ohair@314: ohair@314: ohair@314: EOF ohair@314: ohair@314: print "" ohair@314: ohair@314: cat << \EOF ohair@314: ohair@314: ohair@314: ohair@314: ohair@314: ohair@314: ohair@314: ohair@314: ohair@314: ohair@314:
Diff navigation: ohair@314: Use 'j' and 'k' for next and previous diffs; or use buttons ohair@314: at right ohair@314:
ohair@314: ohair@314: ohair@314: ohair@314: ohair@314: ohair@314: ohair@314: ohair@314: ohair@314: ohair@314: ohair@314: ohair@314:
ohair@314: BOF ohair@314: Scroll Up ohair@314: Prev Diff ohair@314:
ohair@314: EOF ohair@314: Scroll Down ohair@314: Next Diff
ohair@314:
ohair@314:
ohair@314:
ohair@314: ohair@314: ohair@314:
ohair@314:
ohair@314: ohair@314: ohair@314: EOF ohair@314: } ohair@314: ohair@314: ohair@314: ohair@314: # ohair@314: # diff_to_html { U | C } ohair@314: # ohair@314: # Processes the output of diff to produce an HTML file representing either ohair@314: # context or unified diffs. ohair@314: # ohair@314: diff_to_html() ohair@314: { ohair@314: TNAME=$1 ohair@314: TPATH=$2 ohair@314: DIFFTYPE=$3 ohair@314: COMMENT=$4 ohair@314: ohair@314: print "$HTML$STDHEAD" ohair@314: print "$WNAME ${DIFFTYPE}diff $TPATH" ohair@314: ohair@314: if [[ $DIFFTYPE == "U" ]]; then ohair@314: print "$UDIFFCSS" ohair@314: fi ohair@314: ohair@314: cat <<-EOF ohair@314: ohair@314: ohair@314:

$TPATH

ohair@314: Print this page ohair@314:
$COMMENT
ohair@314:
ohair@314: EOF
ohair@314: 
ohair@314: 	html_quote | $AWK '
ohair@314: 	/^--- new/	{ next }
ohair@314: 	/^\+\+\+ new/	{ next }
ohair@314: 	/^--- old/	{ next }
ohair@314: 	/^\*\*\* old/	{ next }
ohair@314: 	/^\*\*\*\*/	{ next }
ohair@314: 	/^-------/	{ printf "

%s

\n", $0; next } ohair@314: /^\@\@.*\@\@$/ { printf "

\n";
ohair@314: 			  printf "%s\n", $0;
ohair@314: 			  next}
ohair@314: 
ohair@314: 	/^\*\*\*/	{ printf "
%s\n", $0; ohair@314: next} ohair@314: /^---/ { printf "%s\n", $0; ohair@314: next} ohair@314: /^\+/ {printf "%s\n", $0; next} ohair@314: /^!/ {printf "%s\n", $0; next} ohair@314: /^-/ {printf "%s\n", $0; next} ohair@314: {printf "%s\n", $0; next} ohair@314: ' ohair@314: ohair@314: print "
\n" ohair@314: } ohair@314: ohair@314: ohair@314: # ohair@314: # source_to_html { new | old } ohair@314: # ohair@314: # Process a plain vanilla source file to transform it into an HTML file. ohair@314: # ohair@314: source_to_html() ohair@314: { ohair@314: WHICH=$1 ohair@314: TNAME=$2 ohair@314: ohair@314: print "$HTML$STDHEAD" ohair@314: print "$WHICH $TNAME" ohair@314: print "" ohair@314: print "
"
ohair@314: 	html_quote | $AWK '{line += 1 ; printf "%4d %s\n", line, $0 }'
ohair@314: 	print "
" ohair@314: } ohair@314: ohair@314: comments_from_mercurial() ohair@314: { ohair@314: fmt=$1 ohair@314: pfile=$PWS/$2 ohair@314: cfile=$CWS/$3 ohair@314: ohair@314: logdir=`dirname $cfile` ohair@314: logf=`basename $cfile` ohair@314: if [ -d $logdir ]; then ohair@314: ( cd $logdir; ohair@314: active=`hg status $logf 2>/dev/null` ohair@314: # If the output from 'hg status' is not empty, it means the file ohair@314: # hasn't been committed, so don't fetch comments. ohair@314: if [[ -z $active ]] ; then ohair@314: if [[ -n $ALL_CREV ]]; then ohair@314: rev_opt= ohair@314: for rev in $ALL_CREV; do ohair@314: rev_opt="$rev_opt --rev $rev" ohair@314: done ohair@314: comm=`hg log $rev_opt --follow --template 'rev {rev} : {desc}\n' $logf` ohair@314: elif [[ -n $FIRST_CREV ]]; then ohair@314: comm=`hg log --rev $FIRST_CREV:tip --follow --template 'rev {rev} : {desc}\n' $logf` ohair@314: else ohair@314: comm=`hg log -l1 --follow --template 'rev {rev} : {desc}\n' $logf` ohair@314: fi ohair@314: else ohair@314: comm="" ohair@314: fi ohair@314: if [[ $fmt == "text" ]]; then ohair@314: print "$comm" ohair@314: return ohair@314: fi mduigou@616: mduigou@851: print "$comm" | html_quote | bug2url ohair@314: ) ohair@314: fi ohair@314: } ohair@314: ohair@314: ohair@314: # ohair@314: # getcomments {text|html} filepath parentpath ohair@314: # ohair@314: # Fetch the comments depending on what SCM mode we're in. ohair@314: # ohair@314: getcomments() ohair@314: { ohair@314: typeset fmt=$1 ohair@314: typeset p=$2 ohair@314: typeset pp=$3 ohair@314: mduigou@851: comments_from_mercurial $fmt $pp $p ohair@314: } ohair@314: ohair@314: # ohair@314: # printCI ohair@314: # ohair@314: # Print out Code Inspection figures similar to sccs-prt(1) format. ohair@314: # ohair@314: function printCI ohair@314: { ohair@314: integer tot=$1 ins=$2 del=$3 mod=$4 unc=$5 ohair@314: typeset str ohair@314: if (( tot == 1 )); then ohair@314: str="line" ohair@314: else ohair@314: str="lines" ohair@314: fi ohair@314: printf '%d %s changed: %d ins; %d del; %d mod; %d unchg' \ ohair@314: $tot $str $ins $del $mod $unc ohair@314: } ohair@314: ohair@314: ohair@314: # ohair@314: # difflines ohair@314: # ohair@314: # Calculate and emit number of added, removed, modified and unchanged lines, ohair@314: # and total lines changed, the sum of added + removed + modified. ohair@314: # ohair@314: function difflines ohair@314: { ohair@314: integer tot mod del ins unc err ohair@314: typeset filename ohair@314: ohair@314: eval $( diff -e $1 $2 | $AWK ' ohair@314: # Change range of lines: N,Nc ohair@314: /^[0-9]*,[0-9]*c$/ { ohair@314: n=split(substr($1,1,length($1)-1), counts, ","); ohair@314: if (n != 2) { ohair@314: error=2 ohair@314: exit; ohair@314: } ohair@314: # ohair@314: # 3,5c means lines 3 , 4 and 5 are changed, a total of 3 lines. ohair@314: # following would be 5 - 3 = 2! Hence +1 for correction. ohair@314: # ohair@314: r=(counts[2]-counts[1])+1; ohair@314: ohair@314: # ohair@314: # Now count replacement lines: each represents a change instead ohair@314: # of a delete, so increment c and decrement r. ohair@314: # ohair@314: while (getline != /^\.$/) { ohair@314: c++; ohair@314: r--; ohair@314: } ohair@314: # ohair@314: # If there were more replacement lines than original lines, ohair@314: # then r will be negative; in this case there are no deletions, ohair@314: # but there are r changes that should be counted as adds, and ohair@314: # since r is negative, subtract it from a and add it to c. ohair@314: # ohair@314: if (r < 0) { ohair@314: a-=r; ohair@314: c+=r; ohair@314: } ohair@314: ohair@314: # ohair@314: # If there were more original lines than replacement lines, then ohair@314: # r will be positive; in this case, increment d by that much. ohair@314: # ohair@314: if (r > 0) { ohair@314: d+=r; ohair@314: } ohair@314: next; ohair@314: } ohair@314: ohair@314: # Change lines: Nc ohair@314: /^[0-9].*c$/ { ohair@314: # The first line is a replacement; any more are additions. ohair@314: if (getline != /^\.$/) { ohair@314: c++; ohair@314: while (getline != /^\.$/) a++; ohair@314: } ohair@314: next; ohair@314: } ohair@314: ohair@314: # Add lines: both Na and N,Na ohair@314: /^[0-9].*a$/ { ohair@314: while (getline != /^\.$/) a++; ohair@314: next; ohair@314: } ohair@314: ohair@314: # Delete range of lines: N,Nd ohair@314: /^[0-9]*,[0-9]*d$/ { ohair@314: n=split(substr($1,1,length($1)-1), counts, ","); ohair@314: if (n != 2) { ohair@314: error=2 ohair@314: exit; ohair@314: } ohair@314: # ohair@314: # 3,5d means lines 3 , 4 and 5 are deleted, a total of 3 lines. ohair@314: # following would be 5 - 3 = 2! Hence +1 for correction. ohair@314: # ohair@314: r=(counts[2]-counts[1])+1; ohair@314: d+=r; ohair@314: next; ohair@314: } ohair@314: ohair@314: # Delete line: Nd. For example 10d says line 10 is deleted. ohair@314: /^[0-9]*d$/ {d++; next} ohair@314: ohair@314: # Should not get here! ohair@314: { ohair@314: error=1; ohair@314: exit; ohair@314: } ohair@314: ohair@314: # Finish off - print results ohair@314: END { ohair@314: printf("tot=%d;mod=%d;del=%d;ins=%d;err=%d\n", ohair@314: (c+d+a), c, d, a, error); ohair@314: }' ) ohair@314: ohair@314: # End of $AWK, Check to see if any trouble occurred. ohair@314: if (( $? > 0 || err > 0 )); then ohair@314: print "Unexpected Error occurred reading" \ ohair@314: "\`diff -e $1 $2\`: \$?=$?, err=" $err ohair@314: return ohair@314: fi ohair@314: ohair@314: # Accumulate totals ohair@314: (( TOTL += tot )) ohair@314: (( TMOD += mod )) ohair@314: (( TDEL += del )) ohair@314: (( TINS += ins )) ohair@314: # Calculate unchanged lines ohair@314: unc=`wc -l < $1` ohair@314: if (( unc > 0 )); then ohair@314: (( unc -= del + mod )) ohair@314: (( TUNC += unc )) ohair@314: fi ohair@314: # print summary ohair@314: print "\c" ohair@314: printCI $tot $ins $del $mod $unc ohair@314: print "" ohair@314: } ohair@314: ohair@314: function outgoing_from_mercurial_forest ohair@314: { ohair@314: hg foutgoing --template 'rev: {rev}\n' $OUTPWS | $FILTER | $AWK ' ohair@314: BEGIN {ntree=0} ohair@314: /^comparing/ {next} ohair@314: /^no changes/ {next} ohair@314: /^searching/ {next} ohair@314: /^\[.*\]$/ {tree=substr($1,2,length($1)-2); ohair@314: trees[ntree++] = tree; ohair@314: revs[tree]=-1; ohair@314: next} ohair@314: /^rev:/ {rev=$2+0; ohair@314: if (revs[tree] == -1 || rev < revs[tree]) ohair@314: { revs[tree] = rev; }; ohair@314: next;} ohair@314: END {for (tree in trees) ohair@314: { rev=revs[trees[tree]]; mduigou@616: if (rev > 0) ohair@314: {printf("%s %d\n",trees[tree],rev-1)} ohair@314: }}' | while read LINE ohair@314: do ohair@314: set - $LINE ohair@314: TREE=$1 ohair@314: REV=$2 ohair@314: A=`hg -R $CWS/$TREE log --rev $REV --template '{node}'` ohair@314: FSTAT_OPT="--rev $A" ohair@314: print "Revision: $A $REV" >> $FLIST ohair@314: treestatus $TREE ohair@314: done ohair@314: } ohair@314: ohair@314: function flist_from_mercurial_forest ohair@314: { ohair@314: rm -f $FLIST ohair@314: if [ -z "$Nflag" ]; then jgish@678: print " File list from hg foutgoing $PWS ..." ohair@314: outgoing_from_mercurial_forest ohair@314: HG_LIST_FROM_COMMIT=1 ohair@314: fi ohair@314: if [ ! -f $FLIST ]; then ohair@314: # hg commit hasn't been run see what is lying around jgish@678: print "\n No outgoing, perhaps you haven't commited." jgish@678: print " File list from hg fstatus -mard ...\c" ohair@314: FSTAT_OPT= ohair@314: fstatus jgish@690: HG_LIST_FROM_COMMIT= ohair@314: fi ohair@314: print " Done." ohair@314: } ohair@314: ohair@314: # ohair@314: # Used when dealing with the result of 'hg foutgoing' ohair@314: # When now go down the tree and generate the change list ohair@314: # ohair@314: function treestatus ohair@314: { ohair@314: TREE=$1 ohair@314: HGCMD="hg -R $CWS/$TREE status $FSTAT_OPT" mduigou@616: ohair@314: $HGCMD -mdn 2>/dev/null | $FILTER | while read F ohair@314: do ohair@314: echo $TREE/$F ohair@314: done >> $FLIST ohair@314: ohair@314: # Then all the added files jgish@678: # But some of these could have been "moved" or renamed ones or copied ones ohair@314: # so let's make sure we get the proper info ohair@314: # hg status -aC will produce something like: ohair@314: # A subdir/File3 ohair@314: # A subdir/File4 ohair@314: # File4 ohair@314: # A subdir/File5 ohair@314: # The first and last are simple addition while the middle one jgish@678: # is a move/rename or a copy. We can't distinguish from a rename vs a copy jgish@678: # without also getting the status of removed files. The middle case above mduigou@792: # is a rename if File4 is also shown a being removed. If File4 is not a jgish@678: # removed file, then the middle case is a copy from File4 to subdir/File4 jgish@678: # FIXME - we're not distinguishing copy from rename ohair@314: $HGCMD -aC | $FILTER | while read LINE; do ohair@314: ldone="" ohair@314: while [ -z "$ldone" ]; do ohair@314: ldone="1" ohair@314: set - $LINE ohair@314: if [ $# -eq 2 -a "$1" == "A" ]; then ohair@314: AFILE=$2 ohair@314: if read LINE2; then ohair@314: set - $LINE2 ohair@314: if [ $# -eq 1 ]; then ohair@314: echo $TREE/$AFILE $TREE/$1 >>$FLIST ohair@314: elif [ $# -eq 2 ]; then ohair@314: echo $TREE/$AFILE >>$FLIST ohair@314: LINE=$LINE2 ohair@314: ldone="" ohair@314: fi ohair@314: else ohair@314: echo $TREE/$AFILE >>$FLIST ohair@314: fi ohair@314: fi ohair@314: done ohair@314: done ohair@314: $HGCMD -rn | $FILTER | while read RFILE; do ohair@314: grep "$TREE/$RFILE" $FLIST >/dev/null ohair@314: if [ $? -eq 1 ]; then ohair@314: echo $TREE/$RFILE >>$FLIST ohair@314: fi ohair@314: done ohair@314: } ohair@314: ohair@314: function fstatus ohair@314: { ohair@314: # ohair@314: # forest extension is still being changed. For instance the output ohair@314: # of fstatus used to no prepend the tree path to filenames, but ohair@314: # this has changed recently. AWK code below does try to handle both ohair@314: # cases ohair@314: # ohair@314: hg fstatus -mdn $FSTAT_OPT 2>/dev/null | $FILTER | $AWK ' ohair@314: /^\[.*\]$/ {tree=substr($1,2,length($1)-2); next} ohair@314: $1 != "" {n=index($1,tree); ohair@314: if (n == 0) ohair@314: { printf("%s/%s\n",tree,$1)} ohair@314: else ohair@314: { printf("%s\n",$1)}}' >> $FLIST ohair@314: ohair@314: # ohair@314: # There is a bug in the output of fstatus -aC on recent versions: it ohair@314: # inserts a space between the name of the tree and the filename of the ohair@314: # old file. e.g.: ohair@314: # ohair@314: # $ hg fstatus -aC ohair@314: # [.] ohair@314: # ohair@314: # [MyWS] ohair@314: # A MyWS/subdir/File2 ohair@314: # MyWS/ File2 ohair@314: # ohair@314: # [MyWS2] ohair@314: # ohair@314: ohair@314: hg fstatus -aC $FSTAT_OPT 2>/dev/null | $FILTER | $AWK ' ohair@314: /^\[.*\]$/ {tree=substr($1,2,length($1)-2); next} ohair@314: /^A .*/ {n=index($2,tree); ohair@314: if (n == 0) ohair@314: { printf("A %s/%s\n",tree,$2)} ohair@314: else mduigou@616: { printf("A %s\n",$2)}; ohair@314: next} ohair@314: /^ / {n=index($1,tree); ohair@314: if (n == 0) ohair@314: { printf("%s/%s\n",tree,$1)} ohair@314: else ohair@314: { if (NF == 2) ohair@314: printf("%s/%s\n",tree,$2) ohair@314: else ohair@314: printf("%s\n",$1) ohair@314: }; ohair@314: next} ohair@314: ' | while read LINE; do ohair@314: ldone="" ohair@314: while [ -z "$ldone" ]; do ohair@314: ldone="1" ohair@314: set - $LINE ohair@314: if [ $# -eq 2 -a "$1" == "A" ]; then ohair@314: AFILE=$2 ohair@314: if read LINE2; then ohair@314: set - $LINE2 ohair@314: if [ $# -eq 1 ]; then ohair@314: echo $AFILE $1 >>$FLIST ohair@314: elif [ $# -eq 2 ]; then ohair@314: echo $AFILE >>$FLIST ohair@314: LINE=$LINE2 ohair@314: ldone="" ohair@314: fi ohair@314: else ohair@314: echo $AFILE >>$FLIST ohair@314: fi ohair@314: fi ohair@314: done ohair@314: done ohair@314: hg fstatus -rn $FSTAT_OPT 2>/dev/null | $FILTER | $AWK ' ohair@314: /^\[.*\]$/ {tree=substr($1,2,length($1)-2); next} ohair@314: $1 != "" {n=index($1,tree); ohair@314: if (n == 0) ohair@314: { printf("%s/%s\n",tree,$1)} ohair@314: else ohair@314: { printf("%s\n",$1)}}' | while read RFILE; do ohair@314: grep "$RFILE" $FLIST >/dev/null ohair@314: if [ $? -eq 1 ]; then ohair@314: echo $RFILE >>$FLIST ohair@314: fi ohair@314: done ohair@314: } ohair@314: ohair@314: # ohair@314: # flist_from_mercurial $PWS ohair@314: # ohair@314: # Only local file based repositories are supported at present ohair@314: # since even though we can determine the list from the parent finding ohair@314: # the changes is harder. ohair@314: # ohair@314: # We first look for any outgoing files, this is for when the user has ohair@314: # run hg commit. If we don't find any then we look with hg status. ohair@314: # ohair@314: # We need at least one of default-push or default paths set in .hg/hgrc ohair@314: # If neither are set we don't know who to compare with. ohair@314: mduigou@616: function flist_from_mercurial ohair@314: { ohair@314: # if [ "${PWS##ssh://}" != "$PWS" -o \ ohair@314: # "${PWS##http://}" != "$PWS" -o \ ohair@314: # "${PWS##https://}" != "$PWS" ]; then ohair@314: # print "Remote Mercurial repositories not currently supported." ohair@314: # print "Set default and/or default-push to a local repository" ohair@314: # exit ohair@314: # fi ohair@314: if [[ -n $forestflag ]]; then ohair@314: HG_LIST_FROM_COMMIT= ohair@314: flist_from_mercurial_forest ohair@314: else ohair@314: STATUS_REV= ohair@314: if [[ -n $rflag ]]; then ohair@314: STATUS_REV="--rev $PARENT_REV" ohair@314: elif [[ -n $OUTREV ]]; then ohair@314: STATUS_REV="--rev $OUTREV" ohair@314: else ohair@314: # hg commit hasn't been run see what is lying around ohair@314: print "\n No outgoing, perhaps you haven't commited." ohair@314: fi ohair@314: # First let's list all the modified or deleted files ohair@314: ohair@314: hg status $STATUS_REV -mdn | $FILTER > $FLIST ohair@314: ohair@314: # Then all the added files ohair@314: # But some of these could have been "moved" or renamed ones ohair@314: # so let's make sure we get the proper info ohair@314: # hg status -aC will produce something like: ohair@314: # A subdir/File3 ohair@314: # A subdir/File4 ohair@314: # File4 ohair@314: # A subdir/File5 jgish@678: # The first and last are simple addition while the middle one jgish@678: # is a move/rename or a copy. We can't distinguish from a rename vs a copy jgish@678: # without also getting the status of removed files. The middle case above mduigou@792: # is a rename if File4 is also shown a being removed. If File4 is not a jgish@678: # removed file, then the middle case is a copy from File4 to subdir/File4 jgish@678: # FIXME - we're not distinguishing copy from rename ohair@314: ohair@314: hg status $STATUS_REV -aC | $FILTER >$FLIST.temp ohair@314: while read LINE; do ohair@314: ldone="" ohair@314: while [ -z "$ldone" ]; do ohair@314: ldone="1" ohair@314: set - $LINE ohair@314: if [ $# -eq 2 -a "$1" == "A" ]; then ohair@314: AFILE=$2 ohair@314: if read LINE2; then ohair@314: set - $LINE2 ohair@314: if [ $# -eq 1 ]; then ohair@314: echo $AFILE $1 >>$FLIST ohair@314: elif [ $# -eq 2 ]; then ohair@314: echo $AFILE >>$FLIST ohair@314: LINE=$LINE2 ohair@314: ldone="" ohair@314: fi ohair@314: else ohair@314: echo $AFILE >>$FLIST ohair@314: fi ohair@314: fi ohair@314: done ohair@314: done < $FLIST.temp ohair@314: hg status $STATUS_REV -rn | $FILTER > $FLIST.temp ohair@314: while read RFILE; do ohair@314: grep "$RFILE" $FLIST >/dev/null ohair@314: if [ $? -eq 1 ]; then ohair@314: echo $RFILE >>$FLIST ohair@314: fi ohair@314: done < $FLIST.temp ohair@314: rm -f $FLIST.temp ohair@314: fi ohair@314: } ohair@314: ohair@314: function env_from_flist ohair@314: { ohair@314: [[ -r $FLIST ]] || return ohair@314: ohair@314: # ohair@314: # Use "eval" to set env variables that are listed in the file ohair@314: # list. Then copy those into our local versions of those ohair@314: # variables if they have not been set already. ohair@314: # ohair@314: eval `sed -e "s/#.*$//" $FLIST | grep = ` ohair@314: ohair@314: [[ -z $codemgr_ws && -n $CODEMGR_WS ]] && codemgr_ws=$CODEMGR_WS ohair@314: ohair@314: # ohair@314: # Check to see if CODEMGR_PARENT is set in the flist file. ohair@314: # ohair@314: [[ -z $codemgr_parent && -n $CODEMGR_PARENT ]] && \ ohair@314: codemgr_parent=$CODEMGR_PARENT ohair@314: } ohair@314: ohair@314: # ohair@314: # detect_scm ohair@314: # ohair@314: # We dynamically test the SCM type; this allows future extensions to ohair@314: # new SCM types ohair@314: # ohair@314: function detect_scm ohair@314: { mduigou@851: if hg root >/dev/null ; then ohair@314: print "mercurial" ohair@314: else ohair@314: print "unknown" ohair@314: fi ohair@314: } ohair@314: ohair@314: function look_for_prog ohair@314: { ohair@314: typeset path ohair@314: typeset ppath ohair@314: typeset progname=$1 ohair@314: ohair@314: DEVTOOLS= ohair@314: OS=`uname` ohair@314: if [[ "$OS" == "SunOS" ]]; then ohair@314: DEVTOOLS="/java/devtools/`uname -p`/bin" ohair@314: elif [[ "$OS" == "Linux" ]]; then ohair@314: DEVTOOLS="/java/devtools/linux/bin" ohair@314: fi mduigou@616: ohair@314: ppath=$PATH ohair@314: ppath=$ppath:/usr/sfw/bin:/usr/bin:/usr/sbin ohair@314: ppath=$ppath:/opt/teamware/bin:/opt/onbld/bin ohair@314: ppath=$ppath:/opt/onbld/bin/`uname -p` ohair@314: ppath=$ppath:/java/devtools/share/bin:$DEVTOOLS ohair@314: ohair@314: PATH=$ppath prog=`whence $progname` ohair@314: if [[ -n $prog ]]; then ohair@314: print $prog ohair@314: fi ohair@314: } ohair@314: ohair@314: # ohair@314: # Find the parent for $1 ohair@314: # ohair@314: function find_outrev ohair@314: { ohair@314: crev=$1 ohair@314: prev=`hg log -r $crev --template '{parents}\n'` ohair@314: if [[ -z "$prev" ]] ohair@314: then ohair@314: # No specific parent means previous changeset is parent ohair@314: prev=`expr $crev - 1` ohair@314: else ohair@314: # Format is either of the following two: ohair@314: # 546:7df6fcf1183b ohair@314: # 548:16f1915bb5cd 547:ffaa4e775815 ohair@314: prev=`echo $prev | sed -e 's/\([0-9]*\):.*/\1/'` ohair@314: fi ohair@314: print $prev ohair@314: } ohair@314: ohair@314: function extract_ssh_infos ohair@314: { ohair@314: CMD=$1 ohair@314: if expr "$CMD" : 'ssh://[^/]*@' >/dev/null; then ohair@314: ssh_user=`echo $CMD | sed -e 's/ssh:\/\/\(.*\)@.*/\1/'` ohair@314: ssh_host=`echo $CMD | sed -e 's/ssh:\/\/.*@\([^/]*\)\/.*/\1/'` ohair@314: ssh_dir=`echo $CMD | sed -e 's/ssh:\/\/.*@[^/]*\/\(.*\)/\1/'` ohair@314: else ohair@314: ssh_user= ohair@314: ssh_host=`echo $CMD | sed -e 's/ssh:\/\/\([^/]*\)\/.*/\1/'` ohair@314: ssh_dir=`echo $CMD | sed -e 's/ssh:\/\/[^/]*\/\(.*\)/\1/'` ohair@314: fi mduigou@616: ohair@314: } ohair@314: ohair@314: function build_old_new_mercurial ohair@314: { ohair@314: olddir=$1 ohair@314: newdir=$2 ohair@314: DIR=$3 ohair@314: F=$4 ohair@314: # ohair@314: # new version of the file. ohair@314: # ohair@314: rm -rf $newdir/$DIR/$F ohair@314: if [ -f $F ]; then ohair@314: cp $F $newdir/$DIR/$F ohair@314: fi ohair@314: ohair@314: # ohair@314: # Old version of the file. ohair@314: # ohair@314: rm -rf $olddir/$DIR/$F ohair@314: ohair@314: if [ -n "$PWS" ]; then ohair@314: if expr "$PWS" : 'ssh://' >/dev/null ohair@314: then ohair@314: extract_ssh_infos $PWS ohair@314: if [ -n "$ssh_user" ]; then ohair@314: parent="ssh -l $ssh_user $ssh_host hg -R $ssh_dir --cwd $ssh_dir" ohair@314: else ohair@314: parent="ssh $ssh_host hg -R $ssh_dir --cwd $ssh_dir" ohair@314: fi ohair@314: else ohair@314: parent="hg -R $PWS --cwd $PWS" ohair@314: fi ohair@314: else ohair@314: parent="" ohair@314: fi ohair@314: ohair@314: if [ -z "$rename" ]; then ohair@314: if [ -n "$rflag" ]; then ohair@314: parentrev=$PARENT_REV ohair@314: elif [ "$HG_LIST_FROM_COMMIT" -eq 1 ]; then ohair@314: parentrev=$OUTREV ohair@314: else ohair@314: if [[ -n $HG_BRANCH ]]; then ohair@314: parentrev=$HG_BRANCH ohair@314: else ohair@314: parentrev="tip" ohair@314: fi ohair@314: fi ohair@314: ohair@314: if [ -n "$parentrev" ]; then ohair@314: if [ -z "$parent" ]; then ohair@314: hg cat --rev $parentrev --output $olddir/$DIR/$F $F 2>/dev/null ohair@314: else ohair@314: # when specifying a workspace we have to provide ohair@314: # the full path ohair@314: $parent cat --rev $parentrev --output $olddir/$DIR/$F $DIR/$F 2>/dev/null ohair@314: fi ohair@314: fi ohair@314: else jgish@678: # It's a rename (or a move), or a copy, so let's make sure we move ohair@314: # to the right directory first, then restore it once done ohair@314: current_dir=`pwd` ohair@314: cd $CWS/$PDIR ohair@314: if [ -n "$rflag" ]; then ohair@314: parentrev=$PARENT_REV ohair@314: elif [ "$HG_LIST_FROM_COMMIT" -eq 1 ]; then ohair@314: parentrev=$OUTREV ohair@314: fi ohair@314: if [ -z "$parentrev" ]; then ohair@314: parentrev=`hg log -l1 $PF | $AWK -F: '/changeset/ {print $2}'` ohair@314: fi ohair@314: if [ -n "$parentrev" ]; then ohair@314: mkdir -p $olddir/$PDIR ohair@314: if [ -z "$parent" ]; then ohair@314: hg cat --rev $parentrev --output $olddir/$PDIR/$PF $PF 2>/dev/null ohair@314: else ohair@314: $parent cat --rev $parentrev --output $olddir/$PDIR/$PF $PDIR/$PF 2>/dev/null ohair@314: fi ohair@314: fi ohair@314: cd $current_dir ohair@314: fi ohair@314: } ohair@314: ohair@314: function build_old_new ohair@314: { ohair@314: if [[ $SCM_MODE == "mercurial" ]]; then ohair@314: build_old_new_mercurial $@ ohair@314: fi ohair@314: } ohair@314: ohair@314: ohair@314: # ohair@314: # Usage message. ohair@314: # ohair@314: function usage ohair@314: { mduigou@851: print "Usage:\twebrev [options] mduigou@851: webrev [options] ( | - ) ohair@314: ohair@314: Options: ohair@314: -v: Print the version of this tool. ohair@314: -b: Do not ignore changes in the amount of white space. ohair@314: -c : Include link to CR (aka bugid) in the main page. ohair@314: -i : Include in the index.html file. ohair@314: -o : Output webrev to specified directory. ohair@314: -p : Use specified parent wkspc or basis for comparison ohair@314: -u : Use that username instead of 'guessing' one. ohair@314: -m: Forces the use of Mercurial ohair@314: ohair@314: Mercurial only options: ohair@314: -r rev: Compare against a specified revision ohair@314: -N: Skip 'hg outgoing', use only 'hg status' ohair@314: -f: Use the forest extension ohair@314: mduigou@851: Arguments: mduigou@851: : Optional file containing list of files to include in webrev mduigou@851: -: read list of files to include in webrev from standard input mduigou@851: ohair@314: Environment: ohair@314: WDIR: Control the output directory. ohair@314: WEBREV_BUGURL: Control the URL prefix for bugids. ohair@314: ohair@314: " ohair@314: ohair@314: exit 2 ohair@314: } ohair@314: ohair@314: # ohair@314: # ohair@314: # Main program starts here ohair@314: # ohair@314: # ohair@314: LANG="C" ohair@314: LC_ALL="C" ohair@314: export LANG LC_ALL ohair@314: trap "rm -f /tmp/$$.* ; exit" 0 1 2 3 15 ohair@314: ohair@314: set +o noclobber ohair@314: ohair@314: [[ -z $WDIFF ]] && WDIFF=`look_for_prog wdiff` ohair@314: [[ -z $CODEREVIEW ]] && CODEREVIEW=`look_for_prog codereview` ohair@314: [[ -z $PS2PDF ]] && PS2PDF=`look_for_prog ps2pdf` ohair@314: [[ -z $PERL ]] && PERL=`look_for_prog perl` ohair@314: [[ -z $SCCS ]] && SCCS=`look_for_prog sccs` ohair@314: [[ -z $AWK ]] && AWK=`look_for_prog nawk` ohair@314: [[ -z $AWK ]] && AWK=`look_for_prog gawk` ohair@314: [[ -z $AWK ]] && AWK=`look_for_prog awk` ohair@314: [[ -z $JAR ]] && JAR=`look_for_prog jar` ohair@314: [[ -z $ZIP ]] && ZIP=`look_for_prog zip` ohair@314: [[ -z $GETENT ]] && GETENT=`look_for_prog getent` ohair@314: [[ -z $WGET ]] && WGET=`look_for_prog wget` ohair@314: ohair@314: if uname | grep CYGWIN >/dev/null ohair@314: then ohair@314: ISWIN=1 ohair@314: # Under windows mercurial outputs '\' instead of '/' ohair@314: FILTER="tr '\\\\' '/'" ohair@314: else ohair@314: FILTER="cat" ohair@314: fi ohair@314: ohair@314: if [[ ! -x $PERL ]]; then ohair@314: print -u2 "Error: No perl interpreter found. Exiting." ohair@314: exit 1 ohair@314: fi ohair@314: ohair@314: # ohair@314: # These aren't fatal, but we want to note them to the user. ohair@314: # ohair@314: # [[ ! -x $CODEREVIEW ]] && print -u2 "WARNING: codereview(1) not found." ohair@314: # [[ ! -x $PS2PDF ]] && print -u2 "WARNING: ps2pdf(1) not found." ohair@314: # [[ ! -x $WDIFF ]] && print -u2 "WARNING: wdiff not found." ohair@314: ohair@314: # Declare global total counters. ohair@314: integer TOTL TINS TDEL TMOD TUNC ohair@314: ohair@314: flist_mode= ohair@314: flist_file= ohair@314: bflag= ohair@314: iflag= ohair@314: oflag= ohair@314: pflag= ohair@314: uflag= ohair@314: Oflag= ohair@314: rflag= ohair@314: Nflag= ohair@314: forestflag= mduigou@851: while getopts "c:i:o:p:r:u:mONvfb" opt ohair@314: do ohair@314: case $opt in ohair@314: b) bflag=1;; ohair@314: ohair@314: i) iflag=1 ohair@314: INCLUDE_FILE=$OPTARG;; ohair@314: ohair@314: o) oflag=1 ohair@314: WDIR=$OPTARG;; ohair@314: ohair@314: p) pflag=1 ohair@314: codemgr_parent=$OPTARG;; ohair@314: ohair@314: u) uflag=1 ohair@314: username=$OPTARG;; ohair@314: ohair@314: c) if [[ -z $CRID ]]; then ohair@314: CRID=$OPTARG ohair@314: else ohair@314: CRID="$CRID $OPTARG" ohair@314: fi;; ohair@314: ohair@314: m) SCM_MODE="mercurial";; ohair@314: mduigou@851: O) Oflag=1;; # ignored (bugs are now all visible at bugs.openjdk.java.net) ohair@314: ohair@314: N) Nflag=1;; ohair@314: ohair@314: f) forestflag=1;; ohair@314: ohair@314: r) rflag=1 ohair@314: PARENT_REV=$OPTARG;; ohair@314: ohair@314: v) print "$0 version: $WEBREV_UPDATED";; mduigou@616: ohair@314: ohair@314: ?) usage;; ohair@314: esac ohair@314: done ohair@314: ohair@314: FLIST=/tmp/$$.flist jgish@690: HG_LIST_FROM_COMMIT= ohair@314: ohair@314: if [[ -n $forestflag && -n $rflag ]]; then ohair@314: print "The -r flag is incompatible with the use of forests" ohair@314: exit 2 ohair@314: fi ohair@314: ohair@314: # ohair@314: # If this manually set as the parent, and it appears to be an earlier webrev, ohair@314: # then note that fact and set the parent to the raw_files/new subdirectory. ohair@314: # ohair@314: if [[ -n $pflag && -d $codemgr_parent/raw_files/new ]]; then ohair@314: parent_webrev="$codemgr_parent" ohair@314: codemgr_parent="$codemgr_parent/raw_files/new" ohair@314: fi ohair@314: mduigou@851: shift $(($OPTIND - 1)) ohair@314: mduigou@851: if [[ $1 == "-" ]]; then mduigou@851: cat > $FLIST mduigou@851: flist_mode="stdin" mduigou@851: flist_done=1 mduigou@851: shift mduigou@851: elif [[ -n $1 ]]; then mduigou@851: if [[ ! -r $1 ]]; then mduigou@851: print -u2 "$1: no such file or not readable" mduigou@851: usage ohair@314: fi mduigou@851: cat $1 > $FLIST mduigou@851: flist_mode="file" mduigou@851: flist_file=$1 mduigou@851: flist_done=1 mduigou@851: shift mduigou@851: else mduigou@851: flist_mode="auto" ohair@314: fi ohair@314: ohair@314: # ohair@314: # Before we go on to further consider -l and -w, work out which SCM we think ohair@314: # is in use. ohair@314: # ohair@314: if [[ -z $SCM_MODE ]]; then ohair@314: SCM_MODE=`detect_scm $FLIST` ohair@314: fi ohair@314: if [[ $SCM_MODE == "unknown" ]]; then mduigou@851: print -u2 "Unable to determine SCM type currently in use." mduigou@851: print -u2 "For mercurial: webrev runs 'hg root'." mduigou@851: exit 1 ohair@314: fi ohair@314: ohair@314: print -u2 " SCM detected: $SCM_MODE" ohair@314: ohair@314: ohair@314: if [[ $SCM_MODE == "mercurial" ]]; then ohair@314: # ohair@314: # determine Workspace and parent workspace paths ohair@314: # ohair@314: CWS=`hg root | $FILTER` ohair@314: if [[ -n $pflag && -z "$PWS" ]]; then ohair@314: OUTPWS=$codemgr_parent ohair@314: # Let's try to expand it if it's an alias defined in [paths] ohair@314: tmp=`hg path $OUTPWS 2>/dev/null | $FILTER` ohair@314: if [[ -n $tmp ]]; then ohair@314: OUTPWS="$tmp" ohair@314: fi ohair@314: if [[ -n $rflag ]]; then ohair@314: if expr "$codemgr_parent" : 'ssh://.*' >/dev/null; then ohair@314: PWS=$codemgr_parent ohair@314: else ohair@314: PWS=`hg -R "$codemgr_parent" root 2>/dev/null | $FILTER` ohair@314: fi ohair@314: fi ohair@314: fi ohair@314: # ohair@314: # OUTPWS is the parent repository to use when using 'hg outgoing' ohair@314: # ohair@314: if [[ -z $Nflag ]]; then ohair@314: if [[ -n $forestflag ]]; then ohair@314: # ohair@314: # for forest we have to rely on properly set default and ohair@314: # default-push because they can be different from the top one. mduigou@851: # unless of course it was explicitly specified with -p ohair@314: if [[ -z $pflag ]]; then ohair@314: OUTPWS= ohair@314: fi ohair@314: else ohair@314: # ohair@314: # Unfortunately mercurial is bugged and doesn't handle ohair@314: # aliases correctly in 'hg path default' ohair@314: # So let's do it ourselves. Sigh... ohair@314: if [[ -z "$OUTPWS" ]]; then ohair@314: OUTPWS=`grep default-push $CWS/.hg/hgrc | $AWK '{print $3}' | $FILTER` ohair@314: fi ohair@314: # Still empty, means no default-push ohair@314: if [[ -z "$OUTPWS" ]]; then ohair@314: OUTPWS=`grep 'default =' $CWS/.hg/hgrc | $AWK '{print $3}' | $FILTER` ohair@314: fi ohair@314: # Let's try to expand it if it's an alias defined in [paths] ohair@314: tmp=`hg path $OUTPWS 2>/dev/null | $FILTER` ohair@314: if [[ -n $tmp ]]; then ohair@314: OUTPWS="$tmp" ohair@314: fi ohair@314: fi ohair@314: fi ohair@314: # ohair@314: # OUTPWS may contain username:password, let's make sure we remove the ohair@314: # sensitive information before we print out anything in the HTML ohair@314: # ohair@314: OUTPWS2=$OUTPWS ohair@314: if [[ -n $OUTPWS ]]; then ohair@314: if [[ `expr "$OUTPWS" : '.*://[^/]*@.*'` -gt 0 ]]; then ohair@314: # Remove everything between '://' and '@' ohair@314: OUTPWS2=`echo $OUTPWS | sed -e 's/\(.*:\/\/\).*@\(.*\)/\1\2/'` ohair@314: fi ohair@314: fi ohair@314: ohair@314: if [[ -z $HG_BRANCH ]]; then ohair@314: HG_BRANCH=`hg branch` ohair@314: if [ "$HG_BRANCH" == "default" ]; then ohair@314: # ohair@314: # 'default' means no particular branch, so let's cancel that ohair@314: # ohair@314: HG_BRANCH= ohair@314: fi ohair@314: fi ohair@314: ohair@314: if [[ -z $forestflag ]]; then ohair@314: if [[ -z $Nflag ]]; then ohair@314: # ohair@314: # If no "-N", always do "hg outgoing" against parent ohair@314: # repository to determine list of outgoing revisions. ohair@314: # ohair@314: ALL_CREV=`hg outgoing -q --template '{rev}\n' $OUTPWS | sort -n` ohair@314: if [[ -n $ALL_CREV ]]; then ohair@314: FIRST_CREV=`echo "$ALL_CREV" | head -1` ohair@314: # ohair@314: # If no "-r", choose revision to compare against by ohair@314: # finding the latest revision not in the outgoing list. ohair@314: # ohair@314: if [[ -z $rflag ]]; then ohair@314: OUTREV=`find_outrev "$FIRST_CREV"` ohair@314: if [[ -n $OUTREV ]]; then ohair@314: HG_LIST_FROM_COMMIT=1 ohair@314: fi ohair@314: fi ohair@314: fi ohair@314: elif [[ -n $rflag ]]; then ohair@314: # ohair@314: # If skipping "hg outgoing" but still comparing against a ohair@314: # specific revision (not the tip), set revision for comment ohair@314: # accumulation. ohair@314: # ohair@314: FIRST_CREV=`hg log --rev $PARENT_REV --template '{rev}'` ohair@314: FIRST_CREV=`expr $FIRST_CREV + 1` ohair@314: fi ohair@314: fi ohair@314: #Let's check if a merge is needed, if so, issue a warning ohair@314: PREV=`hg parent | grep '^tag:.*tip$'` ohair@314: if [[ -z $PREV ]]; then ohair@314: print "WARNING: parent rev is not tip. Maybe an update or merge is needed" ohair@314: fi ohair@314: fi ohair@314: mduigou@851: if [[ $flist_mode == "stdin" ]]; then ohair@314: print -u2 " File list from: standard input" ohair@314: elif [[ $flist_mode == "file" ]]; then ohair@314: print -u2 " File list from: $flist_file" ohair@314: fi ohair@314: ohair@314: if [[ $# -gt 0 ]]; then ohair@314: print -u2 "WARNING: unused arguments: $*" ohair@314: fi ohair@314: mduigou@851: if [[ $SCM_MODE == "mercurial" ]]; then ohair@314: if [[ -z $flist_done ]]; then ohair@314: flist_from_mercurial $PWS ohair@314: fi ohair@314: fi ohair@314: ohair@314: # ohair@314: # If the user didn't specify a -i option, check to see if there is a ohair@314: # webrev-info file in the workspace directory. ohair@314: # ohair@314: if [[ -z $iflag && -r "$CWS/webrev-info" ]]; then ohair@314: iflag=1 ohair@314: INCLUDE_FILE="$CWS/webrev-info" ohair@314: fi ohair@314: ohair@314: if [[ -n $iflag ]]; then ohair@314: if [[ ! -r $INCLUDE_FILE ]]; then ohair@314: print -u2 "include file '$INCLUDE_FILE' does not exist or is" \ ohair@314: "not readable." ohair@314: exit 1 ohair@314: else ohair@314: # ohair@314: # $INCLUDE_FILE may be a relative path, and the script alters ohair@314: # PWD, so we just stash a copy in /tmp. ohair@314: # ohair@314: cp $INCLUDE_FILE /tmp/$$.include ohair@314: fi ohair@314: fi ohair@314: ohair@314: # ohair@314: # Output directory. ohair@314: # ohair@314: if [[ -z $WDIR ]]; then ohair@314: WDIR=$CWS/webrev ohair@314: else ohair@314: # If the output directory doesn't end with '/webrev' or '/webrev/' ohair@314: # then add '/webrev'. This is for backward compatibility ohair@314: if ! expr $WDIR : '.*/webrev/\?$' >/dev/null ohair@314: then ohair@314: WDIR=$WDIR/webrev ohair@314: fi ohair@314: fi ohair@314: # WDIR=${WDIR:-$CWS/webrev} ohair@314: ohair@314: # ohair@314: # Name of the webrev, derived from the workspace name; in the ohair@314: # future this could potentially be an option. ohair@314: # ohair@314: # Let's keep what's after the last '/' ohair@314: WNAME=${CWS##*/} ohair@314: ohair@314: # ohair@314: # If WDIR doesn't start with '/' or 'x:' prepend the current dir ohair@314: # ohair@314: if [ ${WDIR%%/*} ]; then ohair@314: if [[ -n $ISWIN ]]; then ohair@314: if [ ${WDIR%%[A-Za-z]:*} ]; then ohair@314: WDIR=$PWD/$WDIR ohair@314: fi ohair@314: else ohair@314: WDIR=$PWD/$WDIR ohair@314: fi ohair@314: fi ohair@314: ohair@314: if [[ ! -d $WDIR ]]; then ohair@314: mkdir -p $WDIR ohair@314: [[ $? != 0 ]] && exit 1 ohair@314: fi ohair@314: ohair@314: # ohair@314: # Summarize what we're going to do. ohair@314: # ohair@314: print " Workspace: $CWS" ohair@314: if [[ -n $parent_webrev ]]; then ohair@314: print "Compare against: webrev at $parent_webrev" ohair@314: elif [[ -n $OUTPWS2 ]]; then ohair@314: print "Compare against: $OUTPWS2" ohair@314: fi ohair@314: if [[ -n $HG_BRANCH ]]; then ohair@314: print " Branch: $HG_BRANCH" ohair@314: fi ohair@314: if [[ -n $rflag ]]; then ohair@314: print "Compare against version: $PARENT_REV" ohair@314: fi ohair@314: [[ -n $INCLUDE_FILE ]] && print " Including: $INCLUDE_FILE" ohair@314: print " Output to: $WDIR" ohair@314: ohair@314: # ohair@314: # Save the file list in the webrev dir ohair@314: # ohair@314: [[ ! $FLIST -ef $WDIR/file.list ]] && cp $FLIST $WDIR/file.list ohair@314: ohair@314: # ohair@314: # Bug IDs will be replaced by a URL. Order of precedence mduigou@851: # is: default location, $WEBREV_BUGURL ohair@314: # mduigou@792: BUGURL='https://bugs.openjdk.java.net/browse/' ohair@314: [[ -n $WEBREV_BUGURL ]] && BUGURL="$WEBREV_BUGURL" mduigou@851: IDPREFIX='JDK-' mduigou@616: ohair@314: ohair@314: rm -f $WDIR/$WNAME.patch jgish@690: rm -f $WDIR/$WNAME.changeset ohair@314: rm -f $WDIR/$WNAME.ps ohair@314: rm -f $WDIR/$WNAME.pdf ohair@314: ohair@314: touch $WDIR/$WNAME.patch ohair@314: ohair@314: print " Output Files:" ohair@314: ohair@314: # ohair@314: # Clean up the file list: Remove comments, blank lines and env variables. ohair@314: # ohair@314: sed -e "s/#.*$//" -e "/=/d" -e "/^[ ]*$/d" $FLIST > /tmp/$$.flist.clean ohair@314: FLIST=/tmp/$$.flist.clean ohair@314: ohair@314: # ohair@314: # Clean up residual raw files ohair@314: # ohair@314: if [ -d $WDIR/raw_files ]; then ohair@314: rm -rf $WDIR/raw_files 2>/dev/null ohair@314: fi ohair@314: ohair@314: # ohair@314: # Should we ignore changes in white spaces when generating diffs? mduigou@616: # ohair@314: if [[ -n $bflag ]]; then ohair@314: DIFFOPTS="-t" ohair@314: else ohair@314: DIFFOPTS="-bt" ohair@314: fi ohair@314: # ohair@314: # First pass through the files: generate the per-file webrev HTML-files. ohair@314: # ohair@314: while read LINE ohair@314: do ohair@314: set - $LINE ohair@314: P=$1 ohair@314: ohair@314: if [[ $1 == "Revision:" ]]; then ohair@314: OUTREV=$2 ohair@314: continue ohair@314: fi ohair@314: # ohair@314: # Normally, each line in the file list is just a pathname of a ohair@314: # file that has been modified or created in the child. A file ohair@314: # that is renamed in the child workspace has two names on the ohair@314: # line: new name followed by the old name. ohair@314: # ohair@314: oldname="" ohair@314: oldpath="" ohair@314: rename= ohair@314: if [[ $# -eq 2 ]]; then ohair@314: PP=$2 # old filename ohair@314: oldname=" (was $PP)" ohair@314: oldpath="$PP" ohair@314: rename=1 ohair@314: PDIR=${PP%/*} ohair@314: if [[ $PDIR == $PP ]]; then ohair@314: PDIR="." # File at root of workspace ohair@314: fi ohair@314: ohair@314: PF=${PP##*/} ohair@314: ohair@314: DIR=${P%/*} ohair@314: if [[ $DIR == $P ]]; then ohair@314: DIR="." # File at root of workspace ohair@314: fi ohair@314: ohair@314: F=${P##*/} ohair@314: else ohair@314: DIR=${P%/*} ohair@314: if [[ "$DIR" == "$P" ]]; then ohair@314: DIR="." # File at root of workspace ohair@314: fi ohair@314: ohair@314: F=${P##*/} ohair@314: ohair@314: PP=$P ohair@314: PDIR=$DIR ohair@314: PF=$F ohair@314: fi ohair@314: ohair@314: # Make the webrev directory if necessary as it may have been ohair@314: # removed because it was empty ohair@314: if [ ! -d $CWS/$DIR ]; then ohair@314: mkdir -p $CWS/$DIR ohair@314: fi ohair@314: ohair@314: COMM=`getcomments html $P $PP` ohair@314: ohair@314: print "\t$P$oldname\n\t\t\c" ohair@314: ohair@314: # Make the webrev mirror directory if necessary ohair@314: mkdir -p $WDIR/$DIR ohair@314: ohair@314: # cd to the directory so the names are short ohair@314: cd $CWS/$DIR ohair@314: ohair@314: # ohair@314: # We stash old and new files into parallel directories in /tmp ohair@314: # and do our diffs there. This makes it possible to generate ohair@314: # clean looking diffs which don't have absolute paths present. ohair@314: # ohair@314: olddir=$WDIR/raw_files/old ohair@314: newdir=$WDIR/raw_files/new ohair@314: mkdir -p $olddir ohair@314: mkdir -p $newdir ohair@314: mkdir -p $olddir/$PDIR ohair@314: mkdir -p $newdir/$DIR ohair@314: ohair@314: build_old_new $olddir $newdir $DIR $F ohair@314: ohair@314: if [[ ! -f $F && ! -f $olddir/$DIR/$F ]]; then ohair@314: print "*** Error: file not in parent or child" ohair@314: continue ohair@314: fi ohair@314: ohair@314: cd $WDIR/raw_files ohair@314: ofile=old/$PDIR/$PF ohair@314: nfile=new/$DIR/$F ohair@314: ohair@314: mv_but_nodiff= ohair@314: cmp $ofile $nfile > /dev/null 2>&1 ohair@314: if [[ $? == 0 && $rename == 1 ]]; then ohair@314: mv_but_nodiff=1 ohair@314: fi ohair@314: ohair@314: # ohair@314: # Cleaning up ohair@314: # ohair@314: rm -f $WDIR/$DIR/$F.cdiff.html ohair@314: rm -f $WDIR/$DIR/$F.udiff.html ohair@314: rm -f $WDIR/$DIR/$F.wdiff.html ohair@314: rm -f $WDIR/$DIR/$F.sdiff.html ohair@314: rm -f $WDIR/$DIR/$F-.html ohair@314: rm -f $WDIR/$DIR/$F.html ohair@314: ohair@314: its_a_jar= thurka@812: if expr $F : '.*\.jar' \| $F : '.*\.zip' >/dev/null; then ohair@314: its_a_jar=1 thurka@812: # It's a JAR or ZIP file, let's do it differently ohair@314: if [[ -z $JAR ]]; then thurka@812: print "No access to jar, so can't produce diffs for jar or zip files" ohair@314: else ohair@314: if [ -f $ofile ]; then ohair@314: $JAR -tvf $ofile >"$ofile".lst ohair@314: fi ohair@314: if [ -f $nfile ]; then ohair@314: $JAR -tvf $nfile >"$nfile".lst ohair@314: fi ohair@314: ohair@314: if [[ -f $ofile && -f $nfile && -z $mv_but_nodiff ]]; then ohair@314: ohair@314: ${CDIFFCMD:-diff -bt -C 5} $ofile.lst $nfile.lst > $WDIR/$DIR/$F.cdiff ohair@314: diff_to_html $F $DIR/$F "C" "$COMM" < $WDIR/$DIR/$F.cdiff \ ohair@314: > $WDIR/$DIR/$F.cdiff.html ohair@314: print " cdiffs\c" ohair@314: ohair@314: ${UDIFFCMD:-diff -bt -U 5} $ofile.lst $nfile.lst > $WDIR/$DIR/$F.udiff ohair@314: diff_to_html $F $DIR/$F "U" "$COMM" < $WDIR/$DIR/$F.udiff \ ohair@314: > $WDIR/$DIR/$F.udiff.html ohair@314: ohair@314: print " udiffs\c" ohair@314: ohair@314: if [[ -x $WDIFF ]]; then ohair@314: $WDIFF -c "$COMM" \ ohair@314: -t "$WNAME Wdiff $DIR/$F" $ofile.lst $nfile.lst > \ ohair@314: $WDIR/$DIR/$F.wdiff.html 2>/dev/null ohair@314: if [[ $? -eq 0 ]]; then ohair@314: print " wdiffs\c" ohair@314: else ohair@314: print " wdiffs[fail]\c" ohair@314: fi ohair@314: fi ohair@314: ohair@314: sdiff_to_html $ofile $nfile $F $DIR "$COMM" \ ohair@314: > $WDIR/$DIR/$F.sdiff.html ohair@314: print " sdiffs\c" ohair@314: ohair@314: print " frames\c" ohair@314: ohair@314: rm -f $WDIR/$DIR/$F.cdiff $WDIR/$DIR/$F.udiff ohair@314: ohair@314: difflines $ofile.lst $nfile.lst > $WDIR/$DIR/$F.count ohair@314: ohair@314: elif [[ -f $ofile && -f $nfile && -n $mv_but_nodiff ]]; then ohair@314: # renamed file: may also have differences ohair@314: difflines $ofile.lst $nfile.lst > $WDIR/$DIR/$F.count ohair@314: elif [[ -f $nfile ]]; then ohair@314: # new file: count added lines ohair@314: difflines /dev/null $nfile.lst > $WDIR/$DIR/$F.count ohair@314: elif [[ -f $ofile ]]; then ohair@314: # old file: count deleted lines ohair@314: difflines $ofile.lst /dev/null > $WDIR/$DIR/$F.count ohair@314: fi ohair@314: fi ohair@314: else mduigou@616: ohair@314: # ohair@314: # If we have old and new versions of the file then run the ohair@314: # appropriate diffs. This is complicated by a couple of factors: ohair@314: # ohair@314: # - renames must be handled specially: we emit a 'remove' ohair@314: # diff and an 'add' diff ohair@314: # - new files and deleted files must be handled specially ohair@314: # - Solaris patch(1m) can't cope with file creation ohair@314: # (and hence renames) as of this writing. ohair@314: # - To make matters worse, gnu patch doesn't interpret the ohair@314: # output of Solaris diff properly when it comes to ohair@314: # adds and deletes. We need to do some "cleansing" ohair@314: # transformations: ohair@314: # [to add a file] @@ -1,0 +X,Y @@ --> @@ -0,0 +X,Y @@ ohair@314: # [to del a file] @@ -X,Y +1,0 @@ --> @@ -X,Y +0,0 @@ ohair@314: # ohair@314: cleanse_rmfile="sed 's/^\(@@ [0-9+,-]*\) [0-9+,-]* @@$/\1 +0,0 @@/'" ohair@314: cleanse_newfile="sed 's/^@@ [0-9+,-]* \([0-9+,-]* @@\)$/@@ -0,0 \1/'" ohair@314: jgish@690: if [[ ! "$HG_LIST_FROM_COMMIT" -eq 1 || ! $flist_mode == "auto" ]]; jgish@678: then jgish@678: # Only need to generate a patch file here if there are no commits in outgoing jgish@690: # or if we've specified a file list jgish@678: rm -f $WDIR/$DIR/$F.patch jgish@678: if [[ -z $rename ]]; then jgish@678: if [ ! -f $ofile ]; then jgish@678: diff -u /dev/null $nfile | sh -c "$cleanse_newfile" \ jgish@678: > $WDIR/$DIR/$F.patch jgish@678: elif [ ! -f $nfile ]; then jgish@678: diff -u $ofile /dev/null | sh -c "$cleanse_rmfile" \ jgish@678: > $WDIR/$DIR/$F.patch jgish@678: else jgish@678: diff -u $ofile $nfile > $WDIR/$DIR/$F.patch jgish@678: fi jgish@678: else jgish@678: diff -u $ofile /dev/null | sh -c "$cleanse_rmfile" \ jgish@678: > $WDIR/$DIR/$F.patch jgish@678: jgish@678: diff -u /dev/null $nfile | sh -c "$cleanse_newfile" \ jgish@678: >> $WDIR/$DIR/$F.patch jgish@678: jgish@678: fi jgish@678: jgish@678: jgish@678: # jgish@678: # Tack the patch we just made onto the accumulated patch for the jgish@678: # whole wad. jgish@678: # jgish@678: cat $WDIR/$DIR/$F.patch >> $WDIR/$WNAME.patch jgish@678: fi jgish@678: jgish@678: print " patch\c" ohair@314: ohair@314: if [[ -f $ofile && -f $nfile && -z $mv_but_nodiff ]]; then ohair@314: ohair@314: ${CDIFFCMD:-diff -bt -C 5} $ofile $nfile > $WDIR/$DIR/$F.cdiff ohair@314: diff_to_html $F $DIR/$F "C" "$COMM" < $WDIR/$DIR/$F.cdiff \ ohair@314: > $WDIR/$DIR/$F.cdiff.html ohair@314: print " cdiffs\c" ohair@314: ohair@314: ${UDIFFCMD:-diff -bt -U 5} $ofile $nfile > $WDIR/$DIR/$F.udiff ohair@314: diff_to_html $F $DIR/$F "U" "$COMM" < $WDIR/$DIR/$F.udiff \ ohair@314: > $WDIR/$DIR/$F.udiff.html ohair@314: ohair@314: print " udiffs\c" ohair@314: ohair@314: if [[ -x $WDIFF ]]; then ohair@314: $WDIFF -c "$COMM" \ ohair@314: -t "$WNAME Wdiff $DIR/$F" $ofile $nfile > \ ohair@314: $WDIR/$DIR/$F.wdiff.html 2>/dev/null ohair@314: if [[ $? -eq 0 ]]; then ohair@314: print " wdiffs\c" ohair@314: else ohair@314: print " wdiffs[fail]\c" ohair@314: fi ohair@314: fi ohair@314: ohair@314: sdiff_to_html $ofile $nfile $F $DIR "$COMM" \ ohair@314: > $WDIR/$DIR/$F.sdiff.html ohair@314: print " sdiffs\c" ohair@314: ohair@314: print " frames\c" ohair@314: ohair@314: rm -f $WDIR/$DIR/$F.cdiff $WDIR/$DIR/$F.udiff ohair@314: ohair@314: difflines $ofile $nfile > $WDIR/$DIR/$F.count ohair@314: ohair@314: elif [[ -f $ofile && -f $nfile && -n $mv_but_nodiff ]]; then ohair@314: # renamed file: may also have differences ohair@314: difflines $ofile $nfile > $WDIR/$DIR/$F.count ohair@314: elif [[ -f $nfile ]]; then ohair@314: # new file: count added lines ohair@314: difflines /dev/null $nfile > $WDIR/$DIR/$F.count ohair@314: elif [[ -f $ofile ]]; then ohair@314: # old file: count deleted lines ohair@314: difflines $ofile /dev/null > $WDIR/$DIR/$F.count ohair@314: fi ohair@314: fi ohair@314: # ohair@314: # Now we generate the postscript for this file. We generate diffs ohair@314: # only in the event that there is delta, or the file is new (it seems ohair@314: # tree-killing to print out the contents of deleted files). ohair@314: # ohair@314: if [[ -f $nfile ]]; then ohair@314: ocr=$ofile ohair@314: [[ ! -f $ofile ]] && ocr=/dev/null ohair@314: ohair@314: if [[ -z $mv_but_nodiff ]]; then ohair@314: textcomm=`getcomments text $P $PP` ohair@314: if [[ -x $CODEREVIEW ]]; then ohair@314: $CODEREVIEW -y "$textcomm" \ ohair@314: -e $ocr $nfile \ ohair@314: > /tmp/$$.psfile 2>/dev/null && ohair@314: cat /tmp/$$.psfile >> $WDIR/$WNAME.ps ohair@314: if [[ $? -eq 0 ]]; then ohair@314: print " ps\c" ohair@314: else ohair@314: print " ps[fail]\c" ohair@314: fi ohair@314: fi ohair@314: fi ohair@314: fi ohair@314: ohair@314: if [[ -f $ofile && -z $mv_but_nodiff ]]; then ohair@314: if [[ -n $its_a_jar ]]; then ohair@314: source_to_html Old $P < $ofile.lst > $WDIR/$DIR/$F-.html ohair@314: else ohair@314: source_to_html Old $P < $ofile > $WDIR/$DIR/$F-.html ohair@314: fi ohair@314: print " old\c" ohair@314: fi ohair@314: ohair@314: if [[ -f $nfile ]]; then ohair@314: if [[ -n $its_a_jar ]]; then ohair@314: source_to_html New $P < $nfile.lst > $WDIR/$DIR/$F.html ohair@314: else ohair@314: source_to_html New $P < $nfile > $WDIR/$DIR/$F.html ohair@314: fi ohair@314: print " new\c" ohair@314: fi ohair@314: ohair@314: print ohair@314: done < $FLIST ohair@314: jgish@678: # Create the new style mercurial patch here using hg export -r [all-revs] -g -o $CHANGESETPATH jgish@678: if [[ $SCM_MODE == "mercurial" ]]; then jgish@690: if [[ "$HG_LIST_FROM_COMMIT" -eq 1 && $flist_mode == "auto" ]]; then jgish@678: EXPORTCHANGESET="$WNAME.changeset" jgish@678: CHANGESETPATH=${WDIR}/${EXPORTCHANGESET} jgish@678: rm -f $CHANGESETPATH jgish@678: touch $CHANGESETPATH jgish@678: if [[ -n $ALL_CREV ]]; then jgish@678: rev_opt= jgish@678: for rev in $ALL_CREV; do jgish@678: rev_opt="$rev_opt --rev $rev" jgish@678: done jgish@678: elif [[ -n $FIRST_CREV ]]; then jgish@678: rev_opt="--rev $FIRST_CREV" jgish@678: fi jgish@678: jgish@678: if [[ -n $rev_opt ]]; then jgish@678: (cd $CWS;hg export -g $rev_opt -o $CHANGESETPATH) jgish@690: echo "Created changeset: $CHANGESETPATH" 1>&2 jgish@678: # Use it in place of the jdk.patch created above jgish@678: rm -f $WDIR/$WNAME.patch jgish@678: fi jgish@678: set +x jgish@678: fi jgish@678: fi jgish@678: ohair@314: frame_nav_js > $WDIR/ancnav.js ohair@314: frame_navigation > $WDIR/ancnav.html ohair@314: ohair@314: if [[ -f $WDIR/$WNAME.ps && -x $CODEREVIEW && -x $PS2PDF ]]; then ohair@314: print " Generating PDF: \c" ohair@314: fix_postscript $WDIR/$WNAME.ps | $PS2PDF - > $WDIR/$WNAME.pdf ohair@314: print "Done." ohair@314: fi ohair@314: ohair@314: # Now build the index.html file that contains ohair@314: # links to the source files and their diffs. ohair@314: ohair@314: cd $CWS ohair@314: ohair@314: # Save total changed lines for Code Inspection. ohair@314: print "$TOTL" > $WDIR/TotalChangedLines ohair@314: ohair@314: print " index.html: \c" ohair@314: INDEXFILE=$WDIR/index.html ohair@314: exec 3<&1 # duplicate stdout to FD3. ohair@314: exec 1<&- # Close stdout. ohair@314: exec > $INDEXFILE # Open stdout to index file. ohair@314: ohair@314: print "$HTML" ohair@314: print "" ohair@314: print "$STDHEAD" ohair@314: print "$WNAME" ohair@314: print "" ohair@314: print "" ohair@314: print "
" ohair@314: print "

Code Review for $WNAME

" ohair@314: ohair@314: print "" ohair@314: mduigou@851: if [[ -z $uflag ]]; then mduigou@851: if [[ $SCM_MODE == "mercurial" ]]; then ohair@314: # ohair@314: # Let's try to extract the user name from the .hgrc file ohair@314: # ohair@314: username=`grep '^username' $HOME/.hgrc | sed 's/^username[ ]*=[ ]*\(.*\)/\1/'` ohair@314: fi ohair@314: mduigou@851: if [[ -z $username ]]; then ohair@314: # ohair@314: # Figure out the username and gcos name. To maintain compatibility ohair@314: # with passwd(4), we must support '&' substitutions. ohair@314: # ohair@314: username=`id | cut -d '(' -f 2 | cut -d ')' -f 1` ohair@314: if [[ -x $GETENT ]]; then ohair@314: realname=`$GETENT passwd $username | cut -d':' -f 5 | cut -d ',' -f 1` ohair@314: fi ohair@314: userupper=`print "$username" | sed 's/\<./\u&/g'` ohair@314: realname=`print $realname | sed s/\&/$userupper/` ohair@314: fi ohair@314: fi ohair@314: ohair@314: date="on `date`" ohair@314: ohair@314: if [[ -n "$username" && -n "$realname" ]]; then ohair@314: print "" ohair@314: print "" ohair@314: elif [[ -n "$username" ]]; then ohair@314: print "" ohair@314: fi ohair@314: ohair@314: print "" ohair@314: if [[ -n $parent_webrev ]]; then ohair@314: print "" ohair@314: if [[ -n $rflag ]]; then ohair@314: print "" ohair@314: elif [[ -n $OUTREV ]]; then ohair@314: if [[ -z $forestflag ]]; then ohair@314: print "" ohair@314: fi ohair@314: fi ohair@314: if [[ -n $HG_BRANCH ]]; then ohair@314: print "" ohair@314: fi ohair@314: ohair@314: print "" ohair@314: ohair@314: if [[ -f $WDIR/$WNAME.patch ]]; then jgish@678: print "" jgish@678: elif [[ -f $CHANGESETPATH ]]; then jgish@678: print "" ohair@314: fi jgish@678: ohair@314: if [[ -f $WDIR/$WNAME.pdf ]]; then ohair@314: print "" ohair@314: fi ohair@314: ohair@314: if [[ -n "$iflag" ]]; then ohair@314: print "" ohair@314: fi ohair@314: # Add links to referenced CRs, if any mduigou@851: # URL has a like: mduigou@851: # <title>[#JDK-8024688] b106-lambda: j.u.Map.merge doesn't work as specified if contains key:null pair - Java Bug System mduigou@851: # we format this to: mduigou@851: # JDK-8024688: b106-lambda: j.u.Map.merge doesn't work as specified if contains key:null pair ohair@314: if [[ -n $CRID ]]; then ohair@314: for id in $CRID ohair@314: do mduigou@851: #add "JDK-" to raw bug id for openjdk.java.net links. mduigou@851: id=`echo ${id} | sed 's/^\([0-9]\{5,\}\)$/JDK-\1/'` mduigou@851: ohair@314: print "
Prepared by:$realname ($username) $date
Prepared by:$username $date
Workspace:$CWS
Compare against:" ohair@314: print "webrev at $parent_webrev" ohair@314: else ohair@314: if [[ -n $OUTPWS2 ]]; then ohair@314: print "
Compare against:" ohair@314: print "$OUTPWS2" ohair@314: fi ohair@314: fi ohair@314: print "
Compare against version:$PARENT_REV
Compare against version:$OUTREV
Branch:$HG_BRANCH
Summary of changes:" ohair@314: printCI $TOTL $TINS $TDEL $TMOD $TUNC ohair@314: print "
Patch of changes:" jgish@678: print "$WNAME.patch
Changeset:" jgish@678: print "$EXPORTCHANGESET
Printable review:" ohair@314: print "$WNAME.pdf
Author comments:
" ohair@314: cat /tmp/$$.include ohair@314: print "
Bug id:" ohair@314: url="${BUGURL}${id}" mduigou@851: ohair@314: if [[ -n $WGET ]]; then mduigou@851: msg=`$WGET --timeout=10 --tries=1 -q $url -O - | grep '' | sed 's/<title>\[#\(.*\)\] \(.*\) - Java Bug System<\/title>/\1 : \2/' | html_dequote | html_quote` ohair@314: fi mduigou@616: if [[ -z $msg ]]; then mduigou@616: msg="${id}" ohair@314: fi mduigou@616: mduigou@616: print "<a href=\"$url\">$msg</a>" mduigou@616: ohair@314: print "</td></tr>" ohair@314: done ohair@314: fi ohair@314: print "<tr><th>Legend:</th><td>" ohair@314: print "<b>Modified file</b><br><font color=red><b>Deleted file</b></font><br><font color=green><b>New file</b></font></td></tr>" ohair@314: print "</table>" ohair@314: print "</div>" ohair@314: ohair@314: # ohair@314: # Second pass through the files: generate the rest of the index file ohair@314: # ohair@314: while read LINE ohair@314: do ohair@314: set - $LINE ohair@314: if [[ $1 == "Revision:" ]]; then ohair@314: FIRST_CREV=`expr $3 + 1` ohair@314: continue ohair@314: fi ohair@314: P=$1 ohair@314: ohair@314: if [[ $# == 2 ]]; then ohair@314: PP=$2 ohair@314: oldname=" <i>(was $PP)</i>" ohair@314: ohair@314: else ohair@314: PP=$P ohair@314: oldname="" ohair@314: fi ohair@314: ohair@314: DIR=${P%/*} ohair@314: if [[ $DIR == $P ]]; then ohair@314: DIR="." # File at root of workspace ohair@314: fi ohair@314: ohair@314: # Avoid processing the same file twice. ohair@314: # It's possible for renamed files to ohair@314: # appear twice in the file list ohair@314: ohair@314: F=$WDIR/$P ohair@314: ohair@314: print "<p><code>" ohair@314: ohair@314: # If there's a diffs file, make diffs links ohair@314: ohair@314: NODIFFS= ohair@314: if [[ -f $F.cdiff.html ]]; then ohair@314: print "<a href=\"$P.cdiff.html\">Cdiffs</a>" ohair@314: print "<a href=\"$P.udiff.html\">Udiffs</a>" ohair@314: ohair@314: if [[ -f $F.wdiff.html && -x $WDIFF ]]; then ohair@314: print "<a href=\"$P.wdiff.html\">Wdiffs</a>" ohair@314: fi ohair@314: ohair@314: print "<a href=\"$P.sdiff.html\">Sdiffs</a>" ohair@314: ohair@314: print "<a href=\"$P.frames.html\">Frames</a>" ohair@314: else ohair@314: NODIFFS=1 ohair@314: print " ------ ------ ------" ohair@314: ohair@314: if [[ -x $WDIFF ]]; then ohair@314: print " ------" ohair@314: fi ohair@314: ohair@314: print " ------" ohair@314: fi ohair@314: ohair@314: # If there's an old file, make the link ohair@314: ohair@314: NOOLD= ohair@314: if [[ -f $F-.html ]]; then ohair@314: print "<a href=\"$P-.html\">Old</a>" ohair@314: else ohair@314: NOOLD=1 ohair@314: print " ---" ohair@314: fi ohair@314: ohair@314: # If there's an new file, make the link ohair@314: ohair@314: NONEW= ohair@314: if [[ -f $F.html ]]; then ohair@314: print "<a href=\"$P.html\">New</a>" ohair@314: else ohair@314: NONEW=1 ohair@314: print " ---" ohair@314: fi ohair@314: ohair@314: if [[ -f $F.patch ]]; then ohair@314: print "<a href=\"$P.patch\">Patch</a>" ohair@314: else ohair@314: print " -----" ohair@314: fi ohair@314: ohair@314: if [[ -f $WDIR/raw_files/new/$P ]]; then ohair@314: print "<a href=\"raw_files/new/$P\">Raw</a>" ohair@314: else ohair@314: print " ---" ohair@314: fi ohair@314: print "</code>" ohair@314: if [[ -n $NODIFFS && -z $oldname ]]; then ohair@314: if [[ -n $NOOLD ]]; then ohair@314: print "<font color=green><b>$P</b></font>" ohair@314: elif [[ -n $NONEW ]]; then ohair@314: print "<font color=red><b>$P</b></font>" ohair@314: fi ohair@314: else ohair@314: print "<b>$P</b> $oldname" ohair@314: fi ohair@314: ohair@314: print "</p><blockquote>\c" ohair@314: # Insert delta comments if any ohair@314: comments=`getcomments html $P $PP` ohair@314: if [ -n "$comments" ]; then ohair@314: print "<pre>$comments</pre>" ohair@314: fi ohair@314: ohair@314: # Add additional comments comment ohair@314: ohair@314: print "<!-- Add comments to explain changes in $P here -->" ohair@314: ohair@314: # Add count of changes. ohair@314: ohair@314: if [[ -f $F.count ]]; then ohair@314: cat $F.count ohair@314: rm $F.count ohair@314: fi ohair@314: print "</blockquote>" ohair@314: done < $FLIST ohair@314: ohair@314: print ohair@314: print ohair@314: print "<hr />" ohair@314: print "<p style=\"font-size: small\">" ohair@314: print "This code review page was prepared using <b>$0</b>" ohair@314: print "(vers $WEBREV_UPDATED)." ohair@314: print "</body>" ohair@314: print "</html>" ohair@314: ohair@314: if [[ -n $ZIP ]]; then ohair@314: # Let's generate a zip file for convenience ohair@314: cd $WDIR/.. ohair@314: if [ -f webrev.zip ]; then ohair@314: rm webrev.zip ohair@314: fi ohair@314: $ZIP -r webrev webrev >/dev/null 2>&1 ohair@314: fi ohair@314: ohair@314: exec 1<&- # Close FD 1. ohair@314: exec 1<&3 # dup FD 3 to restore stdout. ohair@314: exec 3<&- # close FD 3. ohair@314: ohair@314: print "Done." ohair@314: print "Output to: $WDIR"