xref: /titanic_53/usr/src/tools/scripts/webrev.sh (revision d7b56f414df5eecc5f2cc64674bb2a4be951082d)
148fe8920SMark J. Nelson#!/usr/bin/ksh93 -p
27c478bd9Sstevel@tonic-gate#
37c478bd9Sstevel@tonic-gate# CDDL HEADER START
47c478bd9Sstevel@tonic-gate#
57c478bd9Sstevel@tonic-gate# The contents of this file are subject to the terms of the
6daaffb31Sdp# Common Development and Distribution License (the "License").
7daaffb31Sdp# You may not use this file except in compliance with the License.
87c478bd9Sstevel@tonic-gate#
97c478bd9Sstevel@tonic-gate# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate# or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate# See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate# and limitations under the License.
137c478bd9Sstevel@tonic-gate#
147c478bd9Sstevel@tonic-gate# When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate# If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate# fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate# information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate#
207c478bd9Sstevel@tonic-gate# CDDL HEADER END
217c478bd9Sstevel@tonic-gate#
229a70fc3bSMark J. Nelson
237c478bd9Sstevel@tonic-gate#
2478add226Sjmcp# Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
257c478bd9Sstevel@tonic-gate#
26cdf0c1d5Smjnelson
272f54b716SRichard Lowe# Copyright 2008, 2010, Richard Lowe
287646c8f3SMarcel Telka# Copyright 2012 Marcel Telka <marcel@telka.sk>
29*d7b56f41SBart Coddens# Copyright 2014 Bart Coddens <bart.coddens@gmail.com>
302f54b716SRichard Lowe
31cdf0c1d5Smjnelson#
32daaffb31Sdp# This script takes a file list and a workspace and builds a set of html files
33daaffb31Sdp# suitable for doing a code review of source changes via a web page.
34daaffb31Sdp# Documentation is available via the manual page, webrev.1, or just
35daaffb31Sdp# type 'webrev -h'.
367c478bd9Sstevel@tonic-gate#
37daaffb31Sdp# Acknowledgements to contributors to webrev are listed in the webrev(1)
38daaffb31Sdp# man page.
397c478bd9Sstevel@tonic-gate#
40daaffb31Sdp
417c478bd9Sstevel@tonic-gateREMOVED_COLOR=brown
427c478bd9Sstevel@tonic-gateCHANGED_COLOR=blue
437c478bd9Sstevel@tonic-gateNEW_COLOR=blue
447c478bd9Sstevel@tonic-gate
45daaffb31SdpHTML='<?xml version="1.0"?>
46daaffb31Sdp<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
47daaffb31Sdp    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
48daaffb31Sdp<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">\n'
49daaffb31Sdp
50daaffb31SdpFRAMEHTML='<?xml version="1.0"?>
51daaffb31Sdp<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"
52daaffb31Sdp    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
53daaffb31Sdp<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">\n'
54daaffb31Sdp
55cac38512SmjnelsonSTDHEAD='<meta http-equiv="cache-control" content="no-cache"></meta>
56cac38512Smjnelson<meta http-equiv="Pragma" content="no-cache"></meta>
57cac38512Smjnelson<meta http-equiv="Expires" content="-1"></meta>
58daaffb31Sdp<!--
59daaffb31Sdp   Note to customizers: the body of the webrev is IDed as SUNWwebrev
60daaffb31Sdp   to allow easy overriding by users of webrev via the userContent.css
61daaffb31Sdp   mechanism available in some browsers.
62daaffb31Sdp
63daaffb31Sdp   For example, to have all "removed" information be red instead of
64daaffb31Sdp   brown, set a rule in your userContent.css file like:
65daaffb31Sdp
66daaffb31Sdp       body#SUNWwebrev span.removed { color: red ! important; }
67daaffb31Sdp-->
68daaffb31Sdp<style type="text/css" media="screen">
69daaffb31Sdpbody {
70daaffb31Sdp    background-color: #eeeeee;
71daaffb31Sdp}
72daaffb31Sdphr {
73daaffb31Sdp    border: none 0;
74daaffb31Sdp    border-top: 1px solid #aaa;
75daaffb31Sdp    height: 1px;
76daaffb31Sdp}
77daaffb31Sdpdiv.summary {
78daaffb31Sdp    font-size: .8em;
79daaffb31Sdp    border-bottom: 1px solid #aaa;
80daaffb31Sdp    padding-left: 1em;
81daaffb31Sdp    padding-right: 1em;
82daaffb31Sdp}
83daaffb31Sdpdiv.summary h2 {
84daaffb31Sdp    margin-bottom: 0.3em;
85daaffb31Sdp}
86daaffb31Sdpdiv.summary table th {
87daaffb31Sdp    text-align: right;
88daaffb31Sdp    vertical-align: top;
89daaffb31Sdp    white-space: nowrap;
90daaffb31Sdp}
91daaffb31Sdpspan.lineschanged {
92daaffb31Sdp    font-size: 0.7em;
93daaffb31Sdp}
94daaffb31Sdpspan.oldmarker {
95daaffb31Sdp    color: red;
96daaffb31Sdp    font-size: large;
97daaffb31Sdp    font-weight: bold;
98daaffb31Sdp}
99daaffb31Sdpspan.newmarker {
100daaffb31Sdp    color: green;
101daaffb31Sdp    font-size: large;
102daaffb31Sdp    font-weight: bold;
103daaffb31Sdp}
104daaffb31Sdpspan.removed {
105daaffb31Sdp    color: brown;
106daaffb31Sdp}
107daaffb31Sdpspan.changed {
108daaffb31Sdp    color: blue;
109daaffb31Sdp}
110daaffb31Sdpspan.new {
111daaffb31Sdp    color: blue;
112daaffb31Sdp    font-weight: bold;
113daaffb31Sdp}
114cdf0c1d5Smjnelsonspan.chmod {
115cdf0c1d5Smjnelson    font-size: 0.7em;
116cdf0c1d5Smjnelson    color: #db7800;
117cdf0c1d5Smjnelson}
118daaffb31Sdpa.print { font-size: x-small; }
119daaffb31Sdpa:hover { background-color: #ffcc99; }
120daaffb31Sdp</style>
121daaffb31Sdp
122daaffb31Sdp<style type="text/css" media="print">
123daaffb31Sdppre { font-size: 0.8em; font-family: courier, monospace; }
124daaffb31Sdpspan.removed { color: #444; font-style: italic }
125daaffb31Sdpspan.changed { font-weight: bold; }
126daaffb31Sdpspan.new { font-weight: bold; }
127daaffb31Sdpspan.newmarker { font-size: 1.2em; font-weight: bold; }
128daaffb31Sdpspan.oldmarker { font-size: 1.2em; font-weight: bold; }
129daaffb31Sdpa.print {display: none}
130daaffb31Sdphr { border: none 0; border-top: 1px solid #aaa; height: 1px; }
131daaffb31Sdp</style>
132daaffb31Sdp'
133daaffb31Sdp
134daaffb31Sdp#
135daaffb31Sdp# UDiffs need a slightly different CSS rule for 'new' items (we don't
136daaffb31Sdp# want them to be bolded as we do in cdiffs or sdiffs).
137daaffb31Sdp#
138daaffb31SdpUDIFFCSS='
139daaffb31Sdp<style type="text/css" media="screen">
140daaffb31Sdpspan.new {
141daaffb31Sdp    color: blue;
142daaffb31Sdp    font-weight: normal;
143daaffb31Sdp}
144daaffb31Sdp</style>
145daaffb31Sdp'
146daaffb31Sdp
147b0088928SVladimir Kotal#
148b0088928SVladimir Kotal# Display remote target with prefix and trailing slash.
149b0088928SVladimir Kotal#
150b0088928SVladimir Kotalfunction print_upload_header
151b0088928SVladimir Kotal{
152b0088928SVladimir Kotal	typeset -r prefix=$1
153b0088928SVladimir Kotal	typeset display_target
154b0088928SVladimir Kotal
155b0088928SVladimir Kotal	if [[ -z $tflag ]]; then
156b0088928SVladimir Kotal		display_target=${prefix}${remote_target}
157b0088928SVladimir Kotal	else
158b0088928SVladimir Kotal		display_target=${remote_target}
159b0088928SVladimir Kotal	fi
160b0088928SVladimir Kotal
161b0088928SVladimir Kotal	if [[ ${display_target} != */ ]]; then
162b0088928SVladimir Kotal		display_target=${display_target}/
163b0088928SVladimir Kotal	fi
164b0088928SVladimir Kotal
165b0088928SVladimir Kotal	print "      Upload to: ${display_target}\n" \
166b0088928SVladimir Kotal	    "     Uploading: \c"
167b0088928SVladimir Kotal}
168b0088928SVladimir Kotal
169b0088928SVladimir Kotal#
17002d26c39SVladimir Kotal# Upload the webrev via rsync. Return 0 on success, 1 on error.
171b0088928SVladimir Kotal#
172ba44d8a2SVladimir Kotalfunction rsync_upload
17302d26c39SVladimir Kotal{
174b0088928SVladimir Kotal	if (( $# != 2 )); then
175b0088928SVladimir Kotal		print "\nERROR: rsync_upload: wrong usage ($#)"
176b0088928SVladimir Kotal		exit 1
17702d26c39SVladimir Kotal	fi
17802d26c39SVladimir Kotal
179b0088928SVladimir Kotal	typeset -r dst=$1
180b0088928SVladimir Kotal	integer -r print_err_msg=$2
18102d26c39SVladimir Kotal
182b0088928SVladimir Kotal	print_upload_header ${rsync_prefix}
183b0088928SVladimir Kotal	print "rsync ... \c"
1848a34f8dcSVladimir Kotal	typeset -r err_msg=$( $MKTEMP /tmp/rsync_err.XXXXXX )
185b0088928SVladimir Kotal	if [[ -z $err_msg ]]; then
186b0088928SVladimir Kotal		print "\nERROR: rsync_upload: cannot create temporary file"
187b0088928SVladimir Kotal		return 1
188b0088928SVladimir Kotal	fi
189b0088928SVladimir Kotal	#
190b0088928SVladimir Kotal	# The source directory must end with a slash in order to copy just
191b0088928SVladimir Kotal	# directory contents, not the whole directory.
192b0088928SVladimir Kotal	#
193b0088928SVladimir Kotal	typeset src_dir=$WDIR
194b0088928SVladimir Kotal	if [[ ${src_dir} != */ ]]; then
195b0088928SVladimir Kotal		src_dir=${src_dir}/
196b0088928SVladimir Kotal	fi
197b0088928SVladimir Kotal	$RSYNC -r -q ${src_dir} $dst 2>$err_msg
19802d26c39SVladimir Kotal	if (( $? != 0 )); then
199b0088928SVladimir Kotal		if (( ${print_err_msg} > 0 )); then
200b0088928SVladimir Kotal			print "Failed.\nERROR: rsync failed"
201b0088928SVladimir Kotal			print "src dir: '${src_dir}'\ndst dir: '$dst'"
202b0088928SVladimir Kotal			print "error messages:"
203b0088928SVladimir Kotal			$SED 's/^/> /' $err_msg
204b0088928SVladimir Kotal			rm -f $err_msg
205b0088928SVladimir Kotal		fi
20602d26c39SVladimir Kotal		return 1
20702d26c39SVladimir Kotal	fi
20802d26c39SVladimir Kotal
209b0088928SVladimir Kotal	rm -f $err_msg
21002d26c39SVladimir Kotal	print "Done."
21102d26c39SVladimir Kotal	return 0
21202d26c39SVladimir Kotal}
21302d26c39SVladimir Kotal
214b0088928SVladimir Kotal#
215b0088928SVladimir Kotal# Create directories on remote host using SFTP. Return 0 on success,
216b0088928SVladimir Kotal# 1 on failure.
217b0088928SVladimir Kotal#
218b0088928SVladimir Kotalfunction remote_mkdirs
219b0088928SVladimir Kotal{
220b0088928SVladimir Kotal	typeset -r dir_spec=$1
2219d3952abSVladimir Kotal	typeset -r host_spec=$2
222b0088928SVladimir Kotal
223b0088928SVladimir Kotal	#
224b0088928SVladimir Kotal	# If the supplied path is absolute we assume all directories are
225b0088928SVladimir Kotal	# created, otherwise try to create all directories in the path
226b0088928SVladimir Kotal	# except the last one which will be created by scp.
227b0088928SVladimir Kotal	#
228b0088928SVladimir Kotal	if [[ "${dir_spec}" == */* && "${dir_spec}" != /* ]]; then
229b0088928SVladimir Kotal		print "mkdirs \c"
230b0088928SVladimir Kotal		#
231b0088928SVladimir Kotal		# Remove the last directory from directory specification.
232b0088928SVladimir Kotal		#
233b0088928SVladimir Kotal		typeset -r dirs_mk=${dir_spec%/*}
2348a34f8dcSVladimir Kotal		typeset -r batch_file_mkdir=$( $MKTEMP \
2358a34f8dcSVladimir Kotal		    /tmp/webrev_mkdir.XXXXXX )
236b0088928SVladimir Kotal		if [[ -z $batch_file_mkdir ]]; then
237b0088928SVladimir Kotal			print "\nERROR: remote_mkdirs:" \
238b0088928SVladimir Kotal			    "cannot create temporary file for batch file"
239b0088928SVladimir Kotal			return 1
240b0088928SVladimir Kotal		fi
241b0088928SVladimir Kotal                OLDIFS=$IFS
242b0088928SVladimir Kotal                IFS=/
243b0088928SVladimir Kotal		typeset dir
244b0088928SVladimir Kotal                for dir in ${dirs_mk}; do
245b0088928SVladimir Kotal			#
246b0088928SVladimir Kotal			# Use the '-' prefix to ignore mkdir errors in order
247b0088928SVladimir Kotal			# to avoid an error in case the directory already
248b0088928SVladimir Kotal			# exists. We check the directory with chdir to be sure
249b0088928SVladimir Kotal			# there is one.
250b0088928SVladimir Kotal			#
251b0088928SVladimir Kotal                        print -- "-mkdir ${dir}" >> ${batch_file_mkdir}
252b0088928SVladimir Kotal                        print "chdir ${dir}" >> ${batch_file_mkdir}
253b0088928SVladimir Kotal                done
254b0088928SVladimir Kotal                IFS=$OLDIFS
2558a34f8dcSVladimir Kotal		typeset -r sftp_err_msg=$( $MKTEMP /tmp/webrev_scp_err.XXXXXX )
256b0088928SVladimir Kotal		if [[ -z ${sftp_err_msg} ]]; then
257b0088928SVladimir Kotal			print "\nERROR: remote_mkdirs:" \
258b0088928SVladimir Kotal			    "cannot create temporary file for error messages"
259b0088928SVladimir Kotal			return 1
260b0088928SVladimir Kotal		fi
261b0088928SVladimir Kotal		$SFTP -b ${batch_file_mkdir} ${host_spec} 2>${sftp_err_msg} 1>&2
262b0088928SVladimir Kotal		if (( $? != 0 )); then
263b0088928SVladimir Kotal			print "\nERROR: failed to create remote directories"
264b0088928SVladimir Kotal			print "error messages:"
265b0088928SVladimir Kotal			$SED 's/^/> /' ${sftp_err_msg}
266b0088928SVladimir Kotal			rm -f ${sftp_err_msg} ${batch_file_mkdir}
267b0088928SVladimir Kotal			return 1
268b0088928SVladimir Kotal		fi
269b0088928SVladimir Kotal		rm -f ${sftp_err_msg} ${batch_file_mkdir}
270b0088928SVladimir Kotal	fi
271b0088928SVladimir Kotal
272b0088928SVladimir Kotal	return 0
273b0088928SVladimir Kotal}
274b0088928SVladimir Kotal
275b0088928SVladimir Kotal#
27602d26c39SVladimir Kotal# Upload the webrev via SSH. Return 0 on success, 1 on error.
277b0088928SVladimir Kotal#
278ba44d8a2SVladimir Kotalfunction ssh_upload
27902d26c39SVladimir Kotal{
28002d26c39SVladimir Kotal	if (( $# != 1 )); then
281b0088928SVladimir Kotal		print "\nERROR: ssh_upload: wrong number of arguments"
282b0088928SVladimir Kotal		exit 1
28302d26c39SVladimir Kotal	fi
28402d26c39SVladimir Kotal
28502d26c39SVladimir Kotal	typeset dst=$1
28602d26c39SVladimir Kotal	typeset -r host_spec=${dst%%:*}
287ba44d8a2SVladimir Kotal	typeset -r dir_spec=${dst#*:}
28802d26c39SVladimir Kotal
289b0088928SVladimir Kotal	#
290b0088928SVladimir Kotal	# Display the upload information before calling delete_webrev
291b0088928SVladimir Kotal	# because it will also print its progress.
292b0088928SVladimir Kotal	#
293b0088928SVladimir Kotal	print_upload_header ${ssh_prefix}
294b0088928SVladimir Kotal
295b0088928SVladimir Kotal	#
296b0088928SVladimir Kotal	# If the deletion was explicitly requested there is no need
297b0088928SVladimir Kotal	# to perform it again.
298b0088928SVladimir Kotal	#
299ba44d8a2SVladimir Kotal	if [[ -z $Dflag ]]; then
300b0088928SVladimir Kotal		#
301b0088928SVladimir Kotal		# We do not care about return value because this might be
302b0088928SVladimir Kotal		# the first time this directory is uploaded.
303b0088928SVladimir Kotal		#
304ba44d8a2SVladimir Kotal		delete_webrev 0
30502d26c39SVladimir Kotal	fi
30602d26c39SVladimir Kotal
307b0088928SVladimir Kotal	#
308b0088928SVladimir Kotal	# Create remote directories. Any error reporting will be done
309b0088928SVladimir Kotal	# in remote_mkdirs function.
310b0088928SVladimir Kotal	#
3119d3952abSVladimir Kotal	remote_mkdirs ${dir_spec} ${host_spec}
31202d26c39SVladimir Kotal	if (( $? != 0 )); then
31302d26c39SVladimir Kotal		return 1
31402d26c39SVladimir Kotal	fi
31502d26c39SVladimir Kotal
316b0088928SVladimir Kotal	print "upload ... \c"
3178a34f8dcSVladimir Kotal	typeset -r scp_err_msg=$( $MKTEMP /tmp/scp_err.XXXXXX )
318b0088928SVladimir Kotal	if [[ -z ${scp_err_msg} ]]; then
319b0088928SVladimir Kotal		print "\nERROR: ssh_upload:" \
320b0088928SVladimir Kotal		    "cannot create temporary file for error messages"
321b0088928SVladimir Kotal		return 1
322b0088928SVladimir Kotal	fi
32302d26c39SVladimir Kotal	$SCP -q -C -B -o PreferredAuthentications=publickey -r \
324b0088928SVladimir Kotal		$WDIR $dst 2>${scp_err_msg}
32502d26c39SVladimir Kotal	if (( $? != 0 )); then
326b0088928SVladimir Kotal		print "Failed.\nERROR: scp failed"
327b0088928SVladimir Kotal		print "src dir: '$WDIR'\ndst dir: '$dst'"
328b0088928SVladimir Kotal		print "error messages:"
329b0088928SVladimir Kotal		$SED 's/^/> /' ${scp_err_msg}
330b0088928SVladimir Kotal		rm -f ${scp_err_msg}
33102d26c39SVladimir Kotal		return 1
33202d26c39SVladimir Kotal	fi
33302d26c39SVladimir Kotal
334b0088928SVladimir Kotal	rm -f ${scp_err_msg}
33502d26c39SVladimir Kotal	print "Done."
33602d26c39SVladimir Kotal	return 0
33702d26c39SVladimir Kotal}
33802d26c39SVladimir Kotal
33902d26c39SVladimir Kotal#
340ba44d8a2SVladimir Kotal# Delete webrev at remote site. Return 0 on success, 1 or exit code from sftp
341b0088928SVladimir Kotal# on failure. If first argument is 1 then perform the check of sftp return
342b0088928SVladimir Kotal# value otherwise ignore it. If second argument is present it means this run
343b0088928SVladimir Kotal# only performs deletion.
344ba44d8a2SVladimir Kotal#
345ba44d8a2SVladimir Kotalfunction delete_webrev
346ba44d8a2SVladimir Kotal{
347b0088928SVladimir Kotal	if (( $# < 1 )); then
348b0088928SVladimir Kotal		print "delete_webrev: wrong number of arguments"
349b0088928SVladimir Kotal		exit 1
350ba44d8a2SVladimir Kotal	fi
351ba44d8a2SVladimir Kotal
352b0088928SVladimir Kotal	integer -r check=$1
353b0088928SVladimir Kotal	integer delete_only=0
354b0088928SVladimir Kotal	if (( $# == 2 )); then
355b0088928SVladimir Kotal		delete_only=1
356b0088928SVladimir Kotal	fi
357b0088928SVladimir Kotal
358b0088928SVladimir Kotal	#
359ba44d8a2SVladimir Kotal	# Strip the transport specification part of remote target first.
360b0088928SVladimir Kotal	#
361ba44d8a2SVladimir Kotal	typeset -r stripped_target=${remote_target##*://}
362ba44d8a2SVladimir Kotal	typeset -r host_spec=${stripped_target%%:*}
363ba44d8a2SVladimir Kotal	typeset -r dir_spec=${stripped_target#*:}
364ba44d8a2SVladimir Kotal	typeset dir_rm
365ba44d8a2SVladimir Kotal
366b0088928SVladimir Kotal	#
367ba44d8a2SVladimir Kotal	# Do not accept an absolute path.
368b0088928SVladimir Kotal	#
369ba44d8a2SVladimir Kotal	if [[ ${dir_spec} == /* ]]; then
370ba44d8a2SVladimir Kotal		return 1
371ba44d8a2SVladimir Kotal	fi
372ba44d8a2SVladimir Kotal
373b0088928SVladimir Kotal	#
374ba44d8a2SVladimir Kotal	# Strip the ending slash.
375b0088928SVladimir Kotal	#
376ba44d8a2SVladimir Kotal	if [[ ${dir_spec} == */ ]]; then
377ba44d8a2SVladimir Kotal		dir_rm=${dir_spec%%/}
378ba44d8a2SVladimir Kotal	else
379ba44d8a2SVladimir Kotal		dir_rm=${dir_spec}
380ba44d8a2SVladimir Kotal	fi
381ba44d8a2SVladimir Kotal
382b0088928SVladimir Kotal	if (( ${delete_only} > 0 )); then
383b0088928SVladimir Kotal		print "       Removing: \c"
384b0088928SVladimir Kotal	else
385b0088928SVladimir Kotal		print "rmdir \c"
386b0088928SVladimir Kotal	fi
387ba44d8a2SVladimir Kotal	if [[ -z "$dir_rm" ]]; then
388b0088928SVladimir Kotal		print "\nERROR: empty directory for removal"
389ba44d8a2SVladimir Kotal		return 1
390ba44d8a2SVladimir Kotal	fi
391ba44d8a2SVladimir Kotal
392b0088928SVladimir Kotal	#
393ba44d8a2SVladimir Kotal	# Prepare batch file.
394b0088928SVladimir Kotal	#
3958a34f8dcSVladimir Kotal	typeset -r batch_file_rm=$( $MKTEMP /tmp/webrev_remove.XXXXXX )
396ba44d8a2SVladimir Kotal	if [[ -z $batch_file_rm ]]; then
397b0088928SVladimir Kotal		print "\nERROR: delete_webrev: cannot create temporary file"
398ba44d8a2SVladimir Kotal		return 1
399ba44d8a2SVladimir Kotal	fi
400ba44d8a2SVladimir Kotal	print "rename $dir_rm $TRASH_DIR/removed.$$" > $batch_file_rm
401ba44d8a2SVladimir Kotal
402b0088928SVladimir Kotal	#
403ba44d8a2SVladimir Kotal	# Perform remote deletion and remove the batch file.
404b0088928SVladimir Kotal	#
4058a34f8dcSVladimir Kotal	typeset -r sftp_err_msg=$( $MKTEMP /tmp/webrev_scp_err.XXXXXX )
406b0088928SVladimir Kotal	if [[ -z ${sftp_err_msg} ]]; then
407b0088928SVladimir Kotal		print "\nERROR: delete_webrev:" \
408b0088928SVladimir Kotal		    "cannot create temporary file for error messages"
409b0088928SVladimir Kotal		return 1
410b0088928SVladimir Kotal	fi
411b0088928SVladimir Kotal	$SFTP -b $batch_file_rm $host_spec 2>${sftp_err_msg} 1>&2
412ba44d8a2SVladimir Kotal	integer -r ret=$?
413ba44d8a2SVladimir Kotal	rm -f $batch_file_rm
414ba44d8a2SVladimir Kotal	if (( $ret != 0 && $check > 0 )); then
415b0088928SVladimir Kotal		print "Failed.\nERROR: failed to remove remote directories"
416b0088928SVladimir Kotal		print "error messages:"
417b0088928SVladimir Kotal		$SED 's/^/> /' ${sftp_err_msg}
418b0088928SVladimir Kotal		rm -f ${sftp_err_msg}
419ba44d8a2SVladimir Kotal		return $ret
420ba44d8a2SVladimir Kotal	fi
421b0088928SVladimir Kotal	rm -f ${sftp_err_msg}
422b0088928SVladimir Kotal	if (( ${delete_only} > 0 )); then
423ba44d8a2SVladimir Kotal		print "Done."
424b0088928SVladimir Kotal	fi
425ba44d8a2SVladimir Kotal
426ba44d8a2SVladimir Kotal	return 0
427ba44d8a2SVladimir Kotal}
428ba44d8a2SVladimir Kotal
429ba44d8a2SVladimir Kotal#
43002d26c39SVladimir Kotal# Upload webrev to remote site
43102d26c39SVladimir Kotal#
432ba44d8a2SVladimir Kotalfunction upload_webrev
43302d26c39SVladimir Kotal{
434b0088928SVladimir Kotal	integer ret
43502d26c39SVladimir Kotal
43602d26c39SVladimir Kotal	if [[ ! -d "$WDIR" ]]; then
437b0088928SVladimir Kotal		print "\nERROR: webrev directory '$WDIR' does not exist"
43802d26c39SVladimir Kotal		return 1
43902d26c39SVladimir Kotal	fi
44002d26c39SVladimir Kotal
441b0088928SVladimir Kotal	#
44202d26c39SVladimir Kotal	# Perform a late check to make sure we do not upload closed source
44302d26c39SVladimir Kotal	# to remote target when -n is used. If the user used custom remote
44402d26c39SVladimir Kotal	# target he probably knows what he is doing.
445b0088928SVladimir Kotal	#
44602d26c39SVladimir Kotal	if [[ -n $nflag && -z $tflag ]]; then
447ba44d8a2SVladimir Kotal		$FIND $WDIR -type d -name closed \
44802d26c39SVladimir Kotal			| $GREP closed >/dev/null
44902d26c39SVladimir Kotal		if (( $? == 0 )); then
450b0088928SVladimir Kotal			print "\nERROR: directory '$WDIR' contains" \
451b0088928SVladimir Kotal			    "\"closed\" directory"
45202d26c39SVladimir Kotal			return 1
45302d26c39SVladimir Kotal		fi
45402d26c39SVladimir Kotal	fi
45502d26c39SVladimir Kotal
456b0088928SVladimir Kotal
457b0088928SVladimir Kotal	#
458b0088928SVladimir Kotal	# We have the URI for remote destination now so let's start the upload.
459b0088928SVladimir Kotal	#
46002d26c39SVladimir Kotal	if [[ -n $tflag ]]; then
46102d26c39SVladimir Kotal		if [[ "${remote_target}" == ${rsync_prefix}?* ]]; then
462b0088928SVladimir Kotal			rsync_upload ${remote_target##$rsync_prefix} 1
463b0088928SVladimir Kotal			ret=$?
464b0088928SVladimir Kotal			return $ret
46502d26c39SVladimir Kotal		elif [[ "${remote_target}" == ${ssh_prefix}?* ]]; then
46602d26c39SVladimir Kotal			ssh_upload ${remote_target##$ssh_prefix}
467b0088928SVladimir Kotal			ret=$?
468b0088928SVladimir Kotal			return $ret
46902d26c39SVladimir Kotal		fi
47002d26c39SVladimir Kotal	else
471b0088928SVladimir Kotal		#
472b0088928SVladimir Kotal		# Try rsync first and fallback to SSH in case it fails.
473b0088928SVladimir Kotal		#
474b0088928SVladimir Kotal		rsync_upload ${remote_target} 0
475b0088928SVladimir Kotal		ret=$?
476b0088928SVladimir Kotal		if (( $ret != 0 )); then
477b0088928SVladimir Kotal			print "Failed. (falling back to SSH)"
478ba44d8a2SVladimir Kotal			ssh_upload ${remote_target}
479b0088928SVladimir Kotal			ret=$?
48002d26c39SVladimir Kotal		fi
481b0088928SVladimir Kotal		return $ret
48202d26c39SVladimir Kotal	fi
48302d26c39SVladimir Kotal}
48402d26c39SVladimir Kotal
485daaffb31Sdp#
486371d72daSLubomir Sedlacik# input_cmd | url_encode | output_cmd
487371d72daSLubomir Sedlacik#
488371d72daSLubomir Sedlacik# URL-encode (percent-encode) reserved characters as defined in RFC 3986.
489371d72daSLubomir Sedlacik#
490371d72daSLubomir Sedlacik# Reserved characters are: :/?#[]@!$&'()*+,;=
491371d72daSLubomir Sedlacik#
492371d72daSLubomir Sedlacik# While not a reserved character itself, percent '%' is reserved by definition
493371d72daSLubomir Sedlacik# so encode it first to avoid recursive transformation, and skip '/' which is
494371d72daSLubomir Sedlacik# a path delimiter.
495371d72daSLubomir Sedlacik#
49625cc4e45SVladimir Kotal# The quotation character is deliberately not escaped in order to make
49725cc4e45SVladimir Kotal# the substitution work with GNU sed.
49825cc4e45SVladimir Kotal#
499371d72daSLubomir Sedlacikfunction url_encode
500371d72daSLubomir Sedlacik{
501b0088928SVladimir Kotal	$SED -e "s|%|%25|g" -e "s|:|%3A|g" -e "s|\&|%26|g" \
502371d72daSLubomir Sedlacik	    -e "s|?|%3F|g" -e "s|#|%23|g" -e "s|\[|%5B|g" \
503371d72daSLubomir Sedlacik	    -e "s|*|%2A|g" -e "s|@|%40|g" -e "s|\!|%21|g" \
504371d72daSLubomir Sedlacik	    -e "s|=|%3D|g" -e "s|;|%3B|g" -e "s|\]|%5D|g" \
50525cc4e45SVladimir Kotal	    -e "s|(|%28|g" -e "s|)|%29|g" -e "s|'|%27|g" \
506371d72daSLubomir Sedlacik	    -e "s|+|%2B|g" -e "s|\,|%2C|g" -e "s|\\\$|%24|g"
507371d72daSLubomir Sedlacik}
508371d72daSLubomir Sedlacik
509371d72daSLubomir Sedlacik#
510daaffb31Sdp# input_cmd | html_quote | output_cmd
511daaffb31Sdp# or
512daaffb31Sdp# html_quote filename | output_cmd
5137c478bd9Sstevel@tonic-gate#
5147c478bd9Sstevel@tonic-gate# Make a piece of source code safe for display in an HTML <pre> block.
5157c478bd9Sstevel@tonic-gate#
5167c478bd9Sstevel@tonic-gatehtml_quote()
5177c478bd9Sstevel@tonic-gate{
518b0088928SVladimir Kotal	$SED -e "s/&/\&amp;/g" -e "s/</\&lt;/g" -e "s/>/\&gt;/g" "$@" | expand
5197c478bd9Sstevel@tonic-gate}
5207c478bd9Sstevel@tonic-gate
521daaffb31Sdp#
5228bcea973SRichard Lowe# Trim a digest-style revision to a conventionally readable yet useful length
5238bcea973SRichard Lowe#
5248bcea973SRichard Lowetrim_digest()
5258bcea973SRichard Lowe{
5268bcea973SRichard Lowe	typeset digest=$1
5278bcea973SRichard Lowe
5288bcea973SRichard Lowe	echo $digest | $SED -e 's/\([0-9a-f]\{12\}\).*/\1/'
5298bcea973SRichard Lowe}
5308bcea973SRichard Lowe
5318bcea973SRichard Lowe#
5320fd2682eSMark J. Nelson# input_cmd | its2url | output_cmd
533daaffb31Sdp#
5340fd2682eSMark J. Nelson# Scan for information tracking system references and insert <a> links to the
5350fd2682eSMark J. Nelson# relevant databases.
536daaffb31Sdp#
5370fd2682eSMark J. Nelsonits2url()
5387c478bd9Sstevel@tonic-gate{
5390fd2682eSMark J. Nelson	$SED -f ${its_sed_script}
540daaffb31Sdp}
541daaffb31Sdp
5427c478bd9Sstevel@tonic-gate#
543daaffb31Sdp# strip_unchanged <infile> | output_cmd
5447c478bd9Sstevel@tonic-gate#
545daaffb31Sdp# Removes chunks of sdiff documents that have not changed. This makes it
546daaffb31Sdp# easier for a code reviewer to find the bits that have changed.
5477c478bd9Sstevel@tonic-gate#
548daaffb31Sdp# Deleted lines of text are replaced by a horizontal rule. Some
549daaffb31Sdp# identical lines are retained before and after the changed lines to
550daaffb31Sdp# provide some context.  The number of these lines is controlled by the
551cdf0c1d5Smjnelson# variable C in the $AWK script below.
552daaffb31Sdp#
553daaffb31Sdp# The script detects changed lines as any line that has a "<span class="
554daaffb31Sdp# string embedded (unchanged lines have no particular class and are not
555daaffb31Sdp# part of a <span>).  Blank lines (without a sequence number) are also
556daaffb31Sdp# detected since they flag lines that have been inserted or deleted.
557daaffb31Sdp#
558daaffb31Sdpstrip_unchanged()
559daaffb31Sdp{
560cdf0c1d5Smjnelson	$AWK '
561daaffb31Sdp	BEGIN	{ C = c = 20 }
562cdf0c1d5Smjnelson	NF == 0 || /<span class="/ {
563daaffb31Sdp		if (c > C) {
564daaffb31Sdp			c -= C
565daaffb31Sdp			inx = 0
566daaffb31Sdp			if (c > C) {
567cac38512Smjnelson				print "\n</pre><hr></hr><pre>"
568daaffb31Sdp				inx = c % C
569daaffb31Sdp				c = C
570daaffb31Sdp			}
571daaffb31Sdp
572daaffb31Sdp			for (i = 0; i < c; i++)
573daaffb31Sdp				print ln[(inx + i) % C]
574daaffb31Sdp		}
575daaffb31Sdp		c = 0;
576daaffb31Sdp		print
577daaffb31Sdp		next
578daaffb31Sdp	}
579daaffb31Sdp	{	if (c >= C) {
580daaffb31Sdp			ln[c % C] = $0
581daaffb31Sdp			c++;
582daaffb31Sdp			next;
583daaffb31Sdp		}
584daaffb31Sdp		c++;
585daaffb31Sdp		print
586daaffb31Sdp	}
587cac38512Smjnelson	END	{ if (c > (C * 2)) print "\n</pre><hr></hr>" }
588daaffb31Sdp
589daaffb31Sdp	' $1
590daaffb31Sdp}
591daaffb31Sdp
592daaffb31Sdp#
593daaffb31Sdp# sdiff_to_html
594daaffb31Sdp#
595daaffb31Sdp# This function takes two files as arguments, obtains their diff, and
596daaffb31Sdp# processes the diff output to present the files as an HTML document with
597daaffb31Sdp# the files displayed side-by-side, differences shown in color.  It also
598daaffb31Sdp# takes a delta comment, rendered as an HTML snippet, as the third
599daaffb31Sdp# argument.  The function takes two files as arguments, then the name of
600daaffb31Sdp# file, the path, and the comment.  The HTML will be delivered on stdout,
601daaffb31Sdp# e.g.
602daaffb31Sdp#
603daaffb31Sdp#   $ sdiff_to_html old/usr/src/tools/scripts/webrev.sh \
604daaffb31Sdp#         new/usr/src/tools/scripts/webrev.sh \
605daaffb31Sdp#         webrev.sh usr/src/tools/scripts \
606daaffb31Sdp#         '<a href="http://monaco.sfbay.sun.com/detail.jsp?cr=1234567">
607daaffb31Sdp#          1234567</a> my bugid' > <file>.html
608daaffb31Sdp#
609daaffb31Sdp# framed_sdiff() is then called which creates $2.frames.html
610daaffb31Sdp# in the webrev tree.
611daaffb31Sdp#
612daaffb31Sdp# FYI: This function is rather unusual in its use of awk.  The initial
613daaffb31Sdp# diff run produces conventional diff output showing changed lines mixed
614daaffb31Sdp# with editing codes.  The changed lines are ignored - we're interested in
615daaffb31Sdp# the editing codes, e.g.
6167c478bd9Sstevel@tonic-gate#
6177c478bd9Sstevel@tonic-gate#      8c8
6187c478bd9Sstevel@tonic-gate#      57a61
6197c478bd9Sstevel@tonic-gate#      63c66,76
6207c478bd9Sstevel@tonic-gate#      68,93d80
6217c478bd9Sstevel@tonic-gate#      106d90
6227c478bd9Sstevel@tonic-gate#      108,110d91
6237c478bd9Sstevel@tonic-gate#
624daaffb31Sdp#  These editing codes are parsed by the awk script and used to generate
625daaffb31Sdp#  another awk script that generates HTML, e.g the above lines would turn
626daaffb31Sdp#  into something like this:
6277c478bd9Sstevel@tonic-gate#
6287c478bd9Sstevel@tonic-gate#      BEGIN { printf "<pre>\n" }
6297c478bd9Sstevel@tonic-gate#      function sp(n) {for (i=0;i<n;i++)printf "\n"}
630daaffb31Sdp#      function wl(n) {printf "<font color=%s>%4d %s </font>\n", n, NR, $0}
6317c478bd9Sstevel@tonic-gate#      NR==8           {wl("#7A7ADD");next}
6327c478bd9Sstevel@tonic-gate#      NR==54          {wl("#7A7ADD");sp(3);next}
6337c478bd9Sstevel@tonic-gate#      NR==56          {wl("#7A7ADD");next}
6347c478bd9Sstevel@tonic-gate#      NR==57          {wl("black");printf "\n"; next}
6357c478bd9Sstevel@tonic-gate#        :               :
6367c478bd9Sstevel@tonic-gate#
637daaffb31Sdp#  This script is then run on the original source file to generate the
638daaffb31Sdp#  HTML that corresponds to the source file.
6397c478bd9Sstevel@tonic-gate#
640daaffb31Sdp#  The two HTML files are then combined into a single piece of HTML that
641daaffb31Sdp#  uses an HTML table construct to present the files side by side.  You'll
642daaffb31Sdp#  notice that the changes are color-coded:
6437c478bd9Sstevel@tonic-gate#
6447c478bd9Sstevel@tonic-gate#   black     - unchanged lines
6457c478bd9Sstevel@tonic-gate#   blue      - changed lines
6467c478bd9Sstevel@tonic-gate#   bold blue - new lines
6477c478bd9Sstevel@tonic-gate#   brown     - deleted lines
6487c478bd9Sstevel@tonic-gate#
649daaffb31Sdp#  Blank lines are inserted in each file to keep unchanged lines in sync
650daaffb31Sdp#  (side-by-side).  This format is familiar to users of sdiff(1) or
651daaffb31Sdp#  Teamware's filemerge tool.
652daaffb31Sdp#
653daaffb31Sdpsdiff_to_html()
654daaffb31Sdp{
6557c478bd9Sstevel@tonic-gate	diff -b $1 $2 > /tmp/$$.diffs
6567c478bd9Sstevel@tonic-gate
657daaffb31Sdp	TNAME=$3
658daaffb31Sdp	TPATH=$4
659daaffb31Sdp	COMMENT=$5
660daaffb31Sdp
6617c478bd9Sstevel@tonic-gate	#
6627c478bd9Sstevel@tonic-gate	#  Now we have the diffs, generate the HTML for the old file.
6637c478bd9Sstevel@tonic-gate	#
664cdf0c1d5Smjnelson	$AWK '
6657c478bd9Sstevel@tonic-gate	BEGIN	{
6667c478bd9Sstevel@tonic-gate		printf "function sp(n) {for (i=0;i<n;i++)printf \"\\n\"}\n"
667daaffb31Sdp		printf "function removed() "
668daaffb31Sdp		printf "{printf \"<span class=\\\"removed\\\">%%4d %%s</span>\\n\", NR, $0}\n"
669daaffb31Sdp		printf "function changed() "
670daaffb31Sdp		printf "{printf \"<span class=\\\"changed\\\">%%4d %%s</span>\\n\", NR, $0}\n"
671daaffb31Sdp		printf "function bl() {printf \"%%4d %%s\\n\", NR, $0}\n"
6727c478bd9Sstevel@tonic-gate}
6737c478bd9Sstevel@tonic-gate	/^</	{next}
6747c478bd9Sstevel@tonic-gate	/^>/	{next}
6757c478bd9Sstevel@tonic-gate	/^---/	{next}
676daaffb31Sdp
6777c478bd9Sstevel@tonic-gate	{
6787c478bd9Sstevel@tonic-gate	split($1, a, /[cad]/) ;
6797c478bd9Sstevel@tonic-gate	if (index($1, "a")) {
6807c478bd9Sstevel@tonic-gate		if (a[1] == 0) {
6817c478bd9Sstevel@tonic-gate			n = split(a[2], r, /,/);
6827c478bd9Sstevel@tonic-gate			if (n == 1)
6837c478bd9Sstevel@tonic-gate				printf "BEGIN\t\t{sp(1)}\n"
6847c478bd9Sstevel@tonic-gate			else
6857c478bd9Sstevel@tonic-gate				printf "BEGIN\t\t{sp(%d)}\n",\
6867c478bd9Sstevel@tonic-gate				(r[2] - r[1]) + 1
6877c478bd9Sstevel@tonic-gate			next
6887c478bd9Sstevel@tonic-gate		}
6897c478bd9Sstevel@tonic-gate
6907c478bd9Sstevel@tonic-gate		printf "NR==%s\t\t{", a[1]
6917c478bd9Sstevel@tonic-gate		n = split(a[2], r, /,/);
6927c478bd9Sstevel@tonic-gate		s = r[1];
6937c478bd9Sstevel@tonic-gate		if (n == 1)
6947c478bd9Sstevel@tonic-gate			printf "bl();printf \"\\n\"; next}\n"
6957c478bd9Sstevel@tonic-gate		else {
6967c478bd9Sstevel@tonic-gate			n = r[2] - r[1]
6977c478bd9Sstevel@tonic-gate			printf "bl();sp(%d);next}\n",\
6987c478bd9Sstevel@tonic-gate			(r[2] - r[1]) + 1
6997c478bd9Sstevel@tonic-gate		}
7007c478bd9Sstevel@tonic-gate		next
7017c478bd9Sstevel@tonic-gate	}
7027c478bd9Sstevel@tonic-gate	if (index($1, "d")) {
7037c478bd9Sstevel@tonic-gate		n = split(a[1], r, /,/);
7047c478bd9Sstevel@tonic-gate		n1 = r[1]
7057c478bd9Sstevel@tonic-gate		n2 = r[2]
7067c478bd9Sstevel@tonic-gate		if (n == 1)
707daaffb31Sdp			printf "NR==%s\t\t{removed(); next}\n" , n1
7087c478bd9Sstevel@tonic-gate		else
709daaffb31Sdp			printf "NR==%s,NR==%s\t{removed(); next}\n" , n1, n2
7107c478bd9Sstevel@tonic-gate		next
7117c478bd9Sstevel@tonic-gate	}
7127c478bd9Sstevel@tonic-gate	if (index($1, "c")) {
7137c478bd9Sstevel@tonic-gate		n = split(a[1], r, /,/);
7147c478bd9Sstevel@tonic-gate		n1 = r[1]
7157c478bd9Sstevel@tonic-gate		n2 = r[2]
7167c478bd9Sstevel@tonic-gate		final = n2
7177c478bd9Sstevel@tonic-gate		d1 = 0
7187c478bd9Sstevel@tonic-gate		if (n == 1)
719daaffb31Sdp			printf "NR==%s\t\t{changed();" , n1
7207c478bd9Sstevel@tonic-gate		else {
7217c478bd9Sstevel@tonic-gate			d1 = n2 - n1
722daaffb31Sdp			printf "NR==%s,NR==%s\t{changed();" , n1, n2
7237c478bd9Sstevel@tonic-gate		}
7247c478bd9Sstevel@tonic-gate		m = split(a[2], r, /,/);
7257c478bd9Sstevel@tonic-gate		n1 = r[1]
7267c478bd9Sstevel@tonic-gate		n2 = r[2]
7277c478bd9Sstevel@tonic-gate		if (m > 1) {
7287c478bd9Sstevel@tonic-gate			d2  = n2 - n1
7297c478bd9Sstevel@tonic-gate			if (d2 > d1) {
7307c478bd9Sstevel@tonic-gate				if (n > 1) printf "if (NR==%d)", final
7317c478bd9Sstevel@tonic-gate				printf "sp(%d);", d2 - d1
7327c478bd9Sstevel@tonic-gate			}
7337c478bd9Sstevel@tonic-gate		}
7347c478bd9Sstevel@tonic-gate		printf "next}\n" ;
7357c478bd9Sstevel@tonic-gate
7367c478bd9Sstevel@tonic-gate		next
7377c478bd9Sstevel@tonic-gate	}
7387c478bd9Sstevel@tonic-gate	}
7397c478bd9Sstevel@tonic-gate
740daaffb31Sdp	END	{ printf "{printf \"%%4d %%s\\n\", NR, $0 }\n" }
741daaffb31Sdp	' /tmp/$$.diffs > /tmp/$$.file1
7427c478bd9Sstevel@tonic-gate
7437c478bd9Sstevel@tonic-gate	#
7447c478bd9Sstevel@tonic-gate	#  Now generate the HTML for the new file
7457c478bd9Sstevel@tonic-gate	#
746cdf0c1d5Smjnelson	$AWK '
7477c478bd9Sstevel@tonic-gate	BEGIN	{
7487c478bd9Sstevel@tonic-gate		printf "function sp(n) {for (i=0;i<n;i++)printf \"\\n\"}\n"
749daaffb31Sdp		printf "function new() "
750daaffb31Sdp		printf "{printf \"<span class=\\\"new\\\">%%4d %%s</span>\\n\", NR, $0}\n"
751daaffb31Sdp		printf "function changed() "
752daaffb31Sdp		printf "{printf \"<span class=\\\"changed\\\">%%4d %%s</span>\\n\", NR, $0}\n"
753daaffb31Sdp		printf "function bl() {printf \"%%4d %%s\\n\", NR, $0}\n"
7547c478bd9Sstevel@tonic-gate	}
755daaffb31Sdp
7567c478bd9Sstevel@tonic-gate	/^</	{next}
7577c478bd9Sstevel@tonic-gate	/^>/	{next}
7587c478bd9Sstevel@tonic-gate	/^---/	{next}
759daaffb31Sdp
7607c478bd9Sstevel@tonic-gate	{
7617c478bd9Sstevel@tonic-gate	split($1, a, /[cad]/) ;
7627c478bd9Sstevel@tonic-gate	if (index($1, "d")) {
7637c478bd9Sstevel@tonic-gate		if (a[2] == 0) {
7647c478bd9Sstevel@tonic-gate			n = split(a[1], r, /,/);
7657c478bd9Sstevel@tonic-gate			if (n == 1)
7667c478bd9Sstevel@tonic-gate				printf "BEGIN\t\t{sp(1)}\n"
7677c478bd9Sstevel@tonic-gate			else
7687c478bd9Sstevel@tonic-gate				printf "BEGIN\t\t{sp(%d)}\n",\
7697c478bd9Sstevel@tonic-gate				(r[2] - r[1]) + 1
7707c478bd9Sstevel@tonic-gate			next
7717c478bd9Sstevel@tonic-gate		}
7727c478bd9Sstevel@tonic-gate
7737c478bd9Sstevel@tonic-gate		printf "NR==%s\t\t{", a[2]
7747c478bd9Sstevel@tonic-gate		n = split(a[1], r, /,/);
7757c478bd9Sstevel@tonic-gate		s = r[1];
7767c478bd9Sstevel@tonic-gate		if (n == 1)
7777c478bd9Sstevel@tonic-gate			printf "bl();printf \"\\n\"; next}\n"
7787c478bd9Sstevel@tonic-gate		else {
7797c478bd9Sstevel@tonic-gate			n = r[2] - r[1]
7807c478bd9Sstevel@tonic-gate			printf "bl();sp(%d);next}\n",\
7817c478bd9Sstevel@tonic-gate			(r[2] - r[1]) + 1
7827c478bd9Sstevel@tonic-gate		}
7837c478bd9Sstevel@tonic-gate		next
7847c478bd9Sstevel@tonic-gate	}
7857c478bd9Sstevel@tonic-gate	if (index($1, "a")) {
7867c478bd9Sstevel@tonic-gate		n = split(a[2], r, /,/);
7877c478bd9Sstevel@tonic-gate		n1 = r[1]
7887c478bd9Sstevel@tonic-gate		n2 = r[2]
7897c478bd9Sstevel@tonic-gate		if (n == 1)
790daaffb31Sdp			printf "NR==%s\t\t{new() ; next}\n" , n1
7917c478bd9Sstevel@tonic-gate		else
792daaffb31Sdp			printf "NR==%s,NR==%s\t{new() ; next}\n" , n1, n2
7937c478bd9Sstevel@tonic-gate		next
7947c478bd9Sstevel@tonic-gate	}
7957c478bd9Sstevel@tonic-gate	if (index($1, "c")) {
7967c478bd9Sstevel@tonic-gate		n = split(a[2], r, /,/);
7977c478bd9Sstevel@tonic-gate		n1 = r[1]
7987c478bd9Sstevel@tonic-gate		n2 = r[2]
7997c478bd9Sstevel@tonic-gate		final = n2
8007c478bd9Sstevel@tonic-gate		d2 = 0;
8017c478bd9Sstevel@tonic-gate		if (n == 1) {
8027c478bd9Sstevel@tonic-gate			final = n1
803daaffb31Sdp			printf "NR==%s\t\t{changed();" , n1
8047c478bd9Sstevel@tonic-gate		} else {
8057c478bd9Sstevel@tonic-gate			d2 = n2 - n1
806daaffb31Sdp			printf "NR==%s,NR==%s\t{changed();" , n1, n2
8077c478bd9Sstevel@tonic-gate		}
8087c478bd9Sstevel@tonic-gate		m = split(a[1], r, /,/);
8097c478bd9Sstevel@tonic-gate		n1 = r[1]
8107c478bd9Sstevel@tonic-gate		n2 = r[2]
8117c478bd9Sstevel@tonic-gate		if (m > 1) {
8127c478bd9Sstevel@tonic-gate			d1  = n2 - n1
8137c478bd9Sstevel@tonic-gate			if (d1 > d2) {
8147c478bd9Sstevel@tonic-gate				if (n > 1) printf "if (NR==%d)", final
8157c478bd9Sstevel@tonic-gate				printf "sp(%d);", d1 - d2
8167c478bd9Sstevel@tonic-gate			}
8177c478bd9Sstevel@tonic-gate		}
8187c478bd9Sstevel@tonic-gate		printf "next}\n" ;
8197c478bd9Sstevel@tonic-gate		next
8207c478bd9Sstevel@tonic-gate	}
8217c478bd9Sstevel@tonic-gate	}
822daaffb31Sdp	END	{ printf "{printf \"%%4d %%s\\n\", NR, $0 }\n" }
8237c478bd9Sstevel@tonic-gate	' /tmp/$$.diffs > /tmp/$$.file2
8247c478bd9Sstevel@tonic-gate
825daaffb31Sdp	#
826cdf0c1d5Smjnelson	# Post-process the HTML files by running them back through $AWK
827daaffb31Sdp	#
828cdf0c1d5Smjnelson	html_quote < $1 | $AWK -f /tmp/$$.file1 > /tmp/$$.file1.html
8297c478bd9Sstevel@tonic-gate
830cdf0c1d5Smjnelson	html_quote < $2 | $AWK -f /tmp/$$.file2 > /tmp/$$.file2.html
8317c478bd9Sstevel@tonic-gate
832daaffb31Sdp	#
833daaffb31Sdp	# Now combine into a valid HTML file and side-by-side into a table
834daaffb31Sdp	#
835daaffb31Sdp	print "$HTML<head>$STDHEAD"
836cdf0c1d5Smjnelson	print "<title>$WNAME Sdiff $TPATH/$TNAME</title>"
837daaffb31Sdp	print "</head><body id=\"SUNWwebrev\">"
838daaffb31Sdp        print "<a class=\"print\" href=\"javascript:print()\">Print this page</a>"
839daaffb31Sdp	print "<pre>$COMMENT</pre>\n"
840daaffb31Sdp	print "<table><tr valign=\"top\">"
841daaffb31Sdp	print "<td><pre>"
8427c478bd9Sstevel@tonic-gate
8437c478bd9Sstevel@tonic-gate	strip_unchanged /tmp/$$.file1.html
8447c478bd9Sstevel@tonic-gate
845daaffb31Sdp	print "</pre></td><td><pre>"
8467c478bd9Sstevel@tonic-gate
8477c478bd9Sstevel@tonic-gate	strip_unchanged /tmp/$$.file2.html
8487c478bd9Sstevel@tonic-gate
849daaffb31Sdp	print "</pre></td>"
850daaffb31Sdp	print "</tr></table>"
851daaffb31Sdp	print "</body></html>"
8527c478bd9Sstevel@tonic-gate
853daaffb31Sdp	framed_sdiff $TNAME $TPATH /tmp/$$.file1.html /tmp/$$.file2.html \
854daaffb31Sdp	    "$COMMENT"
8557c478bd9Sstevel@tonic-gate}
8567c478bd9Sstevel@tonic-gate
8577c478bd9Sstevel@tonic-gate
858daaffb31Sdp#
859daaffb31Sdp# framed_sdiff <filename> <filepath> <lhsfile> <rhsfile> <comment>
860daaffb31Sdp#
861daaffb31Sdp# Expects lefthand and righthand side html files created by sdiff_to_html.
862daaffb31Sdp# We use insert_anchors() to augment those with HTML navigation anchors,
863daaffb31Sdp# and then emit the main frame.  Content is placed into:
864daaffb31Sdp#
865daaffb31Sdp#    $WDIR/DIR/$TNAME.lhs.html
866daaffb31Sdp#    $WDIR/DIR/$TNAME.rhs.html
867daaffb31Sdp#    $WDIR/DIR/$TNAME.frames.html
868daaffb31Sdp#
869daaffb31Sdp# NOTE: We rely on standard usage of $WDIR and $DIR.
870daaffb31Sdp#
8717c478bd9Sstevel@tonic-gatefunction framed_sdiff
8727c478bd9Sstevel@tonic-gate{
8737c478bd9Sstevel@tonic-gate	typeset TNAME=$1
874daaffb31Sdp	typeset TPATH=$2
875daaffb31Sdp	typeset lhsfile=$3
876daaffb31Sdp	typeset rhsfile=$4
877daaffb31Sdp	typeset comments=$5
8787c478bd9Sstevel@tonic-gate	typeset RTOP
879daaffb31Sdp
8807c478bd9Sstevel@tonic-gate	# Enable html files to access WDIR via a relative path.
881daaffb31Sdp	RTOP=$(relative_dir $TPATH $WDIR)
882daaffb31Sdp
883daaffb31Sdp	# Make the rhs/lhs files and output the frameset file.
884daaffb31Sdp	print "$HTML<head>$STDHEAD" > $WDIR/$DIR/$TNAME.lhs.html
885daaffb31Sdp
886daaffb31Sdp	cat >> $WDIR/$DIR/$TNAME.lhs.html <<-EOF
8878b3b7b16SMark J. Nelson	    <script type="text/javascript" src="${RTOP}ancnav.js"></script>
8887c478bd9Sstevel@tonic-gate	    </head>
889daaffb31Sdp	    <body id="SUNWwebrev" onkeypress="keypress(event);">
890cac38512Smjnelson	    <a name="0"></a>
891cac38512Smjnelson	    <pre>$comments</pre><hr></hr>
892daaffb31Sdp	EOF
893daaffb31Sdp
894daaffb31Sdp	cp $WDIR/$DIR/$TNAME.lhs.html $WDIR/$DIR/$TNAME.rhs.html
895daaffb31Sdp
896daaffb31Sdp	insert_anchors $lhsfile >> $WDIR/$DIR/$TNAME.lhs.html
897daaffb31Sdp	insert_anchors $rhsfile >> $WDIR/$DIR/$TNAME.rhs.html
898daaffb31Sdp
899daaffb31Sdp	close='</body></html>'
900daaffb31Sdp
901daaffb31Sdp	print $close >> $WDIR/$DIR/$TNAME.lhs.html
902daaffb31Sdp	print $close >> $WDIR/$DIR/$TNAME.rhs.html
903daaffb31Sdp
904daaffb31Sdp	print "$FRAMEHTML<head>$STDHEAD" > $WDIR/$DIR/$TNAME.frames.html
905daaffb31Sdp	print "<title>$WNAME Framed-Sdiff " \
906daaffb31Sdp	    "$TPATH/$TNAME</title> </head>" >> $WDIR/$DIR/$TNAME.frames.html
907daaffb31Sdp	cat >> $WDIR/$DIR/$TNAME.frames.html <<-EOF
908daaffb31Sdp	  <frameset rows="*,60">
909daaffb31Sdp	    <frameset cols="50%,50%">
910cac38512Smjnelson	      <frame src="$TNAME.lhs.html" scrolling="auto" name="lhs"></frame>
911cac38512Smjnelson	      <frame src="$TNAME.rhs.html" scrolling="auto" name="rhs"></frame>
912daaffb31Sdp	    </frameset>
9138b3b7b16SMark J. Nelson	  <frame src="${RTOP}ancnav.html" scrolling="no" marginwidth="0"
914cac38512Smjnelson	   marginheight="0" name="nav"></frame>
915daaffb31Sdp	  <noframes>
916daaffb31Sdp            <body id="SUNWwebrev">
917daaffb31Sdp	      Alas 'frames' webrev requires that your browser supports frames
9187c478bd9Sstevel@tonic-gate	      and has the feature enabled.
919daaffb31Sdp            </body>
920daaffb31Sdp	  </noframes>
921daaffb31Sdp	  </frameset>
9227c478bd9Sstevel@tonic-gate	</html>
9237c478bd9Sstevel@tonic-gate	EOF
9247c478bd9Sstevel@tonic-gate}
9257c478bd9Sstevel@tonic-gate
9267c478bd9Sstevel@tonic-gate
927daaffb31Sdp#
928daaffb31Sdp# fix_postscript
929daaffb31Sdp#
930daaffb31Sdp# Merge codereview output files to a single conforming postscript file, by:
931daaffb31Sdp#	- removing all extraneous headers/trailers
932daaffb31Sdp#	- making the page numbers right
933daaffb31Sdp#	- removing pages devoid of contents which confuse some
934daaffb31Sdp#	  postscript readers.
935daaffb31Sdp#
936daaffb31Sdp# From Casper.
937daaffb31Sdp#
938daaffb31Sdpfunction fix_postscript
9397c478bd9Sstevel@tonic-gate{
940daaffb31Sdp	infile=$1
9417c478bd9Sstevel@tonic-gate
942daaffb31Sdp	cat > /tmp/$$.crmerge.pl << \EOF
9437c478bd9Sstevel@tonic-gate
944daaffb31Sdp	print scalar(<>);		# %!PS-Adobe---
945daaffb31Sdp	print "%%Orientation: Landscape\n";
9467c478bd9Sstevel@tonic-gate
947daaffb31Sdp	$pno = 0;
948daaffb31Sdp	$doprint = 1;
949daaffb31Sdp
950daaffb31Sdp	$page = "";
951daaffb31Sdp
952daaffb31Sdp	while (<>) {
953daaffb31Sdp		next if (/^%%Pages:\s*\d+/);
954daaffb31Sdp
955daaffb31Sdp		if (/^%%Page:/) {
956daaffb31Sdp			if ($pno == 0 || $page =~ /\)S/) {
957daaffb31Sdp				# Header or single page containing text
958daaffb31Sdp				print "%%Page: ? $pno\n" if ($pno > 0);
959daaffb31Sdp				print $page;
960daaffb31Sdp				$pno++;
961daaffb31Sdp			} else {
962daaffb31Sdp				# Empty page, skip it.
9637c478bd9Sstevel@tonic-gate			}
964daaffb31Sdp			$page = "";
965daaffb31Sdp			$doprint = 1;
9667c478bd9Sstevel@tonic-gate			next;
9677c478bd9Sstevel@tonic-gate		}
9687c478bd9Sstevel@tonic-gate
969daaffb31Sdp		# Skip from %%Trailer of one document to Endprolog
970daaffb31Sdp		# %%Page of the next
971daaffb31Sdp		$doprint = 0 if (/^%%Trailer/);
972daaffb31Sdp		$page .= $_ if ($doprint);
9737c478bd9Sstevel@tonic-gate	}
9747c478bd9Sstevel@tonic-gate
975daaffb31Sdp	if ($page =~ /\)S/) {
976daaffb31Sdp		print "%%Page: ? $pno\n";
977daaffb31Sdp		print $page;
978daaffb31Sdp	} else {
979daaffb31Sdp		$pno--;
980daaffb31Sdp	}
981daaffb31Sdp	print "%%Trailer\n%%Pages: $pno\n";
982daaffb31SdpEOF
983daaffb31Sdp
98414983201Sdp	$PERL /tmp/$$.crmerge.pl < $infile
985daaffb31Sdp}
986daaffb31Sdp
987daaffb31Sdp
988daaffb31Sdp#
989daaffb31Sdp# input_cmd | insert_anchors | output_cmd
990daaffb31Sdp#
9917c478bd9Sstevel@tonic-gate# Flag blocks of difference with sequentially numbered invisible
992daaffb31Sdp# anchors.  These are used to drive the frames version of the
9937c478bd9Sstevel@tonic-gate# sdiffs output.
9947c478bd9Sstevel@tonic-gate#
9957c478bd9Sstevel@tonic-gate# NOTE: Anchor zero flags the top of the file irrespective of changes,
9967c478bd9Sstevel@tonic-gate# an additional anchor is also appended to flag the bottom.
9977c478bd9Sstevel@tonic-gate#
998daaffb31Sdp# The script detects changed lines as any line that has a "<span
999daaffb31Sdp# class=" string embedded (unchanged lines have no class set and are
1000daaffb31Sdp# not part of a <span>.  Blank lines (without a sequence number)
10017c478bd9Sstevel@tonic-gate# are also detected since they flag lines that have been inserted or
10027c478bd9Sstevel@tonic-gate# deleted.
10037c478bd9Sstevel@tonic-gate#
1004daaffb31Sdpfunction insert_anchors
1005daaffb31Sdp{
1006cdf0c1d5Smjnelson	$AWK '
10077c478bd9Sstevel@tonic-gate	function ia() {
1008daaffb31Sdp		printf "<a name=\"%d\" id=\"anc%d\"></a>", anc, anc++;
10097c478bd9Sstevel@tonic-gate	}
1010daaffb31Sdp
10117c478bd9Sstevel@tonic-gate	BEGIN {
1012daaffb31Sdp		anc=1;
10137c478bd9Sstevel@tonic-gate		inblock=1;
1014daaffb31Sdp		printf "<pre>\n";
10157c478bd9Sstevel@tonic-gate	}
1016daaffb31Sdp	NF == 0 || /^<span class=/ {
10177c478bd9Sstevel@tonic-gate		if (inblock == 0) {
10187c478bd9Sstevel@tonic-gate			ia();
10197c478bd9Sstevel@tonic-gate			inblock=1;
10207c478bd9Sstevel@tonic-gate		}
10217c478bd9Sstevel@tonic-gate		print;
10227c478bd9Sstevel@tonic-gate		next;
10237c478bd9Sstevel@tonic-gate	}
10247c478bd9Sstevel@tonic-gate	{
10257c478bd9Sstevel@tonic-gate		inblock=0;
10267c478bd9Sstevel@tonic-gate		print;
10277c478bd9Sstevel@tonic-gate	}
10287c478bd9Sstevel@tonic-gate	END {
10297c478bd9Sstevel@tonic-gate		ia();
1030daaffb31Sdp
1031daaffb31Sdp		printf "<b style=\"font-size: large; color: red\">";
1032daaffb31Sdp		printf "--- EOF ---</b>"
10337c478bd9Sstevel@tonic-gate		for(i=0;i<8;i++) printf "\n\n\n\n\n\n\n\n\n\n";
1034daaffb31Sdp		printf "</pre>"
1035daaffb31Sdp		printf "<form name=\"eof\">";
1036cac38512Smjnelson		printf "<input name=\"value\" value=\"%d\" " \
1037cac38512Smjnelson		    "type=\"hidden\"></input>", anc - 1;
1038daaffb31Sdp		printf "</form>";
10397c478bd9Sstevel@tonic-gate	}
10407c478bd9Sstevel@tonic-gate	' $1
10417c478bd9Sstevel@tonic-gate}
10427c478bd9Sstevel@tonic-gate
10437c478bd9Sstevel@tonic-gate
1044daaffb31Sdp#
1045daaffb31Sdp# relative_dir
1046daaffb31Sdp#
1047daaffb31Sdp# Print a relative return path from $1 to $2.  For example if
1048daaffb31Sdp# $1=/tmp/myreview/raw_files/usr/src/tools/scripts and $2=/tmp/myreview,
1049daaffb31Sdp# this function would print "../../../../".
1050daaffb31Sdp#
1051daaffb31Sdp# In the event that $1 is not in $2 a warning is printed to stderr,
1052daaffb31Sdp# and $2 is returned-- the result of this is that the resulting webrev
1053daaffb31Sdp# is not relocatable.
1054daaffb31Sdp#
1055daaffb31Sdpfunction relative_dir
10567c478bd9Sstevel@tonic-gate{
1057daaffb31Sdp        typeset cur="${1##$2?(/)}"
10588b3b7b16SMark J. Nelson
10598b3b7b16SMark J. Nelson        #
10608b3b7b16SMark J. Nelson        # If the first path was specified absolutely, and it does
10618b3b7b16SMark J. Nelson        # not start with the second path, it's an error.
10628b3b7b16SMark J. Nelson        #
10630fd2682eSMark J. Nelson        if [[ "$cur" = "/${1#/}" ]]; then
1064daaffb31Sdp                # Should never happen.
106514983201Sdp                print -u2 "\nWARNING: relative_dir: \"$1\" not relative "
1066daaffb31Sdp                print -u2 "to \"$2\".  Check input paths.  Framed webrev "
1067daaffb31Sdp                print -u2 "will not be relocatable!"
1068daaffb31Sdp                print $2
1069daaffb31Sdp                return
1070daaffb31Sdp        fi
1071daaffb31Sdp
10728b3b7b16SMark J. Nelson	#
10738b3b7b16SMark J. Nelson	# This is kind of ugly.  The sed script will do the following:
10748b3b7b16SMark J. Nelson	#
10758b3b7b16SMark J. Nelson	# 1. Strip off a leading "." or "./": this is important to get
10768b3b7b16SMark J. Nelson	#    the correct arcnav links for files in $WDIR.
10778b3b7b16SMark J. Nelson	# 2. Strip off a trailing "/": this is not strictly necessary,
10788b3b7b16SMark J. Nelson	#    but is kind of nice, since it doesn't end up in "//" at
10798b3b7b16SMark J. Nelson	#    the end of a relative path.
10808b3b7b16SMark J. Nelson	# 3. Replace all remaining sequences of non-"/" with "..": the
10818b3b7b16SMark J. Nelson	#    assumption here is that each dirname represents another
10828b3b7b16SMark J. Nelson	#    level of relative separation.
10838b3b7b16SMark J. Nelson	# 4. Append a trailing "/" only for non-empty paths: this way
10848b3b7b16SMark J. Nelson	#    the caller doesn't need to duplicate this logic, and does
10858b3b7b16SMark J. Nelson	#    not end up using $RTOP/file for files in $WDIR.
10868b3b7b16SMark J. Nelson	#
10870fd2682eSMark J. Nelson	print $cur | $SED -e '{
10888b3b7b16SMark J. Nelson		s:^\./*::
10898b3b7b16SMark J. Nelson		s:/$::
10908b3b7b16SMark J. Nelson		s:[^/][^/]*:..:g
10910fd2682eSMark J. Nelson		s:^\(..*\)$:\1/:
10920fd2682eSMark J. Nelson	}'
10937c478bd9Sstevel@tonic-gate}
10947c478bd9Sstevel@tonic-gate
1095daaffb31Sdp#
1096daaffb31Sdp# frame_nav_js
1097daaffb31Sdp#
1098daaffb31Sdp# Emit javascript for frame navigation
1099daaffb31Sdp#
1100daaffb31Sdpfunction frame_nav_js
11017c478bd9Sstevel@tonic-gate{
11027c478bd9Sstevel@tonic-gatecat << \EOF
11037c478bd9Sstevel@tonic-gatevar myInt;
11047c478bd9Sstevel@tonic-gatevar scrolling=0;
1105daaffb31Sdpvar sfactor = 3;
11067c478bd9Sstevel@tonic-gatevar scount=10;
11077c478bd9Sstevel@tonic-gate
11087c478bd9Sstevel@tonic-gatefunction scrollByPix() {
11097c478bd9Sstevel@tonic-gate	if (scount<=0) {
11107c478bd9Sstevel@tonic-gate		sfactor*=1.2;
11117c478bd9Sstevel@tonic-gate		scount=10;
11127c478bd9Sstevel@tonic-gate	}
11137c478bd9Sstevel@tonic-gate	parent.lhs.scrollBy(0,sfactor);
11147c478bd9Sstevel@tonic-gate	parent.rhs.scrollBy(0,sfactor);
11157c478bd9Sstevel@tonic-gate	scount--;
11167c478bd9Sstevel@tonic-gate}
11177c478bd9Sstevel@tonic-gate
1118daaffb31Sdpfunction scrollToAnc(num) {
1119daaffb31Sdp
1120daaffb31Sdp	// Update the value of the anchor in the form which we use as
1121daaffb31Sdp	// storage for this value.  setAncValue() will take care of
1122daaffb31Sdp	// correcting for overflow and underflow of the value and return
1123daaffb31Sdp	// us the new value.
1124daaffb31Sdp	num = setAncValue(num);
1125daaffb31Sdp
1126daaffb31Sdp	// Set location and scroll back a little to expose previous
1127daaffb31Sdp	// lines.
1128daaffb31Sdp	//
1129daaffb31Sdp	// Note that this could be improved: it is possible although
1130daaffb31Sdp	// complex to compute the x and y position of an anchor, and to
1131daaffb31Sdp	// scroll to that location directly.
1132daaffb31Sdp	//
11337c478bd9Sstevel@tonic-gate	parent.lhs.location.replace(parent.lhs.location.pathname + "#" + num);
11347c478bd9Sstevel@tonic-gate	parent.rhs.location.replace(parent.rhs.location.pathname + "#" + num);
1135daaffb31Sdp
11367c478bd9Sstevel@tonic-gate	parent.lhs.scrollBy(0,-30);
11377c478bd9Sstevel@tonic-gate	parent.rhs.scrollBy(0,-30);
11387c478bd9Sstevel@tonic-gate}
11397c478bd9Sstevel@tonic-gate
1140daaffb31Sdpfunction getAncValue()
1141daaffb31Sdp{
1142daaffb31Sdp	return (parseInt(parent.nav.document.diff.real.value));
1143daaffb31Sdp}
1144daaffb31Sdp
1145daaffb31Sdpfunction setAncValue(val)
1146daaffb31Sdp{
1147daaffb31Sdp	if (val <= 0) {
1148daaffb31Sdp		val = 0;
1149daaffb31Sdp		parent.nav.document.diff.real.value = val;
1150daaffb31Sdp		parent.nav.document.diff.display.value = "BOF";
1151daaffb31Sdp		return (val);
1152daaffb31Sdp	}
1153daaffb31Sdp
1154daaffb31Sdp	//
1155daaffb31Sdp	// The way we compute the max anchor value is to stash it
1156daaffb31Sdp	// inline in the left and right hand side pages-- it's the same
1157daaffb31Sdp	// on each side, so we pluck from the left.
1158daaffb31Sdp	//
1159daaffb31Sdp	maxval = parent.lhs.document.eof.value.value;
1160daaffb31Sdp	if (val < maxval) {
1161daaffb31Sdp		parent.nav.document.diff.real.value = val;
1162daaffb31Sdp		parent.nav.document.diff.display.value = val.toString();
1163daaffb31Sdp		return (val);
1164daaffb31Sdp	}
1165daaffb31Sdp
1166daaffb31Sdp	// this must be: val >= maxval
1167daaffb31Sdp	val = maxval;
1168daaffb31Sdp	parent.nav.document.diff.real.value = val;
1169daaffb31Sdp	parent.nav.document.diff.display.value = "EOF";
1170daaffb31Sdp	return (val);
1171daaffb31Sdp}
1172daaffb31Sdp
11737c478bd9Sstevel@tonic-gatefunction stopScroll() {
11747c478bd9Sstevel@tonic-gate	if (scrolling==1) {
11757c478bd9Sstevel@tonic-gate		clearInterval(myInt);
11767c478bd9Sstevel@tonic-gate		scrolling=0;
11777c478bd9Sstevel@tonic-gate	}
11787c478bd9Sstevel@tonic-gate}
11797c478bd9Sstevel@tonic-gate
11807c478bd9Sstevel@tonic-gatefunction startScroll() {
11817c478bd9Sstevel@tonic-gate	stopScroll();
11827c478bd9Sstevel@tonic-gate	scrolling=1;
11837c478bd9Sstevel@tonic-gate	myInt=setInterval("scrollByPix()",10);
11847c478bd9Sstevel@tonic-gate}
11857c478bd9Sstevel@tonic-gate
11867c478bd9Sstevel@tonic-gatefunction handlePress(b) {
1187daaffb31Sdp
11887c478bd9Sstevel@tonic-gate	switch (b) {
11897c478bd9Sstevel@tonic-gate	    case 1 :
1190daaffb31Sdp		scrollToAnc(-1);
11917c478bd9Sstevel@tonic-gate		break;
11927c478bd9Sstevel@tonic-gate	    case 2 :
1193daaffb31Sdp		scrollToAnc(getAncValue() - 1);
11947c478bd9Sstevel@tonic-gate		break;
11957c478bd9Sstevel@tonic-gate	    case 3 :
11967c478bd9Sstevel@tonic-gate		sfactor=-3;
11977c478bd9Sstevel@tonic-gate		startScroll();
11987c478bd9Sstevel@tonic-gate		break;
11997c478bd9Sstevel@tonic-gate	    case 4 :
12007c478bd9Sstevel@tonic-gate		sfactor=3;
12017c478bd9Sstevel@tonic-gate		startScroll();
12027c478bd9Sstevel@tonic-gate		break;
12037c478bd9Sstevel@tonic-gate	    case 5 :
1204daaffb31Sdp		scrollToAnc(getAncValue() + 1);
12057c478bd9Sstevel@tonic-gate		break;
12067c478bd9Sstevel@tonic-gate	    case 6 :
1207daaffb31Sdp		scrollToAnc(999999);
12087c478bd9Sstevel@tonic-gate		break;
12097c478bd9Sstevel@tonic-gate	}
12107c478bd9Sstevel@tonic-gate}
12117c478bd9Sstevel@tonic-gate
12127c478bd9Sstevel@tonic-gatefunction handleRelease(b) {
12137c478bd9Sstevel@tonic-gate	stopScroll();
12147c478bd9Sstevel@tonic-gate}
12157c478bd9Sstevel@tonic-gate
1216daaffb31Sdpfunction keypress(ev) {
1217daaffb31Sdp	var keynum;
1218daaffb31Sdp	var keychar;
1219daaffb31Sdp
1220daaffb31Sdp	if (window.event) { // IE
1221daaffb31Sdp		keynum = ev.keyCode;
1222daaffb31Sdp	} else if (ev.which) { // non-IE
1223daaffb31Sdp		keynum = ev.which;
1224daaffb31Sdp	}
1225daaffb31Sdp
1226daaffb31Sdp	keychar = String.fromCharCode(keynum);
1227daaffb31Sdp
1228daaffb31Sdp	if (keychar == "k") {
1229daaffb31Sdp		handlePress(2);
1230daaffb31Sdp		return (0);
1231daaffb31Sdp	} else if (keychar == "j" || keychar == " ") {
1232daaffb31Sdp		handlePress(5);
1233daaffb31Sdp		return (0);
1234daaffb31Sdp	}
1235daaffb31Sdp	return (1);
1236daaffb31Sdp}
1237daaffb31Sdp
12387c478bd9Sstevel@tonic-gatefunction ValidateDiffNum(){
1239daaffb31Sdp	val = parent.nav.document.diff.display.value;
1240daaffb31Sdp	if (val == "EOF") {
1241daaffb31Sdp		scrollToAnc(999999);
1242daaffb31Sdp		return;
1243daaffb31Sdp	}
1244daaffb31Sdp
1245daaffb31Sdp	if (val == "BOF") {
1246daaffb31Sdp		scrollToAnc(0);
1247daaffb31Sdp		return;
1248daaffb31Sdp	}
1249daaffb31Sdp
1250daaffb31Sdp        i=parseInt(val);
12517c478bd9Sstevel@tonic-gate        if (isNaN(i)) {
1252daaffb31Sdp                parent.nav.document.diff.display.value = getAncValue();
12537c478bd9Sstevel@tonic-gate        } else {
1254daaffb31Sdp                scrollToAnc(i);
12557c478bd9Sstevel@tonic-gate        }
12567c478bd9Sstevel@tonic-gate        return false;
12577c478bd9Sstevel@tonic-gate}
12587c478bd9Sstevel@tonic-gate
1259daaffb31SdpEOF
1260daaffb31Sdp}
1261daaffb31Sdp
1262daaffb31Sdp#
1263daaffb31Sdp# frame_navigation
1264daaffb31Sdp#
1265daaffb31Sdp# Output anchor navigation file for framed sdiffs.
1266daaffb31Sdp#
1267daaffb31Sdpfunction frame_navigation
1268daaffb31Sdp{
1269daaffb31Sdp	print "$HTML<head>$STDHEAD"
1270daaffb31Sdp
1271daaffb31Sdp	cat << \EOF
1272daaffb31Sdp<title>Anchor Navigation</title>
1273daaffb31Sdp<meta http-equiv="Content-Script-Type" content="text/javascript">
1274daaffb31Sdp<meta http-equiv="Content-Type" content="text/html">
1275daaffb31Sdp
1276daaffb31Sdp<style type="text/css">
1277daaffb31Sdp    div.button td { padding-left: 5px; padding-right: 5px;
1278daaffb31Sdp		    background-color: #eee; text-align: center;
1279daaffb31Sdp		    border: 1px #444 outset; cursor: pointer; }
1280daaffb31Sdp    div.button a { font-weight: bold; color: black }
1281daaffb31Sdp    div.button td:hover { background: #ffcc99; }
1282daaffb31Sdp</style>
1283daaffb31SdpEOF
1284daaffb31Sdp
1285cac38512Smjnelson	print "<script type=\"text/javascript\" src=\"ancnav.js\"></script>"
1286daaffb31Sdp
1287daaffb31Sdp	cat << \EOF
12887c478bd9Sstevel@tonic-gate</head>
1289daaffb31Sdp<body id="SUNWwebrev" bgcolor="#eeeeee" onload="document.diff.real.focus();"
1290daaffb31Sdp	onkeypress="keypress(event);">
12917c478bd9Sstevel@tonic-gate    <noscript lang="javascript">
12927c478bd9Sstevel@tonic-gate      <center>
1293cac38512Smjnelson	<p><big>Framed Navigation controls require Javascript</big><br></br>
12947c478bd9Sstevel@tonic-gate	Either this browser is incompatable or javascript is not enabled</p>
12957c478bd9Sstevel@tonic-gate      </center>
12967c478bd9Sstevel@tonic-gate    </noscript>
12977c478bd9Sstevel@tonic-gate    <table width="100%" border="0" align="center">
1298daaffb31Sdp	<tr>
1299daaffb31Sdp          <td valign="middle" width="25%">Diff navigation:
1300daaffb31Sdp          Use 'j' and 'k' for next and previous diffs; or use buttons
1301daaffb31Sdp          at right</td>
1302daaffb31Sdp	  <td align="center" valign="top" width="50%">
13037c478bd9Sstevel@tonic-gate	    <div class="button">
1304daaffb31Sdp	      <table border="0" align="center">
1305daaffb31Sdp                  <tr>
1306daaffb31Sdp		    <td>
13077c478bd9Sstevel@tonic-gate		      <a onMouseDown="handlePress(1);return true;"
13087c478bd9Sstevel@tonic-gate			 onMouseUp="handleRelease(1);return true;"
13097c478bd9Sstevel@tonic-gate			 onMouseOut="handleRelease(1);return true;"
13107c478bd9Sstevel@tonic-gate			 onClick="return false;"
13117c478bd9Sstevel@tonic-gate			 title="Go to Beginning Of file">BOF</a></td>
1312daaffb31Sdp		    <td>
13137c478bd9Sstevel@tonic-gate		      <a onMouseDown="handlePress(3);return true;"
13147c478bd9Sstevel@tonic-gate			 onMouseUp="handleRelease(3);return true;"
13157c478bd9Sstevel@tonic-gate			 onMouseOut="handleRelease(3);return true;"
13167c478bd9Sstevel@tonic-gate			 title="Scroll Up: Press and Hold to accelerate"
1317daaffb31Sdp			 onClick="return false;">Scroll Up</a></td>
1318daaffb31Sdp		    <td>
13197c478bd9Sstevel@tonic-gate		      <a onMouseDown="handlePress(2);return true;"
13207c478bd9Sstevel@tonic-gate			 onMouseUp="handleRelease(2);return true;"
13217c478bd9Sstevel@tonic-gate			 onMouseOut="handleRelease(2);return true;"
13227c478bd9Sstevel@tonic-gate			 title="Go to previous Diff"
13237c478bd9Sstevel@tonic-gate			 onClick="return false;">Prev Diff</a>
13247c478bd9Sstevel@tonic-gate		    </td></tr>
1325daaffb31Sdp
13267c478bd9Sstevel@tonic-gate		  <tr>
1327daaffb31Sdp		    <td>
13287c478bd9Sstevel@tonic-gate		      <a onMouseDown="handlePress(6);return true;"
13297c478bd9Sstevel@tonic-gate			 onMouseUp="handleRelease(6);return true;"
13307c478bd9Sstevel@tonic-gate			 onMouseOut="handleRelease(6);return true;"
13317c478bd9Sstevel@tonic-gate			 onClick="return false;"
13327c478bd9Sstevel@tonic-gate			 title="Go to End Of File">EOF</a></td>
1333daaffb31Sdp		    <td>
13347c478bd9Sstevel@tonic-gate		      <a onMouseDown="handlePress(4);return true;"
13357c478bd9Sstevel@tonic-gate			 onMouseUp="handleRelease(4);return true;"
13367c478bd9Sstevel@tonic-gate			 onMouseOut="handleRelease(4);return true;"
13377c478bd9Sstevel@tonic-gate			 title="Scroll Down: Press and Hold to accelerate"
1338daaffb31Sdp			 onClick="return false;">Scroll Down</a></td>
1339daaffb31Sdp		    <td>
13407c478bd9Sstevel@tonic-gate		      <a onMouseDown="handlePress(5);return true;"
13417c478bd9Sstevel@tonic-gate			 onMouseUp="handleRelease(5);return true;"
13427c478bd9Sstevel@tonic-gate			 onMouseOut="handleRelease(5);return true;"
13437c478bd9Sstevel@tonic-gate			 title="Go to next Diff"
13447c478bd9Sstevel@tonic-gate			 onClick="return false;">Next Diff</a></td>
1345daaffb31Sdp		  </tr>
1346daaffb31Sdp              </table>
1347daaffb31Sdp	    </div>
1348daaffb31Sdp	  </td>
13497c478bd9Sstevel@tonic-gate	  <th valign="middle" width="25%">
1350daaffb31Sdp	    <form action="" name="diff" onsubmit="return ValidateDiffNum();">
1351cac38512Smjnelson		<input name="display" value="BOF" size="8" type="text"></input>
1352cac38512Smjnelson		<input name="real" value="0" size="8" type="hidden"></input>
13537c478bd9Sstevel@tonic-gate	    </form>
13547c478bd9Sstevel@tonic-gate	  </th>
1355daaffb31Sdp	</tr>
13567c478bd9Sstevel@tonic-gate    </table>
13577c478bd9Sstevel@tonic-gate  </body>
13587c478bd9Sstevel@tonic-gate</html>
13597c478bd9Sstevel@tonic-gateEOF
13607c478bd9Sstevel@tonic-gate}
13617c478bd9Sstevel@tonic-gate
13627c478bd9Sstevel@tonic-gate
1363daaffb31Sdp
1364daaffb31Sdp#
1365daaffb31Sdp# diff_to_html <filename> <filepath> { U | C } <comment>
1366daaffb31Sdp#
1367daaffb31Sdp# Processes the output of diff to produce an HTML file representing either
1368daaffb31Sdp# context or unified diffs.
1369daaffb31Sdp#
13707c478bd9Sstevel@tonic-gatediff_to_html()
13717c478bd9Sstevel@tonic-gate{
13727c478bd9Sstevel@tonic-gate	TNAME=$1
1373daaffb31Sdp	TPATH=$2
1374daaffb31Sdp	DIFFTYPE=$3
1375daaffb31Sdp	COMMENT=$4
1376daaffb31Sdp
1377daaffb31Sdp	print "$HTML<head>$STDHEAD"
1378daaffb31Sdp	print "<title>$WNAME ${DIFFTYPE}diff $TPATH</title>"
1379daaffb31Sdp
1380daaffb31Sdp	if [[ $DIFFTYPE == "U" ]]; then
1381daaffb31Sdp		print "$UDIFFCSS"
1382daaffb31Sdp	fi
1383daaffb31Sdp
1384daaffb31Sdp	cat <<-EOF
1385daaffb31Sdp	</head>
1386daaffb31Sdp	<body id="SUNWwebrev">
1387daaffb31Sdp        <a class="print" href="javascript:print()">Print this page</a>
1388daaffb31Sdp	<pre>$COMMENT</pre>
1389daaffb31Sdp        <pre>
1390daaffb31Sdp	EOF
13917c478bd9Sstevel@tonic-gate
1392cdf0c1d5Smjnelson	html_quote | $AWK '
1393daaffb31Sdp	/^--- new/	{ next }
1394daaffb31Sdp	/^\+\+\+ new/	{ next }
1395daaffb31Sdp	/^--- old/	{ next }
1396daaffb31Sdp	/^\*\*\* old/	{ next }
1397daaffb31Sdp	/^\*\*\*\*/	{ next }
13987c478bd9Sstevel@tonic-gate	/^-------/	{ printf "<center><h1>%s</h1></center>\n", $0; next }
1399cac38512Smjnelson	/^\@\@.*\@\@$/	{ printf "</pre><hr></hr><pre>\n";
1400daaffb31Sdp			  printf "<span class=\"newmarker\">%s</span>\n", $0;
1401daaffb31Sdp			  next}
1402daaffb31Sdp
1403cac38512Smjnelson	/^\*\*\*/	{ printf "<hr></hr><span class=\"oldmarker\">%s</span>\n", $0;
1404daaffb31Sdp			  next}
1405daaffb31Sdp	/^---/		{ printf "<span class=\"newmarker\">%s</span>\n", $0;
1406daaffb31Sdp			  next}
1407daaffb31Sdp	/^\+/		{printf "<span class=\"new\">%s</span>\n", $0; next}
1408daaffb31Sdp	/^!/		{printf "<span class=\"changed\">%s</span>\n", $0; next}
1409daaffb31Sdp	/^-/		{printf "<span class=\"removed\">%s</span>\n", $0; next}
1410daaffb31Sdp			{printf "%s\n", $0; next}
14117c478bd9Sstevel@tonic-gate	'
1412daaffb31Sdp
1413daaffb31Sdp	print "</pre></body></html>\n"
14147c478bd9Sstevel@tonic-gate}
14157c478bd9Sstevel@tonic-gate
14167c478bd9Sstevel@tonic-gate
1417daaffb31Sdp#
1418daaffb31Sdp# source_to_html { new | old } <filename>
1419daaffb31Sdp#
1420daaffb31Sdp# Process a plain vanilla source file to transform it into an HTML file.
1421daaffb31Sdp#
14227c478bd9Sstevel@tonic-gatesource_to_html()
14237c478bd9Sstevel@tonic-gate{
14247c478bd9Sstevel@tonic-gate	WHICH=$1
14257c478bd9Sstevel@tonic-gate	TNAME=$2
14267c478bd9Sstevel@tonic-gate
1427daaffb31Sdp	print "$HTML<head>$STDHEAD"
1428cdf0c1d5Smjnelson	print "<title>$WNAME $WHICH $TNAME</title>"
1429daaffb31Sdp	print "<body id=\"SUNWwebrev\">"
1430daaffb31Sdp	print "<pre>"
1431cdf0c1d5Smjnelson	html_quote | $AWK '{line += 1 ; printf "%4d %s\n", line, $0 }'
1432daaffb31Sdp	print "</pre></body></html>"
14337c478bd9Sstevel@tonic-gate}
14347c478bd9Sstevel@tonic-gate
1435daaffb31Sdp#
1436cdf0c1d5Smjnelson# comments_from_wx {text|html} filepath
1437daaffb31Sdp#
1438cdf0c1d5Smjnelson# Given the pathname of a file, find its location in a "wx" active
1439cdf0c1d5Smjnelson# file list and print the following comment.  Output is either text or
1440cdf0c1d5Smjnelson# HTML; if the latter, embedded bugids (sequence of 5 or more digits)
1441cdf0c1d5Smjnelson# are turned into URLs.
1442cdf0c1d5Smjnelson#
1443cdf0c1d5Smjnelson# This is also used with Mercurial and the file list provided by hg-active.
1444daaffb31Sdp#
1445daaffb31Sdpcomments_from_wx()
14467c478bd9Sstevel@tonic-gate{
1447daaffb31Sdp	typeset fmt=$1
1448daaffb31Sdp	typeset p=$2
14497c478bd9Sstevel@tonic-gate
1450cdf0c1d5Smjnelson	comm=`$AWK '
1451daaffb31Sdp	$1 == "'$p'" {
14527c478bd9Sstevel@tonic-gate		do getline ; while (NF > 0)
14537c478bd9Sstevel@tonic-gate		getline
14547c478bd9Sstevel@tonic-gate		while (NF > 0) { print ; getline }
14557c478bd9Sstevel@tonic-gate		exit
1456daaffb31Sdp	}' < $wxfile`
1457daaffb31Sdp
1458cdf0c1d5Smjnelson	if [[ -z $comm ]]; then
1459cdf0c1d5Smjnelson		comm="*** NO COMMENTS ***"
1460cdf0c1d5Smjnelson	fi
1461cdf0c1d5Smjnelson
1462daaffb31Sdp	if [[ $fmt == "text" ]]; then
1463cdf0c1d5Smjnelson		print -- "$comm"
1464daaffb31Sdp		return
1465daaffb31Sdp	fi
1466daaffb31Sdp
14670fd2682eSMark J. Nelson	print -- "$comm" | html_quote | its2url
1468cdf0c1d5Smjnelson
14697c478bd9Sstevel@tonic-gate}
14707c478bd9Sstevel@tonic-gate
14717c478bd9Sstevel@tonic-gate#
1472daaffb31Sdp# getcomments {text|html} filepath parentpath
1473daaffb31Sdp#
1474daaffb31Sdp# Fetch the comments depending on what SCM mode we're in.
1475daaffb31Sdp#
1476daaffb31Sdpgetcomments()
1477daaffb31Sdp{
1478daaffb31Sdp	typeset fmt=$1
1479daaffb31Sdp	typeset p=$2
1480daaffb31Sdp	typeset pp=$3
14817c478bd9Sstevel@tonic-gate
14823df69ef3SDarren Moffat	if [[ -n $Nflag ]]; then
14833df69ef3SDarren Moffat		return
14843df69ef3SDarren Moffat	fi
1485cdf0c1d5Smjnelson	#
1486cdf0c1d5Smjnelson	# Mercurial support uses a file list in wx format, so this
1487cdf0c1d5Smjnelson	# will be used there, too
1488cdf0c1d5Smjnelson	#
1489daaffb31Sdp	if [[ -n $wxfile ]]; then
1490daaffb31Sdp		comments_from_wx $fmt $p
1491daaffb31Sdp	fi
1492daaffb31Sdp}
1493daaffb31Sdp
1494daaffb31Sdp#
1495daaffb31Sdp# printCI <total-changed> <inserted> <deleted> <modified> <unchanged>
1496daaffb31Sdp#
1497daaffb31Sdp# Print out Code Inspection figures similar to sccs-prt(1) format.
1498daaffb31Sdp#
1499daaffb31Sdpfunction printCI
1500daaffb31Sdp{
1501daaffb31Sdp	integer tot=$1 ins=$2 del=$3 mod=$4 unc=$5
1502daaffb31Sdp	typeset str
1503daaffb31Sdp	if (( tot == 1 )); then
1504daaffb31Sdp		str="line"
1505daaffb31Sdp	else
1506daaffb31Sdp		str="lines"
1507daaffb31Sdp	fi
1508daaffb31Sdp	printf '%d %s changed: %d ins; %d del; %d mod; %d unchg\n' \
1509daaffb31Sdp	    $tot $str $ins $del $mod $unc
1510daaffb31Sdp}
1511daaffb31Sdp
1512daaffb31Sdp
1513daaffb31Sdp#
1514daaffb31Sdp# difflines <oldfile> <newfile>
1515daaffb31Sdp#
1516daaffb31Sdp# Calculate and emit number of added, removed, modified and unchanged lines,
1517daaffb31Sdp# and total lines changed, the sum of added + removed + modified.
1518daaffb31Sdp#
15197c478bd9Sstevel@tonic-gatefunction difflines
15207c478bd9Sstevel@tonic-gate{
1521daaffb31Sdp	integer tot mod del ins unc err
15227c478bd9Sstevel@tonic-gate	typeset filename
15237c478bd9Sstevel@tonic-gate
1524cdf0c1d5Smjnelson	eval $( diff -e $1 $2 | $AWK '
1525daaffb31Sdp	# Change range of lines: N,Nc
15267c478bd9Sstevel@tonic-gate	/^[0-9]*,[0-9]*c$/ {
15277c478bd9Sstevel@tonic-gate		n=split(substr($1,1,length($1)-1), counts, ",");
15287c478bd9Sstevel@tonic-gate		if (n != 2) {
15297c478bd9Sstevel@tonic-gate		    error=2
15307c478bd9Sstevel@tonic-gate		    exit;
15317c478bd9Sstevel@tonic-gate		}
1532daaffb31Sdp		#
1533daaffb31Sdp		# 3,5c means lines 3 , 4 and 5 are changed, a total of 3 lines.
1534daaffb31Sdp		# following would be 5 - 3 = 2! Hence +1 for correction.
1535daaffb31Sdp		#
15367c478bd9Sstevel@tonic-gate		r=(counts[2]-counts[1])+1;
1537daaffb31Sdp
1538daaffb31Sdp		#
1539daaffb31Sdp		# Now count replacement lines: each represents a change instead
1540daaffb31Sdp		# of a delete, so increment c and decrement r.
1541daaffb31Sdp		#
15427c478bd9Sstevel@tonic-gate		while (getline != /^\.$/) {
15437c478bd9Sstevel@tonic-gate			c++;
15447c478bd9Sstevel@tonic-gate			r--;
15457c478bd9Sstevel@tonic-gate		}
1546daaffb31Sdp		#
1547daaffb31Sdp		# If there were more replacement lines than original lines,
1548daaffb31Sdp		# then r will be negative; in this case there are no deletions,
1549daaffb31Sdp		# but there are r changes that should be counted as adds, and
1550daaffb31Sdp		# since r is negative, subtract it from a and add it to c.
1551daaffb31Sdp		#
15527c478bd9Sstevel@tonic-gate		if (r < 0) {
15537c478bd9Sstevel@tonic-gate			a-=r;
15547c478bd9Sstevel@tonic-gate			c+=r;
15557c478bd9Sstevel@tonic-gate		}
1556daaffb31Sdp
1557daaffb31Sdp		#
1558daaffb31Sdp		# If there were more original lines than replacement lines, then
1559daaffb31Sdp		# r will be positive; in this case, increment d by that much.
1560daaffb31Sdp		#
15617c478bd9Sstevel@tonic-gate		if (r > 0) {
15627c478bd9Sstevel@tonic-gate			d+=r;
15637c478bd9Sstevel@tonic-gate		}
15647c478bd9Sstevel@tonic-gate		next;
15657c478bd9Sstevel@tonic-gate	}
15667c478bd9Sstevel@tonic-gate
1567daaffb31Sdp	# Change lines: Nc
15687c478bd9Sstevel@tonic-gate	/^[0-9].*c$/ {
1569daaffb31Sdp		# The first line is a replacement; any more are additions.
15707c478bd9Sstevel@tonic-gate		if (getline != /^\.$/) {
15717c478bd9Sstevel@tonic-gate			c++;
15727c478bd9Sstevel@tonic-gate			while (getline != /^\.$/) a++;
15737c478bd9Sstevel@tonic-gate		}
15747c478bd9Sstevel@tonic-gate		next;
15757c478bd9Sstevel@tonic-gate	}
15767c478bd9Sstevel@tonic-gate
1577daaffb31Sdp	# Add lines: both Na and N,Na
15787c478bd9Sstevel@tonic-gate	/^[0-9].*a$/ {
15797c478bd9Sstevel@tonic-gate		while (getline != /^\.$/) a++;
15807c478bd9Sstevel@tonic-gate		next;
15817c478bd9Sstevel@tonic-gate	}
15827c478bd9Sstevel@tonic-gate
1583daaffb31Sdp	# Delete range of lines: N,Nd
15847c478bd9Sstevel@tonic-gate	/^[0-9]*,[0-9]*d$/ {
15857c478bd9Sstevel@tonic-gate		n=split(substr($1,1,length($1)-1), counts, ",");
15867c478bd9Sstevel@tonic-gate		if (n != 2) {
15877c478bd9Sstevel@tonic-gate			error=2
15887c478bd9Sstevel@tonic-gate			exit;
15897c478bd9Sstevel@tonic-gate		}
1590daaffb31Sdp		#
1591daaffb31Sdp		# 3,5d means lines 3 , 4 and 5 are deleted, a total of 3 lines.
1592daaffb31Sdp		# following would be 5 - 3 = 2! Hence +1 for correction.
1593daaffb31Sdp		#
15947c478bd9Sstevel@tonic-gate		r=(counts[2]-counts[1])+1;
15957c478bd9Sstevel@tonic-gate		d+=r;
15967c478bd9Sstevel@tonic-gate		next;
15977c478bd9Sstevel@tonic-gate	}
15987c478bd9Sstevel@tonic-gate
1599daaffb31Sdp	# Delete line: Nd.   For example 10d says line 10 is deleted.
16007c478bd9Sstevel@tonic-gate	/^[0-9]*d$/ {d++; next}
16017c478bd9Sstevel@tonic-gate
1602daaffb31Sdp	# Should not get here!
16037c478bd9Sstevel@tonic-gate	{
16047c478bd9Sstevel@tonic-gate		error=1;
16057c478bd9Sstevel@tonic-gate		exit;
16067c478bd9Sstevel@tonic-gate	}
16077c478bd9Sstevel@tonic-gate
1608daaffb31Sdp	# Finish off - print results
16097c478bd9Sstevel@tonic-gate	END {
1610daaffb31Sdp		printf("tot=%d;mod=%d;del=%d;ins=%d;err=%d\n",
16117c478bd9Sstevel@tonic-gate		    (c+d+a), c, d, a, error);
16127c478bd9Sstevel@tonic-gate	}' )
16137c478bd9Sstevel@tonic-gate
1614cdf0c1d5Smjnelson	# End of $AWK, Check to see if any trouble occurred.
16157c478bd9Sstevel@tonic-gate	if (( $? > 0 || err > 0 )); then
1616daaffb31Sdp		print "Unexpected Error occurred reading" \
1617daaffb31Sdp		    "\`diff -e $1 $2\`: \$?=$?, err=" $err
1618daaffb31Sdp		return
1619daaffb31Sdp	fi
1620daaffb31Sdp
16217c478bd9Sstevel@tonic-gate	# Accumulate totals
16227c478bd9Sstevel@tonic-gate	(( TOTL += tot ))
1623daaffb31Sdp	(( TMOD += mod ))
16247c478bd9Sstevel@tonic-gate	(( TDEL += del ))
16257c478bd9Sstevel@tonic-gate	(( TINS += ins ))
16267c478bd9Sstevel@tonic-gate	# Calculate unchanged lines
1627cdf0c1d5Smjnelson	unc=`wc -l < $1`
16287c478bd9Sstevel@tonic-gate	if (( unc > 0 )); then
1629daaffb31Sdp		(( unc -= del + mod ))
16307c478bd9Sstevel@tonic-gate		(( TUNC += unc ))
16317c478bd9Sstevel@tonic-gate	fi
16327c478bd9Sstevel@tonic-gate	# print summary
1633daaffb31Sdp	print "<span class=\"lineschanged\">"
1634daaffb31Sdp	printCI $tot $ins $del $mod $unc
1635daaffb31Sdp	print "</span>"
16367c478bd9Sstevel@tonic-gate}
16377c478bd9Sstevel@tonic-gate
1638daaffb31Sdp
16397c478bd9Sstevel@tonic-gate#
1640daaffb31Sdp# flist_from_wx
1641daaffb31Sdp#
1642daaffb31Sdp# Sets up webrev to source its information from a wx-formatted file.
1643daaffb31Sdp# Sets the global 'wxfile' variable.
1644daaffb31Sdp#
1645daaffb31Sdpfunction flist_from_wx
16467c478bd9Sstevel@tonic-gate{
1647daaffb31Sdp	typeset argfile=$1
1648daaffb31Sdp	if [[ -n ${argfile%%/*} ]]; then
1649daaffb31Sdp		#
1650daaffb31Sdp		# If the wx file pathname is relative then make it absolute
1651daaffb31Sdp		# because the webrev does a "cd" later on.
1652daaffb31Sdp		#
1653daaffb31Sdp		wxfile=$PWD/$argfile
16547c478bd9Sstevel@tonic-gate	else
1655daaffb31Sdp		wxfile=$argfile
16567c478bd9Sstevel@tonic-gate	fi
16577c478bd9Sstevel@tonic-gate
1658cdf0c1d5Smjnelson	$AWK '{ c = 1; print;
16597c478bd9Sstevel@tonic-gate	  while (getline) {
16607c478bd9Sstevel@tonic-gate		if (NF == 0) { c = -c; continue }
16617c478bd9Sstevel@tonic-gate		if (c > 0) print
16627c478bd9Sstevel@tonic-gate	  }
1663daaffb31Sdp	}' $wxfile > $FLIST
16647c478bd9Sstevel@tonic-gate
1665daaffb31Sdp	print " Done."
1666daaffb31Sdp}
16677c478bd9Sstevel@tonic-gate
1668daaffb31Sdp#
1669cdf0c1d5Smjnelson# Call hg-active to get the active list output in the wx active list format
1670cdf0c1d5Smjnelson#
1671cdf0c1d5Smjnelsonfunction hg_active_wxfile
1672cdf0c1d5Smjnelson{
1673cdf0c1d5Smjnelson	typeset child=$1
1674cdf0c1d5Smjnelson	typeset parent=$2
1675cdf0c1d5Smjnelson
1676cdf0c1d5Smjnelson	TMPFLIST=/tmp/$$.active
16779a70fc3bSMark J. Nelson	$HG_ACTIVE -w $child -p $parent -o $TMPFLIST
1678cdf0c1d5Smjnelson	wxfile=$TMPFLIST
1679cdf0c1d5Smjnelson}
1680cdf0c1d5Smjnelson
1681cdf0c1d5Smjnelson#
1682cdf0c1d5Smjnelson# flist_from_mercurial
1683cdf0c1d5Smjnelson# Call hg-active to get a wx-style active list, and hand it off to
1684cdf0c1d5Smjnelson# flist_from_wx
1685cdf0c1d5Smjnelson#
1686cdf0c1d5Smjnelsonfunction flist_from_mercurial
1687cdf0c1d5Smjnelson{
1688cdf0c1d5Smjnelson	typeset child=$1
1689cdf0c1d5Smjnelson	typeset parent=$2
1690cdf0c1d5Smjnelson
1691cdf0c1d5Smjnelson	print " File list from: hg-active -p $parent ...\c"
1692cdf0c1d5Smjnelson	if [[ ! -x $HG_ACTIVE ]]; then
1693cdf0c1d5Smjnelson		print		# Blank line for the \c above
1694cdf0c1d5Smjnelson		print -u2 "Error: hg-active tool not found.  Exiting"
1695cdf0c1d5Smjnelson		exit 1
1696cdf0c1d5Smjnelson	fi
1697cdf0c1d5Smjnelson	hg_active_wxfile $child $parent
1698cdf0c1d5Smjnelson
1699cdf0c1d5Smjnelson	# flist_from_wx prints the Done, so we don't have to.
1700cdf0c1d5Smjnelson	flist_from_wx $TMPFLIST
1701cdf0c1d5Smjnelson}
1702cdf0c1d5Smjnelson
1703cdf0c1d5Smjnelson#
17048bcea973SRichard Lowe# Transform a specified 'git log' output format into a wx-like active list.
17058bcea973SRichard Lowe#
17068bcea973SRichard Lowefunction git_wxfile
17078bcea973SRichard Lowe{
17088bcea973SRichard Lowe	typeset child="$1"
17098bcea973SRichard Lowe	typeset parent="$2"
17108bcea973SRichard Lowe
17118bcea973SRichard Lowe	TMPFLIST=/tmp/$$.active
17128bcea973SRichard Lowe	$PERL -e 'my (%files, %realfiles, $msg);
17138bcea973SRichard Lowe	my $branch = $ARGV[0];
17148bcea973SRichard Lowe
17158bcea973SRichard Lowe	open(F, "git diff -M --name-status $branch |");
17168bcea973SRichard Lowe	while (<F>) {
17178bcea973SRichard Lowe	    chomp;
17188bcea973SRichard Lowe	    if (/^R(\d+)\s+([^ ]+)\s+([^ ]+)/) { # rename
17198bcea973SRichard Lowe		if ($1 >= 75) {			 # Probably worth treating as a rename
17203cb02613SRichard Lowe		    $realfiles{$3} = $2;
17218bcea973SRichard Lowe		} else {
17228bcea973SRichard Lowe		    $realfiles{$3} = $3;
17238bcea973SRichard Lowe		    $realfiles{$2} = $2;
17248bcea973SRichard Lowe	        }
17258bcea973SRichard Lowe	    } else {
17268bcea973SRichard Lowe		my $f = (split /\s+/, $_)[1];
17278bcea973SRichard Lowe		$realfiles{$f} = $f;
17288bcea973SRichard Lowe	    }
17298bcea973SRichard Lowe	}
17308bcea973SRichard Lowe	close(F);
17318bcea973SRichard Lowe
17328bcea973SRichard Lowe	my $state = 1;		    # 0|comments, 1|files
17338bcea973SRichard Lowe	open(F, "git whatchanged --pretty=format:%B $branch.. |");
17348bcea973SRichard Lowe	while (<F>) {
17358bcea973SRichard Lowe	    chomp;
17368bcea973SRichard Lowe	    if (/^:[0-9]{6}/) {
17378bcea973SRichard Lowe		my $fname = (split /\t/, $_)[1];
17388bcea973SRichard Lowe		next if !defined($realfiles{$fname}); # No real change
17398bcea973SRichard Lowe		$state = 1;
17403cb02613SRichard Lowe		chomp $msg;
17413cb02613SRichard Lowe		$files{$fname} .= $msg;
17428bcea973SRichard Lowe	    } else {
17438bcea973SRichard Lowe		if ($state == 1) {
17448bcea973SRichard Lowe		    $state = 0;
17458bcea973SRichard Lowe		    $msg = /^\n/ ? "" : "\n";
17468bcea973SRichard Lowe		}
17478bcea973SRichard Lowe		$msg .= "$_\n" if ($_);
17488bcea973SRichard Lowe	    }
17498bcea973SRichard Lowe	}
17508bcea973SRichard Lowe	close(F);
17518bcea973SRichard Lowe
17528bcea973SRichard Lowe	for (sort keys %files) {
17538bcea973SRichard Lowe	    if ($realfiles{$_} ne $_) {
17543cb02613SRichard Lowe		print "$_ $realfiles{$_}\n$files{$_}\n\n";
17558bcea973SRichard Lowe	    } else {
17563cb02613SRichard Lowe		print "$_\n$files{$_}\n\n"
17578bcea973SRichard Lowe	    }
17588bcea973SRichard Lowe	}' ${parent} > $TMPFLIST
17598bcea973SRichard Lowe
17608bcea973SRichard Lowe	wxfile=$TMPFLIST
17618bcea973SRichard Lowe}
17628bcea973SRichard Lowe
17638bcea973SRichard Lowe#
17648bcea973SRichard Lowe# flist_from_git
17658bcea973SRichard Lowe# Build a wx-style active list, and hand it off to flist_from_wx
17668bcea973SRichard Lowe#
17678bcea973SRichard Lowefunction flist_from_git
17688bcea973SRichard Lowe{
17698bcea973SRichard Lowe	typeset child=$1
17708bcea973SRichard Lowe	typeset parent=$2
17718bcea973SRichard Lowe
17728bcea973SRichard Lowe	print " File list from: git ...\c"
17738bcea973SRichard Lowe	git_wxfile "$child" "$parent";
17748bcea973SRichard Lowe
17758bcea973SRichard Lowe	# flist_from_wx prints the Done, so we don't have to.
17768bcea973SRichard Lowe	flist_from_wx $TMPFLIST
17778bcea973SRichard Lowe}
17788bcea973SRichard Lowe
17798bcea973SRichard Lowe#
1780cdf0c1d5Smjnelson# flist_from_subversion
1781cdf0c1d5Smjnelson#
1782cdf0c1d5Smjnelson# Generate the file list by extracting file names from svn status.
1783cdf0c1d5Smjnelson#
1784cdf0c1d5Smjnelsonfunction flist_from_subversion
1785cdf0c1d5Smjnelson{
1786cdf0c1d5Smjnelson	CWS=$1
1787cdf0c1d5Smjnelson	OLDPWD=$2
1788cdf0c1d5Smjnelson
1789cdf0c1d5Smjnelson	cd $CWS
1790cdf0c1d5Smjnelson	print -u2 " File list from: svn status ... \c"
1791cdf0c1d5Smjnelson	svn status | $AWK '/^[ACDMR]/ { print $NF }' > $FLIST
1792cdf0c1d5Smjnelson	print -u2 " Done."
1793cdf0c1d5Smjnelson	cd $OLDPWD
1794cdf0c1d5Smjnelson}
1795cdf0c1d5Smjnelson
1796daaffb31Sdpfunction env_from_flist
1797daaffb31Sdp{
1798daaffb31Sdp	[[ -r $FLIST ]] || return
1799daaffb31Sdp
1800daaffb31Sdp	#
1801daaffb31Sdp	# Use "eval" to set env variables that are listed in the file
1802daaffb31Sdp	# list.  Then copy those into our local versions of those
1803daaffb31Sdp	# variables if they have not been set already.
1804daaffb31Sdp	#
1805b0088928SVladimir Kotal	eval `$SED -e "s/#.*$//" $FLIST | $GREP = `
18067c478bd9Sstevel@tonic-gate
1807cdf0c1d5Smjnelson	if [[ -z $codemgr_ws && -n $CODEMGR_WS ]]; then
1808cdf0c1d5Smjnelson		codemgr_ws=$CODEMGR_WS
1809cdf0c1d5Smjnelson		export CODEMGR_WS
1810cdf0c1d5Smjnelson	fi
18117c478bd9Sstevel@tonic-gate
1812daaffb31Sdp	#
1813daaffb31Sdp	# Check to see if CODEMGR_PARENT is set in the flist file.
1814daaffb31Sdp	#
1815cdf0c1d5Smjnelson	if [[ -z $codemgr_parent && -n $CODEMGR_PARENT ]]; then
1816daaffb31Sdp		codemgr_parent=$CODEMGR_PARENT
1817cdf0c1d5Smjnelson		export CODEMGR_PARENT
1818daaffb31Sdp	fi
1819daaffb31Sdp}
1820daaffb31Sdp
182114983201Sdpfunction look_for_prog
182214983201Sdp{
182314983201Sdp	typeset path
182414983201Sdp	typeset ppath
182514983201Sdp	typeset progname=$1
182614983201Sdp
182714983201Sdp	ppath=$PATH
182814983201Sdp	ppath=$ppath:/usr/sfw/bin:/usr/bin:/usr/sbin
1829*d7b56f41SBart Coddens	ppath=$ppath:/opt/onbld/bin
1830cdf0c1d5Smjnelson	ppath=$ppath:/opt/onbld/bin/`uname -p`
183114983201Sdp
183214983201Sdp	PATH=$ppath prog=`whence $progname`
183314983201Sdp	if [[ -n $prog ]]; then
183414983201Sdp		print $prog
183514983201Sdp	fi
183614983201Sdp}
183714983201Sdp
1838cdf0c1d5Smjnelsonfunction get_file_mode
1839cdf0c1d5Smjnelson{
1840cdf0c1d5Smjnelson	$PERL -e '
1841cdf0c1d5Smjnelson		if (@stat = stat($ARGV[0])) {
1842cdf0c1d5Smjnelson			$mode = $stat[2] & 0777;
1843cdf0c1d5Smjnelson			printf "%03o\n", $mode;
1844cdf0c1d5Smjnelson			exit 0;
1845cdf0c1d5Smjnelson		} else {
1846cdf0c1d5Smjnelson			exit 1;
1847cdf0c1d5Smjnelson		}
1848cdf0c1d5Smjnelson	    ' $1
1849cdf0c1d5Smjnelson}
1850cdf0c1d5Smjnelson
1851cdf0c1d5Smjnelsonfunction build_old_new_mercurial
1852cdf0c1d5Smjnelson{
1853cdf0c1d5Smjnelson	typeset olddir="$1"
1854cdf0c1d5Smjnelson	typeset newdir="$2"
1855cdf0c1d5Smjnelson	typeset old_mode=
1856cdf0c1d5Smjnelson	typeset new_mode=
1857cdf0c1d5Smjnelson	typeset file
1858cdf0c1d5Smjnelson
1859cdf0c1d5Smjnelson	#
1860cdf0c1d5Smjnelson	# Get old file mode, from the parent revision manifest entry.
1861cdf0c1d5Smjnelson	# Mercurial only stores a "file is executable" flag, but the
1862cdf0c1d5Smjnelson	# manifest will display an octal mode "644" or "755".
1863cdf0c1d5Smjnelson	#
1864cdf0c1d5Smjnelson	if [[ "$PDIR" == "." ]]; then
1865cdf0c1d5Smjnelson		file="$PF"
1866cdf0c1d5Smjnelson	else
1867cdf0c1d5Smjnelson		file="$PDIR/$PF"
1868cdf0c1d5Smjnelson	fi
1869b0088928SVladimir Kotal	file=`echo $file | $SED 's#/#\\\/#g'`
1870cdf0c1d5Smjnelson	# match the exact filename, and return only the permission digits
1871b0088928SVladimir Kotal	old_mode=`$SED -n -e "/^\\(...\\) . ${file}$/s//\\1/p" \
1872cdf0c1d5Smjnelson	    < $HG_PARENT_MANIFEST`
1873cdf0c1d5Smjnelson
1874cdf0c1d5Smjnelson	#
1875cdf0c1d5Smjnelson	# Get new file mode, directly from the filesystem.
1876cdf0c1d5Smjnelson	# Normalize the mode to match Mercurial's behavior.
1877cdf0c1d5Smjnelson	#
1878cdf0c1d5Smjnelson	new_mode=`get_file_mode $CWS/$DIR/$F`
1879cdf0c1d5Smjnelson	if [[ -n "$new_mode" ]]; then
1880cdf0c1d5Smjnelson		if [[ "$new_mode" = *[1357]* ]]; then
1881cdf0c1d5Smjnelson			new_mode=755
1882cdf0c1d5Smjnelson		else
1883cdf0c1d5Smjnelson			new_mode=644
1884cdf0c1d5Smjnelson		fi
1885cdf0c1d5Smjnelson	fi
1886cdf0c1d5Smjnelson
1887cdf0c1d5Smjnelson	#
1888cdf0c1d5Smjnelson	# new version of the file.
1889cdf0c1d5Smjnelson	#
1890cdf0c1d5Smjnelson	rm -rf $newdir/$DIR/$F
1891cdf0c1d5Smjnelson	if [[ -e $CWS/$DIR/$F ]]; then
1892cdf0c1d5Smjnelson		cp $CWS/$DIR/$F $newdir/$DIR/$F
1893cdf0c1d5Smjnelson		if [[ -n $new_mode ]]; then
1894cdf0c1d5Smjnelson			chmod $new_mode $newdir/$DIR/$F
1895cdf0c1d5Smjnelson		else
1896cdf0c1d5Smjnelson			# should never happen
1897cdf0c1d5Smjnelson			print -u2 "ERROR: set mode of $newdir/$DIR/$F"
1898cdf0c1d5Smjnelson		fi
1899cdf0c1d5Smjnelson	fi
1900cdf0c1d5Smjnelson
1901cdf0c1d5Smjnelson	#
1902cdf0c1d5Smjnelson	# parent's version of the file
1903cdf0c1d5Smjnelson	#
1904cdf0c1d5Smjnelson	# Note that we get this from the last version common to both
1905cdf0c1d5Smjnelson	# ourselves and the parent.  References are via $CWS since we have no
1906cdf0c1d5Smjnelson	# guarantee that the parent workspace is reachable via the filesystem.
1907cdf0c1d5Smjnelson	#
1908cdf0c1d5Smjnelson	if [[ -n $parent_webrev && -e $PWS/$PDIR/$PF ]]; then
1909cdf0c1d5Smjnelson		cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF
1910cdf0c1d5Smjnelson	elif [[ -n $HG_PARENT ]]; then
1911cdf0c1d5Smjnelson		hg cat -R $CWS -r $HG_PARENT $CWS/$PDIR/$PF > \
1912cdf0c1d5Smjnelson		    $olddir/$PDIR/$PF 2>/dev/null
1913cdf0c1d5Smjnelson
191402d26c39SVladimir Kotal		if (( $? != 0 )); then
1915cdf0c1d5Smjnelson			rm -f $olddir/$PDIR/$PF
1916cdf0c1d5Smjnelson		else
1917cdf0c1d5Smjnelson			if [[ -n $old_mode ]]; then
1918cdf0c1d5Smjnelson				chmod $old_mode $olddir/$PDIR/$PF
1919cdf0c1d5Smjnelson			else
1920cdf0c1d5Smjnelson				# should never happen
1921cdf0c1d5Smjnelson				print -u2 "ERROR: set mode of $olddir/$PDIR/$PF"
1922cdf0c1d5Smjnelson			fi
1923cdf0c1d5Smjnelson		fi
1924cdf0c1d5Smjnelson	fi
1925cdf0c1d5Smjnelson}
1926cdf0c1d5Smjnelson
19278bcea973SRichard Lowefunction build_old_new_git
19288bcea973SRichard Lowe{
19298bcea973SRichard Lowe	typeset olddir="$1"
19308bcea973SRichard Lowe	typeset newdir="$2"
19318bcea973SRichard Lowe	typeset o_mode=
19328bcea973SRichard Lowe	typeset n_mode=
19338bcea973SRichard Lowe	typeset o_object=
19348bcea973SRichard Lowe	typeset n_object=
19358bcea973SRichard Lowe	typeset OWD=$PWD
19368bcea973SRichard Lowe	typeset file
19378bcea973SRichard Lowe	typeset type
19388bcea973SRichard Lowe
19398bcea973SRichard Lowe	cd $CWS
19408bcea973SRichard Lowe
19418bcea973SRichard Lowe	#
19428bcea973SRichard Lowe	# Get old file and its mode from the git object tree
19438bcea973SRichard Lowe	#
19448bcea973SRichard Lowe	if [[ "$PDIR" == "." ]]; then
19458bcea973SRichard Lowe		file="$PF"
19468bcea973SRichard Lowe	else
19478bcea973SRichard Lowe	       file="$PDIR/$PF"
19488bcea973SRichard Lowe	fi
19498bcea973SRichard Lowe
19508bcea973SRichard Lowe	if [[ -n $parent_webrev && -e $PWS/$PDIR/$PF ]]; then
19518bcea973SRichard Lowe		cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF
19528bcea973SRichard Lowe	else
19538bcea973SRichard Lowe                $GIT ls-tree $GIT_PARENT $file | read o_mode type o_object junk
19548bcea973SRichard Lowe                $GIT cat-file $type $o_object > $olddir/$file 2>/dev/null
19558bcea973SRichard Lowe
19568bcea973SRichard Lowe                if (( $? != 0 )); then
19578bcea973SRichard Lowe                        rm -f $olddir/$file
19588bcea973SRichard Lowe                elif [[ -n $o_mode ]]; then
19598bcea973SRichard Lowe                        # Strip the first 3 digits, to get a regular octal mode
19608bcea973SRichard Lowe                        o_mode=${o_mode/???/}
19618bcea973SRichard Lowe                        chmod $o_mode $olddir/$file
19628bcea973SRichard Lowe                else
19638bcea973SRichard Lowe                        # should never happen
19648bcea973SRichard Lowe                        print -u2 "ERROR: set mode of $olddir/$file"
19658bcea973SRichard Lowe                fi
19668bcea973SRichard Lowe	fi
19678bcea973SRichard Lowe
19688bcea973SRichard Lowe	#
19698bcea973SRichard Lowe	# new version of the file.
19708bcea973SRichard Lowe	#
19718bcea973SRichard Lowe	if [[ "$DIR" == "." ]]; then
19728bcea973SRichard Lowe		file="$F"
19738bcea973SRichard Lowe	else
19748bcea973SRichard Lowe		file="$DIR/$F"
19758bcea973SRichard Lowe	fi
19768bcea973SRichard Lowe	rm -rf $newdir/$file
19778bcea973SRichard Lowe
19788bcea973SRichard Lowe        if [[ -e $CWS/$DIR/$F ]]; then
19798bcea973SRichard Lowe            cp $CWS/$DIR/$F $newdir/$DIR/$F
19808bcea973SRichard Lowe            chmod $(get_file_mode $CWS/$DIR/$F) $newdir/$DIR/$F
19818bcea973SRichard Lowe        fi
19828bcea973SRichard Lowe	cd $OWD
19838bcea973SRichard Lowe}
19848bcea973SRichard Lowe
1985cdf0c1d5Smjnelsonfunction build_old_new_subversion
1986cdf0c1d5Smjnelson{
1987cdf0c1d5Smjnelson	typeset olddir="$1"
1988cdf0c1d5Smjnelson	typeset newdir="$2"
1989cdf0c1d5Smjnelson
1990cdf0c1d5Smjnelson	# Snag new version of file.
1991cdf0c1d5Smjnelson	rm -f $newdir/$DIR/$F
1992cdf0c1d5Smjnelson	[[ -e $CWS/$DIR/$F ]] && cp $CWS/$DIR/$F $newdir/$DIR/$F
1993cdf0c1d5Smjnelson
1994cdf0c1d5Smjnelson	if [[ -n $PWS && -e $PWS/$PDIR/$PF ]]; then
1995cdf0c1d5Smjnelson		cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF
1996cdf0c1d5Smjnelson	else
1997cdf0c1d5Smjnelson		# Get the parent's version of the file.
1998cdf0c1d5Smjnelson		svn status $CWS/$DIR/$F | read stat file
1999cdf0c1d5Smjnelson		if [[ $stat != "A" ]]; then
2000cdf0c1d5Smjnelson			svn cat -r BASE $CWS/$DIR/$F > $olddir/$PDIR/$PF
2001cdf0c1d5Smjnelson		fi
2002cdf0c1d5Smjnelson	fi
2003cdf0c1d5Smjnelson}
2004cdf0c1d5Smjnelson
2005cdf0c1d5Smjnelsonfunction build_old_new_unknown
2006cdf0c1d5Smjnelson{
2007cdf0c1d5Smjnelson	typeset olddir="$1"
2008cdf0c1d5Smjnelson	typeset newdir="$2"
2009cdf0c1d5Smjnelson
2010cdf0c1d5Smjnelson	#
2011cdf0c1d5Smjnelson	# Snag new version of file.
2012cdf0c1d5Smjnelson	#
2013cdf0c1d5Smjnelson	rm -f $newdir/$DIR/$F
2014cdf0c1d5Smjnelson	[[ -e $CWS/$DIR/$F ]] && cp $CWS/$DIR/$F $newdir/$DIR/$F
2015cdf0c1d5Smjnelson
2016cdf0c1d5Smjnelson	#
2017cdf0c1d5Smjnelson	# Snag the parent's version of the file.
2018cdf0c1d5Smjnelson	#
2019cdf0c1d5Smjnelson	if [[ -f $PWS/$PDIR/$PF ]]; then
2020cdf0c1d5Smjnelson		rm -f $olddir/$PDIR/$PF
2021cdf0c1d5Smjnelson		cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF
2022cdf0c1d5Smjnelson	fi
2023cdf0c1d5Smjnelson}
2024cdf0c1d5Smjnelson
2025cdf0c1d5Smjnelsonfunction build_old_new
2026cdf0c1d5Smjnelson{
2027cdf0c1d5Smjnelson	typeset WDIR=$1
2028cdf0c1d5Smjnelson	typeset PWS=$2
2029cdf0c1d5Smjnelson	typeset PDIR=$3
2030cdf0c1d5Smjnelson	typeset PF=$4
2031cdf0c1d5Smjnelson	typeset CWS=$5
2032cdf0c1d5Smjnelson	typeset DIR=$6
2033cdf0c1d5Smjnelson	typeset F=$7
2034cdf0c1d5Smjnelson
2035cdf0c1d5Smjnelson	typeset olddir="$WDIR/raw_files/old"
2036cdf0c1d5Smjnelson	typeset newdir="$WDIR/raw_files/new"
2037cdf0c1d5Smjnelson
2038cdf0c1d5Smjnelson	mkdir -p $olddir/$PDIR
2039cdf0c1d5Smjnelson	mkdir -p $newdir/$DIR
2040cdf0c1d5Smjnelson
2041*d7b56f41SBart Coddens	if [[ $SCM_MODE == "mercurial" ]]; then
2042cdf0c1d5Smjnelson		build_old_new_mercurial "$olddir" "$newdir"
20438bcea973SRichard Lowe	elif [[ $SCM_MODE == "git" ]]; then
20448bcea973SRichard Lowe		build_old_new_git "$olddir" "$newdir"
2045cdf0c1d5Smjnelson	elif [[ $SCM_MODE == "subversion" ]]; then
2046cdf0c1d5Smjnelson		build_old_new_subversion "$olddir" "$newdir"
2047cdf0c1d5Smjnelson	elif [[ $SCM_MODE == "unknown" ]]; then
2048cdf0c1d5Smjnelson		build_old_new_unknown "$olddir" "$newdir"
2049cdf0c1d5Smjnelson	fi
2050cdf0c1d5Smjnelson
2051cdf0c1d5Smjnelson	if [[ ! -f $olddir/$PDIR/$PF && ! -f $newdir/$DIR/$F ]]; then
2052cdf0c1d5Smjnelson		print "*** Error: file not in parent or child"
2053cdf0c1d5Smjnelson		return 1
2054cdf0c1d5Smjnelson	fi
2055cdf0c1d5Smjnelson	return 0
2056cdf0c1d5Smjnelson}
2057cdf0c1d5Smjnelson
2058cdf0c1d5Smjnelson
2059daaffb31Sdp#
2060daaffb31Sdp# Usage message.
2061daaffb31Sdp#
2062daaffb31Sdpfunction usage
2063daaffb31Sdp{
2064daaffb31Sdp	print 'Usage:\twebrev [common-options]
2065daaffb31Sdp	webrev [common-options] ( <file> | - )
2066daaffb31Sdp	webrev [common-options] -w <wx file>
2067daaffb31Sdp
2068daaffb31SdpOptions:
20690fd2682eSMark J. Nelson	-C <filename>: Use <filename> for the information tracking configuration.
2070ba44d8a2SVladimir Kotal	-D: delete remote webrev
2071daaffb31Sdp	-i <filename>: Include <filename> in the index.html file.
20720fd2682eSMark J. Nelson	-I <filename>: Use <filename> for the information tracking registry.
2073ba44d8a2SVladimir Kotal	-n: do not generate the webrev (useful with -U)
2074ba44d8a2SVladimir Kotal	-O: Print bugids/arc cases suitable for OpenSolaris.
2075daaffb31Sdp	-o <outdir>: Output webrev to specified directory.
2076daaffb31Sdp	-p <compare-against>: Use specified parent wkspc or basis for comparison
207702d26c39SVladimir Kotal	-t <remote_target>: Specify remote destination for webrev upload
207802d26c39SVladimir Kotal	-U: upload the webrev to remote destination
2079daaffb31Sdp	-w <wxfile>: Use specified wx active file.
2080daaffb31Sdp
2081daaffb31SdpEnvironment:
2082daaffb31Sdp	WDIR: Control the output directory.
2083ba44d8a2SVladimir Kotal	WEBREV_TRASH_DIR: Set directory for webrev delete.
2084daaffb31Sdp
2085daaffb31SdpSCM Environment:
2086cdf0c1d5Smjnelson	CODEMGR_WS: Workspace location.
2087cdf0c1d5Smjnelson	CODEMGR_PARENT: Parent workspace location.
2088daaffb31Sdp'
2089daaffb31Sdp
2090daaffb31Sdp	exit 2
2091daaffb31Sdp}
2092daaffb31Sdp
2093daaffb31Sdp#
2094daaffb31Sdp#
2095daaffb31Sdp# Main program starts here
2096daaffb31Sdp#
2097daaffb31Sdp#
2098daaffb31Sdp
2099daaffb31Sdptrap "rm -f /tmp/$$.* ; exit" 0 1 2 3 15
2100daaffb31Sdp
2101daaffb31Sdpset +o noclobber
2102daaffb31Sdp
21038bcea973SRichard LowePATH=$(/bin/dirname "$(whence $0)"):$PATH
2104cdf0c1d5Smjnelson
210514983201Sdp[[ -z $WDIFF ]] && WDIFF=`look_for_prog wdiff`
210614983201Sdp[[ -z $WX ]] && WX=`look_for_prog wx`
2107cdf0c1d5Smjnelson[[ -z $HG_ACTIVE ]] && HG_ACTIVE=`look_for_prog hg-active`
21088bcea973SRichard Lowe[[ -z $GIT ]] && GIT=`look_for_prog git`
2109cdf0c1d5Smjnelson[[ -z $WHICH_SCM ]] && WHICH_SCM=`look_for_prog which_scm`
211014983201Sdp[[ -z $CODEREVIEW ]] && CODEREVIEW=`look_for_prog codereview`
211114983201Sdp[[ -z $PS2PDF ]] && PS2PDF=`look_for_prog ps2pdf`
211214983201Sdp[[ -z $PERL ]] && PERL=`look_for_prog perl`
211302d26c39SVladimir Kotal[[ -z $RSYNC ]] && RSYNC=`look_for_prog rsync`
2114cdf0c1d5Smjnelson[[ -z $SCCS ]] && SCCS=`look_for_prog sccs`
2115cdf0c1d5Smjnelson[[ -z $AWK ]] && AWK=`look_for_prog nawk`
2116cdf0c1d5Smjnelson[[ -z $AWK ]] && AWK=`look_for_prog gawk`
2117cdf0c1d5Smjnelson[[ -z $AWK ]] && AWK=`look_for_prog awk`
211802d26c39SVladimir Kotal[[ -z $SCP ]] && SCP=`look_for_prog scp`
2119b0088928SVladimir Kotal[[ -z $SED ]] && SED=`look_for_prog sed`
212002d26c39SVladimir Kotal[[ -z $SFTP ]] && SFTP=`look_for_prog sftp`
2121e6ccc173SEdward Pilatowicz[[ -z $SORT ]] && SORT=`look_for_prog sort`
212202d26c39SVladimir Kotal[[ -z $MKTEMP ]] && MKTEMP=`look_for_prog mktemp`
212302d26c39SVladimir Kotal[[ -z $GREP ]] && GREP=`look_for_prog grep`
2124ba44d8a2SVladimir Kotal[[ -z $FIND ]] && FIND=`look_for_prog find`
2125cdf0c1d5Smjnelson
2126ba44d8a2SVladimir Kotal# set name of trash directory for remote webrev deletion
2127ba44d8a2SVladimir KotalTRASH_DIR=".trash"
2128ba44d8a2SVladimir Kotal[[ -n $WEBREV_TRASH_DIR ]] && TRASH_DIR=$WEBREV_TRASH_DIR
212914983201Sdp
213014983201Sdpif [[ ! -x $PERL ]]; then
213114983201Sdp	print -u2 "Error: No perl interpreter found.  Exiting."
213214983201Sdp	exit 1
2133daaffb31Sdpfi
213414983201Sdp
2135cdf0c1d5Smjnelsonif [[ ! -x $WHICH_SCM ]]; then
2136cdf0c1d5Smjnelson	print -u2 "Error: Could not find which_scm.  Exiting."
2137cdf0c1d5Smjnelson	exit 1
2138cdf0c1d5Smjnelsonfi
2139cdf0c1d5Smjnelson
214014983201Sdp#
214114983201Sdp# These aren't fatal, but we want to note them to the user.
214214983201Sdp# We don't warn on the absence of 'wx' until later when we've
214314983201Sdp# determined that we actually need to try to invoke it.
214414983201Sdp#
214514983201Sdp[[ ! -x $CODEREVIEW ]] && print -u2 "WARNING: codereview(1) not found."
214614983201Sdp[[ ! -x $PS2PDF ]] && print -u2 "WARNING: ps2pdf(1) not found."
214714983201Sdp[[ ! -x $WDIFF ]] && print -u2 "WARNING: wdiff not found."
2148daaffb31Sdp
2149daaffb31Sdp# Declare global total counters.
2150daaffb31Sdpinteger TOTL TINS TDEL TMOD TUNC
2151daaffb31Sdp
2152ba44d8a2SVladimir Kotal# default remote host for upload/delete
2153ba44d8a2SVladimir Kotaltypeset -r DEFAULT_REMOTE_HOST="cr.opensolaris.org"
2154b0088928SVladimir Kotal# prefixes for upload targets
2155b0088928SVladimir Kotaltypeset -r rsync_prefix="rsync://"
2156b0088928SVladimir Kotaltypeset -r ssh_prefix="ssh://"
2157ba44d8a2SVladimir Kotal
21580fd2682eSMark J. NelsonCflag=
2159ba44d8a2SVladimir KotalDflag=
216014983201Sdpflist_mode=
216114983201Sdpflist_file=
2162daaffb31Sdpiflag=
21630fd2682eSMark J. NelsonIflag=
216402d26c39SVladimir Kotallflag=
216502d26c39SVladimir KotalNflag=
216602d26c39SVladimir Kotalnflag=
216702d26c39SVladimir KotalOflag=
2168daaffb31Sdpoflag=
2169daaffb31Sdppflag=
217002d26c39SVladimir Kotaltflag=
217102d26c39SVladimir Kotaluflag=
217202d26c39SVladimir KotalUflag=
2173daaffb31Sdpwflag=
217402d26c39SVladimir Kotalremote_target=
2175ba44d8a2SVladimir Kotal
2176ba44d8a2SVladimir Kotal#
2177ba44d8a2SVladimir Kotal# NOTE: when adding/removing options it is necessary to sync the list
2178ba44d8a2SVladimir Kotal#	with usr/src/tools/onbld/hgext/cdm.py
2179ba44d8a2SVladimir Kotal#
218025cc4e45SVladimir Kotalwhile getopts "C:Di:I:lnNo:Op:t:Uw" opt
2181daaffb31Sdpdo
2182daaffb31Sdp	case $opt in
21830fd2682eSMark J. Nelson	C)	Cflag=1
21840fd2682eSMark J. Nelson		ITSCONF=$OPTARG;;
21850fd2682eSMark J. Nelson
2186ba44d8a2SVladimir Kotal	D)	Dflag=1;;
2187ba44d8a2SVladimir Kotal
2188daaffb31Sdp	i)	iflag=1
2189daaffb31Sdp		INCLUDE_FILE=$OPTARG;;
2190daaffb31Sdp
21910fd2682eSMark J. Nelson	I)	Iflag=1
21920fd2682eSMark J. Nelson		ITSREG=$OPTARG;;
21930fd2682eSMark J. Nelson
219402d26c39SVladimir Kotal	N)	Nflag=1;;
219502d26c39SVladimir Kotal
219602d26c39SVladimir Kotal	n)	nflag=1;;
2197daaffb31Sdp
2198daaffb31Sdp	O)	Oflag=1;;
2199daaffb31Sdp
220002d26c39SVladimir Kotal	o)	oflag=1
22019d3952abSVladimir Kotal		# Strip the trailing slash to correctly form remote target.
22029d3952abSVladimir Kotal		WDIR=${OPTARG%/};;
220302d26c39SVladimir Kotal
220402d26c39SVladimir Kotal	p)	pflag=1
220502d26c39SVladimir Kotal		codemgr_parent=$OPTARG;;
220602d26c39SVladimir Kotal
220702d26c39SVladimir Kotal	t)	tflag=1
220802d26c39SVladimir Kotal		remote_target=$OPTARG;;
220902d26c39SVladimir Kotal
221002d26c39SVladimir Kotal	U)	Uflag=1;;
221102d26c39SVladimir Kotal
221202d26c39SVladimir Kotal	w)	wflag=1;;
22133df69ef3SDarren Moffat
2214daaffb31Sdp	?)	usage;;
2215daaffb31Sdp	esac
2216daaffb31Sdpdone
2217daaffb31Sdp
2218daaffb31SdpFLIST=/tmp/$$.flist
2219daaffb31Sdp
2220daaffb31Sdpif [[ -n $wflag && -n $lflag ]]; then
2221daaffb31Sdp	usage
2222daaffb31Sdpfi
2223daaffb31Sdp
222402d26c39SVladimir Kotal# more sanity checking
222502d26c39SVladimir Kotalif [[ -n $nflag && -z $Uflag ]]; then
2226ba44d8a2SVladimir Kotal	print "it does not make sense to skip webrev generation" \
2227ba44d8a2SVladimir Kotal	    "without -U"
222802d26c39SVladimir Kotal	exit 1
222902d26c39SVladimir Kotalfi
223002d26c39SVladimir Kotal
2231ba44d8a2SVladimir Kotalif [[ -n $tflag && -z $Uflag && -z $Dflag ]]; then
2232ba44d8a2SVladimir Kotal	echo "remote target has to be used only for upload or delete"
223302d26c39SVladimir Kotal	exit 1
223402d26c39SVladimir Kotalfi
223502d26c39SVladimir Kotal
2236daaffb31Sdp#
22372d9224a3SMark J. Nelson# For the invocation "webrev -n -U" with no other options, webrev will assume
22382d9224a3SMark J. Nelson# that the webrev exists in ${CWS}/webrev, but will upload it using the name
22392d9224a3SMark J. Nelson# $(basename ${CWS}).  So we need to get CWS set before we skip any remaining
22402d9224a3SMark J. Nelson# logic.
22412d9224a3SMark J. Nelson#
22422d9224a3SMark J. Nelson$WHICH_SCM | read SCM_MODE junk || exit 1
2243*d7b56f41SBart Coddensif [[ $SCM_MODE == "mercurial" ]]; then
22442d9224a3SMark J. Nelson	#
22452d9224a3SMark J. Nelson	# Mercurial priorities:
22462d9224a3SMark J. Nelson	# 1. hg root from CODEMGR_WS environment variable
224778add226Sjmcp	# 1a. hg root from CODEMGR_WS/usr/closed if we're somewhere under
224878add226Sjmcp	#    usr/closed when we run webrev
22492d9224a3SMark J. Nelson	# 2. hg root from directory of invocation
22502d9224a3SMark J. Nelson	#
225178add226Sjmcp	if [[ ${PWD} =~ "usr/closed" ]]; then
225278add226Sjmcp		testparent=${CODEMGR_WS}/usr/closed
225378add226Sjmcp		# If we're in OpenSolaris mode, we enforce a minor policy:
225478add226Sjmcp		# help to make sure the reviewer doesn't accidentally publish
225578add226Sjmcp		# source which is under usr/closed
225678add226Sjmcp		if [[ -n "$Oflag" ]]; then
225778add226Sjmcp			print -u2 "OpenSolaris output not permitted with" \
225878add226Sjmcp			    "usr/closed changes"
225978add226Sjmcp			exit 1
226078add226Sjmcp		fi
226178add226Sjmcp	else
226278add226Sjmcp	        testparent=${CODEMGR_WS}
226378add226Sjmcp	fi
226478add226Sjmcp	[[ -z $codemgr_ws && -n $testparent ]] && \
226578add226Sjmcp	    codemgr_ws=$(hg root -R $testparent 2>/dev/null)
22662d9224a3SMark J. Nelson	[[ -z $codemgr_ws ]] && codemgr_ws=$(hg root 2>/dev/null)
22672d9224a3SMark J. Nelson	CWS=$codemgr_ws
22688bcea973SRichard Loweelif [[ $SCM_MODE == "git" ]]; then
22698bcea973SRichard Lowe	#
22708bcea973SRichard Lowe	# Git priorities:
22718bcea973SRichard Lowe	# 1. git rev-parse --git-dir from CODEMGR_WS environment variable
22728bcea973SRichard Lowe	# 2. git rev-parse --git-dir from directory of invocation
22738bcea973SRichard Lowe	#
22748bcea973SRichard Lowe	[[ -z $codemgr_ws && -n $CODEMGR_WS ]] && \
22758bcea973SRichard Lowe	    codemgr_ws=$($GIT --git-dir=$CODEMGR_WS/.git rev-parse --git-dir \
22768bcea973SRichard Lowe                2>/dev/null)
22778bcea973SRichard Lowe	[[ -z $codemgr_ws ]] && \
22788bcea973SRichard Lowe	    codemgr_ws=$($GIT rev-parse --git-dir 2>/dev/null)
22798bcea973SRichard Lowe
22808bcea973SRichard Lowe	if [[ "$codemgr_ws" == ".git" ]]; then
22818bcea973SRichard Lowe		codemgr_ws="${PWD}/${codemgr_ws}"
22828bcea973SRichard Lowe	fi
22838bcea973SRichard Lowe
22848bcea973SRichard Lowe	codemgr_ws=$(dirname $codemgr_ws) # Lose the '/.git'
22858bcea973SRichard Lowe	CWS="$codemgr_ws"
22862d9224a3SMark J. Nelsonelif [[ $SCM_MODE == "subversion" ]]; then
22872d9224a3SMark J. Nelson	#
22882d9224a3SMark J. Nelson	# Subversion priorities:
22892d9224a3SMark J. Nelson	# 1. CODEMGR_WS from environment
22902d9224a3SMark J. Nelson	# 2. Relative path from current directory to SVN repository root
22912d9224a3SMark J. Nelson	#
22922d9224a3SMark J. Nelson	if [[ -n $CODEMGR_WS && -d $CODEMGR_WS/.svn ]]; then
22932d9224a3SMark J. Nelson		CWS=$CODEMGR_WS
22942d9224a3SMark J. Nelson	else
22952d9224a3SMark J. Nelson		svn info | while read line; do
22962d9224a3SMark J. Nelson			if [[ $line == "URL: "* ]]; then
22972d9224a3SMark J. Nelson				url=${line#URL: }
22982d9224a3SMark J. Nelson			elif [[ $line == "Repository Root: "* ]]; then
22992d9224a3SMark J. Nelson				repo=${line#Repository Root: }
23002d9224a3SMark J. Nelson			fi
23012d9224a3SMark J. Nelson		done
23022d9224a3SMark J. Nelson
23032d9224a3SMark J. Nelson		rel=${url#$repo}
23042d9224a3SMark J. Nelson		CWS=${PWD%$rel}
23052d9224a3SMark J. Nelson	fi
23062d9224a3SMark J. Nelsonfi
23072d9224a3SMark J. Nelson
23082d9224a3SMark J. Nelson#
23092d9224a3SMark J. Nelson# If no SCM has been determined, take either the environment setting
23102d9224a3SMark J. Nelson# setting for CODEMGR_WS, or the current directory if that wasn't set.
23112d9224a3SMark J. Nelson#
23122d9224a3SMark J. Nelsonif [[ -z ${CWS} ]]; then
23132d9224a3SMark J. Nelson	CWS=${CODEMGR_WS:-.}
23142d9224a3SMark J. Nelsonfi
23152d9224a3SMark J. Nelson
23162d9224a3SMark J. Nelson#
23170fd2682eSMark J. Nelson# If the command line options indicate no webrev generation, either
23180fd2682eSMark J. Nelson# explicitly (-n) or implicitly (-D but not -U), then there's a whole
23190fd2682eSMark J. Nelson# ton of logic we can skip.
23200fd2682eSMark J. Nelson#
23210fd2682eSMark J. Nelson# Instead of increasing indentation, we intentionally leave this loop
23220fd2682eSMark J. Nelson# body open here, and exit via break from multiple points within.
23230fd2682eSMark J. Nelson# Search for DO_EVERYTHING below to find the break points and closure.
23240fd2682eSMark J. Nelson#
23250fd2682eSMark J. Nelsonfor do_everything in 1; do
23260fd2682eSMark J. Nelson
23270fd2682eSMark J. Nelson# DO_EVERYTHING: break point
23280fd2682eSMark J. Nelsonif [[ -n $nflag || ( -z $Uflag && -n $Dflag ) ]]; then
23290fd2682eSMark J. Nelson	break
23300fd2682eSMark J. Nelsonfi
23310fd2682eSMark J. Nelson
23320fd2682eSMark J. Nelson#
2333daaffb31Sdp# If this manually set as the parent, and it appears to be an earlier webrev,
2334daaffb31Sdp# then note that fact and set the parent to the raw_files/new subdirectory.
2335daaffb31Sdp#
2336daaffb31Sdpif [[ -n $pflag && -d $codemgr_parent/raw_files/new ]]; then
23378bcea973SRichard Lowe	parent_webrev=$(readlink -f "$codemgr_parent")
23388bcea973SRichard Lowe	codemgr_parent=$(readlink -f "$codemgr_parent/raw_files/new")
2339daaffb31Sdpfi
2340daaffb31Sdp
2341daaffb31Sdpif [[ -z $wflag && -z $lflag ]]; then
2342daaffb31Sdp	shift $(($OPTIND - 1))
2343daaffb31Sdp
2344daaffb31Sdp	if [[ $1 == "-" ]]; then
2345daaffb31Sdp		cat > $FLIST
234614983201Sdp		flist_mode="stdin"
234714983201Sdp		flist_done=1
234814983201Sdp		shift
2349daaffb31Sdp	elif [[ -n $1 ]]; then
235014983201Sdp		if [[ ! -r $1 ]]; then
2351daaffb31Sdp			print -u2 "$1: no such file or not readable"
2352daaffb31Sdp			usage
2353daaffb31Sdp		fi
2354daaffb31Sdp		cat $1 > $FLIST
235514983201Sdp		flist_mode="file"
235614983201Sdp		flist_file=$1
235714983201Sdp		flist_done=1
235814983201Sdp		shift
2359daaffb31Sdp	else
236014983201Sdp		flist_mode="auto"
2361daaffb31Sdp	fi
2362daaffb31Sdpfi
2363daaffb31Sdp
2364daaffb31Sdp#
2365daaffb31Sdp# Before we go on to further consider -l and -w, work out which SCM we think
2366daaffb31Sdp# is in use.
2367daaffb31Sdp#
2368cdf0c1d5Smjnelsoncase "$SCM_MODE" in
2369*d7b56f41SBart Coddensmercurial|git|subversion)
2370cdf0c1d5Smjnelson	;;
2371cdf0c1d5Smjnelsonunknown)
2372cdf0c1d5Smjnelson	if [[ $flist_mode == "auto" ]]; then
2373cdf0c1d5Smjnelson		print -u2 "Unable to determine SCM in use and file list not specified"
2374cdf0c1d5Smjnelson		print -u2 "See which_scm(1) for SCM detection information."
23757c478bd9Sstevel@tonic-gate		exit 1
23767c478bd9Sstevel@tonic-gate	fi
2377cdf0c1d5Smjnelson	;;
2378cdf0c1d5Smjnelson*)
2379cdf0c1d5Smjnelson	if [[ $flist_mode == "auto" ]]; then
2380cdf0c1d5Smjnelson		print -u2 "Unsupported SCM in use ($SCM_MODE) and file list not specified"
2381cdf0c1d5Smjnelson		exit 1
2382cdf0c1d5Smjnelson	fi
2383cdf0c1d5Smjnelson	;;
2384cdf0c1d5Smjnelsonesac
23857c478bd9Sstevel@tonic-gate
2386daaffb31Sdpprint -u2 "   SCM detected: $SCM_MODE"
2387daaffb31Sdp
2388*d7b56f41SBart Coddensif [[ -n $wflag ]]; then
2389daaffb31Sdp	#
2390daaffb31Sdp	# If the -w is given then assume the file list is in Bonwick's "wx"
2391daaffb31Sdp	# command format, i.e.  pathname lines alternating with SCCS comment
2392daaffb31Sdp	# lines with blank lines as separators.  Use the SCCS comments later
2393daaffb31Sdp	# in building the index.html file.
2394daaffb31Sdp	#
2395daaffb31Sdp	shift $(($OPTIND - 1))
2396daaffb31Sdp	wxfile=$1
2397daaffb31Sdp	if [[ -z $wxfile && -n $CODEMGR_WS ]]; then
2398daaffb31Sdp		if [[ -r $CODEMGR_WS/wx/active ]]; then
2399daaffb31Sdp			wxfile=$CODEMGR_WS/wx/active
2400daaffb31Sdp		fi
2401daaffb31Sdp	fi
2402daaffb31Sdp
2403daaffb31Sdp	[[ -z $wxfile ]] && print -u2 "wx file not specified, and could not " \
2404daaffb31Sdp	    "be auto-detected (check \$CODEMGR_WS)" && exit 1
2405daaffb31Sdp
2406cdf0c1d5Smjnelson	if [[ ! -r $wxfile ]]; then
2407cdf0c1d5Smjnelson		print -u2 "$wxfile: no such file or not readable"
2408cdf0c1d5Smjnelson		usage
2409cdf0c1d5Smjnelson	fi
2410cdf0c1d5Smjnelson
2411daaffb31Sdp	print -u2 " File list from: wx 'active' file '$wxfile' ... \c"
2412daaffb31Sdp	flist_from_wx $wxfile
2413daaffb31Sdp	flist_done=1
2414daaffb31Sdp	if [[ -n "$*" ]]; then
2415daaffb31Sdp		shift
2416daaffb31Sdp	fi
241714983201Sdpelif [[ $flist_mode == "stdin" ]]; then
241814983201Sdp	print -u2 " File list from: standard input"
241914983201Sdpelif [[ $flist_mode == "file" ]]; then
242014983201Sdp	print -u2 " File list from: $flist_file"
2421daaffb31Sdpfi
2422daaffb31Sdp
2423daaffb31Sdpif [[ $# -gt 0 ]]; then
242414983201Sdp	print -u2 "WARNING: unused arguments: $*"
2425daaffb31Sdpfi
2426daaffb31Sdp
24272d9224a3SMark J. Nelson#
24282d9224a3SMark J. Nelson# Before we entered the DO_EVERYTHING loop, we should have already set CWS
24292d9224a3SMark J. Nelson# and CODEMGR_WS as needed.  Here, we set the parent workspace.
24302d9224a3SMark J. Nelson#
2431*d7b56f41SBart Coddensif [[ $SCM_MODE == "mercurial" ]]; then
2432cdf0c1d5Smjnelson	#
2433cdf0c1d5Smjnelson	# Parent can either be specified with -p
2434cdf0c1d5Smjnelson	# Specified with CODEMGR_PARENT in the environment
2435cdf0c1d5Smjnelson	# or taken from hg's default path.
2436cdf0c1d5Smjnelson	#
2437cdf0c1d5Smjnelson
2438cdf0c1d5Smjnelson	if [[ -z $codemgr_parent && -n $CODEMGR_PARENT ]]; then
2439cdf0c1d5Smjnelson		codemgr_parent=$CODEMGR_PARENT
2440cdf0c1d5Smjnelson	fi
2441cdf0c1d5Smjnelson
2442cdf0c1d5Smjnelson	if [[ -z $codemgr_parent ]]; then
2443cdf0c1d5Smjnelson		codemgr_parent=`hg path -R $codemgr_ws default 2>/dev/null`
2444cdf0c1d5Smjnelson	fi
2445cdf0c1d5Smjnelson
2446cdf0c1d5Smjnelson	PWS=$codemgr_parent
2447cdf0c1d5Smjnelson
2448cdf0c1d5Smjnelson	#
2449cdf0c1d5Smjnelson	# If the parent is a webrev, we want to do some things against
2450cdf0c1d5Smjnelson	# the natural workspace parent (file list, comments, etc)
2451cdf0c1d5Smjnelson	#
2452cdf0c1d5Smjnelson	if [[ -n $parent_webrev ]]; then
2453cdf0c1d5Smjnelson		real_parent=$(hg path -R $codemgr_ws default 2>/dev/null)
2454cdf0c1d5Smjnelson	else
2455cdf0c1d5Smjnelson		real_parent=$PWS
2456cdf0c1d5Smjnelson	fi
2457cdf0c1d5Smjnelson
2458cdf0c1d5Smjnelson	#
2459cdf0c1d5Smjnelson	# If hg-active exists, then we run it.  In the case of no explicit
2460cdf0c1d5Smjnelson	# flist given, we'll use it for our comments.  In the case of an
2461cdf0c1d5Smjnelson	# explicit flist given we'll try to use it for comments for any
2462cdf0c1d5Smjnelson	# files mentioned in the flist.
2463cdf0c1d5Smjnelson	#
2464cdf0c1d5Smjnelson	if [[ -z $flist_done ]]; then
2465cdf0c1d5Smjnelson		flist_from_mercurial $CWS $real_parent
2466cdf0c1d5Smjnelson		flist_done=1
2467cdf0c1d5Smjnelson	fi
2468cdf0c1d5Smjnelson
2469cdf0c1d5Smjnelson	#
2470cdf0c1d5Smjnelson	# If we have a file list now, pull out any variables set
2471cdf0c1d5Smjnelson	# therein.  We do this now (rather than when we possibly use
2472cdf0c1d5Smjnelson	# hg-active to find comments) to avoid stomping specifications
2473cdf0c1d5Smjnelson	# in the user-specified flist.
2474cdf0c1d5Smjnelson	#
2475cdf0c1d5Smjnelson	if [[ -n $flist_done ]]; then
2476cdf0c1d5Smjnelson		env_from_flist
2477cdf0c1d5Smjnelson	fi
2478cdf0c1d5Smjnelson
2479cdf0c1d5Smjnelson	#
2480cdf0c1d5Smjnelson	# Only call hg-active if we don't have a wx formatted file already
2481cdf0c1d5Smjnelson	#
2482cdf0c1d5Smjnelson	if [[ -x $HG_ACTIVE && -z $wxfile ]]; then
2483cdf0c1d5Smjnelson		print "  Comments from: hg-active -p $real_parent ...\c"
2484cdf0c1d5Smjnelson		hg_active_wxfile $CWS $real_parent
2485cdf0c1d5Smjnelson		print " Done."
2486cdf0c1d5Smjnelson	fi
2487cdf0c1d5Smjnelson
2488cdf0c1d5Smjnelson	#
2489cdf0c1d5Smjnelson	# At this point we must have a wx flist either from hg-active,
2490cdf0c1d5Smjnelson	# or in general.  Use it to try and find our parent revision,
2491cdf0c1d5Smjnelson	# if we don't have one.
2492cdf0c1d5Smjnelson	#
2493cdf0c1d5Smjnelson	if [[ -z $HG_PARENT ]]; then
2494b0088928SVladimir Kotal		eval `$SED -e "s/#.*$//" $wxfile | $GREP HG_PARENT=`
2495cdf0c1d5Smjnelson	fi
2496cdf0c1d5Smjnelson
2497cdf0c1d5Smjnelson	#
2498cdf0c1d5Smjnelson	# If we still don't have a parent, we must have been given a
2499cdf0c1d5Smjnelson	# wx-style active list with no HG_PARENT specification, run
2500cdf0c1d5Smjnelson	# hg-active and pull an HG_PARENT out of it, ignore the rest.
2501cdf0c1d5Smjnelson	#
2502cdf0c1d5Smjnelson	if [[ -z $HG_PARENT && -x $HG_ACTIVE ]]; then
2503cdf0c1d5Smjnelson		$HG_ACTIVE -w $codemgr_ws -p $real_parent | \
2504b0088928SVladimir Kotal		    eval `$SED -e "s/#.*$//" | $GREP HG_PARENT=`
2505cdf0c1d5Smjnelson	elif [[ -z $HG_PARENT ]]; then
2506cdf0c1d5Smjnelson		print -u2 "Error: Cannot discover parent revision"
2507cdf0c1d5Smjnelson		exit 1
2508cdf0c1d5Smjnelson	fi
25098bcea973SRichard Lowe
25108bcea973SRichard Lowe	pnode=$(trim_digest $HG_PARENT)
25118bcea973SRichard Lowe	PRETTY_PWS="${PWS} (at ${pnode})"
25128bcea973SRichard Lowe	cnode=$(hg parent -R $codemgr_ws --template '{node|short}' \
25138bcea973SRichard Lowe	    2>/dev/null)
25148bcea973SRichard Lowe	PRETTY_CWS="${CWS} (at ${cnode})"}
25158bcea973SRichard Loweelif [[ $SCM_MODE == "git" ]]; then
25168bcea973SRichard Lowe	#
25178bcea973SRichard Lowe	# Parent can either be specified with -p, or specified with
25188bcea973SRichard Lowe	# CODEMGR_PARENT in the environment.
25198bcea973SRichard Lowe	#
25208bcea973SRichard Lowe
25218bcea973SRichard Lowe	if [[ -z $codemgr_parent && -n $CODEMGR_PARENT ]]; then
25228bcea973SRichard Lowe		codemgr_parent=$CODEMGR_PARENT
25238bcea973SRichard Lowe	fi
25248bcea973SRichard Lowe
25258bcea973SRichard Lowe	# Try to figure out the parent based on the branch the current
25268bcea973SRichard Lowe	# branch is tracking, if we fail, use origin/master
25278bcea973SRichard Lowe	this_branch=$($GIT branch | nawk '$1 == "*" { print $2 }')
25288bcea973SRichard Lowe	par_branch="origin/master"
25298bcea973SRichard Lowe
25308bcea973SRichard Lowe        # If we're not on a branch there's nothing we can do
25318bcea973SRichard Lowe        if [[ $this_branch != "(no branch)" ]]; then
25328bcea973SRichard Lowe                $GIT for-each-ref                                                 \
25338bcea973SRichard Lowe                    --format='%(refname:short) %(upstream:short)' refs/heads/ |   \
25348bcea973SRichard Lowe                    while read local remote; do                                   \
25358bcea973SRichard Lowe                	[[ "$local" == "$this_branch" ]] && par_branch="$remote"; \
25368bcea973SRichard Lowe                    done
25378bcea973SRichard Lowe	fi
25388bcea973SRichard Lowe
25398bcea973SRichard Lowe	if [[ -z $codemgr_parent ]]; then
25408bcea973SRichard Lowe		codemgr_parent=$par_branch
25418bcea973SRichard Lowe	fi
25428bcea973SRichard Lowe	PWS=$codemgr_parent
25438bcea973SRichard Lowe
25448bcea973SRichard Lowe	#
25458bcea973SRichard Lowe	# If the parent is a webrev, we want to do some things against
25468bcea973SRichard Lowe	# the natural workspace parent (file list, comments, etc)
25478bcea973SRichard Lowe	#
25488bcea973SRichard Lowe	if [[ -n $parent_webrev ]]; then
25498bcea973SRichard Lowe		real_parent=$par_branch
25508bcea973SRichard Lowe	else
25518bcea973SRichard Lowe		real_parent=$PWS
25528bcea973SRichard Lowe	fi
25538bcea973SRichard Lowe
25548bcea973SRichard Lowe	if [[ -z $flist_done ]]; then
25558bcea973SRichard Lowe		flist_from_git "$CWS" "$real_parent"
25568bcea973SRichard Lowe		flist_done=1
25578bcea973SRichard Lowe	fi
25588bcea973SRichard Lowe
25598bcea973SRichard Lowe	#
25608bcea973SRichard Lowe	# If we have a file list now, pull out any variables set
25618bcea973SRichard Lowe	# therein.
25628bcea973SRichard Lowe	#
25638bcea973SRichard Lowe	if [[ -n $flist_done ]]; then
25648bcea973SRichard Lowe		env_from_flist
25658bcea973SRichard Lowe	fi
25668bcea973SRichard Lowe
25678bcea973SRichard Lowe	#
25688bcea973SRichard Lowe	# If we don't have a wx-format file list, build one we can pull change
25698bcea973SRichard Lowe	# comments from.
25708bcea973SRichard Lowe	#
25718bcea973SRichard Lowe	if [[ -z $wxfile ]]; then
25728bcea973SRichard Lowe		print "  Comments from: git...\c"
25738bcea973SRichard Lowe		git_wxfile "$CWS" "$real_parent"
25748bcea973SRichard Lowe		print " Done."
25758bcea973SRichard Lowe	fi
25768bcea973SRichard Lowe
25778bcea973SRichard Lowe	if [[ -z $GIT_PARENT ]]; then
25788bcea973SRichard Lowe		GIT_PARENT=$($GIT merge-base "$real_parent" HEAD)
25798bcea973SRichard Lowe	fi
25808bcea973SRichard Lowe	if [[ -z $GIT_PARENT ]]; then
25818bcea973SRichard Lowe		print -u2 "Error: Cannot discover parent revision"
25828bcea973SRichard Lowe		exit 1
25838bcea973SRichard Lowe	fi
25848bcea973SRichard Lowe
25858bcea973SRichard Lowe	pnode=$(trim_digest $GIT_PARENT)
25868bcea973SRichard Lowe
25878bcea973SRichard Lowe	if [[ $real_parent == */* ]]; then
25888bcea973SRichard Lowe		origin=$(echo $real_parent | cut -d/ -f1)
25898bcea973SRichard Lowe		origin=$($GIT remote -v | \
25908bcea973SRichard Lowe		    $AWK '$1 == "'$origin'" { print $2; exit }')
25918bcea973SRichard Lowe		PRETTY_PWS="${PWS} (${origin} at ${pnode})"
25928bcea973SRichard Lowe	else
25938bcea973SRichard Lowe		PRETTY_PWS="${PWS} (at ${pnode})"
25948bcea973SRichard Lowe	fi
25958bcea973SRichard Lowe
25968bcea973SRichard Lowe	cnode=$($GIT --git-dir=${codemgr_ws}/.git rev-parse --short=12 HEAD \
25978bcea973SRichard Lowe	    2>/dev/null)
25988bcea973SRichard Lowe	PRETTY_CWS="${CWS} (at ${cnode})"
2599cdf0c1d5Smjnelsonelif [[ $SCM_MODE == "subversion" ]]; then
2600cdf0c1d5Smjnelson
2601cdf0c1d5Smjnelson	#
2602cdf0c1d5Smjnelson	# We only will have a real parent workspace in the case one
2603cdf0c1d5Smjnelson	# was specified (be it an older webrev, or another checkout).
2604cdf0c1d5Smjnelson	#
2605cdf0c1d5Smjnelson	[[ -n $codemgr_parent ]] && PWS=$codemgr_parent
2606cdf0c1d5Smjnelson
2607cdf0c1d5Smjnelson	if [[ -z $flist_done && $flist_mode == "auto" ]]; then
2608cdf0c1d5Smjnelson		flist_from_subversion $CWS $OLDPWD
2609cdf0c1d5Smjnelson	fi
2610cdf0c1d5Smjnelsonelse
2611cdf0c1d5Smjnelson    if [[ $SCM_MODE == "unknown" ]]; then
2612cdf0c1d5Smjnelson	print -u2 "    Unknown type of SCM in use"
2613cdf0c1d5Smjnelson    else
2614cdf0c1d5Smjnelson	print -u2 "    Unsupported SCM in use: $SCM_MODE"
2615cdf0c1d5Smjnelson    fi
2616cdf0c1d5Smjnelson
2617cdf0c1d5Smjnelson    env_from_flist
2618cdf0c1d5Smjnelson
2619cdf0c1d5Smjnelson    if [[ -z $CODEMGR_WS ]]; then
2620cdf0c1d5Smjnelson	print -u2 "SCM not detected/supported and CODEMGR_WS not specified"
2621cdf0c1d5Smjnelson	exit 1
2622cdf0c1d5Smjnelson    fi
2623cdf0c1d5Smjnelson
2624cdf0c1d5Smjnelson    if [[ -z $CODEMGR_PARENT ]]; then
2625cdf0c1d5Smjnelson	print -u2 "SCM not detected/supported and CODEMGR_PARENT not specified"
2626cdf0c1d5Smjnelson	exit 1
2627cdf0c1d5Smjnelson    fi
2628cdf0c1d5Smjnelson
2629cdf0c1d5Smjnelson    CWS=$CODEMGR_WS
2630cdf0c1d5Smjnelson    PWS=$CODEMGR_PARENT
2631daaffb31Sdpfi
2632daaffb31Sdp
2633daaffb31Sdp#
2634daaffb31Sdp# If the user didn't specify a -i option, check to see if there is a
2635daaffb31Sdp# webrev-info file in the workspace directory.
2636daaffb31Sdp#
2637daaffb31Sdpif [[ -z $iflag && -r "$CWS/webrev-info" ]]; then
2638daaffb31Sdp	iflag=1
2639daaffb31Sdp	INCLUDE_FILE="$CWS/webrev-info"
2640daaffb31Sdpfi
2641daaffb31Sdp
2642daaffb31Sdpif [[ -n $iflag ]]; then
2643daaffb31Sdp	if [[ ! -r $INCLUDE_FILE ]]; then
2644daaffb31Sdp		print -u2 "include file '$INCLUDE_FILE' does not exist or is" \
2645daaffb31Sdp		    "not readable."
2646daaffb31Sdp		exit 1
2647daaffb31Sdp	else
2648daaffb31Sdp		#
2649daaffb31Sdp		# $INCLUDE_FILE may be a relative path, and the script alters
2650daaffb31Sdp		# PWD, so we just stash a copy in /tmp.
2651daaffb31Sdp		#
2652daaffb31Sdp		cp $INCLUDE_FILE /tmp/$$.include
2653daaffb31Sdp	fi
2654daaffb31Sdpfi
2655daaffb31Sdp
26560fd2682eSMark J. Nelson# DO_EVERYTHING: break point
26570fd2682eSMark J. Nelsonif [[ -n $Nflag ]]; then
26580fd2682eSMark J. Nelson	break
26590fd2682eSMark J. Nelsonfi
26600fd2682eSMark J. Nelson
26610fd2682eSMark J. Nelsontypeset -A itsinfo
26620fd2682eSMark J. Nelsontypeset -r its_sed_script=/tmp/$$.its_sed
26630fd2682eSMark J. Nelsonvalid_prefixes=
26640fd2682eSMark J. Nelsonif [[ -z $nflag ]]; then
26658bcea973SRichard Lowe	DEFREGFILE="$(/bin/dirname "$(whence $0)")/../etc/its.reg"
26660fd2682eSMark J. Nelson	if [[ -n $Iflag ]]; then
26670fd2682eSMark J. Nelson		REGFILE=$ITSREG
26680fd2682eSMark J. Nelson	elif [[ -r $HOME/.its.reg ]]; then
26690fd2682eSMark J. Nelson		REGFILE=$HOME/.its.reg
26700fd2682eSMark J. Nelson	else
26710fd2682eSMark J. Nelson		REGFILE=$DEFREGFILE
26720fd2682eSMark J. Nelson	fi
26730fd2682eSMark J. Nelson	if [[ ! -r $REGFILE ]]; then
26740fd2682eSMark J. Nelson		print "ERROR: Unable to read database registry file $REGFILE"
26750fd2682eSMark J. Nelson		exit 1
26760fd2682eSMark J. Nelson	elif [[ $REGFILE != $DEFREGFILE ]]; then
26770fd2682eSMark J. Nelson		print "   its.reg from: $REGFILE"
26780fd2682eSMark J. Nelson	fi
26790fd2682eSMark J. Nelson
26800fd2682eSMark J. Nelson	$SED -e '/^#/d' -e '/^[ 	]*$/d' $REGFILE | while read LINE; do
26810fd2682eSMark J. Nelson
26820fd2682eSMark J. Nelson		name=${LINE%%=*}
26830fd2682eSMark J. Nelson		value="${LINE#*=}"
26840fd2682eSMark J. Nelson
26850fd2682eSMark J. Nelson		if [[ $name == PREFIX ]]; then
26860fd2682eSMark J. Nelson			p=${value}
26870fd2682eSMark J. Nelson			valid_prefixes="${p} ${valid_prefixes}"
26880fd2682eSMark J. Nelson		else
26890fd2682eSMark J. Nelson			itsinfo["${p}_${name}"]="${value}"
26900fd2682eSMark J. Nelson		fi
26910fd2682eSMark J. Nelson	done
26920fd2682eSMark J. Nelson
26930fd2682eSMark J. Nelson
26948bcea973SRichard Lowe	DEFCONFFILE="$(/bin/dirname "$(whence $0)")/../etc/its.conf"
26950fd2682eSMark J. Nelson	CONFFILES=$DEFCONFFILE
26960fd2682eSMark J. Nelson	if [[ -r $HOME/.its.conf ]]; then
26970fd2682eSMark J. Nelson		CONFFILES="${CONFFILES} $HOME/.its.conf"
26980fd2682eSMark J. Nelson	fi
26990fd2682eSMark J. Nelson	if [[ -n $Cflag ]]; then
27000fd2682eSMark J. Nelson		CONFFILES="${CONFFILES} ${ITSCONF}"
27010fd2682eSMark J. Nelson	fi
27020fd2682eSMark J. Nelson	its_domain=
27030fd2682eSMark J. Nelson	its_priority=
27040fd2682eSMark J. Nelson	for cf in ${CONFFILES}; do
27050fd2682eSMark J. Nelson		if [[ ! -r $cf ]]; then
27060fd2682eSMark J. Nelson			print "ERROR: Unable to read database configuration file $cf"
27070fd2682eSMark J. Nelson			exit 1
27080fd2682eSMark J. Nelson		elif [[ $cf != $DEFCONFFILE ]]; then
27090fd2682eSMark J. Nelson			print "       its.conf: reading $cf"
27100fd2682eSMark J. Nelson		fi
27110fd2682eSMark J. Nelson		$SED -e '/^#/d' -e '/^[ 	]*$/d' $cf | while read LINE; do
27120fd2682eSMark J. Nelson		    eval "${LINE}"
27130fd2682eSMark J. Nelson		done
27140fd2682eSMark J. Nelson	done
27150fd2682eSMark J. Nelson
27160fd2682eSMark J. Nelson	#
27170fd2682eSMark J. Nelson	# If an information tracking system is explicitly identified by prefix,
27180fd2682eSMark J. Nelson	# we want to disregard the specified priorities and resolve it accordingly.
27190fd2682eSMark J. Nelson	#
27200fd2682eSMark J. Nelson	# To that end, we'll build a sed script to do each valid prefix in turn.
27210fd2682eSMark J. Nelson	#
27220fd2682eSMark J. Nelson	for p in ${valid_prefixes}; do
27230fd2682eSMark J. Nelson		#
27240fd2682eSMark J. Nelson		# When an informational URL was provided, translate it to a
27250fd2682eSMark J. Nelson		# hyperlink.  When omitted, simply use the prefix text.
27260fd2682eSMark J. Nelson		#
27270fd2682eSMark J. Nelson		if [[ -z ${itsinfo["${p}_INFO"]} ]]; then
27280fd2682eSMark J. Nelson			itsinfo["${p}_INFO"]=${p}
27290fd2682eSMark J. Nelson		else
27300fd2682eSMark J. Nelson			itsinfo["${p}_INFO"]="<a href=\\\"${itsinfo["${p}_INFO"]}\\\">${p}</a>"
27310fd2682eSMark J. Nelson		fi
27320fd2682eSMark J. Nelson
27330fd2682eSMark J. Nelson		#
27340fd2682eSMark J. Nelson		# Assume that, for this invocation of webrev, all references
27350fd2682eSMark J. Nelson		# to this information tracking system should resolve through
27360fd2682eSMark J. Nelson		# the same URL.
27370fd2682eSMark J. Nelson		#
27380fd2682eSMark J. Nelson		# If the caller specified -O, then always use EXTERNAL_URL.
27390fd2682eSMark J. Nelson		#
27400fd2682eSMark J. Nelson		# Otherwise, look in the list of domains for a matching
27410fd2682eSMark J. Nelson		# INTERNAL_URL.
27420fd2682eSMark J. Nelson		#
27430fd2682eSMark J. Nelson		[[ -z $Oflag ]] && for d in ${its_domain}; do
27440fd2682eSMark J. Nelson			if [[ -n ${itsinfo["${p}_INTERNAL_URL_${d}"]} ]]; then
27450fd2682eSMark J. Nelson				itsinfo["${p}_URL"]="${itsinfo[${p}_INTERNAL_URL_${d}]}"
27460fd2682eSMark J. Nelson				break
27470fd2682eSMark J. Nelson			fi
27480fd2682eSMark J. Nelson		done
27490fd2682eSMark J. Nelson		if [[ -z ${itsinfo["${p}_URL"]} ]]; then
27500fd2682eSMark J. Nelson			itsinfo["${p}_URL"]="${itsinfo[${p}_EXTERNAL_URL]}"
27510fd2682eSMark J. Nelson		fi
27520fd2682eSMark J. Nelson
27530fd2682eSMark J. Nelson		#
27540fd2682eSMark J. Nelson		# Turn the destination URL into a hyperlink
27550fd2682eSMark J. Nelson		#
27560fd2682eSMark J. Nelson		itsinfo["${p}_URL"]="<a href=\\\"${itsinfo[${p}_URL]}\\\">&</a>"
27570fd2682eSMark J. Nelson
27582f54b716SRichard Lowe		# The character class below contains a literal tab
27592f54b716SRichard Lowe		print "/^${p}[: 	]/ {
27600fd2682eSMark J. Nelson				s;${itsinfo[${p}_REGEX]};${itsinfo[${p}_URL]};g
27610fd2682eSMark J. Nelson				s;^${p};${itsinfo[${p}_INFO]};
27620fd2682eSMark J. Nelson			}" >> ${its_sed_script}
27630fd2682eSMark J. Nelson	done
27640fd2682eSMark J. Nelson
27650fd2682eSMark J. Nelson	#
27660fd2682eSMark J. Nelson	# The previous loop took care of explicit specification.  Now use
27670fd2682eSMark J. Nelson	# the configured priorities to attempt implicit translations.
27680fd2682eSMark J. Nelson	#
27690fd2682eSMark J. Nelson	for p in ${its_priority}; do
27700fd2682eSMark J. Nelson		print "/^${itsinfo[${p}_REGEX]}[ 	]/ {
27712f54b716SRichard Lowe				s;^${itsinfo[${p}_REGEX]};${itsinfo[${p}_URL]};g
27720fd2682eSMark J. Nelson			}" >> ${its_sed_script}
27730fd2682eSMark J. Nelson	done
27740fd2682eSMark J. Nelsonfi
27750fd2682eSMark J. Nelson
27760fd2682eSMark J. Nelson#
27770fd2682eSMark J. Nelson# Search for DO_EVERYTHING above for matching "for" statement
27780fd2682eSMark J. Nelson# and explanation of this terminator.
27790fd2682eSMark J. Nelson#
27800fd2682eSMark J. Nelsondone
27810fd2682eSMark J. Nelson
2782daaffb31Sdp#
2783daaffb31Sdp# Output directory.
2784daaffb31Sdp#
2785daaffb31SdpWDIR=${WDIR:-$CWS/webrev}
2786daaffb31Sdp
2787daaffb31Sdp#
278802d26c39SVladimir Kotal# Name of the webrev, derived from the workspace name or output directory;
278902d26c39SVladimir Kotal# in the future this could potentially be an option.
2790daaffb31Sdp#
279102d26c39SVladimir Kotalif [[ -n $oflag ]]; then
279202d26c39SVladimir Kotal	WNAME=${WDIR##*/}
279302d26c39SVladimir Kotalelse
2794daaffb31Sdp	WNAME=${CWS##*/}
279502d26c39SVladimir Kotalfi
279602d26c39SVladimir Kotal
2797ba44d8a2SVladimir Kotal# Make sure remote target is well formed for remote upload/delete.
2798ba44d8a2SVladimir Kotalif [[ -n $Dflag || -n $Uflag ]]; then
2799b0088928SVladimir Kotal	#
2800ba44d8a2SVladimir Kotal	# If remote target is not specified, build it from scratch using
2801ba44d8a2SVladimir Kotal	# the default values.
2802b0088928SVladimir Kotal	#
2803ba44d8a2SVladimir Kotal	if [[ -z $tflag ]]; then
2804ba44d8a2SVladimir Kotal		remote_target=${DEFAULT_REMOTE_HOST}:${WNAME}
2805ba44d8a2SVladimir Kotal	else
2806b0088928SVladimir Kotal		#
2807b0088928SVladimir Kotal		# Check upload target prefix first.
2808b0088928SVladimir Kotal		#
2809b0088928SVladimir Kotal		if [[ "${remote_target}" != ${rsync_prefix}* &&
2810b0088928SVladimir Kotal		    "${remote_target}" != ${ssh_prefix}* ]]; then
2811b0088928SVladimir Kotal			print "ERROR: invalid prefix of upload URI" \
2812b0088928SVladimir Kotal			    "($remote_target)"
2813b0088928SVladimir Kotal			exit 1
2814b0088928SVladimir Kotal		fi
2815b0088928SVladimir Kotal		#
2816ba44d8a2SVladimir Kotal		# If destination specification is not in the form of
2817ba44d8a2SVladimir Kotal		# host_spec:remote_dir then assume it is just remote hostname
2818ba44d8a2SVladimir Kotal		# and append a colon and destination directory formed from
2819ba44d8a2SVladimir Kotal		# local webrev directory name.
2820b0088928SVladimir Kotal		#
2821b0088928SVladimir Kotal		typeset target_no_prefix=${remote_target##*://}
2822b0088928SVladimir Kotal		if [[ ${target_no_prefix} == *:* ]]; then
2823ba44d8a2SVladimir Kotal			if [[ "${remote_target}" == *: ]]; then
2824b0088928SVladimir Kotal				remote_target=${remote_target}${WNAME}
2825ba44d8a2SVladimir Kotal			fi
2826b0088928SVladimir Kotal		else
2827b0088928SVladimir Kotal			if [[ ${target_no_prefix} == */* ]]; then
2828b0088928SVladimir Kotal				print "ERROR: badly formed upload URI" \
2829b0088928SVladimir Kotal					"($remote_target)"
2830b0088928SVladimir Kotal				exit 1
2831b0088928SVladimir Kotal			else
2832b0088928SVladimir Kotal				remote_target=${remote_target}:${WNAME}
2833ba44d8a2SVladimir Kotal			fi
2834ba44d8a2SVladimir Kotal		fi
2835ba44d8a2SVladimir Kotal	fi
2836ba44d8a2SVladimir Kotal
2837b0088928SVladimir Kotal	#
2838b0088928SVladimir Kotal	# Strip trailing slash. Each upload method will deal with directory
2839b0088928SVladimir Kotal	# specification separately.
2840b0088928SVladimir Kotal	#
2841b0088928SVladimir Kotal	remote_target=${remote_target%/}
2842b0088928SVladimir Kotalfi
2843b0088928SVladimir Kotal
2844b0088928SVladimir Kotal#
2845ba44d8a2SVladimir Kotal# Option -D by itself (option -U not present) implies no webrev generation.
2846b0088928SVladimir Kotal#
2847ba44d8a2SVladimir Kotalif [[ -z $Uflag && -n $Dflag ]]; then
2848b0088928SVladimir Kotal	delete_webrev 1 1
2849ba44d8a2SVladimir Kotal	exit $?
2850ba44d8a2SVladimir Kotalfi
2851ba44d8a2SVladimir Kotal
2852b0088928SVladimir Kotal#
2853ba44d8a2SVladimir Kotal# Do not generate the webrev, just upload it or delete it.
2854b0088928SVladimir Kotal#
2855ba44d8a2SVladimir Kotalif [[ -n $nflag ]]; then
2856ba44d8a2SVladimir Kotal	if [[ -n $Dflag ]]; then
2857b0088928SVladimir Kotal		delete_webrev 1 1
2858ba44d8a2SVladimir Kotal		(( $? == 0 )) || exit $?
2859ba44d8a2SVladimir Kotal	fi
2860ba44d8a2SVladimir Kotal	if [[ -n $Uflag ]]; then
286102d26c39SVladimir Kotal		upload_webrev
286202d26c39SVladimir Kotal		exit $?
286302d26c39SVladimir Kotal	fi
2864ba44d8a2SVladimir Kotalfi
2865daaffb31Sdp
2866e0e0293aSjmcpif [ "${WDIR%%/*}" ]; then
28677c478bd9Sstevel@tonic-gate	WDIR=$PWD/$WDIR
28687c478bd9Sstevel@tonic-gatefi
2869daaffb31Sdp
2870daaffb31Sdpif [[ ! -d $WDIR ]]; then
2871daaffb31Sdp	mkdir -p $WDIR
2872ba44d8a2SVladimir Kotal	(( $? != 0 )) && exit 1
28737c478bd9Sstevel@tonic-gatefi
28747c478bd9Sstevel@tonic-gate
2875daaffb31Sdp#
2876daaffb31Sdp# Summarize what we're going to do.
2877daaffb31Sdp#
28788bcea973SRichard Loweprint "      Workspace: ${PRETTY_CWS:-$CWS}"
2879daaffb31Sdpif [[ -n $parent_webrev ]]; then
2880daaffb31Sdp	print "Compare against: webrev at $parent_webrev"
2881daaffb31Sdpelse
28828bcea973SRichard Lowe	print "Compare against: ${PRETTY_PWS:-$PWS}"
2883cdf0c1d5Smjnelsonfi
2884daaffb31Sdp
2885daaffb31Sdp[[ -n $INCLUDE_FILE ]] && print "      Including: $INCLUDE_FILE"
2886daaffb31Sdpprint "      Output to: $WDIR"
2887daaffb31Sdp
2888daaffb31Sdp#
28897c478bd9Sstevel@tonic-gate# Save the file list in the webrev dir
2890daaffb31Sdp#
2891daaffb31Sdp[[ ! $FLIST -ef $WDIR/file.list ]] && cp $FLIST $WDIR/file.list
28927c478bd9Sstevel@tonic-gate
2893daaffb31Sdprm -f $WDIR/$WNAME.patch
2894daaffb31Sdprm -f $WDIR/$WNAME.ps
2895daaffb31Sdprm -f $WDIR/$WNAME.pdf
28967c478bd9Sstevel@tonic-gate
2897daaffb31Sdptouch $WDIR/$WNAME.patch
28987c478bd9Sstevel@tonic-gate
2899daaffb31Sdpprint "   Output Files:"
2900daaffb31Sdp
2901daaffb31Sdp#
2902daaffb31Sdp# Clean up the file list: Remove comments, blank lines and env variables.
2903daaffb31Sdp#
2904b0088928SVladimir Kotal$SED -e "s/#.*$//" -e "/=/d" -e "/^[   ]*$/d" $FLIST > /tmp/$$.flist.clean
2905daaffb31SdpFLIST=/tmp/$$.flist.clean
2906daaffb31Sdp
2907daaffb31Sdp#
2908cdf0c1d5Smjnelson# For Mercurial, create a cache of manifest entries.
2909cdf0c1d5Smjnelson#
2910cdf0c1d5Smjnelsonif [[ $SCM_MODE == "mercurial" ]]; then
2911cdf0c1d5Smjnelson	#
2912cdf0c1d5Smjnelson	# Transform the FLIST into a temporary sed script that matches
2913cdf0c1d5Smjnelson	# relevant entries in the Mercurial manifest as follows:
2914cdf0c1d5Smjnelson	# 1) The script will be used against the parent revision manifest,
2915cdf0c1d5Smjnelson	#    so for FLIST lines that have two filenames (a renamed file)
2916cdf0c1d5Smjnelson	#    keep only the old name.
2917cdf0c1d5Smjnelson	# 2) Escape all forward slashes the filename.
2918cdf0c1d5Smjnelson	# 3) Change the filename into another sed command that matches
2919cdf0c1d5Smjnelson	#    that file in "hg manifest -v" output:  start of line, three
2920cdf0c1d5Smjnelson	#    octal digits for file permissions, space, a file type flag
2921cdf0c1d5Smjnelson	#    character, space, the filename, end of line.
2922e6ccc173SEdward Pilatowicz	# 4) Eliminate any duplicate entries.  (This can occur if a
2923e6ccc173SEdward Pilatowicz	#    file has been used as the source of an hg cp and it's
2924e6ccc173SEdward Pilatowicz	#    also been modified in the same changeset.)
2925cdf0c1d5Smjnelson	#
2926cdf0c1d5Smjnelson	SEDFILE=/tmp/$$.manifest.sed
2927b0088928SVladimir Kotal	$SED '
2928cdf0c1d5Smjnelson		s#^[^ ]* ##
2929cdf0c1d5Smjnelson		s#/#\\\/#g
2930cdf0c1d5Smjnelson		s#^.*$#/^... . &$/p#
2931e6ccc173SEdward Pilatowicz	' < $FLIST | $SORT -u > $SEDFILE
2932cdf0c1d5Smjnelson
2933cdf0c1d5Smjnelson	#
2934cdf0c1d5Smjnelson	# Apply the generated script to the output of "hg manifest -v"
2935cdf0c1d5Smjnelson	# to get the relevant subset for this webrev.
2936cdf0c1d5Smjnelson	#
2937cdf0c1d5Smjnelson	HG_PARENT_MANIFEST=/tmp/$$.manifest
2938cdf0c1d5Smjnelson	hg -R $CWS manifest -v -r $HG_PARENT |
2939b0088928SVladimir Kotal	    $SED -n -f $SEDFILE > $HG_PARENT_MANIFEST
2940cdf0c1d5Smjnelsonfi
2941cdf0c1d5Smjnelson
2942cdf0c1d5Smjnelson#
2943daaffb31Sdp# First pass through the files: generate the per-file webrev HTML-files.
2944daaffb31Sdp#
2945daaffb31Sdpcat $FLIST | while read LINE
29467c478bd9Sstevel@tonic-gatedo
29477c478bd9Sstevel@tonic-gate	set - $LINE
29487c478bd9Sstevel@tonic-gate	P=$1
29497c478bd9Sstevel@tonic-gate
2950daaffb31Sdp	#
2951daaffb31Sdp	# Normally, each line in the file list is just a pathname of a
2952daaffb31Sdp	# file that has been modified or created in the child.  A file
2953daaffb31Sdp	# that is renamed in the child workspace has two names on the
2954daaffb31Sdp	# line: new name followed by the old name.
2955daaffb31Sdp	#
2956daaffb31Sdp	oldname=""
2957daaffb31Sdp	oldpath=""
2958daaffb31Sdp	rename=
2959daaffb31Sdp	if [[ $# -eq 2 ]]; then
29607c478bd9Sstevel@tonic-gate		PP=$2			# old filename
2961e6ccc173SEdward Pilatowicz		if [[ -f $PP ]]; then
2962e6ccc173SEdward Pilatowicz			oldname=" (copied from $PP)"
2963e6ccc173SEdward Pilatowicz		else
2964e6ccc173SEdward Pilatowicz			oldname=" (renamed from $PP)"
2965e6ccc173SEdward Pilatowicz		fi
2966daaffb31Sdp		oldpath="$PP"
2967daaffb31Sdp		rename=1
29687c478bd9Sstevel@tonic-gate		PDIR=${PP%/*}
2969daaffb31Sdp		if [[ $PDIR == $PP ]]; then
29707c478bd9Sstevel@tonic-gate			PDIR="."   # File at root of workspace
29717c478bd9Sstevel@tonic-gate		fi
29727c478bd9Sstevel@tonic-gate
29737c478bd9Sstevel@tonic-gate		PF=${PP##*/}
29747c478bd9Sstevel@tonic-gate
29757c478bd9Sstevel@tonic-gate		DIR=${P%/*}
2976daaffb31Sdp		if [[ $DIR == $P ]]; then
29777c478bd9Sstevel@tonic-gate			DIR="."   # File at root of workspace
29787c478bd9Sstevel@tonic-gate		fi
29797c478bd9Sstevel@tonic-gate
29807c478bd9Sstevel@tonic-gate		F=${P##*/}
2981daaffb31Sdp
29827c478bd9Sstevel@tonic-gate        else
29837c478bd9Sstevel@tonic-gate		DIR=${P%/*}
2984daaffb31Sdp		if [[ "$DIR" == "$P" ]]; then
29857c478bd9Sstevel@tonic-gate			DIR="."   # File at root of workspace
29867c478bd9Sstevel@tonic-gate		fi
29877c478bd9Sstevel@tonic-gate
29887c478bd9Sstevel@tonic-gate		F=${P##*/}
29897c478bd9Sstevel@tonic-gate
29907c478bd9Sstevel@tonic-gate		PP=$P
29917c478bd9Sstevel@tonic-gate		PDIR=$DIR
29927c478bd9Sstevel@tonic-gate		PF=$F
29937c478bd9Sstevel@tonic-gate	fi
29947c478bd9Sstevel@tonic-gate
2995daaffb31Sdp	COMM=`getcomments html $P $PP`
29967c478bd9Sstevel@tonic-gate
2997daaffb31Sdp	print "\t$P$oldname\n\t\t\c"
29987c478bd9Sstevel@tonic-gate
29997c478bd9Sstevel@tonic-gate	# Make the webrev mirror directory if necessary
30007c478bd9Sstevel@tonic-gate	mkdir -p $WDIR/$DIR
30017c478bd9Sstevel@tonic-gate
3002daaffb31Sdp	#
3003cdf0c1d5Smjnelson	# We stash old and new files into parallel directories in $WDIR
3004daaffb31Sdp	# and do our diffs there.  This makes it possible to generate
3005daaffb31Sdp	# clean looking diffs which don't have absolute paths present.
3006daaffb31Sdp	#
3007daaffb31Sdp
3008cdf0c1d5Smjnelson	build_old_new "$WDIR" "$PWS" "$PDIR" "$PF" "$CWS" "$DIR" "$F" || \
30097c478bd9Sstevel@tonic-gate	    continue
30107c478bd9Sstevel@tonic-gate
3011cdf0c1d5Smjnelson	#
3012cdf0c1d5Smjnelson	# Keep the old PWD around, so we can safely switch back after
3013cdf0c1d5Smjnelson	# diff generation, such that build_old_new runs in a
3014cdf0c1d5Smjnelson	# consistent environment.
3015cdf0c1d5Smjnelson	#
3016cdf0c1d5Smjnelson	OWD=$PWD
3017daaffb31Sdp	cd $WDIR/raw_files
3018daaffb31Sdp	ofile=old/$PDIR/$PF
3019daaffb31Sdp	nfile=new/$DIR/$F
30207c478bd9Sstevel@tonic-gate
3021daaffb31Sdp	mv_but_nodiff=
3022daaffb31Sdp	cmp $ofile $nfile > /dev/null 2>&1
3023daaffb31Sdp	if [[ $? == 0 && $rename == 1 ]]; then
3024daaffb31Sdp		mv_but_nodiff=1
3025daaffb31Sdp	fi
3026daaffb31Sdp
3027daaffb31Sdp	#
3028daaffb31Sdp	# If we have old and new versions of the file then run the appropriate
3029daaffb31Sdp	# diffs.  This is complicated by a couple of factors:
3030daaffb31Sdp	#
3031daaffb31Sdp	#	- renames must be handled specially: we emit a 'remove'
3032daaffb31Sdp	#	  diff and an 'add' diff
3033daaffb31Sdp	#	- new files and deleted files must be handled specially
3034daaffb31Sdp	#	- Solaris patch(1m) can't cope with file creation
3035daaffb31Sdp	#	  (and hence renames) as of this writing.
3036daaffb31Sdp	#       - To make matters worse, gnu patch doesn't interpret the
3037daaffb31Sdp	#	  output of Solaris diff properly when it comes to
3038daaffb31Sdp	#	  adds and deletes.  We need to do some "cleansing"
3039daaffb31Sdp	#         transformations:
3040daaffb31Sdp	#	    [to add a file] @@ -1,0 +X,Y @@  -->  @@ -0,0 +X,Y @@
3041daaffb31Sdp	#	    [to del a file] @@ -X,Y +1,0 @@  -->  @@ -X,Y +0,0 @@
3042daaffb31Sdp	#
3043b0088928SVladimir Kotal	cleanse_rmfile="$SED 's/^\(@@ [0-9+,-]*\) [0-9+,-]* @@$/\1 +0,0 @@/'"
3044b0088928SVladimir Kotal	cleanse_newfile="$SED 's/^@@ [0-9+,-]* \([0-9+,-]* @@\)$/@@ -0,0 \1/'"
3045daaffb31Sdp
3046daaffb31Sdp	rm -f $WDIR/$DIR/$F.patch
3047daaffb31Sdp	if [[ -z $rename ]]; then
3048e0e0293aSjmcp		if [ ! -f "$ofile" ]; then
3049daaffb31Sdp			diff -u /dev/null $nfile | sh -c "$cleanse_newfile" \
3050daaffb31Sdp			    > $WDIR/$DIR/$F.patch
3051e0e0293aSjmcp		elif [ ! -f "$nfile" ]; then
3052daaffb31Sdp			diff -u $ofile /dev/null | sh -c "$cleanse_rmfile" \
3053daaffb31Sdp			    > $WDIR/$DIR/$F.patch
3054daaffb31Sdp		else
3055daaffb31Sdp			diff -u $ofile $nfile > $WDIR/$DIR/$F.patch
3056daaffb31Sdp		fi
3057daaffb31Sdp	else
3058daaffb31Sdp		diff -u $ofile /dev/null | sh -c "$cleanse_rmfile" \
3059daaffb31Sdp		    > $WDIR/$DIR/$F.patch
3060daaffb31Sdp
3061daaffb31Sdp		diff -u /dev/null $nfile | sh -c "$cleanse_newfile" \
3062daaffb31Sdp		    >> $WDIR/$DIR/$F.patch
3063daaffb31Sdp	fi
3064daaffb31Sdp
3065daaffb31Sdp	#
3066daaffb31Sdp	# Tack the patch we just made onto the accumulated patch for the
3067daaffb31Sdp	# whole wad.
3068daaffb31Sdp	#
3069daaffb31Sdp	cat $WDIR/$DIR/$F.patch >> $WDIR/$WNAME.patch
3070daaffb31Sdp
3071daaffb31Sdp	print " patch\c"
3072daaffb31Sdp
3073daaffb31Sdp	if [[ -f $ofile && -f $nfile && -z $mv_but_nodiff ]]; then
3074daaffb31Sdp
3075daaffb31Sdp		${CDIFFCMD:-diff -bt -C 5} $ofile $nfile > $WDIR/$DIR/$F.cdiff
3076daaffb31Sdp		diff_to_html $F $DIR/$F "C" "$COMM" < $WDIR/$DIR/$F.cdiff \
3077daaffb31Sdp		    > $WDIR/$DIR/$F.cdiff.html
30787c478bd9Sstevel@tonic-gate		print " cdiffs\c"
30797c478bd9Sstevel@tonic-gate
3080daaffb31Sdp		${UDIFFCMD:-diff -bt -U 5} $ofile $nfile > $WDIR/$DIR/$F.udiff
3081daaffb31Sdp		diff_to_html $F $DIR/$F "U" "$COMM" < $WDIR/$DIR/$F.udiff \
3082daaffb31Sdp		    > $WDIR/$DIR/$F.udiff.html
3083daaffb31Sdp
30847c478bd9Sstevel@tonic-gate		print " udiffs\c"
30857c478bd9Sstevel@tonic-gate
30867c478bd9Sstevel@tonic-gate		if [[ -x $WDIFF ]]; then
3087daaffb31Sdp			$WDIFF -c "$COMM" \
3088daaffb31Sdp			    -t "$WNAME Wdiff $DIR/$F" $ofile $nfile > \
3089daaffb31Sdp			    $WDIR/$DIR/$F.wdiff.html 2>/dev/null
3090daaffb31Sdp			if [[ $? -eq 0 ]]; then
30917c478bd9Sstevel@tonic-gate				print " wdiffs\c"
3092daaffb31Sdp			else
3093daaffb31Sdp				print " wdiffs[fail]\c"
3094daaffb31Sdp			fi
30957c478bd9Sstevel@tonic-gate		fi
30967c478bd9Sstevel@tonic-gate
3097daaffb31Sdp		sdiff_to_html $ofile $nfile $F $DIR "$COMM" \
3098daaffb31Sdp		    > $WDIR/$DIR/$F.sdiff.html
30997c478bd9Sstevel@tonic-gate		print " sdiffs\c"
31007c478bd9Sstevel@tonic-gate
31017c478bd9Sstevel@tonic-gate		print " frames\c"
31027c478bd9Sstevel@tonic-gate
31037c478bd9Sstevel@tonic-gate		rm -f $WDIR/$DIR/$F.cdiff $WDIR/$DIR/$F.udiff
31047c478bd9Sstevel@tonic-gate
3105daaffb31Sdp		difflines $ofile $nfile > $WDIR/$DIR/$F.count
3106daaffb31Sdp
3107daaffb31Sdp	elif [[ -f $ofile && -f $nfile && -n $mv_but_nodiff ]]; then
3108daaffb31Sdp		# renamed file: may also have differences
3109daaffb31Sdp		difflines $ofile $nfile > $WDIR/$DIR/$F.count
3110daaffb31Sdp	elif [[ -f $nfile ]]; then
31117c478bd9Sstevel@tonic-gate		# new file: count added lines
3112daaffb31Sdp		difflines /dev/null $nfile > $WDIR/$DIR/$F.count
3113daaffb31Sdp	elif [[ -f $ofile ]]; then
31147c478bd9Sstevel@tonic-gate		# old file: count deleted lines
3115daaffb31Sdp		difflines $ofile /dev/null > $WDIR/$DIR/$F.count
31167c478bd9Sstevel@tonic-gate	fi
31177c478bd9Sstevel@tonic-gate
3118daaffb31Sdp	#
3119daaffb31Sdp	# Now we generate the postscript for this file.  We generate diffs
3120daaffb31Sdp	# only in the event that there is delta, or the file is new (it seems
3121daaffb31Sdp	# tree-killing to print out the contents of deleted files).
3122daaffb31Sdp	#
3123daaffb31Sdp	if [[ -f $nfile ]]; then
3124daaffb31Sdp		ocr=$ofile
3125daaffb31Sdp		[[ ! -f $ofile ]] && ocr=/dev/null
3126daaffb31Sdp
3127daaffb31Sdp		if [[ -z $mv_but_nodiff ]]; then
3128daaffb31Sdp			textcomm=`getcomments text $P $PP`
312914983201Sdp			if [[ -x $CODEREVIEW ]]; then
313014983201Sdp				$CODEREVIEW -y "$textcomm" \
313114983201Sdp				    -e $ocr $nfile \
313214983201Sdp				    > /tmp/$$.psfile 2>/dev/null &&
313314983201Sdp				    cat /tmp/$$.psfile >> $WDIR/$WNAME.ps
3134daaffb31Sdp				if [[ $? -eq 0 ]]; then
3135daaffb31Sdp					print " ps\c"
3136daaffb31Sdp				else
3137daaffb31Sdp					print " ps[fail]\c"
3138daaffb31Sdp				fi
3139daaffb31Sdp			fi
3140daaffb31Sdp		fi
314114983201Sdp	fi
3142daaffb31Sdp
3143cdf0c1d5Smjnelson	if [[ -f $ofile ]]; then
3144cdf0c1d5Smjnelson		source_to_html Old $PP < $ofile > $WDIR/$DIR/$F-.html
31457c478bd9Sstevel@tonic-gate		print " old\c"
31467c478bd9Sstevel@tonic-gate	fi
31477c478bd9Sstevel@tonic-gate
3148daaffb31Sdp	if [[ -f $nfile ]]; then
3149daaffb31Sdp		source_to_html New $P < $nfile > $WDIR/$DIR/$F.html
31507c478bd9Sstevel@tonic-gate		print " new\c"
31517c478bd9Sstevel@tonic-gate	fi
31527c478bd9Sstevel@tonic-gate
3153cdf0c1d5Smjnelson	cd $OWD
3154cdf0c1d5Smjnelson
3155daaffb31Sdp	print
31567c478bd9Sstevel@tonic-gatedone
31577c478bd9Sstevel@tonic-gate
3158daaffb31Sdpframe_nav_js > $WDIR/ancnav.js
31597c478bd9Sstevel@tonic-gateframe_navigation > $WDIR/ancnav.html
3160daaffb31Sdp
316114983201Sdpif [[ ! -f $WDIR/$WNAME.ps ]]; then
316214983201Sdp	print " Generating PDF: Skipped: no output available"
316314983201Sdpelif [[ -x $CODEREVIEW && -x $PS2PDF ]]; then
316414983201Sdp	print " Generating PDF: \c"
316514983201Sdp	fix_postscript $WDIR/$WNAME.ps | $PS2PDF - > $WDIR/$WNAME.pdf
3166daaffb31Sdp	print "Done."
316714983201Sdpelse
316814983201Sdp	print " Generating PDF: Skipped: missing 'ps2pdf' or 'codereview'"
316914983201Sdpfi
31707c478bd9Sstevel@tonic-gate
3171e0e0293aSjmcp# If we're in OpenSolaris mode and there's a closed dir under $WDIR,
3172e0e0293aSjmcp# delete it - prevent accidental publishing of closed source
3173e0e0293aSjmcp
3174e0e0293aSjmcpif [[ -n "$Oflag" ]]; then
3175ba44d8a2SVladimir Kotal	$FIND $WDIR -type d -name closed -exec /bin/rm -rf {} \;
3176e0e0293aSjmcpfi
3177e0e0293aSjmcp
31787c478bd9Sstevel@tonic-gate# Now build the index.html file that contains
31797c478bd9Sstevel@tonic-gate# links to the source files and their diffs.
31807c478bd9Sstevel@tonic-gate
31817c478bd9Sstevel@tonic-gatecd $CWS
31827c478bd9Sstevel@tonic-gate
31837c478bd9Sstevel@tonic-gate# Save total changed lines for Code Inspection.
3184daaffb31Sdpprint "$TOTL" > $WDIR/TotalChangedLines
31857c478bd9Sstevel@tonic-gate
3186daaffb31Sdpprint "     index.html: \c"
31877c478bd9Sstevel@tonic-gateINDEXFILE=$WDIR/index.html
31887c478bd9Sstevel@tonic-gateexec 3<&1			# duplicate stdout to FD3.
31897c478bd9Sstevel@tonic-gateexec 1<&-			# Close stdout.
31907c478bd9Sstevel@tonic-gateexec > $INDEXFILE		# Open stdout to index file.
31917c478bd9Sstevel@tonic-gate
3192daaffb31Sdpprint "$HTML<head>$STDHEAD"
3193daaffb31Sdpprint "<title>$WNAME</title>"
3194daaffb31Sdpprint "</head>"
3195daaffb31Sdpprint "<body id=\"SUNWwebrev\">"
3196daaffb31Sdpprint "<div class=\"summary\">"
3197daaffb31Sdpprint "<h2>Code Review for $WNAME</h2>"
31987c478bd9Sstevel@tonic-gate
3199daaffb31Sdpprint "<table>"
32007c478bd9Sstevel@tonic-gate
3201daaffb31Sdp#
3202cdf0c1d5Smjnelson# Get the preparer's name:
3203daaffb31Sdp#
3204cdf0c1d5Smjnelson# If the SCM detected is Mercurial, and the configuration property
3205cdf0c1d5Smjnelson# ui.username is available, use that, but be careful to properly escape
3206cdf0c1d5Smjnelson# angle brackets (HTML syntax characters) in the email address.
3207cdf0c1d5Smjnelson#
3208cdf0c1d5Smjnelson# Otherwise, use the current userid in the form "John Doe (jdoe)", but
3209cdf0c1d5Smjnelson# to maintain compatibility with passwd(4), we must support '&' substitutions.
3210cdf0c1d5Smjnelson#
3211cdf0c1d5Smjnelsonpreparer=
3212cdf0c1d5Smjnelsonif [[ "$SCM_MODE" == mercurial ]]; then
3213cdf0c1d5Smjnelson	preparer=`hg showconfig ui.username 2>/dev/null`
3214cdf0c1d5Smjnelson	if [[ -n "$preparer" ]]; then
3215cdf0c1d5Smjnelson		preparer="$(echo "$preparer" | html_quote)"
3216cdf0c1d5Smjnelson	fi
3217cdf0c1d5Smjnelsonfi
3218cdf0c1d5Smjnelsonif [[ -z "$preparer" ]]; then
3219cdf0c1d5Smjnelson	preparer=$(
3220cdf0c1d5Smjnelson	    $PERL -e '
3221cdf0c1d5Smjnelson	        ($login, $pw, $uid, $gid, $quota, $cmt, $gcos) = getpwuid($<);
3222cdf0c1d5Smjnelson	        if ($login) {
3223cdf0c1d5Smjnelson	            $gcos =~ s/\&/ucfirst($login)/e;
3224cdf0c1d5Smjnelson	            printf "%s (%s)\n", $gcos, $login;
3225cdf0c1d5Smjnelson	        } else {
3226cdf0c1d5Smjnelson	            printf "(unknown)\n";
3227cdf0c1d5Smjnelson	        }
3228cdf0c1d5Smjnelson	')
3229daaffb31Sdpfi
3230daaffb31Sdp
323148bc00d6SjmcpPREPDATE=$(LC_ALL=C /usr/bin/date +%Y-%b-%d\ %R\ %z\ %Z)
323248bc00d6Sjmcpprint "<tr><th>Prepared by:</th><td>$preparer on $PREPDATE</td></tr>"
32338bcea973SRichard Loweprint "<tr><th>Workspace:</th><td>${PRETTY_CWS:-$CWS}"
3234cdf0c1d5Smjnelsonprint "</td></tr>"
3235daaffb31Sdpprint "<tr><th>Compare against:</th><td>"
3236daaffb31Sdpif [[ -n $parent_webrev ]]; then
3237daaffb31Sdp	print "webrev at $parent_webrev"
3238daaffb31Sdpelse
32398bcea973SRichard Lowe	print "${PRETTY_PWS:-$PWS}"
3240daaffb31Sdpfi
3241daaffb31Sdpprint "</td></tr>"
3242daaffb31Sdpprint "<tr><th>Summary of changes:</th><td>"
3243daaffb31SdpprintCI $TOTL $TINS $TDEL $TMOD $TUNC
3244daaffb31Sdpprint "</td></tr>"
3245daaffb31Sdp
3246daaffb31Sdpif [[ -f $WDIR/$WNAME.patch ]]; then
3247371d72daSLubomir Sedlacik	wpatch_url="$(print $WNAME.patch | url_encode)"
3248daaffb31Sdp	print "<tr><th>Patch of changes:</th><td>"
3249371d72daSLubomir Sedlacik	print "<a href=\"$wpatch_url\">$WNAME.patch</a></td></tr>"
3250daaffb31Sdpfi
3251daaffb31Sdpif [[ -f $WDIR/$WNAME.pdf ]]; then
3252371d72daSLubomir Sedlacik	wpdf_url="$(print $WNAME.pdf | url_encode)"
3253daaffb31Sdp	print "<tr><th>Printable review:</th><td>"
3254371d72daSLubomir Sedlacik	print "<a href=\"$wpdf_url\">$WNAME.pdf</a></td></tr>"
3255daaffb31Sdpfi
3256daaffb31Sdp
3257daaffb31Sdpif [[ -n "$iflag" ]]; then
3258daaffb31Sdp	print "<tr><th>Author comments:</th><td><div>"
3259daaffb31Sdp	cat /tmp/$$.include
3260daaffb31Sdp	print "</div></td></tr>"
3261daaffb31Sdpfi
3262daaffb31Sdpprint "</table>"
3263daaffb31Sdpprint "</div>"
3264daaffb31Sdp
3265daaffb31Sdp#
3266daaffb31Sdp# Second pass through the files: generate the rest of the index file
3267daaffb31Sdp#
3268daaffb31Sdpcat $FLIST | while read LINE
32697c478bd9Sstevel@tonic-gatedo
32707c478bd9Sstevel@tonic-gate	set - $LINE
32717c478bd9Sstevel@tonic-gate	P=$1
32727c478bd9Sstevel@tonic-gate
3273daaffb31Sdp	if [[ $# == 2 ]]; then
32747c478bd9Sstevel@tonic-gate		PP=$2
3275cdf0c1d5Smjnelson		oldname="$PP"
32767c478bd9Sstevel@tonic-gate	else
32777c478bd9Sstevel@tonic-gate		PP=$P
3278daaffb31Sdp		oldname=""
3279daaffb31Sdp	fi
3280daaffb31Sdp
3281cdf0c1d5Smjnelson	mv_but_nodiff=
3282cdf0c1d5Smjnelson	cmp $WDIR/raw_files/old/$PP $WDIR/raw_files/new/$P > /dev/null 2>&1
3283cdf0c1d5Smjnelson	if [[ $? == 0 && -n "$oldname" ]]; then
3284cdf0c1d5Smjnelson		mv_but_nodiff=1
3285cdf0c1d5Smjnelson	fi
3286cdf0c1d5Smjnelson
3287daaffb31Sdp	DIR=${P%/*}
3288daaffb31Sdp	if [[ $DIR == $P ]]; then
3289daaffb31Sdp		DIR="."   # File at root of workspace
32907c478bd9Sstevel@tonic-gate	fi
32917c478bd9Sstevel@tonic-gate
32927c478bd9Sstevel@tonic-gate	# Avoid processing the same file twice.
32937c478bd9Sstevel@tonic-gate	# It's possible for renamed files to
32947c478bd9Sstevel@tonic-gate	# appear twice in the file list
32957c478bd9Sstevel@tonic-gate
32967c478bd9Sstevel@tonic-gate	F=$WDIR/$P
32977c478bd9Sstevel@tonic-gate
3298daaffb31Sdp	print "<p>"
32997c478bd9Sstevel@tonic-gate
33007c478bd9Sstevel@tonic-gate	# If there's a diffs file, make diffs links
33017c478bd9Sstevel@tonic-gate
3302daaffb31Sdp	if [[ -f $F.cdiff.html ]]; then
3303371d72daSLubomir Sedlacik		cdiff_url="$(print $P.cdiff.html | url_encode)"
3304371d72daSLubomir Sedlacik		udiff_url="$(print $P.udiff.html | url_encode)"
3305371d72daSLubomir Sedlacik		print "<a href=\"$cdiff_url\">Cdiffs</a>"
3306371d72daSLubomir Sedlacik		print "<a href=\"$udiff_url\">Udiffs</a>"
33077c478bd9Sstevel@tonic-gate
3308daaffb31Sdp		if [[ -f $F.wdiff.html && -x $WDIFF ]]; then
3309371d72daSLubomir Sedlacik			wdiff_url="$(print $P.wdiff.html | url_encode)"
3310371d72daSLubomir Sedlacik			print "<a href=\"$wdiff_url\">Wdiffs</a>"
33117c478bd9Sstevel@tonic-gate		fi
33127c478bd9Sstevel@tonic-gate
3313371d72daSLubomir Sedlacik		sdiff_url="$(print $P.sdiff.html | url_encode)"
3314371d72daSLubomir Sedlacik		print "<a href=\"$sdiff_url\">Sdiffs</a>"
33157c478bd9Sstevel@tonic-gate
3316371d72daSLubomir Sedlacik		frames_url="$(print $P.frames.html | url_encode)"
3317371d72daSLubomir Sedlacik		print "<a href=\"$frames_url\">Frames</a>"
33187c478bd9Sstevel@tonic-gate	else
3319daaffb31Sdp		print " ------ ------ ------"
33207c478bd9Sstevel@tonic-gate
3321daaffb31Sdp		if [[ -x $WDIFF ]]; then
33227c478bd9Sstevel@tonic-gate			print " ------"
33237c478bd9Sstevel@tonic-gate		fi
3324daaffb31Sdp
3325daaffb31Sdp		print " ------"
33267c478bd9Sstevel@tonic-gate	fi
33277c478bd9Sstevel@tonic-gate
33287c478bd9Sstevel@tonic-gate	# If there's an old file, make the link
33297c478bd9Sstevel@tonic-gate
3330daaffb31Sdp	if [[ -f $F-.html ]]; then
3331371d72daSLubomir Sedlacik		oldfile_url="$(print $P-.html | url_encode)"
3332371d72daSLubomir Sedlacik		print "<a href=\"$oldfile_url\">Old</a>"
33337c478bd9Sstevel@tonic-gate	else
3334daaffb31Sdp		print " ---"
33357c478bd9Sstevel@tonic-gate	fi
33367c478bd9Sstevel@tonic-gate
33377c478bd9Sstevel@tonic-gate	# If there's an new file, make the link
33387c478bd9Sstevel@tonic-gate
3339daaffb31Sdp	if [[ -f $F.html ]]; then
3340371d72daSLubomir Sedlacik		newfile_url="$(print $P.html | url_encode)"
3341371d72daSLubomir Sedlacik		print "<a href=\"$newfile_url\">New</a>"
33427c478bd9Sstevel@tonic-gate	else
3343daaffb31Sdp		print " ---"
33447c478bd9Sstevel@tonic-gate	fi
33457c478bd9Sstevel@tonic-gate
3346daaffb31Sdp	if [[ -f $F.patch ]]; then
3347371d72daSLubomir Sedlacik		patch_url="$(print $P.patch | url_encode)"
3348371d72daSLubomir Sedlacik		print "<a href=\"$patch_url\">Patch</a>"
3349daaffb31Sdp	else
3350daaffb31Sdp		print " -----"
3351daaffb31Sdp	fi
3352daaffb31Sdp
3353daaffb31Sdp	if [[ -f $WDIR/raw_files/new/$P ]]; then
3354371d72daSLubomir Sedlacik		rawfiles_url="$(print raw_files/new/$P | url_encode)"
3355371d72daSLubomir Sedlacik		print "<a href=\"$rawfiles_url\">Raw</a>"
3356daaffb31Sdp	else
3357daaffb31Sdp		print " ---"
3358daaffb31Sdp	fi
3359daaffb31Sdp
3360cdf0c1d5Smjnelson	print "<b>$P</b>"
3361cdf0c1d5Smjnelson
3362cdf0c1d5Smjnelson	# For renamed files, clearly state whether or not they are modified
3363e6ccc173SEdward Pilatowicz	if [[ -f "$oldname" ]]; then
3364cdf0c1d5Smjnelson		if [[ -n "$mv_but_nodiff" ]]; then
3365e6ccc173SEdward Pilatowicz			print "<i>(copied from $oldname)</i>"
3366cdf0c1d5Smjnelson		else
3367e6ccc173SEdward Pilatowicz			print "<i>(copied and modified from $oldname)</i>"
3368e6ccc173SEdward Pilatowicz		fi
3369e6ccc173SEdward Pilatowicz	elif [[ -n "$oldname" ]]; then
3370e6ccc173SEdward Pilatowicz		if [[ -n "$mv_but_nodiff" ]]; then
3371e6ccc173SEdward Pilatowicz			print "<i>(renamed from $oldname)</i>"
3372e6ccc173SEdward Pilatowicz		else
3373e6ccc173SEdward Pilatowicz			print "<i>(renamed and modified from $oldname)</i>"
3374cdf0c1d5Smjnelson		fi
3375cdf0c1d5Smjnelson	fi
3376cdf0c1d5Smjnelson
3377cdf0c1d5Smjnelson	# If there's an old file, but no new file, the file was deleted
3378cdf0c1d5Smjnelson	if [[ -f $F-.html && ! -f $F.html ]]; then
3379cdf0c1d5Smjnelson		print " <i>(deleted)</i>"
3380cdf0c1d5Smjnelson	fi
3381daaffb31Sdp
3382daaffb31Sdp	#
3383e0e0293aSjmcp	# Check for usr/closed and deleted_files/usr/closed
3384daaffb31Sdp	#
3385daaffb31Sdp	if [ ! -z "$Oflag" ]; then
3386e0e0293aSjmcp		if [[ $P == usr/closed/* || \
3387e0e0293aSjmcp		    $P == deleted_files/usr/closed/* ]]; then
3388daaffb31Sdp			print "&nbsp;&nbsp;<i>Closed source: omitted from" \
3389daaffb31Sdp			    "this review</i>"
3390daaffb31Sdp		fi
3391daaffb31Sdp	fi
3392daaffb31Sdp
3393daaffb31Sdp	print "</p>"
33947c478bd9Sstevel@tonic-gate	# Insert delta comments
33957c478bd9Sstevel@tonic-gate
3396daaffb31Sdp	print "<blockquote><pre>"
3397daaffb31Sdp	getcomments html $P $PP
3398daaffb31Sdp	print "</pre>"
33997c478bd9Sstevel@tonic-gate
34007c478bd9Sstevel@tonic-gate	# Add additional comments comment
34017c478bd9Sstevel@tonic-gate
3402daaffb31Sdp	print "<!-- Add comments to explain changes in $P here -->"
34037c478bd9Sstevel@tonic-gate
34047c478bd9Sstevel@tonic-gate	# Add count of changes.
34057c478bd9Sstevel@tonic-gate
3406daaffb31Sdp	if [[ -f $F.count ]]; then
34077c478bd9Sstevel@tonic-gate	    cat $F.count
34087c478bd9Sstevel@tonic-gate	    rm $F.count
34097c478bd9Sstevel@tonic-gate	fi
3410cdf0c1d5Smjnelson
3411*d7b56f41SBart Coddens	if [[ $SCM_MODE == "mercurial" ||
3412cdf0c1d5Smjnelson	    $SCM_MODE == "unknown" ]]; then
3413cdf0c1d5Smjnelson
3414cdf0c1d5Smjnelson		# Include warnings for important file mode situations:
3415cdf0c1d5Smjnelson		# 1) New executable files
3416cdf0c1d5Smjnelson		# 2) Permission changes of any kind
3417cdf0c1d5Smjnelson		# 3) Existing executable files
3418cdf0c1d5Smjnelson
3419cdf0c1d5Smjnelson		old_mode=
3420cdf0c1d5Smjnelson		if [[ -f $WDIR/raw_files/old/$PP ]]; then
3421cdf0c1d5Smjnelson			old_mode=`get_file_mode $WDIR/raw_files/old/$PP`
3422cdf0c1d5Smjnelson		fi
3423cdf0c1d5Smjnelson
3424cdf0c1d5Smjnelson		new_mode=
3425cdf0c1d5Smjnelson		if [[ -f $WDIR/raw_files/new/$P ]]; then
3426cdf0c1d5Smjnelson			new_mode=`get_file_mode $WDIR/raw_files/new/$P`
3427cdf0c1d5Smjnelson		fi
3428cdf0c1d5Smjnelson
3429cdf0c1d5Smjnelson		if [[ -z "$old_mode" && "$new_mode" = *[1357]* ]]; then
3430cdf0c1d5Smjnelson			print "<span class=\"chmod\">"
3431cdf0c1d5Smjnelson			print "<p>new executable file: mode $new_mode</p>"
3432cdf0c1d5Smjnelson			print "</span>"
3433cdf0c1d5Smjnelson		elif [[ -n "$old_mode" && -n "$new_mode" &&
3434cdf0c1d5Smjnelson		    "$old_mode" != "$new_mode" ]]; then
3435cdf0c1d5Smjnelson			print "<span class=\"chmod\">"
3436cdf0c1d5Smjnelson			print "<p>mode change: $old_mode to $new_mode</p>"
3437cdf0c1d5Smjnelson			print "</span>"
3438cdf0c1d5Smjnelson		elif [[ "$new_mode" = *[1357]* ]]; then
3439cdf0c1d5Smjnelson			print "<span class=\"chmod\">"
3440cdf0c1d5Smjnelson			print "<p>executable file: mode $new_mode</p>"
3441cdf0c1d5Smjnelson			print "</span>"
3442cdf0c1d5Smjnelson		fi
3443cdf0c1d5Smjnelson	fi
3444cdf0c1d5Smjnelson
3445daaffb31Sdp	print "</blockquote>"
34467c478bd9Sstevel@tonic-gatedone
34477c478bd9Sstevel@tonic-gate
3448daaffb31Sdpprint
3449daaffb31Sdpprint
3450cac38512Smjnelsonprint "<hr></hr>"
3451daaffb31Sdpprint "<p style=\"font-size: small\">"
34529a70fc3bSMark J. Nelsonprint "This code review page was prepared using <b>$0</b>."
345387a4464eSChris Loveprint "Webrev is maintained by the <a href=\"http://www.illumos.org\">"
345487a4464eSChris Loveprint "illumos</a> project.  The latest version may be obtained"
34557646c8f3SMarcel Telkaprint "<a href=\"http://src.illumos.org/source/xref/illumos-gate/usr/src/tools/scripts/webrev.sh\">here</a>.</p>"
3456daaffb31Sdpprint "</body>"
3457daaffb31Sdpprint "</html>"
34587c478bd9Sstevel@tonic-gate
34597c478bd9Sstevel@tonic-gateexec 1<&-			# Close FD 1.
34607c478bd9Sstevel@tonic-gateexec 1<&3			# dup FD 3 to restore stdout.
34617c478bd9Sstevel@tonic-gateexec 3<&-			# close FD 3.
34627c478bd9Sstevel@tonic-gate
3463daaffb31Sdpprint "Done."
346402d26c39SVladimir Kotal
3465b0088928SVladimir Kotal#
3466ba44d8a2SVladimir Kotal# If remote deletion was specified and fails do not continue.
3467b0088928SVladimir Kotal#
3468ba44d8a2SVladimir Kotalif [[ -n $Dflag ]]; then
3469b0088928SVladimir Kotal	delete_webrev 1 1
3470ba44d8a2SVladimir Kotal	(( $? == 0 )) || exit $?
3471ba44d8a2SVladimir Kotalfi
3472ba44d8a2SVladimir Kotal
347302d26c39SVladimir Kotalif [[ -n $Uflag ]]; then
347402d26c39SVladimir Kotal	upload_webrev
347502d26c39SVladimir Kotal	exit $?
347602d26c39SVladimir Kotalfi
3477