xref: /titanic_53/usr/src/tools/scripts/webrev.sh (revision 2f54b716e4d3cb0dc99066638fed631e3cbec97c)
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
27*2f54b716SRichard Lowe# Copyright 2008, 2010, Richard Lowe
28*2f54b716SRichard Lowe
29cdf0c1d5Smjnelson#
30daaffb31Sdp# This script takes a file list and a workspace and builds a set of html files
31daaffb31Sdp# suitable for doing a code review of source changes via a web page.
32daaffb31Sdp# Documentation is available via the manual page, webrev.1, or just
33daaffb31Sdp# type 'webrev -h'.
347c478bd9Sstevel@tonic-gate#
35daaffb31Sdp# Acknowledgements to contributors to webrev are listed in the webrev(1)
36daaffb31Sdp# man page.
377c478bd9Sstevel@tonic-gate#
38daaffb31Sdp
397c478bd9Sstevel@tonic-gateREMOVED_COLOR=brown
407c478bd9Sstevel@tonic-gateCHANGED_COLOR=blue
417c478bd9Sstevel@tonic-gateNEW_COLOR=blue
427c478bd9Sstevel@tonic-gate
43daaffb31SdpHTML='<?xml version="1.0"?>
44daaffb31Sdp<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
45daaffb31Sdp    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
46daaffb31Sdp<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">\n'
47daaffb31Sdp
48daaffb31SdpFRAMEHTML='<?xml version="1.0"?>
49daaffb31Sdp<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"
50daaffb31Sdp    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
51daaffb31Sdp<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">\n'
52daaffb31Sdp
53cac38512SmjnelsonSTDHEAD='<meta http-equiv="cache-control" content="no-cache"></meta>
54cac38512Smjnelson<meta http-equiv="Pragma" content="no-cache"></meta>
55cac38512Smjnelson<meta http-equiv="Expires" content="-1"></meta>
56daaffb31Sdp<!--
57daaffb31Sdp   Note to customizers: the body of the webrev is IDed as SUNWwebrev
58daaffb31Sdp   to allow easy overriding by users of webrev via the userContent.css
59daaffb31Sdp   mechanism available in some browsers.
60daaffb31Sdp
61daaffb31Sdp   For example, to have all "removed" information be red instead of
62daaffb31Sdp   brown, set a rule in your userContent.css file like:
63daaffb31Sdp
64daaffb31Sdp       body#SUNWwebrev span.removed { color: red ! important; }
65daaffb31Sdp-->
66daaffb31Sdp<style type="text/css" media="screen">
67daaffb31Sdpbody {
68daaffb31Sdp    background-color: #eeeeee;
69daaffb31Sdp}
70daaffb31Sdphr {
71daaffb31Sdp    border: none 0;
72daaffb31Sdp    border-top: 1px solid #aaa;
73daaffb31Sdp    height: 1px;
74daaffb31Sdp}
75daaffb31Sdpdiv.summary {
76daaffb31Sdp    font-size: .8em;
77daaffb31Sdp    border-bottom: 1px solid #aaa;
78daaffb31Sdp    padding-left: 1em;
79daaffb31Sdp    padding-right: 1em;
80daaffb31Sdp}
81daaffb31Sdpdiv.summary h2 {
82daaffb31Sdp    margin-bottom: 0.3em;
83daaffb31Sdp}
84daaffb31Sdpdiv.summary table th {
85daaffb31Sdp    text-align: right;
86daaffb31Sdp    vertical-align: top;
87daaffb31Sdp    white-space: nowrap;
88daaffb31Sdp}
89daaffb31Sdpspan.lineschanged {
90daaffb31Sdp    font-size: 0.7em;
91daaffb31Sdp}
92daaffb31Sdpspan.oldmarker {
93daaffb31Sdp    color: red;
94daaffb31Sdp    font-size: large;
95daaffb31Sdp    font-weight: bold;
96daaffb31Sdp}
97daaffb31Sdpspan.newmarker {
98daaffb31Sdp    color: green;
99daaffb31Sdp    font-size: large;
100daaffb31Sdp    font-weight: bold;
101daaffb31Sdp}
102daaffb31Sdpspan.removed {
103daaffb31Sdp    color: brown;
104daaffb31Sdp}
105daaffb31Sdpspan.changed {
106daaffb31Sdp    color: blue;
107daaffb31Sdp}
108daaffb31Sdpspan.new {
109daaffb31Sdp    color: blue;
110daaffb31Sdp    font-weight: bold;
111daaffb31Sdp}
112cdf0c1d5Smjnelsonspan.chmod {
113cdf0c1d5Smjnelson    font-size: 0.7em;
114cdf0c1d5Smjnelson    color: #db7800;
115cdf0c1d5Smjnelson}
116daaffb31Sdpa.print { font-size: x-small; }
117daaffb31Sdpa:hover { background-color: #ffcc99; }
118daaffb31Sdp</style>
119daaffb31Sdp
120daaffb31Sdp<style type="text/css" media="print">
121daaffb31Sdppre { font-size: 0.8em; font-family: courier, monospace; }
122daaffb31Sdpspan.removed { color: #444; font-style: italic }
123daaffb31Sdpspan.changed { font-weight: bold; }
124daaffb31Sdpspan.new { font-weight: bold; }
125daaffb31Sdpspan.newmarker { font-size: 1.2em; font-weight: bold; }
126daaffb31Sdpspan.oldmarker { font-size: 1.2em; font-weight: bold; }
127daaffb31Sdpa.print {display: none}
128daaffb31Sdphr { border: none 0; border-top: 1px solid #aaa; height: 1px; }
129daaffb31Sdp</style>
130daaffb31Sdp'
131daaffb31Sdp
132daaffb31Sdp#
133daaffb31Sdp# UDiffs need a slightly different CSS rule for 'new' items (we don't
134daaffb31Sdp# want them to be bolded as we do in cdiffs or sdiffs).
135daaffb31Sdp#
136daaffb31SdpUDIFFCSS='
137daaffb31Sdp<style type="text/css" media="screen">
138daaffb31Sdpspan.new {
139daaffb31Sdp    color: blue;
140daaffb31Sdp    font-weight: normal;
141daaffb31Sdp}
142daaffb31Sdp</style>
143daaffb31Sdp'
144daaffb31Sdp
145b0088928SVladimir Kotal#
146b0088928SVladimir Kotal# Display remote target with prefix and trailing slash.
147b0088928SVladimir Kotal#
148b0088928SVladimir Kotalfunction print_upload_header
149b0088928SVladimir Kotal{
150b0088928SVladimir Kotal	typeset -r prefix=$1
151b0088928SVladimir Kotal	typeset display_target
152b0088928SVladimir Kotal
153b0088928SVladimir Kotal	if [[ -z $tflag ]]; then
154b0088928SVladimir Kotal		display_target=${prefix}${remote_target}
155b0088928SVladimir Kotal	else
156b0088928SVladimir Kotal		display_target=${remote_target}
157b0088928SVladimir Kotal	fi
158b0088928SVladimir Kotal
159b0088928SVladimir Kotal	if [[ ${display_target} != */ ]]; then
160b0088928SVladimir Kotal		display_target=${display_target}/
161b0088928SVladimir Kotal	fi
162b0088928SVladimir Kotal
163b0088928SVladimir Kotal	print "      Upload to: ${display_target}\n" \
164b0088928SVladimir Kotal	    "     Uploading: \c"
165b0088928SVladimir Kotal}
166b0088928SVladimir Kotal
167b0088928SVladimir Kotal#
16802d26c39SVladimir Kotal# Upload the webrev via rsync. Return 0 on success, 1 on error.
169b0088928SVladimir Kotal#
170ba44d8a2SVladimir Kotalfunction rsync_upload
17102d26c39SVladimir Kotal{
172b0088928SVladimir Kotal	if (( $# != 2 )); then
173b0088928SVladimir Kotal		print "\nERROR: rsync_upload: wrong usage ($#)"
174b0088928SVladimir Kotal		exit 1
17502d26c39SVladimir Kotal	fi
17602d26c39SVladimir Kotal
177b0088928SVladimir Kotal	typeset -r dst=$1
178b0088928SVladimir Kotal	integer -r print_err_msg=$2
17902d26c39SVladimir Kotal
180b0088928SVladimir Kotal	print_upload_header ${rsync_prefix}
181b0088928SVladimir Kotal	print "rsync ... \c"
1828a34f8dcSVladimir Kotal	typeset -r err_msg=$( $MKTEMP /tmp/rsync_err.XXXXXX )
183b0088928SVladimir Kotal	if [[ -z $err_msg ]]; then
184b0088928SVladimir Kotal		print "\nERROR: rsync_upload: cannot create temporary file"
185b0088928SVladimir Kotal		return 1
186b0088928SVladimir Kotal	fi
187b0088928SVladimir Kotal	#
188b0088928SVladimir Kotal	# The source directory must end with a slash in order to copy just
189b0088928SVladimir Kotal	# directory contents, not the whole directory.
190b0088928SVladimir Kotal	#
191b0088928SVladimir Kotal	typeset src_dir=$WDIR
192b0088928SVladimir Kotal	if [[ ${src_dir} != */ ]]; then
193b0088928SVladimir Kotal		src_dir=${src_dir}/
194b0088928SVladimir Kotal	fi
195b0088928SVladimir Kotal	$RSYNC -r -q ${src_dir} $dst 2>$err_msg
19602d26c39SVladimir Kotal	if (( $? != 0 )); then
197b0088928SVladimir Kotal		if (( ${print_err_msg} > 0 )); then
198b0088928SVladimir Kotal			print "Failed.\nERROR: rsync failed"
199b0088928SVladimir Kotal			print "src dir: '${src_dir}'\ndst dir: '$dst'"
200b0088928SVladimir Kotal			print "error messages:"
201b0088928SVladimir Kotal			$SED 's/^/> /' $err_msg
202b0088928SVladimir Kotal			rm -f $err_msg
203b0088928SVladimir Kotal		fi
20402d26c39SVladimir Kotal		return 1
20502d26c39SVladimir Kotal	fi
20602d26c39SVladimir Kotal
207b0088928SVladimir Kotal	rm -f $err_msg
20802d26c39SVladimir Kotal	print "Done."
20902d26c39SVladimir Kotal	return 0
21002d26c39SVladimir Kotal}
21102d26c39SVladimir Kotal
212b0088928SVladimir Kotal#
213b0088928SVladimir Kotal# Create directories on remote host using SFTP. Return 0 on success,
214b0088928SVladimir Kotal# 1 on failure.
215b0088928SVladimir Kotal#
216b0088928SVladimir Kotalfunction remote_mkdirs
217b0088928SVladimir Kotal{
218b0088928SVladimir Kotal	typeset -r dir_spec=$1
2199d3952abSVladimir Kotal	typeset -r host_spec=$2
220b0088928SVladimir Kotal
221b0088928SVladimir Kotal	#
222b0088928SVladimir Kotal	# If the supplied path is absolute we assume all directories are
223b0088928SVladimir Kotal	# created, otherwise try to create all directories in the path
224b0088928SVladimir Kotal	# except the last one which will be created by scp.
225b0088928SVladimir Kotal	#
226b0088928SVladimir Kotal	if [[ "${dir_spec}" == */* && "${dir_spec}" != /* ]]; then
227b0088928SVladimir Kotal		print "mkdirs \c"
228b0088928SVladimir Kotal		#
229b0088928SVladimir Kotal		# Remove the last directory from directory specification.
230b0088928SVladimir Kotal		#
231b0088928SVladimir Kotal		typeset -r dirs_mk=${dir_spec%/*}
2328a34f8dcSVladimir Kotal		typeset -r batch_file_mkdir=$( $MKTEMP \
2338a34f8dcSVladimir Kotal		    /tmp/webrev_mkdir.XXXXXX )
234b0088928SVladimir Kotal		if [[ -z $batch_file_mkdir ]]; then
235b0088928SVladimir Kotal			print "\nERROR: remote_mkdirs:" \
236b0088928SVladimir Kotal			    "cannot create temporary file for batch file"
237b0088928SVladimir Kotal			return 1
238b0088928SVladimir Kotal		fi
239b0088928SVladimir Kotal                OLDIFS=$IFS
240b0088928SVladimir Kotal                IFS=/
241b0088928SVladimir Kotal		typeset dir
242b0088928SVladimir Kotal                for dir in ${dirs_mk}; do
243b0088928SVladimir Kotal			#
244b0088928SVladimir Kotal			# Use the '-' prefix to ignore mkdir errors in order
245b0088928SVladimir Kotal			# to avoid an error in case the directory already
246b0088928SVladimir Kotal			# exists. We check the directory with chdir to be sure
247b0088928SVladimir Kotal			# there is one.
248b0088928SVladimir Kotal			#
249b0088928SVladimir Kotal                        print -- "-mkdir ${dir}" >> ${batch_file_mkdir}
250b0088928SVladimir Kotal                        print "chdir ${dir}" >> ${batch_file_mkdir}
251b0088928SVladimir Kotal                done
252b0088928SVladimir Kotal                IFS=$OLDIFS
2538a34f8dcSVladimir Kotal		typeset -r sftp_err_msg=$( $MKTEMP /tmp/webrev_scp_err.XXXXXX )
254b0088928SVladimir Kotal		if [[ -z ${sftp_err_msg} ]]; then
255b0088928SVladimir Kotal			print "\nERROR: remote_mkdirs:" \
256b0088928SVladimir Kotal			    "cannot create temporary file for error messages"
257b0088928SVladimir Kotal			return 1
258b0088928SVladimir Kotal		fi
259b0088928SVladimir Kotal		$SFTP -b ${batch_file_mkdir} ${host_spec} 2>${sftp_err_msg} 1>&2
260b0088928SVladimir Kotal		if (( $? != 0 )); then
261b0088928SVladimir Kotal			print "\nERROR: failed to create remote directories"
262b0088928SVladimir Kotal			print "error messages:"
263b0088928SVladimir Kotal			$SED 's/^/> /' ${sftp_err_msg}
264b0088928SVladimir Kotal			rm -f ${sftp_err_msg} ${batch_file_mkdir}
265b0088928SVladimir Kotal			return 1
266b0088928SVladimir Kotal		fi
267b0088928SVladimir Kotal		rm -f ${sftp_err_msg} ${batch_file_mkdir}
268b0088928SVladimir Kotal	fi
269b0088928SVladimir Kotal
270b0088928SVladimir Kotal	return 0
271b0088928SVladimir Kotal}
272b0088928SVladimir Kotal
273b0088928SVladimir Kotal#
27402d26c39SVladimir Kotal# Upload the webrev via SSH. Return 0 on success, 1 on error.
275b0088928SVladimir Kotal#
276ba44d8a2SVladimir Kotalfunction ssh_upload
27702d26c39SVladimir Kotal{
27802d26c39SVladimir Kotal	if (( $# != 1 )); then
279b0088928SVladimir Kotal		print "\nERROR: ssh_upload: wrong number of arguments"
280b0088928SVladimir Kotal		exit 1
28102d26c39SVladimir Kotal	fi
28202d26c39SVladimir Kotal
28302d26c39SVladimir Kotal	typeset dst=$1
28402d26c39SVladimir Kotal	typeset -r host_spec=${dst%%:*}
285ba44d8a2SVladimir Kotal	typeset -r dir_spec=${dst#*:}
28602d26c39SVladimir Kotal
287b0088928SVladimir Kotal	#
288b0088928SVladimir Kotal	# Display the upload information before calling delete_webrev
289b0088928SVladimir Kotal	# because it will also print its progress.
290b0088928SVladimir Kotal	#
291b0088928SVladimir Kotal	print_upload_header ${ssh_prefix}
292b0088928SVladimir Kotal
293b0088928SVladimir Kotal	#
294b0088928SVladimir Kotal	# If the deletion was explicitly requested there is no need
295b0088928SVladimir Kotal	# to perform it again.
296b0088928SVladimir Kotal	#
297ba44d8a2SVladimir Kotal	if [[ -z $Dflag ]]; then
298b0088928SVladimir Kotal		#
299b0088928SVladimir Kotal		# We do not care about return value because this might be
300b0088928SVladimir Kotal		# the first time this directory is uploaded.
301b0088928SVladimir Kotal		#
302ba44d8a2SVladimir Kotal		delete_webrev 0
30302d26c39SVladimir Kotal	fi
30402d26c39SVladimir Kotal
305b0088928SVladimir Kotal	#
306b0088928SVladimir Kotal	# Create remote directories. Any error reporting will be done
307b0088928SVladimir Kotal	# in remote_mkdirs function.
308b0088928SVladimir Kotal	#
3099d3952abSVladimir Kotal	remote_mkdirs ${dir_spec} ${host_spec}
31002d26c39SVladimir Kotal	if (( $? != 0 )); then
31102d26c39SVladimir Kotal		return 1
31202d26c39SVladimir Kotal	fi
31302d26c39SVladimir Kotal
314b0088928SVladimir Kotal	print "upload ... \c"
3158a34f8dcSVladimir Kotal	typeset -r scp_err_msg=$( $MKTEMP /tmp/scp_err.XXXXXX )
316b0088928SVladimir Kotal	if [[ -z ${scp_err_msg} ]]; then
317b0088928SVladimir Kotal		print "\nERROR: ssh_upload:" \
318b0088928SVladimir Kotal		    "cannot create temporary file for error messages"
319b0088928SVladimir Kotal		return 1
320b0088928SVladimir Kotal	fi
32102d26c39SVladimir Kotal	$SCP -q -C -B -o PreferredAuthentications=publickey -r \
322b0088928SVladimir Kotal		$WDIR $dst 2>${scp_err_msg}
32302d26c39SVladimir Kotal	if (( $? != 0 )); then
324b0088928SVladimir Kotal		print "Failed.\nERROR: scp failed"
325b0088928SVladimir Kotal		print "src dir: '$WDIR'\ndst dir: '$dst'"
326b0088928SVladimir Kotal		print "error messages:"
327b0088928SVladimir Kotal		$SED 's/^/> /' ${scp_err_msg}
328b0088928SVladimir Kotal		rm -f ${scp_err_msg}
32902d26c39SVladimir Kotal		return 1
33002d26c39SVladimir Kotal	fi
33102d26c39SVladimir Kotal
332b0088928SVladimir Kotal	rm -f ${scp_err_msg}
33302d26c39SVladimir Kotal	print "Done."
33402d26c39SVladimir Kotal	return 0
33502d26c39SVladimir Kotal}
33602d26c39SVladimir Kotal
33702d26c39SVladimir Kotal#
338ba44d8a2SVladimir Kotal# Delete webrev at remote site. Return 0 on success, 1 or exit code from sftp
339b0088928SVladimir Kotal# on failure. If first argument is 1 then perform the check of sftp return
340b0088928SVladimir Kotal# value otherwise ignore it. If second argument is present it means this run
341b0088928SVladimir Kotal# only performs deletion.
342ba44d8a2SVladimir Kotal#
343ba44d8a2SVladimir Kotalfunction delete_webrev
344ba44d8a2SVladimir Kotal{
345b0088928SVladimir Kotal	if (( $# < 1 )); then
346b0088928SVladimir Kotal		print "delete_webrev: wrong number of arguments"
347b0088928SVladimir Kotal		exit 1
348ba44d8a2SVladimir Kotal	fi
349ba44d8a2SVladimir Kotal
350b0088928SVladimir Kotal	integer -r check=$1
351b0088928SVladimir Kotal	integer delete_only=0
352b0088928SVladimir Kotal	if (( $# == 2 )); then
353b0088928SVladimir Kotal		delete_only=1
354b0088928SVladimir Kotal	fi
355b0088928SVladimir Kotal
356b0088928SVladimir Kotal	#
357ba44d8a2SVladimir Kotal	# Strip the transport specification part of remote target first.
358b0088928SVladimir Kotal	#
359ba44d8a2SVladimir Kotal	typeset -r stripped_target=${remote_target##*://}
360ba44d8a2SVladimir Kotal	typeset -r host_spec=${stripped_target%%:*}
361ba44d8a2SVladimir Kotal	typeset -r dir_spec=${stripped_target#*:}
362ba44d8a2SVladimir Kotal	typeset dir_rm
363ba44d8a2SVladimir Kotal
364b0088928SVladimir Kotal	#
365ba44d8a2SVladimir Kotal	# Do not accept an absolute path.
366b0088928SVladimir Kotal	#
367ba44d8a2SVladimir Kotal	if [[ ${dir_spec} == /* ]]; then
368ba44d8a2SVladimir Kotal		return 1
369ba44d8a2SVladimir Kotal	fi
370ba44d8a2SVladimir Kotal
371b0088928SVladimir Kotal	#
372ba44d8a2SVladimir Kotal	# Strip the ending slash.
373b0088928SVladimir Kotal	#
374ba44d8a2SVladimir Kotal	if [[ ${dir_spec} == */ ]]; then
375ba44d8a2SVladimir Kotal		dir_rm=${dir_spec%%/}
376ba44d8a2SVladimir Kotal	else
377ba44d8a2SVladimir Kotal		dir_rm=${dir_spec}
378ba44d8a2SVladimir Kotal	fi
379ba44d8a2SVladimir Kotal
380b0088928SVladimir Kotal	if (( ${delete_only} > 0 )); then
381b0088928SVladimir Kotal		print "       Removing: \c"
382b0088928SVladimir Kotal	else
383b0088928SVladimir Kotal		print "rmdir \c"
384b0088928SVladimir Kotal	fi
385ba44d8a2SVladimir Kotal	if [[ -z "$dir_rm" ]]; then
386b0088928SVladimir Kotal		print "\nERROR: empty directory for removal"
387ba44d8a2SVladimir Kotal		return 1
388ba44d8a2SVladimir Kotal	fi
389ba44d8a2SVladimir Kotal
390b0088928SVladimir Kotal	#
391ba44d8a2SVladimir Kotal	# Prepare batch file.
392b0088928SVladimir Kotal	#
3938a34f8dcSVladimir Kotal	typeset -r batch_file_rm=$( $MKTEMP /tmp/webrev_remove.XXXXXX )
394ba44d8a2SVladimir Kotal	if [[ -z $batch_file_rm ]]; then
395b0088928SVladimir Kotal		print "\nERROR: delete_webrev: cannot create temporary file"
396ba44d8a2SVladimir Kotal		return 1
397ba44d8a2SVladimir Kotal	fi
398ba44d8a2SVladimir Kotal	print "rename $dir_rm $TRASH_DIR/removed.$$" > $batch_file_rm
399ba44d8a2SVladimir Kotal
400b0088928SVladimir Kotal	#
401ba44d8a2SVladimir Kotal	# Perform remote deletion and remove the batch file.
402b0088928SVladimir Kotal	#
4038a34f8dcSVladimir Kotal	typeset -r sftp_err_msg=$( $MKTEMP /tmp/webrev_scp_err.XXXXXX )
404b0088928SVladimir Kotal	if [[ -z ${sftp_err_msg} ]]; then
405b0088928SVladimir Kotal		print "\nERROR: delete_webrev:" \
406b0088928SVladimir Kotal		    "cannot create temporary file for error messages"
407b0088928SVladimir Kotal		return 1
408b0088928SVladimir Kotal	fi
409b0088928SVladimir Kotal	$SFTP -b $batch_file_rm $host_spec 2>${sftp_err_msg} 1>&2
410ba44d8a2SVladimir Kotal	integer -r ret=$?
411ba44d8a2SVladimir Kotal	rm -f $batch_file_rm
412ba44d8a2SVladimir Kotal	if (( $ret != 0 && $check > 0 )); then
413b0088928SVladimir Kotal		print "Failed.\nERROR: failed to remove remote directories"
414b0088928SVladimir Kotal		print "error messages:"
415b0088928SVladimir Kotal		$SED 's/^/> /' ${sftp_err_msg}
416b0088928SVladimir Kotal		rm -f ${sftp_err_msg}
417ba44d8a2SVladimir Kotal		return $ret
418ba44d8a2SVladimir Kotal	fi
419b0088928SVladimir Kotal	rm -f ${sftp_err_msg}
420b0088928SVladimir Kotal	if (( ${delete_only} > 0 )); then
421ba44d8a2SVladimir Kotal		print "Done."
422b0088928SVladimir Kotal	fi
423ba44d8a2SVladimir Kotal
424ba44d8a2SVladimir Kotal	return 0
425ba44d8a2SVladimir Kotal}
426ba44d8a2SVladimir Kotal
427ba44d8a2SVladimir Kotal#
42802d26c39SVladimir Kotal# Upload webrev to remote site
42902d26c39SVladimir Kotal#
430ba44d8a2SVladimir Kotalfunction upload_webrev
43102d26c39SVladimir Kotal{
432b0088928SVladimir Kotal	integer ret
43302d26c39SVladimir Kotal
43402d26c39SVladimir Kotal	if [[ ! -d "$WDIR" ]]; then
435b0088928SVladimir Kotal		print "\nERROR: webrev directory '$WDIR' does not exist"
43602d26c39SVladimir Kotal		return 1
43702d26c39SVladimir Kotal	fi
43802d26c39SVladimir Kotal
439b0088928SVladimir Kotal	#
44002d26c39SVladimir Kotal	# Perform a late check to make sure we do not upload closed source
44102d26c39SVladimir Kotal	# to remote target when -n is used. If the user used custom remote
44202d26c39SVladimir Kotal	# target he probably knows what he is doing.
443b0088928SVladimir Kotal	#
44402d26c39SVladimir Kotal	if [[ -n $nflag && -z $tflag ]]; then
445ba44d8a2SVladimir Kotal		$FIND $WDIR -type d -name closed \
44602d26c39SVladimir Kotal			| $GREP closed >/dev/null
44702d26c39SVladimir Kotal		if (( $? == 0 )); then
448b0088928SVladimir Kotal			print "\nERROR: directory '$WDIR' contains" \
449b0088928SVladimir Kotal			    "\"closed\" directory"
45002d26c39SVladimir Kotal			return 1
45102d26c39SVladimir Kotal		fi
45202d26c39SVladimir Kotal	fi
45302d26c39SVladimir Kotal
454b0088928SVladimir Kotal
455b0088928SVladimir Kotal	#
456b0088928SVladimir Kotal	# We have the URI for remote destination now so let's start the upload.
457b0088928SVladimir Kotal	#
45802d26c39SVladimir Kotal	if [[ -n $tflag ]]; then
45902d26c39SVladimir Kotal		if [[ "${remote_target}" == ${rsync_prefix}?* ]]; then
460b0088928SVladimir Kotal			rsync_upload ${remote_target##$rsync_prefix} 1
461b0088928SVladimir Kotal			ret=$?
462b0088928SVladimir Kotal			return $ret
46302d26c39SVladimir Kotal		elif [[ "${remote_target}" == ${ssh_prefix}?* ]]; then
46402d26c39SVladimir Kotal			ssh_upload ${remote_target##$ssh_prefix}
465b0088928SVladimir Kotal			ret=$?
466b0088928SVladimir Kotal			return $ret
46702d26c39SVladimir Kotal		fi
46802d26c39SVladimir Kotal	else
469b0088928SVladimir Kotal		#
470b0088928SVladimir Kotal		# Try rsync first and fallback to SSH in case it fails.
471b0088928SVladimir Kotal		#
472b0088928SVladimir Kotal		rsync_upload ${remote_target} 0
473b0088928SVladimir Kotal		ret=$?
474b0088928SVladimir Kotal		if (( $ret != 0 )); then
475b0088928SVladimir Kotal			print "Failed. (falling back to SSH)"
476ba44d8a2SVladimir Kotal			ssh_upload ${remote_target}
477b0088928SVladimir Kotal			ret=$?
47802d26c39SVladimir Kotal		fi
479b0088928SVladimir Kotal		return $ret
48002d26c39SVladimir Kotal	fi
48102d26c39SVladimir Kotal}
48202d26c39SVladimir Kotal
483daaffb31Sdp#
484371d72daSLubomir Sedlacik# input_cmd | url_encode | output_cmd
485371d72daSLubomir Sedlacik#
486371d72daSLubomir Sedlacik# URL-encode (percent-encode) reserved characters as defined in RFC 3986.
487371d72daSLubomir Sedlacik#
488371d72daSLubomir Sedlacik# Reserved characters are: :/?#[]@!$&'()*+,;=
489371d72daSLubomir Sedlacik#
490371d72daSLubomir Sedlacik# While not a reserved character itself, percent '%' is reserved by definition
491371d72daSLubomir Sedlacik# so encode it first to avoid recursive transformation, and skip '/' which is
492371d72daSLubomir Sedlacik# a path delimiter.
493371d72daSLubomir Sedlacik#
49425cc4e45SVladimir Kotal# The quotation character is deliberately not escaped in order to make
49525cc4e45SVladimir Kotal# the substitution work with GNU sed.
49625cc4e45SVladimir Kotal#
497371d72daSLubomir Sedlacikfunction url_encode
498371d72daSLubomir Sedlacik{
499b0088928SVladimir Kotal	$SED -e "s|%|%25|g" -e "s|:|%3A|g" -e "s|\&|%26|g" \
500371d72daSLubomir Sedlacik	    -e "s|?|%3F|g" -e "s|#|%23|g" -e "s|\[|%5B|g" \
501371d72daSLubomir Sedlacik	    -e "s|*|%2A|g" -e "s|@|%40|g" -e "s|\!|%21|g" \
502371d72daSLubomir Sedlacik	    -e "s|=|%3D|g" -e "s|;|%3B|g" -e "s|\]|%5D|g" \
50325cc4e45SVladimir Kotal	    -e "s|(|%28|g" -e "s|)|%29|g" -e "s|'|%27|g" \
504371d72daSLubomir Sedlacik	    -e "s|+|%2B|g" -e "s|\,|%2C|g" -e "s|\\\$|%24|g"
505371d72daSLubomir Sedlacik}
506371d72daSLubomir Sedlacik
507371d72daSLubomir Sedlacik#
508daaffb31Sdp# input_cmd | html_quote | output_cmd
509daaffb31Sdp# or
510daaffb31Sdp# html_quote filename | output_cmd
5117c478bd9Sstevel@tonic-gate#
5127c478bd9Sstevel@tonic-gate# Make a piece of source code safe for display in an HTML <pre> block.
5137c478bd9Sstevel@tonic-gate#
5147c478bd9Sstevel@tonic-gatehtml_quote()
5157c478bd9Sstevel@tonic-gate{
516b0088928SVladimir Kotal	$SED -e "s/&/\&amp;/g" -e "s/</\&lt;/g" -e "s/>/\&gt;/g" "$@" | expand
5177c478bd9Sstevel@tonic-gate}
5187c478bd9Sstevel@tonic-gate
519daaffb31Sdp#
5200fd2682eSMark J. Nelson# input_cmd | its2url | output_cmd
521daaffb31Sdp#
5220fd2682eSMark J. Nelson# Scan for information tracking system references and insert <a> links to the
5230fd2682eSMark J. Nelson# relevant databases.
524daaffb31Sdp#
5250fd2682eSMark J. Nelsonits2url()
5267c478bd9Sstevel@tonic-gate{
5270fd2682eSMark J. Nelson	$SED -f ${its_sed_script}
528daaffb31Sdp}
529daaffb31Sdp
5307c478bd9Sstevel@tonic-gate#
531daaffb31Sdp# strip_unchanged <infile> | output_cmd
5327c478bd9Sstevel@tonic-gate#
533daaffb31Sdp# Removes chunks of sdiff documents that have not changed. This makes it
534daaffb31Sdp# easier for a code reviewer to find the bits that have changed.
5357c478bd9Sstevel@tonic-gate#
536daaffb31Sdp# Deleted lines of text are replaced by a horizontal rule. Some
537daaffb31Sdp# identical lines are retained before and after the changed lines to
538daaffb31Sdp# provide some context.  The number of these lines is controlled by the
539cdf0c1d5Smjnelson# variable C in the $AWK script below.
540daaffb31Sdp#
541daaffb31Sdp# The script detects changed lines as any line that has a "<span class="
542daaffb31Sdp# string embedded (unchanged lines have no particular class and are not
543daaffb31Sdp# part of a <span>).  Blank lines (without a sequence number) are also
544daaffb31Sdp# detected since they flag lines that have been inserted or deleted.
545daaffb31Sdp#
546daaffb31Sdpstrip_unchanged()
547daaffb31Sdp{
548cdf0c1d5Smjnelson	$AWK '
549daaffb31Sdp	BEGIN	{ C = c = 20 }
550cdf0c1d5Smjnelson	NF == 0 || /<span class="/ {
551daaffb31Sdp		if (c > C) {
552daaffb31Sdp			c -= C
553daaffb31Sdp			inx = 0
554daaffb31Sdp			if (c > C) {
555cac38512Smjnelson				print "\n</pre><hr></hr><pre>"
556daaffb31Sdp				inx = c % C
557daaffb31Sdp				c = C
558daaffb31Sdp			}
559daaffb31Sdp
560daaffb31Sdp			for (i = 0; i < c; i++)
561daaffb31Sdp				print ln[(inx + i) % C]
562daaffb31Sdp		}
563daaffb31Sdp		c = 0;
564daaffb31Sdp		print
565daaffb31Sdp		next
566daaffb31Sdp	}
567daaffb31Sdp	{	if (c >= C) {
568daaffb31Sdp			ln[c % C] = $0
569daaffb31Sdp			c++;
570daaffb31Sdp			next;
571daaffb31Sdp		}
572daaffb31Sdp		c++;
573daaffb31Sdp		print
574daaffb31Sdp	}
575cac38512Smjnelson	END	{ if (c > (C * 2)) print "\n</pre><hr></hr>" }
576daaffb31Sdp
577daaffb31Sdp	' $1
578daaffb31Sdp}
579daaffb31Sdp
580daaffb31Sdp#
581daaffb31Sdp# sdiff_to_html
582daaffb31Sdp#
583daaffb31Sdp# This function takes two files as arguments, obtains their diff, and
584daaffb31Sdp# processes the diff output to present the files as an HTML document with
585daaffb31Sdp# the files displayed side-by-side, differences shown in color.  It also
586daaffb31Sdp# takes a delta comment, rendered as an HTML snippet, as the third
587daaffb31Sdp# argument.  The function takes two files as arguments, then the name of
588daaffb31Sdp# file, the path, and the comment.  The HTML will be delivered on stdout,
589daaffb31Sdp# e.g.
590daaffb31Sdp#
591daaffb31Sdp#   $ sdiff_to_html old/usr/src/tools/scripts/webrev.sh \
592daaffb31Sdp#         new/usr/src/tools/scripts/webrev.sh \
593daaffb31Sdp#         webrev.sh usr/src/tools/scripts \
594daaffb31Sdp#         '<a href="http://monaco.sfbay.sun.com/detail.jsp?cr=1234567">
595daaffb31Sdp#          1234567</a> my bugid' > <file>.html
596daaffb31Sdp#
597daaffb31Sdp# framed_sdiff() is then called which creates $2.frames.html
598daaffb31Sdp# in the webrev tree.
599daaffb31Sdp#
600daaffb31Sdp# FYI: This function is rather unusual in its use of awk.  The initial
601daaffb31Sdp# diff run produces conventional diff output showing changed lines mixed
602daaffb31Sdp# with editing codes.  The changed lines are ignored - we're interested in
603daaffb31Sdp# the editing codes, e.g.
6047c478bd9Sstevel@tonic-gate#
6057c478bd9Sstevel@tonic-gate#      8c8
6067c478bd9Sstevel@tonic-gate#      57a61
6077c478bd9Sstevel@tonic-gate#      63c66,76
6087c478bd9Sstevel@tonic-gate#      68,93d80
6097c478bd9Sstevel@tonic-gate#      106d90
6107c478bd9Sstevel@tonic-gate#      108,110d91
6117c478bd9Sstevel@tonic-gate#
612daaffb31Sdp#  These editing codes are parsed by the awk script and used to generate
613daaffb31Sdp#  another awk script that generates HTML, e.g the above lines would turn
614daaffb31Sdp#  into something like this:
6157c478bd9Sstevel@tonic-gate#
6167c478bd9Sstevel@tonic-gate#      BEGIN { printf "<pre>\n" }
6177c478bd9Sstevel@tonic-gate#      function sp(n) {for (i=0;i<n;i++)printf "\n"}
618daaffb31Sdp#      function wl(n) {printf "<font color=%s>%4d %s </font>\n", n, NR, $0}
6197c478bd9Sstevel@tonic-gate#      NR==8           {wl("#7A7ADD");next}
6207c478bd9Sstevel@tonic-gate#      NR==54          {wl("#7A7ADD");sp(3);next}
6217c478bd9Sstevel@tonic-gate#      NR==56          {wl("#7A7ADD");next}
6227c478bd9Sstevel@tonic-gate#      NR==57          {wl("black");printf "\n"; next}
6237c478bd9Sstevel@tonic-gate#        :               :
6247c478bd9Sstevel@tonic-gate#
625daaffb31Sdp#  This script is then run on the original source file to generate the
626daaffb31Sdp#  HTML that corresponds to the source file.
6277c478bd9Sstevel@tonic-gate#
628daaffb31Sdp#  The two HTML files are then combined into a single piece of HTML that
629daaffb31Sdp#  uses an HTML table construct to present the files side by side.  You'll
630daaffb31Sdp#  notice that the changes are color-coded:
6317c478bd9Sstevel@tonic-gate#
6327c478bd9Sstevel@tonic-gate#   black     - unchanged lines
6337c478bd9Sstevel@tonic-gate#   blue      - changed lines
6347c478bd9Sstevel@tonic-gate#   bold blue - new lines
6357c478bd9Sstevel@tonic-gate#   brown     - deleted lines
6367c478bd9Sstevel@tonic-gate#
637daaffb31Sdp#  Blank lines are inserted in each file to keep unchanged lines in sync
638daaffb31Sdp#  (side-by-side).  This format is familiar to users of sdiff(1) or
639daaffb31Sdp#  Teamware's filemerge tool.
640daaffb31Sdp#
641daaffb31Sdpsdiff_to_html()
642daaffb31Sdp{
6437c478bd9Sstevel@tonic-gate	diff -b $1 $2 > /tmp/$$.diffs
6447c478bd9Sstevel@tonic-gate
645daaffb31Sdp	TNAME=$3
646daaffb31Sdp	TPATH=$4
647daaffb31Sdp	COMMENT=$5
648daaffb31Sdp
6497c478bd9Sstevel@tonic-gate	#
6507c478bd9Sstevel@tonic-gate	#  Now we have the diffs, generate the HTML for the old file.
6517c478bd9Sstevel@tonic-gate	#
652cdf0c1d5Smjnelson	$AWK '
6537c478bd9Sstevel@tonic-gate	BEGIN	{
6547c478bd9Sstevel@tonic-gate		printf "function sp(n) {for (i=0;i<n;i++)printf \"\\n\"}\n"
655daaffb31Sdp		printf "function removed() "
656daaffb31Sdp		printf "{printf \"<span class=\\\"removed\\\">%%4d %%s</span>\\n\", NR, $0}\n"
657daaffb31Sdp		printf "function changed() "
658daaffb31Sdp		printf "{printf \"<span class=\\\"changed\\\">%%4d %%s</span>\\n\", NR, $0}\n"
659daaffb31Sdp		printf "function bl() {printf \"%%4d %%s\\n\", NR, $0}\n"
6607c478bd9Sstevel@tonic-gate}
6617c478bd9Sstevel@tonic-gate	/^</	{next}
6627c478bd9Sstevel@tonic-gate	/^>/	{next}
6637c478bd9Sstevel@tonic-gate	/^---/	{next}
664daaffb31Sdp
6657c478bd9Sstevel@tonic-gate	{
6667c478bd9Sstevel@tonic-gate	split($1, a, /[cad]/) ;
6677c478bd9Sstevel@tonic-gate	if (index($1, "a")) {
6687c478bd9Sstevel@tonic-gate		if (a[1] == 0) {
6697c478bd9Sstevel@tonic-gate			n = split(a[2], r, /,/);
6707c478bd9Sstevel@tonic-gate			if (n == 1)
6717c478bd9Sstevel@tonic-gate				printf "BEGIN\t\t{sp(1)}\n"
6727c478bd9Sstevel@tonic-gate			else
6737c478bd9Sstevel@tonic-gate				printf "BEGIN\t\t{sp(%d)}\n",\
6747c478bd9Sstevel@tonic-gate				(r[2] - r[1]) + 1
6757c478bd9Sstevel@tonic-gate			next
6767c478bd9Sstevel@tonic-gate		}
6777c478bd9Sstevel@tonic-gate
6787c478bd9Sstevel@tonic-gate		printf "NR==%s\t\t{", a[1]
6797c478bd9Sstevel@tonic-gate		n = split(a[2], r, /,/);
6807c478bd9Sstevel@tonic-gate		s = r[1];
6817c478bd9Sstevel@tonic-gate		if (n == 1)
6827c478bd9Sstevel@tonic-gate			printf "bl();printf \"\\n\"; next}\n"
6837c478bd9Sstevel@tonic-gate		else {
6847c478bd9Sstevel@tonic-gate			n = r[2] - r[1]
6857c478bd9Sstevel@tonic-gate			printf "bl();sp(%d);next}\n",\
6867c478bd9Sstevel@tonic-gate			(r[2] - r[1]) + 1
6877c478bd9Sstevel@tonic-gate		}
6887c478bd9Sstevel@tonic-gate		next
6897c478bd9Sstevel@tonic-gate	}
6907c478bd9Sstevel@tonic-gate	if (index($1, "d")) {
6917c478bd9Sstevel@tonic-gate		n = split(a[1], r, /,/);
6927c478bd9Sstevel@tonic-gate		n1 = r[1]
6937c478bd9Sstevel@tonic-gate		n2 = r[2]
6947c478bd9Sstevel@tonic-gate		if (n == 1)
695daaffb31Sdp			printf "NR==%s\t\t{removed(); next}\n" , n1
6967c478bd9Sstevel@tonic-gate		else
697daaffb31Sdp			printf "NR==%s,NR==%s\t{removed(); next}\n" , n1, n2
6987c478bd9Sstevel@tonic-gate		next
6997c478bd9Sstevel@tonic-gate	}
7007c478bd9Sstevel@tonic-gate	if (index($1, "c")) {
7017c478bd9Sstevel@tonic-gate		n = split(a[1], r, /,/);
7027c478bd9Sstevel@tonic-gate		n1 = r[1]
7037c478bd9Sstevel@tonic-gate		n2 = r[2]
7047c478bd9Sstevel@tonic-gate		final = n2
7057c478bd9Sstevel@tonic-gate		d1 = 0
7067c478bd9Sstevel@tonic-gate		if (n == 1)
707daaffb31Sdp			printf "NR==%s\t\t{changed();" , n1
7087c478bd9Sstevel@tonic-gate		else {
7097c478bd9Sstevel@tonic-gate			d1 = n2 - n1
710daaffb31Sdp			printf "NR==%s,NR==%s\t{changed();" , n1, n2
7117c478bd9Sstevel@tonic-gate		}
7127c478bd9Sstevel@tonic-gate		m = split(a[2], r, /,/);
7137c478bd9Sstevel@tonic-gate		n1 = r[1]
7147c478bd9Sstevel@tonic-gate		n2 = r[2]
7157c478bd9Sstevel@tonic-gate		if (m > 1) {
7167c478bd9Sstevel@tonic-gate			d2  = n2 - n1
7177c478bd9Sstevel@tonic-gate			if (d2 > d1) {
7187c478bd9Sstevel@tonic-gate				if (n > 1) printf "if (NR==%d)", final
7197c478bd9Sstevel@tonic-gate				printf "sp(%d);", d2 - d1
7207c478bd9Sstevel@tonic-gate			}
7217c478bd9Sstevel@tonic-gate		}
7227c478bd9Sstevel@tonic-gate		printf "next}\n" ;
7237c478bd9Sstevel@tonic-gate
7247c478bd9Sstevel@tonic-gate		next
7257c478bd9Sstevel@tonic-gate	}
7267c478bd9Sstevel@tonic-gate	}
7277c478bd9Sstevel@tonic-gate
728daaffb31Sdp	END	{ printf "{printf \"%%4d %%s\\n\", NR, $0 }\n" }
729daaffb31Sdp	' /tmp/$$.diffs > /tmp/$$.file1
7307c478bd9Sstevel@tonic-gate
7317c478bd9Sstevel@tonic-gate	#
7327c478bd9Sstevel@tonic-gate	#  Now generate the HTML for the new file
7337c478bd9Sstevel@tonic-gate	#
734cdf0c1d5Smjnelson	$AWK '
7357c478bd9Sstevel@tonic-gate	BEGIN	{
7367c478bd9Sstevel@tonic-gate		printf "function sp(n) {for (i=0;i<n;i++)printf \"\\n\"}\n"
737daaffb31Sdp		printf "function new() "
738daaffb31Sdp		printf "{printf \"<span class=\\\"new\\\">%%4d %%s</span>\\n\", NR, $0}\n"
739daaffb31Sdp		printf "function changed() "
740daaffb31Sdp		printf "{printf \"<span class=\\\"changed\\\">%%4d %%s</span>\\n\", NR, $0}\n"
741daaffb31Sdp		printf "function bl() {printf \"%%4d %%s\\n\", NR, $0}\n"
7427c478bd9Sstevel@tonic-gate	}
743daaffb31Sdp
7447c478bd9Sstevel@tonic-gate	/^</	{next}
7457c478bd9Sstevel@tonic-gate	/^>/	{next}
7467c478bd9Sstevel@tonic-gate	/^---/	{next}
747daaffb31Sdp
7487c478bd9Sstevel@tonic-gate	{
7497c478bd9Sstevel@tonic-gate	split($1, a, /[cad]/) ;
7507c478bd9Sstevel@tonic-gate	if (index($1, "d")) {
7517c478bd9Sstevel@tonic-gate		if (a[2] == 0) {
7527c478bd9Sstevel@tonic-gate			n = split(a[1], r, /,/);
7537c478bd9Sstevel@tonic-gate			if (n == 1)
7547c478bd9Sstevel@tonic-gate				printf "BEGIN\t\t{sp(1)}\n"
7557c478bd9Sstevel@tonic-gate			else
7567c478bd9Sstevel@tonic-gate				printf "BEGIN\t\t{sp(%d)}\n",\
7577c478bd9Sstevel@tonic-gate				(r[2] - r[1]) + 1
7587c478bd9Sstevel@tonic-gate			next
7597c478bd9Sstevel@tonic-gate		}
7607c478bd9Sstevel@tonic-gate
7617c478bd9Sstevel@tonic-gate		printf "NR==%s\t\t{", a[2]
7627c478bd9Sstevel@tonic-gate		n = split(a[1], r, /,/);
7637c478bd9Sstevel@tonic-gate		s = r[1];
7647c478bd9Sstevel@tonic-gate		if (n == 1)
7657c478bd9Sstevel@tonic-gate			printf "bl();printf \"\\n\"; next}\n"
7667c478bd9Sstevel@tonic-gate		else {
7677c478bd9Sstevel@tonic-gate			n = r[2] - r[1]
7687c478bd9Sstevel@tonic-gate			printf "bl();sp(%d);next}\n",\
7697c478bd9Sstevel@tonic-gate			(r[2] - r[1]) + 1
7707c478bd9Sstevel@tonic-gate		}
7717c478bd9Sstevel@tonic-gate		next
7727c478bd9Sstevel@tonic-gate	}
7737c478bd9Sstevel@tonic-gate	if (index($1, "a")) {
7747c478bd9Sstevel@tonic-gate		n = split(a[2], r, /,/);
7757c478bd9Sstevel@tonic-gate		n1 = r[1]
7767c478bd9Sstevel@tonic-gate		n2 = r[2]
7777c478bd9Sstevel@tonic-gate		if (n == 1)
778daaffb31Sdp			printf "NR==%s\t\t{new() ; next}\n" , n1
7797c478bd9Sstevel@tonic-gate		else
780daaffb31Sdp			printf "NR==%s,NR==%s\t{new() ; next}\n" , n1, n2
7817c478bd9Sstevel@tonic-gate		next
7827c478bd9Sstevel@tonic-gate	}
7837c478bd9Sstevel@tonic-gate	if (index($1, "c")) {
7847c478bd9Sstevel@tonic-gate		n = split(a[2], r, /,/);
7857c478bd9Sstevel@tonic-gate		n1 = r[1]
7867c478bd9Sstevel@tonic-gate		n2 = r[2]
7877c478bd9Sstevel@tonic-gate		final = n2
7887c478bd9Sstevel@tonic-gate		d2 = 0;
7897c478bd9Sstevel@tonic-gate		if (n == 1) {
7907c478bd9Sstevel@tonic-gate			final = n1
791daaffb31Sdp			printf "NR==%s\t\t{changed();" , n1
7927c478bd9Sstevel@tonic-gate		} else {
7937c478bd9Sstevel@tonic-gate			d2 = n2 - n1
794daaffb31Sdp			printf "NR==%s,NR==%s\t{changed();" , n1, n2
7957c478bd9Sstevel@tonic-gate		}
7967c478bd9Sstevel@tonic-gate		m = split(a[1], r, /,/);
7977c478bd9Sstevel@tonic-gate		n1 = r[1]
7987c478bd9Sstevel@tonic-gate		n2 = r[2]
7997c478bd9Sstevel@tonic-gate		if (m > 1) {
8007c478bd9Sstevel@tonic-gate			d1  = n2 - n1
8017c478bd9Sstevel@tonic-gate			if (d1 > d2) {
8027c478bd9Sstevel@tonic-gate				if (n > 1) printf "if (NR==%d)", final
8037c478bd9Sstevel@tonic-gate				printf "sp(%d);", d1 - d2
8047c478bd9Sstevel@tonic-gate			}
8057c478bd9Sstevel@tonic-gate		}
8067c478bd9Sstevel@tonic-gate		printf "next}\n" ;
8077c478bd9Sstevel@tonic-gate		next
8087c478bd9Sstevel@tonic-gate	}
8097c478bd9Sstevel@tonic-gate	}
810daaffb31Sdp	END	{ printf "{printf \"%%4d %%s\\n\", NR, $0 }\n" }
8117c478bd9Sstevel@tonic-gate	' /tmp/$$.diffs > /tmp/$$.file2
8127c478bd9Sstevel@tonic-gate
813daaffb31Sdp	#
814cdf0c1d5Smjnelson	# Post-process the HTML files by running them back through $AWK
815daaffb31Sdp	#
816cdf0c1d5Smjnelson	html_quote < $1 | $AWK -f /tmp/$$.file1 > /tmp/$$.file1.html
8177c478bd9Sstevel@tonic-gate
818cdf0c1d5Smjnelson	html_quote < $2 | $AWK -f /tmp/$$.file2 > /tmp/$$.file2.html
8197c478bd9Sstevel@tonic-gate
820daaffb31Sdp	#
821daaffb31Sdp	# Now combine into a valid HTML file and side-by-side into a table
822daaffb31Sdp	#
823daaffb31Sdp	print "$HTML<head>$STDHEAD"
824cdf0c1d5Smjnelson	print "<title>$WNAME Sdiff $TPATH/$TNAME</title>"
825daaffb31Sdp	print "</head><body id=\"SUNWwebrev\">"
826daaffb31Sdp        print "<a class=\"print\" href=\"javascript:print()\">Print this page</a>"
827daaffb31Sdp	print "<pre>$COMMENT</pre>\n"
828daaffb31Sdp	print "<table><tr valign=\"top\">"
829daaffb31Sdp	print "<td><pre>"
8307c478bd9Sstevel@tonic-gate
8317c478bd9Sstevel@tonic-gate	strip_unchanged /tmp/$$.file1.html
8327c478bd9Sstevel@tonic-gate
833daaffb31Sdp	print "</pre></td><td><pre>"
8347c478bd9Sstevel@tonic-gate
8357c478bd9Sstevel@tonic-gate	strip_unchanged /tmp/$$.file2.html
8367c478bd9Sstevel@tonic-gate
837daaffb31Sdp	print "</pre></td>"
838daaffb31Sdp	print "</tr></table>"
839daaffb31Sdp	print "</body></html>"
8407c478bd9Sstevel@tonic-gate
841daaffb31Sdp	framed_sdiff $TNAME $TPATH /tmp/$$.file1.html /tmp/$$.file2.html \
842daaffb31Sdp	    "$COMMENT"
8437c478bd9Sstevel@tonic-gate}
8447c478bd9Sstevel@tonic-gate
8457c478bd9Sstevel@tonic-gate
846daaffb31Sdp#
847daaffb31Sdp# framed_sdiff <filename> <filepath> <lhsfile> <rhsfile> <comment>
848daaffb31Sdp#
849daaffb31Sdp# Expects lefthand and righthand side html files created by sdiff_to_html.
850daaffb31Sdp# We use insert_anchors() to augment those with HTML navigation anchors,
851daaffb31Sdp# and then emit the main frame.  Content is placed into:
852daaffb31Sdp#
853daaffb31Sdp#    $WDIR/DIR/$TNAME.lhs.html
854daaffb31Sdp#    $WDIR/DIR/$TNAME.rhs.html
855daaffb31Sdp#    $WDIR/DIR/$TNAME.frames.html
856daaffb31Sdp#
857daaffb31Sdp# NOTE: We rely on standard usage of $WDIR and $DIR.
858daaffb31Sdp#
8597c478bd9Sstevel@tonic-gatefunction framed_sdiff
8607c478bd9Sstevel@tonic-gate{
8617c478bd9Sstevel@tonic-gate	typeset TNAME=$1
862daaffb31Sdp	typeset TPATH=$2
863daaffb31Sdp	typeset lhsfile=$3
864daaffb31Sdp	typeset rhsfile=$4
865daaffb31Sdp	typeset comments=$5
8667c478bd9Sstevel@tonic-gate	typeset RTOP
867daaffb31Sdp
8687c478bd9Sstevel@tonic-gate	# Enable html files to access WDIR via a relative path.
869daaffb31Sdp	RTOP=$(relative_dir $TPATH $WDIR)
870daaffb31Sdp
871daaffb31Sdp	# Make the rhs/lhs files and output the frameset file.
872daaffb31Sdp	print "$HTML<head>$STDHEAD" > $WDIR/$DIR/$TNAME.lhs.html
873daaffb31Sdp
874daaffb31Sdp	cat >> $WDIR/$DIR/$TNAME.lhs.html <<-EOF
8758b3b7b16SMark J. Nelson	    <script type="text/javascript" src="${RTOP}ancnav.js"></script>
8767c478bd9Sstevel@tonic-gate	    </head>
877daaffb31Sdp	    <body id="SUNWwebrev" onkeypress="keypress(event);">
878cac38512Smjnelson	    <a name="0"></a>
879cac38512Smjnelson	    <pre>$comments</pre><hr></hr>
880daaffb31Sdp	EOF
881daaffb31Sdp
882daaffb31Sdp	cp $WDIR/$DIR/$TNAME.lhs.html $WDIR/$DIR/$TNAME.rhs.html
883daaffb31Sdp
884daaffb31Sdp	insert_anchors $lhsfile >> $WDIR/$DIR/$TNAME.lhs.html
885daaffb31Sdp	insert_anchors $rhsfile >> $WDIR/$DIR/$TNAME.rhs.html
886daaffb31Sdp
887daaffb31Sdp	close='</body></html>'
888daaffb31Sdp
889daaffb31Sdp	print $close >> $WDIR/$DIR/$TNAME.lhs.html
890daaffb31Sdp	print $close >> $WDIR/$DIR/$TNAME.rhs.html
891daaffb31Sdp
892daaffb31Sdp	print "$FRAMEHTML<head>$STDHEAD" > $WDIR/$DIR/$TNAME.frames.html
893daaffb31Sdp	print "<title>$WNAME Framed-Sdiff " \
894daaffb31Sdp	    "$TPATH/$TNAME</title> </head>" >> $WDIR/$DIR/$TNAME.frames.html
895daaffb31Sdp	cat >> $WDIR/$DIR/$TNAME.frames.html <<-EOF
896daaffb31Sdp	  <frameset rows="*,60">
897daaffb31Sdp	    <frameset cols="50%,50%">
898cac38512Smjnelson	      <frame src="$TNAME.lhs.html" scrolling="auto" name="lhs"></frame>
899cac38512Smjnelson	      <frame src="$TNAME.rhs.html" scrolling="auto" name="rhs"></frame>
900daaffb31Sdp	    </frameset>
9018b3b7b16SMark J. Nelson	  <frame src="${RTOP}ancnav.html" scrolling="no" marginwidth="0"
902cac38512Smjnelson	   marginheight="0" name="nav"></frame>
903daaffb31Sdp	  <noframes>
904daaffb31Sdp            <body id="SUNWwebrev">
905daaffb31Sdp	      Alas 'frames' webrev requires that your browser supports frames
9067c478bd9Sstevel@tonic-gate	      and has the feature enabled.
907daaffb31Sdp            </body>
908daaffb31Sdp	  </noframes>
909daaffb31Sdp	  </frameset>
9107c478bd9Sstevel@tonic-gate	</html>
9117c478bd9Sstevel@tonic-gate	EOF
9127c478bd9Sstevel@tonic-gate}
9137c478bd9Sstevel@tonic-gate
9147c478bd9Sstevel@tonic-gate
915daaffb31Sdp#
916daaffb31Sdp# fix_postscript
917daaffb31Sdp#
918daaffb31Sdp# Merge codereview output files to a single conforming postscript file, by:
919daaffb31Sdp#	- removing all extraneous headers/trailers
920daaffb31Sdp#	- making the page numbers right
921daaffb31Sdp#	- removing pages devoid of contents which confuse some
922daaffb31Sdp#	  postscript readers.
923daaffb31Sdp#
924daaffb31Sdp# From Casper.
925daaffb31Sdp#
926daaffb31Sdpfunction fix_postscript
9277c478bd9Sstevel@tonic-gate{
928daaffb31Sdp	infile=$1
9297c478bd9Sstevel@tonic-gate
930daaffb31Sdp	cat > /tmp/$$.crmerge.pl << \EOF
9317c478bd9Sstevel@tonic-gate
932daaffb31Sdp	print scalar(<>);		# %!PS-Adobe---
933daaffb31Sdp	print "%%Orientation: Landscape\n";
9347c478bd9Sstevel@tonic-gate
935daaffb31Sdp	$pno = 0;
936daaffb31Sdp	$doprint = 1;
937daaffb31Sdp
938daaffb31Sdp	$page = "";
939daaffb31Sdp
940daaffb31Sdp	while (<>) {
941daaffb31Sdp		next if (/^%%Pages:\s*\d+/);
942daaffb31Sdp
943daaffb31Sdp		if (/^%%Page:/) {
944daaffb31Sdp			if ($pno == 0 || $page =~ /\)S/) {
945daaffb31Sdp				# Header or single page containing text
946daaffb31Sdp				print "%%Page: ? $pno\n" if ($pno > 0);
947daaffb31Sdp				print $page;
948daaffb31Sdp				$pno++;
949daaffb31Sdp			} else {
950daaffb31Sdp				# Empty page, skip it.
9517c478bd9Sstevel@tonic-gate			}
952daaffb31Sdp			$page = "";
953daaffb31Sdp			$doprint = 1;
9547c478bd9Sstevel@tonic-gate			next;
9557c478bd9Sstevel@tonic-gate		}
9567c478bd9Sstevel@tonic-gate
957daaffb31Sdp		# Skip from %%Trailer of one document to Endprolog
958daaffb31Sdp		# %%Page of the next
959daaffb31Sdp		$doprint = 0 if (/^%%Trailer/);
960daaffb31Sdp		$page .= $_ if ($doprint);
9617c478bd9Sstevel@tonic-gate	}
9627c478bd9Sstevel@tonic-gate
963daaffb31Sdp	if ($page =~ /\)S/) {
964daaffb31Sdp		print "%%Page: ? $pno\n";
965daaffb31Sdp		print $page;
966daaffb31Sdp	} else {
967daaffb31Sdp		$pno--;
968daaffb31Sdp	}
969daaffb31Sdp	print "%%Trailer\n%%Pages: $pno\n";
970daaffb31SdpEOF
971daaffb31Sdp
97214983201Sdp	$PERL /tmp/$$.crmerge.pl < $infile
973daaffb31Sdp}
974daaffb31Sdp
975daaffb31Sdp
976daaffb31Sdp#
977daaffb31Sdp# input_cmd | insert_anchors | output_cmd
978daaffb31Sdp#
9797c478bd9Sstevel@tonic-gate# Flag blocks of difference with sequentially numbered invisible
980daaffb31Sdp# anchors.  These are used to drive the frames version of the
9817c478bd9Sstevel@tonic-gate# sdiffs output.
9827c478bd9Sstevel@tonic-gate#
9837c478bd9Sstevel@tonic-gate# NOTE: Anchor zero flags the top of the file irrespective of changes,
9847c478bd9Sstevel@tonic-gate# an additional anchor is also appended to flag the bottom.
9857c478bd9Sstevel@tonic-gate#
986daaffb31Sdp# The script detects changed lines as any line that has a "<span
987daaffb31Sdp# class=" string embedded (unchanged lines have no class set and are
988daaffb31Sdp# not part of a <span>.  Blank lines (without a sequence number)
9897c478bd9Sstevel@tonic-gate# are also detected since they flag lines that have been inserted or
9907c478bd9Sstevel@tonic-gate# deleted.
9917c478bd9Sstevel@tonic-gate#
992daaffb31Sdpfunction insert_anchors
993daaffb31Sdp{
994cdf0c1d5Smjnelson	$AWK '
9957c478bd9Sstevel@tonic-gate	function ia() {
996daaffb31Sdp		printf "<a name=\"%d\" id=\"anc%d\"></a>", anc, anc++;
9977c478bd9Sstevel@tonic-gate	}
998daaffb31Sdp
9997c478bd9Sstevel@tonic-gate	BEGIN {
1000daaffb31Sdp		anc=1;
10017c478bd9Sstevel@tonic-gate		inblock=1;
1002daaffb31Sdp		printf "<pre>\n";
10037c478bd9Sstevel@tonic-gate	}
1004daaffb31Sdp	NF == 0 || /^<span class=/ {
10057c478bd9Sstevel@tonic-gate		if (inblock == 0) {
10067c478bd9Sstevel@tonic-gate			ia();
10077c478bd9Sstevel@tonic-gate			inblock=1;
10087c478bd9Sstevel@tonic-gate		}
10097c478bd9Sstevel@tonic-gate		print;
10107c478bd9Sstevel@tonic-gate		next;
10117c478bd9Sstevel@tonic-gate	}
10127c478bd9Sstevel@tonic-gate	{
10137c478bd9Sstevel@tonic-gate		inblock=0;
10147c478bd9Sstevel@tonic-gate		print;
10157c478bd9Sstevel@tonic-gate	}
10167c478bd9Sstevel@tonic-gate	END {
10177c478bd9Sstevel@tonic-gate		ia();
1018daaffb31Sdp
1019daaffb31Sdp		printf "<b style=\"font-size: large; color: red\">";
1020daaffb31Sdp		printf "--- EOF ---</b>"
10217c478bd9Sstevel@tonic-gate		for(i=0;i<8;i++) printf "\n\n\n\n\n\n\n\n\n\n";
1022daaffb31Sdp		printf "</pre>"
1023daaffb31Sdp		printf "<form name=\"eof\">";
1024cac38512Smjnelson		printf "<input name=\"value\" value=\"%d\" " \
1025cac38512Smjnelson		    "type=\"hidden\"></input>", anc - 1;
1026daaffb31Sdp		printf "</form>";
10277c478bd9Sstevel@tonic-gate	}
10287c478bd9Sstevel@tonic-gate	' $1
10297c478bd9Sstevel@tonic-gate}
10307c478bd9Sstevel@tonic-gate
10317c478bd9Sstevel@tonic-gate
1032daaffb31Sdp#
1033daaffb31Sdp# relative_dir
1034daaffb31Sdp#
1035daaffb31Sdp# Print a relative return path from $1 to $2.  For example if
1036daaffb31Sdp# $1=/tmp/myreview/raw_files/usr/src/tools/scripts and $2=/tmp/myreview,
1037daaffb31Sdp# this function would print "../../../../".
1038daaffb31Sdp#
1039daaffb31Sdp# In the event that $1 is not in $2 a warning is printed to stderr,
1040daaffb31Sdp# and $2 is returned-- the result of this is that the resulting webrev
1041daaffb31Sdp# is not relocatable.
1042daaffb31Sdp#
1043daaffb31Sdpfunction relative_dir
10447c478bd9Sstevel@tonic-gate{
1045daaffb31Sdp        typeset cur="${1##$2?(/)}"
10468b3b7b16SMark J. Nelson
10478b3b7b16SMark J. Nelson        #
10488b3b7b16SMark J. Nelson        # If the first path was specified absolutely, and it does
10498b3b7b16SMark J. Nelson        # not start with the second path, it's an error.
10508b3b7b16SMark J. Nelson        #
10510fd2682eSMark J. Nelson        if [[ "$cur" = "/${1#/}" ]]; then
1052daaffb31Sdp                # Should never happen.
105314983201Sdp                print -u2 "\nWARNING: relative_dir: \"$1\" not relative "
1054daaffb31Sdp                print -u2 "to \"$2\".  Check input paths.  Framed webrev "
1055daaffb31Sdp                print -u2 "will not be relocatable!"
1056daaffb31Sdp                print $2
1057daaffb31Sdp                return
1058daaffb31Sdp        fi
1059daaffb31Sdp
10608b3b7b16SMark J. Nelson	#
10618b3b7b16SMark J. Nelson	# This is kind of ugly.  The sed script will do the following:
10628b3b7b16SMark J. Nelson	#
10638b3b7b16SMark J. Nelson	# 1. Strip off a leading "." or "./": this is important to get
10648b3b7b16SMark J. Nelson	#    the correct arcnav links for files in $WDIR.
10658b3b7b16SMark J. Nelson	# 2. Strip off a trailing "/": this is not strictly necessary,
10668b3b7b16SMark J. Nelson	#    but is kind of nice, since it doesn't end up in "//" at
10678b3b7b16SMark J. Nelson	#    the end of a relative path.
10688b3b7b16SMark J. Nelson	# 3. Replace all remaining sequences of non-"/" with "..": the
10698b3b7b16SMark J. Nelson	#    assumption here is that each dirname represents another
10708b3b7b16SMark J. Nelson	#    level of relative separation.
10718b3b7b16SMark J. Nelson	# 4. Append a trailing "/" only for non-empty paths: this way
10728b3b7b16SMark J. Nelson	#    the caller doesn't need to duplicate this logic, and does
10738b3b7b16SMark J. Nelson	#    not end up using $RTOP/file for files in $WDIR.
10748b3b7b16SMark J. Nelson	#
10750fd2682eSMark J. Nelson	print $cur | $SED -e '{
10768b3b7b16SMark J. Nelson		s:^\./*::
10778b3b7b16SMark J. Nelson		s:/$::
10788b3b7b16SMark J. Nelson		s:[^/][^/]*:..:g
10790fd2682eSMark J. Nelson		s:^\(..*\)$:\1/:
10800fd2682eSMark J. Nelson	}'
10817c478bd9Sstevel@tonic-gate}
10827c478bd9Sstevel@tonic-gate
1083daaffb31Sdp#
1084daaffb31Sdp# frame_nav_js
1085daaffb31Sdp#
1086daaffb31Sdp# Emit javascript for frame navigation
1087daaffb31Sdp#
1088daaffb31Sdpfunction frame_nav_js
10897c478bd9Sstevel@tonic-gate{
10907c478bd9Sstevel@tonic-gatecat << \EOF
10917c478bd9Sstevel@tonic-gatevar myInt;
10927c478bd9Sstevel@tonic-gatevar scrolling=0;
1093daaffb31Sdpvar sfactor = 3;
10947c478bd9Sstevel@tonic-gatevar scount=10;
10957c478bd9Sstevel@tonic-gate
10967c478bd9Sstevel@tonic-gatefunction scrollByPix() {
10977c478bd9Sstevel@tonic-gate	if (scount<=0) {
10987c478bd9Sstevel@tonic-gate		sfactor*=1.2;
10997c478bd9Sstevel@tonic-gate		scount=10;
11007c478bd9Sstevel@tonic-gate	}
11017c478bd9Sstevel@tonic-gate	parent.lhs.scrollBy(0,sfactor);
11027c478bd9Sstevel@tonic-gate	parent.rhs.scrollBy(0,sfactor);
11037c478bd9Sstevel@tonic-gate	scount--;
11047c478bd9Sstevel@tonic-gate}
11057c478bd9Sstevel@tonic-gate
1106daaffb31Sdpfunction scrollToAnc(num) {
1107daaffb31Sdp
1108daaffb31Sdp	// Update the value of the anchor in the form which we use as
1109daaffb31Sdp	// storage for this value.  setAncValue() will take care of
1110daaffb31Sdp	// correcting for overflow and underflow of the value and return
1111daaffb31Sdp	// us the new value.
1112daaffb31Sdp	num = setAncValue(num);
1113daaffb31Sdp
1114daaffb31Sdp	// Set location and scroll back a little to expose previous
1115daaffb31Sdp	// lines.
1116daaffb31Sdp	//
1117daaffb31Sdp	// Note that this could be improved: it is possible although
1118daaffb31Sdp	// complex to compute the x and y position of an anchor, and to
1119daaffb31Sdp	// scroll to that location directly.
1120daaffb31Sdp	//
11217c478bd9Sstevel@tonic-gate	parent.lhs.location.replace(parent.lhs.location.pathname + "#" + num);
11227c478bd9Sstevel@tonic-gate	parent.rhs.location.replace(parent.rhs.location.pathname + "#" + num);
1123daaffb31Sdp
11247c478bd9Sstevel@tonic-gate	parent.lhs.scrollBy(0,-30);
11257c478bd9Sstevel@tonic-gate	parent.rhs.scrollBy(0,-30);
11267c478bd9Sstevel@tonic-gate}
11277c478bd9Sstevel@tonic-gate
1128daaffb31Sdpfunction getAncValue()
1129daaffb31Sdp{
1130daaffb31Sdp	return (parseInt(parent.nav.document.diff.real.value));
1131daaffb31Sdp}
1132daaffb31Sdp
1133daaffb31Sdpfunction setAncValue(val)
1134daaffb31Sdp{
1135daaffb31Sdp	if (val <= 0) {
1136daaffb31Sdp		val = 0;
1137daaffb31Sdp		parent.nav.document.diff.real.value = val;
1138daaffb31Sdp		parent.nav.document.diff.display.value = "BOF";
1139daaffb31Sdp		return (val);
1140daaffb31Sdp	}
1141daaffb31Sdp
1142daaffb31Sdp	//
1143daaffb31Sdp	// The way we compute the max anchor value is to stash it
1144daaffb31Sdp	// inline in the left and right hand side pages-- it's the same
1145daaffb31Sdp	// on each side, so we pluck from the left.
1146daaffb31Sdp	//
1147daaffb31Sdp	maxval = parent.lhs.document.eof.value.value;
1148daaffb31Sdp	if (val < maxval) {
1149daaffb31Sdp		parent.nav.document.diff.real.value = val;
1150daaffb31Sdp		parent.nav.document.diff.display.value = val.toString();
1151daaffb31Sdp		return (val);
1152daaffb31Sdp	}
1153daaffb31Sdp
1154daaffb31Sdp	// this must be: val >= maxval
1155daaffb31Sdp	val = maxval;
1156daaffb31Sdp	parent.nav.document.diff.real.value = val;
1157daaffb31Sdp	parent.nav.document.diff.display.value = "EOF";
1158daaffb31Sdp	return (val);
1159daaffb31Sdp}
1160daaffb31Sdp
11617c478bd9Sstevel@tonic-gatefunction stopScroll() {
11627c478bd9Sstevel@tonic-gate	if (scrolling==1) {
11637c478bd9Sstevel@tonic-gate		clearInterval(myInt);
11647c478bd9Sstevel@tonic-gate		scrolling=0;
11657c478bd9Sstevel@tonic-gate	}
11667c478bd9Sstevel@tonic-gate}
11677c478bd9Sstevel@tonic-gate
11687c478bd9Sstevel@tonic-gatefunction startScroll() {
11697c478bd9Sstevel@tonic-gate	stopScroll();
11707c478bd9Sstevel@tonic-gate	scrolling=1;
11717c478bd9Sstevel@tonic-gate	myInt=setInterval("scrollByPix()",10);
11727c478bd9Sstevel@tonic-gate}
11737c478bd9Sstevel@tonic-gate
11747c478bd9Sstevel@tonic-gatefunction handlePress(b) {
1175daaffb31Sdp
11767c478bd9Sstevel@tonic-gate	switch (b) {
11777c478bd9Sstevel@tonic-gate	    case 1 :
1178daaffb31Sdp		scrollToAnc(-1);
11797c478bd9Sstevel@tonic-gate		break;
11807c478bd9Sstevel@tonic-gate	    case 2 :
1181daaffb31Sdp		scrollToAnc(getAncValue() - 1);
11827c478bd9Sstevel@tonic-gate		break;
11837c478bd9Sstevel@tonic-gate	    case 3 :
11847c478bd9Sstevel@tonic-gate		sfactor=-3;
11857c478bd9Sstevel@tonic-gate		startScroll();
11867c478bd9Sstevel@tonic-gate		break;
11877c478bd9Sstevel@tonic-gate	    case 4 :
11887c478bd9Sstevel@tonic-gate		sfactor=3;
11897c478bd9Sstevel@tonic-gate		startScroll();
11907c478bd9Sstevel@tonic-gate		break;
11917c478bd9Sstevel@tonic-gate	    case 5 :
1192daaffb31Sdp		scrollToAnc(getAncValue() + 1);
11937c478bd9Sstevel@tonic-gate		break;
11947c478bd9Sstevel@tonic-gate	    case 6 :
1195daaffb31Sdp		scrollToAnc(999999);
11967c478bd9Sstevel@tonic-gate		break;
11977c478bd9Sstevel@tonic-gate	}
11987c478bd9Sstevel@tonic-gate}
11997c478bd9Sstevel@tonic-gate
12007c478bd9Sstevel@tonic-gatefunction handleRelease(b) {
12017c478bd9Sstevel@tonic-gate	stopScroll();
12027c478bd9Sstevel@tonic-gate}
12037c478bd9Sstevel@tonic-gate
1204daaffb31Sdpfunction keypress(ev) {
1205daaffb31Sdp	var keynum;
1206daaffb31Sdp	var keychar;
1207daaffb31Sdp
1208daaffb31Sdp	if (window.event) { // IE
1209daaffb31Sdp		keynum = ev.keyCode;
1210daaffb31Sdp	} else if (ev.which) { // non-IE
1211daaffb31Sdp		keynum = ev.which;
1212daaffb31Sdp	}
1213daaffb31Sdp
1214daaffb31Sdp	keychar = String.fromCharCode(keynum);
1215daaffb31Sdp
1216daaffb31Sdp	if (keychar == "k") {
1217daaffb31Sdp		handlePress(2);
1218daaffb31Sdp		return (0);
1219daaffb31Sdp	} else if (keychar == "j" || keychar == " ") {
1220daaffb31Sdp		handlePress(5);
1221daaffb31Sdp		return (0);
1222daaffb31Sdp	}
1223daaffb31Sdp	return (1);
1224daaffb31Sdp}
1225daaffb31Sdp
12267c478bd9Sstevel@tonic-gatefunction ValidateDiffNum(){
1227daaffb31Sdp	val = parent.nav.document.diff.display.value;
1228daaffb31Sdp	if (val == "EOF") {
1229daaffb31Sdp		scrollToAnc(999999);
1230daaffb31Sdp		return;
1231daaffb31Sdp	}
1232daaffb31Sdp
1233daaffb31Sdp	if (val == "BOF") {
1234daaffb31Sdp		scrollToAnc(0);
1235daaffb31Sdp		return;
1236daaffb31Sdp	}
1237daaffb31Sdp
1238daaffb31Sdp        i=parseInt(val);
12397c478bd9Sstevel@tonic-gate        if (isNaN(i)) {
1240daaffb31Sdp                parent.nav.document.diff.display.value = getAncValue();
12417c478bd9Sstevel@tonic-gate        } else {
1242daaffb31Sdp                scrollToAnc(i);
12437c478bd9Sstevel@tonic-gate        }
12447c478bd9Sstevel@tonic-gate        return false;
12457c478bd9Sstevel@tonic-gate}
12467c478bd9Sstevel@tonic-gate
1247daaffb31SdpEOF
1248daaffb31Sdp}
1249daaffb31Sdp
1250daaffb31Sdp#
1251daaffb31Sdp# frame_navigation
1252daaffb31Sdp#
1253daaffb31Sdp# Output anchor navigation file for framed sdiffs.
1254daaffb31Sdp#
1255daaffb31Sdpfunction frame_navigation
1256daaffb31Sdp{
1257daaffb31Sdp	print "$HTML<head>$STDHEAD"
1258daaffb31Sdp
1259daaffb31Sdp	cat << \EOF
1260daaffb31Sdp<title>Anchor Navigation</title>
1261daaffb31Sdp<meta http-equiv="Content-Script-Type" content="text/javascript">
1262daaffb31Sdp<meta http-equiv="Content-Type" content="text/html">
1263daaffb31Sdp
1264daaffb31Sdp<style type="text/css">
1265daaffb31Sdp    div.button td { padding-left: 5px; padding-right: 5px;
1266daaffb31Sdp		    background-color: #eee; text-align: center;
1267daaffb31Sdp		    border: 1px #444 outset; cursor: pointer; }
1268daaffb31Sdp    div.button a { font-weight: bold; color: black }
1269daaffb31Sdp    div.button td:hover { background: #ffcc99; }
1270daaffb31Sdp</style>
1271daaffb31SdpEOF
1272daaffb31Sdp
1273cac38512Smjnelson	print "<script type=\"text/javascript\" src=\"ancnav.js\"></script>"
1274daaffb31Sdp
1275daaffb31Sdp	cat << \EOF
12767c478bd9Sstevel@tonic-gate</head>
1277daaffb31Sdp<body id="SUNWwebrev" bgcolor="#eeeeee" onload="document.diff.real.focus();"
1278daaffb31Sdp	onkeypress="keypress(event);">
12797c478bd9Sstevel@tonic-gate    <noscript lang="javascript">
12807c478bd9Sstevel@tonic-gate      <center>
1281cac38512Smjnelson	<p><big>Framed Navigation controls require Javascript</big><br></br>
12827c478bd9Sstevel@tonic-gate	Either this browser is incompatable or javascript is not enabled</p>
12837c478bd9Sstevel@tonic-gate      </center>
12847c478bd9Sstevel@tonic-gate    </noscript>
12857c478bd9Sstevel@tonic-gate    <table width="100%" border="0" align="center">
1286daaffb31Sdp	<tr>
1287daaffb31Sdp          <td valign="middle" width="25%">Diff navigation:
1288daaffb31Sdp          Use 'j' and 'k' for next and previous diffs; or use buttons
1289daaffb31Sdp          at right</td>
1290daaffb31Sdp	  <td align="center" valign="top" width="50%">
12917c478bd9Sstevel@tonic-gate	    <div class="button">
1292daaffb31Sdp	      <table border="0" align="center">
1293daaffb31Sdp                  <tr>
1294daaffb31Sdp		    <td>
12957c478bd9Sstevel@tonic-gate		      <a onMouseDown="handlePress(1);return true;"
12967c478bd9Sstevel@tonic-gate			 onMouseUp="handleRelease(1);return true;"
12977c478bd9Sstevel@tonic-gate			 onMouseOut="handleRelease(1);return true;"
12987c478bd9Sstevel@tonic-gate			 onClick="return false;"
12997c478bd9Sstevel@tonic-gate			 title="Go to Beginning Of file">BOF</a></td>
1300daaffb31Sdp		    <td>
13017c478bd9Sstevel@tonic-gate		      <a onMouseDown="handlePress(3);return true;"
13027c478bd9Sstevel@tonic-gate			 onMouseUp="handleRelease(3);return true;"
13037c478bd9Sstevel@tonic-gate			 onMouseOut="handleRelease(3);return true;"
13047c478bd9Sstevel@tonic-gate			 title="Scroll Up: Press and Hold to accelerate"
1305daaffb31Sdp			 onClick="return false;">Scroll Up</a></td>
1306daaffb31Sdp		    <td>
13077c478bd9Sstevel@tonic-gate		      <a onMouseDown="handlePress(2);return true;"
13087c478bd9Sstevel@tonic-gate			 onMouseUp="handleRelease(2);return true;"
13097c478bd9Sstevel@tonic-gate			 onMouseOut="handleRelease(2);return true;"
13107c478bd9Sstevel@tonic-gate			 title="Go to previous Diff"
13117c478bd9Sstevel@tonic-gate			 onClick="return false;">Prev Diff</a>
13127c478bd9Sstevel@tonic-gate		    </td></tr>
1313daaffb31Sdp
13147c478bd9Sstevel@tonic-gate		  <tr>
1315daaffb31Sdp		    <td>
13167c478bd9Sstevel@tonic-gate		      <a onMouseDown="handlePress(6);return true;"
13177c478bd9Sstevel@tonic-gate			 onMouseUp="handleRelease(6);return true;"
13187c478bd9Sstevel@tonic-gate			 onMouseOut="handleRelease(6);return true;"
13197c478bd9Sstevel@tonic-gate			 onClick="return false;"
13207c478bd9Sstevel@tonic-gate			 title="Go to End Of File">EOF</a></td>
1321daaffb31Sdp		    <td>
13227c478bd9Sstevel@tonic-gate		      <a onMouseDown="handlePress(4);return true;"
13237c478bd9Sstevel@tonic-gate			 onMouseUp="handleRelease(4);return true;"
13247c478bd9Sstevel@tonic-gate			 onMouseOut="handleRelease(4);return true;"
13257c478bd9Sstevel@tonic-gate			 title="Scroll Down: Press and Hold to accelerate"
1326daaffb31Sdp			 onClick="return false;">Scroll Down</a></td>
1327daaffb31Sdp		    <td>
13287c478bd9Sstevel@tonic-gate		      <a onMouseDown="handlePress(5);return true;"
13297c478bd9Sstevel@tonic-gate			 onMouseUp="handleRelease(5);return true;"
13307c478bd9Sstevel@tonic-gate			 onMouseOut="handleRelease(5);return true;"
13317c478bd9Sstevel@tonic-gate			 title="Go to next Diff"
13327c478bd9Sstevel@tonic-gate			 onClick="return false;">Next Diff</a></td>
1333daaffb31Sdp		  </tr>
1334daaffb31Sdp              </table>
1335daaffb31Sdp	    </div>
1336daaffb31Sdp	  </td>
13377c478bd9Sstevel@tonic-gate	  <th valign="middle" width="25%">
1338daaffb31Sdp	    <form action="" name="diff" onsubmit="return ValidateDiffNum();">
1339cac38512Smjnelson		<input name="display" value="BOF" size="8" type="text"></input>
1340cac38512Smjnelson		<input name="real" value="0" size="8" type="hidden"></input>
13417c478bd9Sstevel@tonic-gate	    </form>
13427c478bd9Sstevel@tonic-gate	  </th>
1343daaffb31Sdp	</tr>
13447c478bd9Sstevel@tonic-gate    </table>
13457c478bd9Sstevel@tonic-gate  </body>
13467c478bd9Sstevel@tonic-gate</html>
13477c478bd9Sstevel@tonic-gateEOF
13487c478bd9Sstevel@tonic-gate}
13497c478bd9Sstevel@tonic-gate
13507c478bd9Sstevel@tonic-gate
1351daaffb31Sdp
1352daaffb31Sdp#
1353daaffb31Sdp# diff_to_html <filename> <filepath> { U | C } <comment>
1354daaffb31Sdp#
1355daaffb31Sdp# Processes the output of diff to produce an HTML file representing either
1356daaffb31Sdp# context or unified diffs.
1357daaffb31Sdp#
13587c478bd9Sstevel@tonic-gatediff_to_html()
13597c478bd9Sstevel@tonic-gate{
13607c478bd9Sstevel@tonic-gate	TNAME=$1
1361daaffb31Sdp	TPATH=$2
1362daaffb31Sdp	DIFFTYPE=$3
1363daaffb31Sdp	COMMENT=$4
1364daaffb31Sdp
1365daaffb31Sdp	print "$HTML<head>$STDHEAD"
1366daaffb31Sdp	print "<title>$WNAME ${DIFFTYPE}diff $TPATH</title>"
1367daaffb31Sdp
1368daaffb31Sdp	if [[ $DIFFTYPE == "U" ]]; then
1369daaffb31Sdp		print "$UDIFFCSS"
1370daaffb31Sdp	fi
1371daaffb31Sdp
1372daaffb31Sdp	cat <<-EOF
1373daaffb31Sdp	</head>
1374daaffb31Sdp	<body id="SUNWwebrev">
1375daaffb31Sdp        <a class="print" href="javascript:print()">Print this page</a>
1376daaffb31Sdp	<pre>$COMMENT</pre>
1377daaffb31Sdp        <pre>
1378daaffb31Sdp	EOF
13797c478bd9Sstevel@tonic-gate
1380cdf0c1d5Smjnelson	html_quote | $AWK '
1381daaffb31Sdp	/^--- new/	{ next }
1382daaffb31Sdp	/^\+\+\+ new/	{ next }
1383daaffb31Sdp	/^--- old/	{ next }
1384daaffb31Sdp	/^\*\*\* old/	{ next }
1385daaffb31Sdp	/^\*\*\*\*/	{ next }
13867c478bd9Sstevel@tonic-gate	/^-------/	{ printf "<center><h1>%s</h1></center>\n", $0; next }
1387cac38512Smjnelson	/^\@\@.*\@\@$/	{ printf "</pre><hr></hr><pre>\n";
1388daaffb31Sdp			  printf "<span class=\"newmarker\">%s</span>\n", $0;
1389daaffb31Sdp			  next}
1390daaffb31Sdp
1391cac38512Smjnelson	/^\*\*\*/	{ printf "<hr></hr><span class=\"oldmarker\">%s</span>\n", $0;
1392daaffb31Sdp			  next}
1393daaffb31Sdp	/^---/		{ printf "<span class=\"newmarker\">%s</span>\n", $0;
1394daaffb31Sdp			  next}
1395daaffb31Sdp	/^\+/		{printf "<span class=\"new\">%s</span>\n", $0; next}
1396daaffb31Sdp	/^!/		{printf "<span class=\"changed\">%s</span>\n", $0; next}
1397daaffb31Sdp	/^-/		{printf "<span class=\"removed\">%s</span>\n", $0; next}
1398daaffb31Sdp			{printf "%s\n", $0; next}
13997c478bd9Sstevel@tonic-gate	'
1400daaffb31Sdp
1401daaffb31Sdp	print "</pre></body></html>\n"
14027c478bd9Sstevel@tonic-gate}
14037c478bd9Sstevel@tonic-gate
14047c478bd9Sstevel@tonic-gate
1405daaffb31Sdp#
1406daaffb31Sdp# source_to_html { new | old } <filename>
1407daaffb31Sdp#
1408daaffb31Sdp# Process a plain vanilla source file to transform it into an HTML file.
1409daaffb31Sdp#
14107c478bd9Sstevel@tonic-gatesource_to_html()
14117c478bd9Sstevel@tonic-gate{
14127c478bd9Sstevel@tonic-gate	WHICH=$1
14137c478bd9Sstevel@tonic-gate	TNAME=$2
14147c478bd9Sstevel@tonic-gate
1415daaffb31Sdp	print "$HTML<head>$STDHEAD"
1416cdf0c1d5Smjnelson	print "<title>$WNAME $WHICH $TNAME</title>"
1417daaffb31Sdp	print "<body id=\"SUNWwebrev\">"
1418daaffb31Sdp	print "<pre>"
1419cdf0c1d5Smjnelson	html_quote | $AWK '{line += 1 ; printf "%4d %s\n", line, $0 }'
1420daaffb31Sdp	print "</pre></body></html>"
14217c478bd9Sstevel@tonic-gate}
14227c478bd9Sstevel@tonic-gate
1423daaffb31Sdp#
1424cdf0c1d5Smjnelson# comments_from_teamware {text|html} parent-file child-file
1425daaffb31Sdp#
1426daaffb31Sdp# Find the first delta in the child that's not in the parent.  Get the
1427daaffb31Sdp# newest delta from the parent, get all deltas from the child starting
1428daaffb31Sdp# with that delta, and then get all info starting with the second oldest
1429daaffb31Sdp# delta in that list (the first delta unique to the child).
14307c478bd9Sstevel@tonic-gate#
14317c478bd9Sstevel@tonic-gate# This code adapted from Bill Shannon's "spc" script
1432daaffb31Sdp#
1433daaffb31Sdpcomments_from_teamware()
14347c478bd9Sstevel@tonic-gate{
1435daaffb31Sdp	fmt=$1
1436daaffb31Sdp	pfile=$PWS/$2
1437daaffb31Sdp	cfile=$CWS/$3
14387c478bd9Sstevel@tonic-gate
1439cdf0c1d5Smjnelson	if [[ ! -f $PWS/${2%/*}/SCCS/s.${2##*/} && -n $RWS ]]; then
1440cdf0c1d5Smjnelson		pfile=$RWS/$2
1441cdf0c1d5Smjnelson	fi
1442cdf0c1d5Smjnelson
1443daaffb31Sdp	if [[ -f $pfile ]]; then
1444cdf0c1d5Smjnelson		psid=$($SCCS prs -d:I: $pfile 2>/dev/null)
14457c478bd9Sstevel@tonic-gate	else
14467c478bd9Sstevel@tonic-gate		psid=1.1
14477c478bd9Sstevel@tonic-gate	fi
14487c478bd9Sstevel@tonic-gate
1449cdf0c1d5Smjnelson	set -A sids $($SCCS prs -l -r$psid -d:I: $cfile 2>/dev/null)
14507c478bd9Sstevel@tonic-gate	N=${#sids[@]}
14517c478bd9Sstevel@tonic-gate
1452daaffb31Sdp	nawkprg='
1453daaffb31Sdp		/^COMMENTS:/	{p=1; continue}
1454daaffb31Sdp		/^D [0-9]+\.[0-9]+/ {printf "--- %s ---\n", $2; p=0; }
1455daaffb31Sdp		NF == 0u	{ continue }
1456daaffb31Sdp		{if (p==0) continue; print $0 }'
1457daaffb31Sdp
14587c478bd9Sstevel@tonic-gate	if [[ $N -ge 2 ]]; then
14597c478bd9Sstevel@tonic-gate		sid1=${sids[$((N-2))]}	# Gets 2nd to last sid
14607c478bd9Sstevel@tonic-gate
1461daaffb31Sdp		if [[ $fmt == "text" ]]; then
1462cdf0c1d5Smjnelson			$SCCS prs -l -r$sid1 $cfile  2>/dev/null | \
1463cdf0c1d5Smjnelson			    $AWK "$nawkprg"
1464daaffb31Sdp			return
1465daaffb31Sdp		fi
1466daaffb31Sdp
1467cdf0c1d5Smjnelson		$SCCS prs -l -r$sid1 $cfile  2>/dev/null | \
14680fd2682eSMark J. Nelson		    html_quote | its2url | $AWK "$nawkprg"
14697c478bd9Sstevel@tonic-gate	fi
14707c478bd9Sstevel@tonic-gate}
14717c478bd9Sstevel@tonic-gate
1472daaffb31Sdp#
1473cdf0c1d5Smjnelson# comments_from_wx {text|html} filepath
1474daaffb31Sdp#
1475cdf0c1d5Smjnelson# Given the pathname of a file, find its location in a "wx" active
1476cdf0c1d5Smjnelson# file list and print the following comment.  Output is either text or
1477cdf0c1d5Smjnelson# HTML; if the latter, embedded bugids (sequence of 5 or more digits)
1478cdf0c1d5Smjnelson# are turned into URLs.
1479cdf0c1d5Smjnelson#
1480cdf0c1d5Smjnelson# This is also used with Mercurial and the file list provided by hg-active.
1481daaffb31Sdp#
1482daaffb31Sdpcomments_from_wx()
14837c478bd9Sstevel@tonic-gate{
1484daaffb31Sdp	typeset fmt=$1
1485daaffb31Sdp	typeset p=$2
14867c478bd9Sstevel@tonic-gate
1487cdf0c1d5Smjnelson	comm=`$AWK '
1488daaffb31Sdp	$1 == "'$p'" {
14897c478bd9Sstevel@tonic-gate		do getline ; while (NF > 0)
14907c478bd9Sstevel@tonic-gate		getline
14917c478bd9Sstevel@tonic-gate		while (NF > 0) { print ; getline }
14927c478bd9Sstevel@tonic-gate		exit
1493daaffb31Sdp	}' < $wxfile`
1494daaffb31Sdp
1495cdf0c1d5Smjnelson	if [[ -z $comm ]]; then
1496cdf0c1d5Smjnelson		comm="*** NO COMMENTS ***"
1497cdf0c1d5Smjnelson	fi
1498cdf0c1d5Smjnelson
1499daaffb31Sdp	if [[ $fmt == "text" ]]; then
1500cdf0c1d5Smjnelson		print -- "$comm"
1501daaffb31Sdp		return
1502daaffb31Sdp	fi
1503daaffb31Sdp
15040fd2682eSMark J. Nelson	print -- "$comm" | html_quote | its2url
1505cdf0c1d5Smjnelson
15067c478bd9Sstevel@tonic-gate}
15077c478bd9Sstevel@tonic-gate
15087c478bd9Sstevel@tonic-gate#
1509daaffb31Sdp# getcomments {text|html} filepath parentpath
1510daaffb31Sdp#
1511daaffb31Sdp# Fetch the comments depending on what SCM mode we're in.
1512daaffb31Sdp#
1513daaffb31Sdpgetcomments()
1514daaffb31Sdp{
1515daaffb31Sdp	typeset fmt=$1
1516daaffb31Sdp	typeset p=$2
1517daaffb31Sdp	typeset pp=$3
15187c478bd9Sstevel@tonic-gate
15193df69ef3SDarren Moffat	if [[ -n $Nflag ]]; then
15203df69ef3SDarren Moffat		return
15213df69ef3SDarren Moffat	fi
1522cdf0c1d5Smjnelson	#
1523cdf0c1d5Smjnelson	# Mercurial support uses a file list in wx format, so this
1524cdf0c1d5Smjnelson	# will be used there, too
1525cdf0c1d5Smjnelson	#
1526daaffb31Sdp	if [[ -n $wxfile ]]; then
1527daaffb31Sdp		comments_from_wx $fmt $p
1528daaffb31Sdp	else
1529daaffb31Sdp		if [[ $SCM_MODE == "teamware" ]]; then
1530daaffb31Sdp			comments_from_teamware $fmt $pp $p
1531daaffb31Sdp		fi
1532daaffb31Sdp	fi
1533daaffb31Sdp}
1534daaffb31Sdp
1535daaffb31Sdp#
1536daaffb31Sdp# printCI <total-changed> <inserted> <deleted> <modified> <unchanged>
1537daaffb31Sdp#
1538daaffb31Sdp# Print out Code Inspection figures similar to sccs-prt(1) format.
1539daaffb31Sdp#
1540daaffb31Sdpfunction printCI
1541daaffb31Sdp{
1542daaffb31Sdp	integer tot=$1 ins=$2 del=$3 mod=$4 unc=$5
1543daaffb31Sdp	typeset str
1544daaffb31Sdp	if (( tot == 1 )); then
1545daaffb31Sdp		str="line"
1546daaffb31Sdp	else
1547daaffb31Sdp		str="lines"
1548daaffb31Sdp	fi
1549daaffb31Sdp	printf '%d %s changed: %d ins; %d del; %d mod; %d unchg\n' \
1550daaffb31Sdp	    $tot $str $ins $del $mod $unc
1551daaffb31Sdp}
1552daaffb31Sdp
1553daaffb31Sdp
1554daaffb31Sdp#
1555daaffb31Sdp# difflines <oldfile> <newfile>
1556daaffb31Sdp#
1557daaffb31Sdp# Calculate and emit number of added, removed, modified and unchanged lines,
1558daaffb31Sdp# and total lines changed, the sum of added + removed + modified.
1559daaffb31Sdp#
15607c478bd9Sstevel@tonic-gatefunction difflines
15617c478bd9Sstevel@tonic-gate{
1562daaffb31Sdp	integer tot mod del ins unc err
15637c478bd9Sstevel@tonic-gate	typeset filename
15647c478bd9Sstevel@tonic-gate
1565cdf0c1d5Smjnelson	eval $( diff -e $1 $2 | $AWK '
1566daaffb31Sdp	# Change range of lines: N,Nc
15677c478bd9Sstevel@tonic-gate	/^[0-9]*,[0-9]*c$/ {
15687c478bd9Sstevel@tonic-gate		n=split(substr($1,1,length($1)-1), counts, ",");
15697c478bd9Sstevel@tonic-gate		if (n != 2) {
15707c478bd9Sstevel@tonic-gate		    error=2
15717c478bd9Sstevel@tonic-gate		    exit;
15727c478bd9Sstevel@tonic-gate		}
1573daaffb31Sdp		#
1574daaffb31Sdp		# 3,5c means lines 3 , 4 and 5 are changed, a total of 3 lines.
1575daaffb31Sdp		# following would be 5 - 3 = 2! Hence +1 for correction.
1576daaffb31Sdp		#
15777c478bd9Sstevel@tonic-gate		r=(counts[2]-counts[1])+1;
1578daaffb31Sdp
1579daaffb31Sdp		#
1580daaffb31Sdp		# Now count replacement lines: each represents a change instead
1581daaffb31Sdp		# of a delete, so increment c and decrement r.
1582daaffb31Sdp		#
15837c478bd9Sstevel@tonic-gate		while (getline != /^\.$/) {
15847c478bd9Sstevel@tonic-gate			c++;
15857c478bd9Sstevel@tonic-gate			r--;
15867c478bd9Sstevel@tonic-gate		}
1587daaffb31Sdp		#
1588daaffb31Sdp		# If there were more replacement lines than original lines,
1589daaffb31Sdp		# then r will be negative; in this case there are no deletions,
1590daaffb31Sdp		# but there are r changes that should be counted as adds, and
1591daaffb31Sdp		# since r is negative, subtract it from a and add it to c.
1592daaffb31Sdp		#
15937c478bd9Sstevel@tonic-gate		if (r < 0) {
15947c478bd9Sstevel@tonic-gate			a-=r;
15957c478bd9Sstevel@tonic-gate			c+=r;
15967c478bd9Sstevel@tonic-gate		}
1597daaffb31Sdp
1598daaffb31Sdp		#
1599daaffb31Sdp		# If there were more original lines than replacement lines, then
1600daaffb31Sdp		# r will be positive; in this case, increment d by that much.
1601daaffb31Sdp		#
16027c478bd9Sstevel@tonic-gate		if (r > 0) {
16037c478bd9Sstevel@tonic-gate			d+=r;
16047c478bd9Sstevel@tonic-gate		}
16057c478bd9Sstevel@tonic-gate		next;
16067c478bd9Sstevel@tonic-gate	}
16077c478bd9Sstevel@tonic-gate
1608daaffb31Sdp	# Change lines: Nc
16097c478bd9Sstevel@tonic-gate	/^[0-9].*c$/ {
1610daaffb31Sdp		# The first line is a replacement; any more are additions.
16117c478bd9Sstevel@tonic-gate		if (getline != /^\.$/) {
16127c478bd9Sstevel@tonic-gate			c++;
16137c478bd9Sstevel@tonic-gate			while (getline != /^\.$/) a++;
16147c478bd9Sstevel@tonic-gate		}
16157c478bd9Sstevel@tonic-gate		next;
16167c478bd9Sstevel@tonic-gate	}
16177c478bd9Sstevel@tonic-gate
1618daaffb31Sdp	# Add lines: both Na and N,Na
16197c478bd9Sstevel@tonic-gate	/^[0-9].*a$/ {
16207c478bd9Sstevel@tonic-gate		while (getline != /^\.$/) a++;
16217c478bd9Sstevel@tonic-gate		next;
16227c478bd9Sstevel@tonic-gate	}
16237c478bd9Sstevel@tonic-gate
1624daaffb31Sdp	# Delete range of lines: N,Nd
16257c478bd9Sstevel@tonic-gate	/^[0-9]*,[0-9]*d$/ {
16267c478bd9Sstevel@tonic-gate		n=split(substr($1,1,length($1)-1), counts, ",");
16277c478bd9Sstevel@tonic-gate		if (n != 2) {
16287c478bd9Sstevel@tonic-gate			error=2
16297c478bd9Sstevel@tonic-gate			exit;
16307c478bd9Sstevel@tonic-gate		}
1631daaffb31Sdp		#
1632daaffb31Sdp		# 3,5d means lines 3 , 4 and 5 are deleted, a total of 3 lines.
1633daaffb31Sdp		# following would be 5 - 3 = 2! Hence +1 for correction.
1634daaffb31Sdp		#
16357c478bd9Sstevel@tonic-gate		r=(counts[2]-counts[1])+1;
16367c478bd9Sstevel@tonic-gate		d+=r;
16377c478bd9Sstevel@tonic-gate		next;
16387c478bd9Sstevel@tonic-gate	}
16397c478bd9Sstevel@tonic-gate
1640daaffb31Sdp	# Delete line: Nd.   For example 10d says line 10 is deleted.
16417c478bd9Sstevel@tonic-gate	/^[0-9]*d$/ {d++; next}
16427c478bd9Sstevel@tonic-gate
1643daaffb31Sdp	# Should not get here!
16447c478bd9Sstevel@tonic-gate	{
16457c478bd9Sstevel@tonic-gate		error=1;
16467c478bd9Sstevel@tonic-gate		exit;
16477c478bd9Sstevel@tonic-gate	}
16487c478bd9Sstevel@tonic-gate
1649daaffb31Sdp	# Finish off - print results
16507c478bd9Sstevel@tonic-gate	END {
1651daaffb31Sdp		printf("tot=%d;mod=%d;del=%d;ins=%d;err=%d\n",
16527c478bd9Sstevel@tonic-gate		    (c+d+a), c, d, a, error);
16537c478bd9Sstevel@tonic-gate	}' )
16547c478bd9Sstevel@tonic-gate
1655cdf0c1d5Smjnelson	# End of $AWK, Check to see if any trouble occurred.
16567c478bd9Sstevel@tonic-gate	if (( $? > 0 || err > 0 )); then
1657daaffb31Sdp		print "Unexpected Error occurred reading" \
1658daaffb31Sdp		    "\`diff -e $1 $2\`: \$?=$?, err=" $err
1659daaffb31Sdp		return
1660daaffb31Sdp	fi
1661daaffb31Sdp
16627c478bd9Sstevel@tonic-gate	# Accumulate totals
16637c478bd9Sstevel@tonic-gate	(( TOTL += tot ))
1664daaffb31Sdp	(( TMOD += mod ))
16657c478bd9Sstevel@tonic-gate	(( TDEL += del ))
16667c478bd9Sstevel@tonic-gate	(( TINS += ins ))
16677c478bd9Sstevel@tonic-gate	# Calculate unchanged lines
1668cdf0c1d5Smjnelson	unc=`wc -l < $1`
16697c478bd9Sstevel@tonic-gate	if (( unc > 0 )); then
1670daaffb31Sdp		(( unc -= del + mod ))
16717c478bd9Sstevel@tonic-gate		(( TUNC += unc ))
16727c478bd9Sstevel@tonic-gate	fi
16737c478bd9Sstevel@tonic-gate	# print summary
1674daaffb31Sdp	print "<span class=\"lineschanged\">"
1675daaffb31Sdp	printCI $tot $ins $del $mod $unc
1676daaffb31Sdp	print "</span>"
16777c478bd9Sstevel@tonic-gate}
16787c478bd9Sstevel@tonic-gate
1679daaffb31Sdp
16807c478bd9Sstevel@tonic-gate#
1681daaffb31Sdp# flist_from_wx
1682daaffb31Sdp#
1683daaffb31Sdp# Sets up webrev to source its information from a wx-formatted file.
1684daaffb31Sdp# Sets the global 'wxfile' variable.
1685daaffb31Sdp#
1686daaffb31Sdpfunction flist_from_wx
16877c478bd9Sstevel@tonic-gate{
1688daaffb31Sdp	typeset argfile=$1
1689daaffb31Sdp	if [[ -n ${argfile%%/*} ]]; then
1690daaffb31Sdp		#
1691daaffb31Sdp		# If the wx file pathname is relative then make it absolute
1692daaffb31Sdp		# because the webrev does a "cd" later on.
1693daaffb31Sdp		#
1694daaffb31Sdp		wxfile=$PWD/$argfile
16957c478bd9Sstevel@tonic-gate	else
1696daaffb31Sdp		wxfile=$argfile
16977c478bd9Sstevel@tonic-gate	fi
16987c478bd9Sstevel@tonic-gate
1699cdf0c1d5Smjnelson	$AWK '{ c = 1; print;
17007c478bd9Sstevel@tonic-gate	  while (getline) {
17017c478bd9Sstevel@tonic-gate		if (NF == 0) { c = -c; continue }
17027c478bd9Sstevel@tonic-gate		if (c > 0) print
17037c478bd9Sstevel@tonic-gate	  }
1704daaffb31Sdp	}' $wxfile > $FLIST
17057c478bd9Sstevel@tonic-gate
1706daaffb31Sdp	print " Done."
1707daaffb31Sdp}
17087c478bd9Sstevel@tonic-gate
1709daaffb31Sdp#
1710daaffb31Sdp# flist_from_teamware [ <args-to-putback-n> ]
1711daaffb31Sdp#
1712daaffb31Sdp# Generate the file list by extracting file names from a putback -n.  Some
1713daaffb31Sdp# names may come from the "update/create" messages and others from the
1714daaffb31Sdp# "currently checked out" warning.  Renames are detected here too.  Extract
1715daaffb31Sdp# values for CODEMGR_WS and CODEMGR_PARENT from the output of the putback
1716daaffb31Sdp# -n as well, but remove them if they are already defined.
1717daaffb31Sdp#
1718daaffb31Sdpfunction flist_from_teamware
1719daaffb31Sdp{
1720cdf0c1d5Smjnelson	if [[ -n $codemgr_parent && -z $parent_webrev ]]; then
1721daaffb31Sdp		if [[ ! -d $codemgr_parent/Codemgr_wsdata ]]; then
1722daaffb31Sdp			print -u2 "parent $codemgr_parent doesn't look like a" \
1723daaffb31Sdp			    "valid teamware workspace"
17247c478bd9Sstevel@tonic-gate			exit 1
17257c478bd9Sstevel@tonic-gate		fi
1726daaffb31Sdp		parent_args="-p $codemgr_parent"
17277c478bd9Sstevel@tonic-gate	fi
17287c478bd9Sstevel@tonic-gate
1729daaffb31Sdp	print " File list from: 'putback -n $parent_args $*' ... \c"
17307c478bd9Sstevel@tonic-gate
1731daaffb31Sdp	putback -n $parent_args $* 2>&1 |
1732cdf0c1d5Smjnelson	    $AWK '
1733daaffb31Sdp		/^update:|^create:/	{print $2}
1734daaffb31Sdp		/^Parent workspace:/	{printf("CODEMGR_PARENT=%s\n",$3)}
1735daaffb31Sdp		/^Child workspace:/	{printf("CODEMGR_WS=%s\n",$3)}
1736daaffb31Sdp		/^The following files are currently checked out/ {p = 1; continue}
1737daaffb31Sdp		NF == 0			{p=0 ; continue}
1738daaffb31Sdp		/^rename/		{old=$3}
1739daaffb31Sdp		$1 == "to:"		{print $2, old}
1740daaffb31Sdp		/^"/			{continue}
1741daaffb31Sdp		p == 1			{print $1}' |
1742daaffb31Sdp	    sort -r -k 1,1 -u | sort > $FLIST
17437c478bd9Sstevel@tonic-gate
1744daaffb31Sdp	print " Done."
1745daaffb31Sdp}
1746daaffb31Sdp
1747cdf0c1d5Smjnelson#
1748cdf0c1d5Smjnelson# Call hg-active to get the active list output in the wx active list format
1749cdf0c1d5Smjnelson#
1750cdf0c1d5Smjnelsonfunction hg_active_wxfile
1751cdf0c1d5Smjnelson{
1752cdf0c1d5Smjnelson	typeset child=$1
1753cdf0c1d5Smjnelson	typeset parent=$2
1754cdf0c1d5Smjnelson
1755cdf0c1d5Smjnelson	TMPFLIST=/tmp/$$.active
17569a70fc3bSMark J. Nelson	$HG_ACTIVE -w $child -p $parent -o $TMPFLIST
1757cdf0c1d5Smjnelson	wxfile=$TMPFLIST
1758cdf0c1d5Smjnelson}
1759cdf0c1d5Smjnelson
1760cdf0c1d5Smjnelson#
1761cdf0c1d5Smjnelson# flist_from_mercurial
1762cdf0c1d5Smjnelson# Call hg-active to get a wx-style active list, and hand it off to
1763cdf0c1d5Smjnelson# flist_from_wx
1764cdf0c1d5Smjnelson#
1765cdf0c1d5Smjnelsonfunction flist_from_mercurial
1766cdf0c1d5Smjnelson{
1767cdf0c1d5Smjnelson	typeset child=$1
1768cdf0c1d5Smjnelson	typeset parent=$2
1769cdf0c1d5Smjnelson
1770cdf0c1d5Smjnelson	print " File list from: hg-active -p $parent ...\c"
1771cdf0c1d5Smjnelson	if [[ ! -x $HG_ACTIVE ]]; then
1772cdf0c1d5Smjnelson		print		# Blank line for the \c above
1773cdf0c1d5Smjnelson		print -u2 "Error: hg-active tool not found.  Exiting"
1774cdf0c1d5Smjnelson		exit 1
1775cdf0c1d5Smjnelson	fi
1776cdf0c1d5Smjnelson	hg_active_wxfile $child $parent
1777cdf0c1d5Smjnelson
1778cdf0c1d5Smjnelson	# flist_from_wx prints the Done, so we don't have to.
1779cdf0c1d5Smjnelson	flist_from_wx $TMPFLIST
1780cdf0c1d5Smjnelson}
1781cdf0c1d5Smjnelson
1782cdf0c1d5Smjnelson#
1783cdf0c1d5Smjnelson# flist_from_subversion
1784cdf0c1d5Smjnelson#
1785cdf0c1d5Smjnelson# Generate the file list by extracting file names from svn status.
1786cdf0c1d5Smjnelson#
1787cdf0c1d5Smjnelsonfunction flist_from_subversion
1788cdf0c1d5Smjnelson{
1789cdf0c1d5Smjnelson	CWS=$1
1790cdf0c1d5Smjnelson	OLDPWD=$2
1791cdf0c1d5Smjnelson
1792cdf0c1d5Smjnelson	cd $CWS
1793cdf0c1d5Smjnelson	print -u2 " File list from: svn status ... \c"
1794cdf0c1d5Smjnelson	svn status | $AWK '/^[ACDMR]/ { print $NF }' > $FLIST
1795cdf0c1d5Smjnelson	print -u2 " Done."
1796cdf0c1d5Smjnelson	cd $OLDPWD
1797cdf0c1d5Smjnelson}
1798cdf0c1d5Smjnelson
1799daaffb31Sdpfunction env_from_flist
1800daaffb31Sdp{
1801daaffb31Sdp	[[ -r $FLIST ]] || return
1802daaffb31Sdp
1803daaffb31Sdp	#
1804daaffb31Sdp	# Use "eval" to set env variables that are listed in the file
1805daaffb31Sdp	# list.  Then copy those into our local versions of those
1806daaffb31Sdp	# variables if they have not been set already.
1807daaffb31Sdp	#
1808b0088928SVladimir Kotal	eval `$SED -e "s/#.*$//" $FLIST | $GREP = `
18097c478bd9Sstevel@tonic-gate
1810cdf0c1d5Smjnelson	if [[ -z $codemgr_ws && -n $CODEMGR_WS ]]; then
1811cdf0c1d5Smjnelson		codemgr_ws=$CODEMGR_WS
1812cdf0c1d5Smjnelson		export CODEMGR_WS
1813cdf0c1d5Smjnelson	fi
18147c478bd9Sstevel@tonic-gate
1815daaffb31Sdp	#
1816daaffb31Sdp	# Check to see if CODEMGR_PARENT is set in the flist file.
1817daaffb31Sdp	#
1818cdf0c1d5Smjnelson	if [[ -z $codemgr_parent && -n $CODEMGR_PARENT ]]; then
1819daaffb31Sdp		codemgr_parent=$CODEMGR_PARENT
1820cdf0c1d5Smjnelson		export CODEMGR_PARENT
1821daaffb31Sdp	fi
1822daaffb31Sdp}
1823daaffb31Sdp
182414983201Sdpfunction look_for_prog
182514983201Sdp{
182614983201Sdp	typeset path
182714983201Sdp	typeset ppath
182814983201Sdp	typeset progname=$1
182914983201Sdp
183014983201Sdp	ppath=$PATH
183114983201Sdp	ppath=$ppath:/usr/sfw/bin:/usr/bin:/usr/sbin
183214983201Sdp	ppath=$ppath:/opt/teamware/bin:/opt/onbld/bin
1833cdf0c1d5Smjnelson	ppath=$ppath:/opt/onbld/bin/`uname -p`
183414983201Sdp
183514983201Sdp	PATH=$ppath prog=`whence $progname`
183614983201Sdp	if [[ -n $prog ]]; then
183714983201Sdp		print $prog
183814983201Sdp	fi
183914983201Sdp}
184014983201Sdp
1841cdf0c1d5Smjnelsonfunction get_file_mode
1842cdf0c1d5Smjnelson{
1843cdf0c1d5Smjnelson	$PERL -e '
1844cdf0c1d5Smjnelson		if (@stat = stat($ARGV[0])) {
1845cdf0c1d5Smjnelson			$mode = $stat[2] & 0777;
1846cdf0c1d5Smjnelson			printf "%03o\n", $mode;
1847cdf0c1d5Smjnelson			exit 0;
1848cdf0c1d5Smjnelson		} else {
1849cdf0c1d5Smjnelson			exit 1;
1850cdf0c1d5Smjnelson		}
1851cdf0c1d5Smjnelson	    ' $1
1852cdf0c1d5Smjnelson}
1853cdf0c1d5Smjnelson
1854cdf0c1d5Smjnelsonfunction build_old_new_teamware
1855cdf0c1d5Smjnelson{
1856cdf0c1d5Smjnelson	typeset olddir="$1"
1857cdf0c1d5Smjnelson	typeset newdir="$2"
1858cdf0c1d5Smjnelson
1859cdf0c1d5Smjnelson	# If the child's version doesn't exist then
1860cdf0c1d5Smjnelson	# get a readonly copy.
1861cdf0c1d5Smjnelson
1862cdf0c1d5Smjnelson	if [[ ! -f $CWS/$DIR/$F && -f $CWS/$DIR/SCCS/s.$F ]]; then
1863cdf0c1d5Smjnelson		$SCCS get -s -p $CWS/$DIR/$F > $CWS/$DIR/$F
1864cdf0c1d5Smjnelson	fi
1865cdf0c1d5Smjnelson
1866cdf0c1d5Smjnelson	# The following two sections propagate file permissions the
1867cdf0c1d5Smjnelson	# same way SCCS does.  If the file is already under version
1868cdf0c1d5Smjnelson	# control, always use permissions from the SCCS/s.file.  If
1869cdf0c1d5Smjnelson	# the file is not under SCCS control, use permissions from the
1870cdf0c1d5Smjnelson	# working copy.  In all cases, the file copied to the webrev
1871cdf0c1d5Smjnelson	# is set to read only, and group/other permissions are set to
1872cdf0c1d5Smjnelson	# match those of the file owner.  This way, even if the file
1873cdf0c1d5Smjnelson	# is currently checked out, the webrev will display the final
1874cdf0c1d5Smjnelson	# permissions that would result after check in.
1875cdf0c1d5Smjnelson
1876cdf0c1d5Smjnelson	#
1877cdf0c1d5Smjnelson	# Snag new version of file.
1878cdf0c1d5Smjnelson	#
1879cdf0c1d5Smjnelson	rm -f $newdir/$DIR/$F
1880cdf0c1d5Smjnelson	cp $CWS/$DIR/$F $newdir/$DIR/$F
1881cdf0c1d5Smjnelson	if [[ -f $CWS/$DIR/SCCS/s.$F ]]; then
1882cdf0c1d5Smjnelson		chmod `get_file_mode $CWS/$DIR/SCCS/s.$F` \
1883cdf0c1d5Smjnelson		    $newdir/$DIR/$F
1884cdf0c1d5Smjnelson	fi
1885cdf0c1d5Smjnelson	chmod u-w,go=u $newdir/$DIR/$F
1886cdf0c1d5Smjnelson
1887cdf0c1d5Smjnelson	#
1888cdf0c1d5Smjnelson	# Get the parent's version of the file. First see whether the
1889cdf0c1d5Smjnelson	# child's version is checked out and get the parent's version
1890cdf0c1d5Smjnelson	# with keywords expanded or unexpanded as appropriate.
1891cdf0c1d5Smjnelson	#
1892cdf0c1d5Smjnelson	if [[ -f $PWS/$PDIR/$PF && ! -f $PWS/$PDIR/SCCS/s.$PF && \
1893cdf0c1d5Smjnelson	    ! -f $PWS/$PDIR/SCCS/p.$PF ]]; then
1894cdf0c1d5Smjnelson		# Parent is not a real workspace, but just a raw
1895cdf0c1d5Smjnelson		# directory tree - use the file that's there as
1896cdf0c1d5Smjnelson		# the old file.
1897cdf0c1d5Smjnelson
1898cdf0c1d5Smjnelson		rm -f $olddir/$PDIR/$PF
1899cdf0c1d5Smjnelson		cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF
1900cdf0c1d5Smjnelson	else
1901cdf0c1d5Smjnelson		if [[ -f $PWS/$PDIR/SCCS/s.$PF ]]; then
1902cdf0c1d5Smjnelson			real_parent=$PWS
1903cdf0c1d5Smjnelson		else
1904cdf0c1d5Smjnelson			real_parent=$RWS
1905cdf0c1d5Smjnelson		fi
1906cdf0c1d5Smjnelson
1907cdf0c1d5Smjnelson		rm -f $olddir/$PDIR/$PF
1908cdf0c1d5Smjnelson
1909cdf0c1d5Smjnelson		if [[ -f $real_parent/$PDIR/$PF ]]; then
1910cdf0c1d5Smjnelson			if [ -f $CWS/$DIR/SCCS/p.$F ]; then
1911cdf0c1d5Smjnelson				$SCCS get -s -p -k $real_parent/$PDIR/$PF > \
1912cdf0c1d5Smjnelson				    $olddir/$PDIR/$PF
1913cdf0c1d5Smjnelson			else
1914cdf0c1d5Smjnelson				$SCCS get -s -p    $real_parent/$PDIR/$PF > \
1915cdf0c1d5Smjnelson				    $olddir/$PDIR/$PF
1916cdf0c1d5Smjnelson			fi
1917cdf0c1d5Smjnelson			chmod `get_file_mode $real_parent/$PDIR/SCCS/s.$PF` \
1918cdf0c1d5Smjnelson			    $olddir/$PDIR/$PF
1919cdf0c1d5Smjnelson		fi
1920cdf0c1d5Smjnelson	fi
1921cdf0c1d5Smjnelson	if [[ -f $olddir/$PDIR/$PF ]]; then
1922cdf0c1d5Smjnelson		chmod u-w,go=u $olddir/$PDIR/$PF
1923cdf0c1d5Smjnelson	fi
1924cdf0c1d5Smjnelson}
1925cdf0c1d5Smjnelson
1926cdf0c1d5Smjnelsonfunction build_old_new_mercurial
1927cdf0c1d5Smjnelson{
1928cdf0c1d5Smjnelson	typeset olddir="$1"
1929cdf0c1d5Smjnelson	typeset newdir="$2"
1930cdf0c1d5Smjnelson	typeset old_mode=
1931cdf0c1d5Smjnelson	typeset new_mode=
1932cdf0c1d5Smjnelson	typeset file
1933cdf0c1d5Smjnelson
1934cdf0c1d5Smjnelson	#
1935cdf0c1d5Smjnelson	# Get old file mode, from the parent revision manifest entry.
1936cdf0c1d5Smjnelson	# Mercurial only stores a "file is executable" flag, but the
1937cdf0c1d5Smjnelson	# manifest will display an octal mode "644" or "755".
1938cdf0c1d5Smjnelson	#
1939cdf0c1d5Smjnelson	if [[ "$PDIR" == "." ]]; then
1940cdf0c1d5Smjnelson		file="$PF"
1941cdf0c1d5Smjnelson	else
1942cdf0c1d5Smjnelson		file="$PDIR/$PF"
1943cdf0c1d5Smjnelson	fi
1944b0088928SVladimir Kotal	file=`echo $file | $SED 's#/#\\\/#g'`
1945cdf0c1d5Smjnelson	# match the exact filename, and return only the permission digits
1946b0088928SVladimir Kotal	old_mode=`$SED -n -e "/^\\(...\\) . ${file}$/s//\\1/p" \
1947cdf0c1d5Smjnelson	    < $HG_PARENT_MANIFEST`
1948cdf0c1d5Smjnelson
1949cdf0c1d5Smjnelson	#
1950cdf0c1d5Smjnelson	# Get new file mode, directly from the filesystem.
1951cdf0c1d5Smjnelson	# Normalize the mode to match Mercurial's behavior.
1952cdf0c1d5Smjnelson	#
1953cdf0c1d5Smjnelson	new_mode=`get_file_mode $CWS/$DIR/$F`
1954cdf0c1d5Smjnelson	if [[ -n "$new_mode" ]]; then
1955cdf0c1d5Smjnelson		if [[ "$new_mode" = *[1357]* ]]; then
1956cdf0c1d5Smjnelson			new_mode=755
1957cdf0c1d5Smjnelson		else
1958cdf0c1d5Smjnelson			new_mode=644
1959cdf0c1d5Smjnelson		fi
1960cdf0c1d5Smjnelson	fi
1961cdf0c1d5Smjnelson
1962cdf0c1d5Smjnelson	#
1963cdf0c1d5Smjnelson	# new version of the file.
1964cdf0c1d5Smjnelson	#
1965cdf0c1d5Smjnelson	rm -rf $newdir/$DIR/$F
1966cdf0c1d5Smjnelson	if [[ -e $CWS/$DIR/$F ]]; then
1967cdf0c1d5Smjnelson		cp $CWS/$DIR/$F $newdir/$DIR/$F
1968cdf0c1d5Smjnelson		if [[ -n $new_mode ]]; then
1969cdf0c1d5Smjnelson			chmod $new_mode $newdir/$DIR/$F
1970cdf0c1d5Smjnelson		else
1971cdf0c1d5Smjnelson			# should never happen
1972cdf0c1d5Smjnelson			print -u2 "ERROR: set mode of $newdir/$DIR/$F"
1973cdf0c1d5Smjnelson		fi
1974cdf0c1d5Smjnelson	fi
1975cdf0c1d5Smjnelson
1976cdf0c1d5Smjnelson	#
1977cdf0c1d5Smjnelson	# parent's version of the file
1978cdf0c1d5Smjnelson	#
1979cdf0c1d5Smjnelson	# Note that we get this from the last version common to both
1980cdf0c1d5Smjnelson	# ourselves and the parent.  References are via $CWS since we have no
1981cdf0c1d5Smjnelson	# guarantee that the parent workspace is reachable via the filesystem.
1982cdf0c1d5Smjnelson	#
1983cdf0c1d5Smjnelson	if [[ -n $parent_webrev && -e $PWS/$PDIR/$PF ]]; then
1984cdf0c1d5Smjnelson		cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF
1985cdf0c1d5Smjnelson	elif [[ -n $HG_PARENT ]]; then
1986cdf0c1d5Smjnelson		hg cat -R $CWS -r $HG_PARENT $CWS/$PDIR/$PF > \
1987cdf0c1d5Smjnelson		    $olddir/$PDIR/$PF 2>/dev/null
1988cdf0c1d5Smjnelson
198902d26c39SVladimir Kotal		if (( $? != 0 )); then
1990cdf0c1d5Smjnelson			rm -f $olddir/$PDIR/$PF
1991cdf0c1d5Smjnelson		else
1992cdf0c1d5Smjnelson			if [[ -n $old_mode ]]; then
1993cdf0c1d5Smjnelson				chmod $old_mode $olddir/$PDIR/$PF
1994cdf0c1d5Smjnelson			else
1995cdf0c1d5Smjnelson				# should never happen
1996cdf0c1d5Smjnelson				print -u2 "ERROR: set mode of $olddir/$PDIR/$PF"
1997cdf0c1d5Smjnelson			fi
1998cdf0c1d5Smjnelson		fi
1999cdf0c1d5Smjnelson	fi
2000cdf0c1d5Smjnelson}
2001cdf0c1d5Smjnelson
2002cdf0c1d5Smjnelsonfunction build_old_new_subversion
2003cdf0c1d5Smjnelson{
2004cdf0c1d5Smjnelson	typeset olddir="$1"
2005cdf0c1d5Smjnelson	typeset newdir="$2"
2006cdf0c1d5Smjnelson
2007cdf0c1d5Smjnelson	# Snag new version of file.
2008cdf0c1d5Smjnelson	rm -f $newdir/$DIR/$F
2009cdf0c1d5Smjnelson	[[ -e $CWS/$DIR/$F ]] && cp $CWS/$DIR/$F $newdir/$DIR/$F
2010cdf0c1d5Smjnelson
2011cdf0c1d5Smjnelson	if [[ -n $PWS && -e $PWS/$PDIR/$PF ]]; then
2012cdf0c1d5Smjnelson		cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF
2013cdf0c1d5Smjnelson	else
2014cdf0c1d5Smjnelson		# Get the parent's version of the file.
2015cdf0c1d5Smjnelson		svn status $CWS/$DIR/$F | read stat file
2016cdf0c1d5Smjnelson		if [[ $stat != "A" ]]; then
2017cdf0c1d5Smjnelson			svn cat -r BASE $CWS/$DIR/$F > $olddir/$PDIR/$PF
2018cdf0c1d5Smjnelson		fi
2019cdf0c1d5Smjnelson	fi
2020cdf0c1d5Smjnelson}
2021cdf0c1d5Smjnelson
2022cdf0c1d5Smjnelsonfunction build_old_new_unknown
2023cdf0c1d5Smjnelson{
2024cdf0c1d5Smjnelson	typeset olddir="$1"
2025cdf0c1d5Smjnelson	typeset newdir="$2"
2026cdf0c1d5Smjnelson
2027cdf0c1d5Smjnelson	#
2028cdf0c1d5Smjnelson	# Snag new version of file.
2029cdf0c1d5Smjnelson	#
2030cdf0c1d5Smjnelson	rm -f $newdir/$DIR/$F
2031cdf0c1d5Smjnelson	[[ -e $CWS/$DIR/$F ]] && cp $CWS/$DIR/$F $newdir/$DIR/$F
2032cdf0c1d5Smjnelson
2033cdf0c1d5Smjnelson	#
2034cdf0c1d5Smjnelson	# Snag the parent's version of the file.
2035cdf0c1d5Smjnelson	#
2036cdf0c1d5Smjnelson	if [[ -f $PWS/$PDIR/$PF ]]; then
2037cdf0c1d5Smjnelson		rm -f $olddir/$PDIR/$PF
2038cdf0c1d5Smjnelson		cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF
2039cdf0c1d5Smjnelson	fi
2040cdf0c1d5Smjnelson}
2041cdf0c1d5Smjnelson
2042cdf0c1d5Smjnelsonfunction build_old_new
2043cdf0c1d5Smjnelson{
2044cdf0c1d5Smjnelson	typeset WDIR=$1
2045cdf0c1d5Smjnelson	typeset PWS=$2
2046cdf0c1d5Smjnelson	typeset PDIR=$3
2047cdf0c1d5Smjnelson	typeset PF=$4
2048cdf0c1d5Smjnelson	typeset CWS=$5
2049cdf0c1d5Smjnelson	typeset DIR=$6
2050cdf0c1d5Smjnelson	typeset F=$7
2051cdf0c1d5Smjnelson
2052cdf0c1d5Smjnelson	typeset olddir="$WDIR/raw_files/old"
2053cdf0c1d5Smjnelson	typeset newdir="$WDIR/raw_files/new"
2054cdf0c1d5Smjnelson
2055cdf0c1d5Smjnelson	mkdir -p $olddir/$PDIR
2056cdf0c1d5Smjnelson	mkdir -p $newdir/$DIR
2057cdf0c1d5Smjnelson
2058cdf0c1d5Smjnelson	if [[ $SCM_MODE == "teamware" ]]; then
2059cdf0c1d5Smjnelson		build_old_new_teamware "$olddir" "$newdir"
2060cdf0c1d5Smjnelson	elif [[ $SCM_MODE == "mercurial" ]]; then
2061cdf0c1d5Smjnelson		build_old_new_mercurial "$olddir" "$newdir"
2062cdf0c1d5Smjnelson	elif [[ $SCM_MODE == "subversion" ]]; then
2063cdf0c1d5Smjnelson		build_old_new_subversion "$olddir" "$newdir"
2064cdf0c1d5Smjnelson	elif [[ $SCM_MODE == "unknown" ]]; then
2065cdf0c1d5Smjnelson		build_old_new_unknown "$olddir" "$newdir"
2066cdf0c1d5Smjnelson	fi
2067cdf0c1d5Smjnelson
2068cdf0c1d5Smjnelson	if [[ ! -f $olddir/$PDIR/$PF && ! -f $newdir/$DIR/$F ]]; then
2069cdf0c1d5Smjnelson		print "*** Error: file not in parent or child"
2070cdf0c1d5Smjnelson		return 1
2071cdf0c1d5Smjnelson	fi
2072cdf0c1d5Smjnelson	return 0
2073cdf0c1d5Smjnelson}
2074cdf0c1d5Smjnelson
2075cdf0c1d5Smjnelson
2076daaffb31Sdp#
2077daaffb31Sdp# Usage message.
2078daaffb31Sdp#
2079daaffb31Sdpfunction usage
2080daaffb31Sdp{
2081daaffb31Sdp	print 'Usage:\twebrev [common-options]
2082daaffb31Sdp	webrev [common-options] ( <file> | - )
2083daaffb31Sdp	webrev [common-options] -w <wx file>
2084daaffb31Sdp
2085daaffb31SdpOptions:
20860fd2682eSMark J. Nelson	-C <filename>: Use <filename> for the information tracking configuration.
2087ba44d8a2SVladimir Kotal	-D: delete remote webrev
2088daaffb31Sdp	-i <filename>: Include <filename> in the index.html file.
20890fd2682eSMark J. Nelson	-I <filename>: Use <filename> for the information tracking registry.
2090ba44d8a2SVladimir Kotal	-n: do not generate the webrev (useful with -U)
2091ba44d8a2SVladimir Kotal	-O: Print bugids/arc cases suitable for OpenSolaris.
2092daaffb31Sdp	-o <outdir>: Output webrev to specified directory.
2093daaffb31Sdp	-p <compare-against>: Use specified parent wkspc or basis for comparison
209402d26c39SVladimir Kotal	-t <remote_target>: Specify remote destination for webrev upload
209502d26c39SVladimir Kotal	-U: upload the webrev to remote destination
2096daaffb31Sdp	-w <wxfile>: Use specified wx active file.
2097daaffb31Sdp
2098daaffb31SdpEnvironment:
2099daaffb31Sdp	WDIR: Control the output directory.
2100ba44d8a2SVladimir Kotal	WEBREV_TRASH_DIR: Set directory for webrev delete.
2101daaffb31Sdp
2102cdf0c1d5SmjnelsonSCM Specific Options:
2103cdf0c1d5Smjnelson	TeamWare: webrev [common-options] -l [arguments to 'putback']
2104cdf0c1d5Smjnelson
2105daaffb31SdpSCM Environment:
2106cdf0c1d5Smjnelson	CODEMGR_WS: Workspace location.
2107cdf0c1d5Smjnelson	CODEMGR_PARENT: Parent workspace location.
2108daaffb31Sdp'
2109daaffb31Sdp
2110daaffb31Sdp	exit 2
2111daaffb31Sdp}
2112daaffb31Sdp
2113daaffb31Sdp#
2114daaffb31Sdp#
2115daaffb31Sdp# Main program starts here
2116daaffb31Sdp#
2117daaffb31Sdp#
2118daaffb31Sdp
2119daaffb31Sdptrap "rm -f /tmp/$$.* ; exit" 0 1 2 3 15
2120daaffb31Sdp
2121daaffb31Sdpset +o noclobber
2122daaffb31Sdp
2123cdf0c1d5SmjnelsonPATH=$(dirname $(whence $0)):$PATH
2124cdf0c1d5Smjnelson
212514983201Sdp[[ -z $WDIFF ]] && WDIFF=`look_for_prog wdiff`
212614983201Sdp[[ -z $WX ]] && WX=`look_for_prog wx`
2127cdf0c1d5Smjnelson[[ -z $HG_ACTIVE ]] && HG_ACTIVE=`look_for_prog hg-active`
2128cdf0c1d5Smjnelson[[ -z $WHICH_SCM ]] && WHICH_SCM=`look_for_prog which_scm`
212914983201Sdp[[ -z $CODEREVIEW ]] && CODEREVIEW=`look_for_prog codereview`
213014983201Sdp[[ -z $PS2PDF ]] && PS2PDF=`look_for_prog ps2pdf`
213114983201Sdp[[ -z $PERL ]] && PERL=`look_for_prog perl`
213202d26c39SVladimir Kotal[[ -z $RSYNC ]] && RSYNC=`look_for_prog rsync`
2133cdf0c1d5Smjnelson[[ -z $SCCS ]] && SCCS=`look_for_prog sccs`
2134cdf0c1d5Smjnelson[[ -z $AWK ]] && AWK=`look_for_prog nawk`
2135cdf0c1d5Smjnelson[[ -z $AWK ]] && AWK=`look_for_prog gawk`
2136cdf0c1d5Smjnelson[[ -z $AWK ]] && AWK=`look_for_prog awk`
213702d26c39SVladimir Kotal[[ -z $SCP ]] && SCP=`look_for_prog scp`
2138b0088928SVladimir Kotal[[ -z $SED ]] && SED=`look_for_prog sed`
213902d26c39SVladimir Kotal[[ -z $SFTP ]] && SFTP=`look_for_prog sftp`
2140e6ccc173SEdward Pilatowicz[[ -z $SORT ]] && SORT=`look_for_prog sort`
214102d26c39SVladimir Kotal[[ -z $MKTEMP ]] && MKTEMP=`look_for_prog mktemp`
214202d26c39SVladimir Kotal[[ -z $GREP ]] && GREP=`look_for_prog grep`
2143ba44d8a2SVladimir Kotal[[ -z $FIND ]] && FIND=`look_for_prog find`
2144cdf0c1d5Smjnelson
2145ba44d8a2SVladimir Kotal# set name of trash directory for remote webrev deletion
2146ba44d8a2SVladimir KotalTRASH_DIR=".trash"
2147ba44d8a2SVladimir Kotal[[ -n $WEBREV_TRASH_DIR ]] && TRASH_DIR=$WEBREV_TRASH_DIR
214814983201Sdp
214914983201Sdpif [[ ! -x $PERL ]]; then
215014983201Sdp	print -u2 "Error: No perl interpreter found.  Exiting."
215114983201Sdp	exit 1
2152daaffb31Sdpfi
215314983201Sdp
2154cdf0c1d5Smjnelsonif [[ ! -x $WHICH_SCM ]]; then
2155cdf0c1d5Smjnelson	print -u2 "Error: Could not find which_scm.  Exiting."
2156cdf0c1d5Smjnelson	exit 1
2157cdf0c1d5Smjnelsonfi
2158cdf0c1d5Smjnelson
215914983201Sdp#
216014983201Sdp# These aren't fatal, but we want to note them to the user.
216114983201Sdp# We don't warn on the absence of 'wx' until later when we've
216214983201Sdp# determined that we actually need to try to invoke it.
216314983201Sdp#
216414983201Sdp[[ ! -x $CODEREVIEW ]] && print -u2 "WARNING: codereview(1) not found."
216514983201Sdp[[ ! -x $PS2PDF ]] && print -u2 "WARNING: ps2pdf(1) not found."
216614983201Sdp[[ ! -x $WDIFF ]] && print -u2 "WARNING: wdiff not found."
2167daaffb31Sdp
2168daaffb31Sdp# Declare global total counters.
2169daaffb31Sdpinteger TOTL TINS TDEL TMOD TUNC
2170daaffb31Sdp
2171ba44d8a2SVladimir Kotal# default remote host for upload/delete
2172ba44d8a2SVladimir Kotaltypeset -r DEFAULT_REMOTE_HOST="cr.opensolaris.org"
2173b0088928SVladimir Kotal# prefixes for upload targets
2174b0088928SVladimir Kotaltypeset -r rsync_prefix="rsync://"
2175b0088928SVladimir Kotaltypeset -r ssh_prefix="ssh://"
2176ba44d8a2SVladimir Kotal
21770fd2682eSMark J. NelsonCflag=
2178ba44d8a2SVladimir KotalDflag=
217914983201Sdpflist_mode=
218014983201Sdpflist_file=
2181daaffb31Sdpiflag=
21820fd2682eSMark J. NelsonIflag=
218302d26c39SVladimir Kotallflag=
218402d26c39SVladimir KotalNflag=
218502d26c39SVladimir Kotalnflag=
218602d26c39SVladimir KotalOflag=
2187daaffb31Sdpoflag=
2188daaffb31Sdppflag=
218902d26c39SVladimir Kotaltflag=
219002d26c39SVladimir Kotaluflag=
219102d26c39SVladimir KotalUflag=
2192daaffb31Sdpwflag=
219302d26c39SVladimir Kotalremote_target=
2194ba44d8a2SVladimir Kotal
2195ba44d8a2SVladimir Kotal#
2196ba44d8a2SVladimir Kotal# NOTE: when adding/removing options it is necessary to sync the list
2197ba44d8a2SVladimir Kotal#	with usr/src/tools/onbld/hgext/cdm.py
2198ba44d8a2SVladimir Kotal#
219925cc4e45SVladimir Kotalwhile getopts "C:Di:I:lnNo:Op:t:Uw" opt
2200daaffb31Sdpdo
2201daaffb31Sdp	case $opt in
22020fd2682eSMark J. Nelson	C)	Cflag=1
22030fd2682eSMark J. Nelson		ITSCONF=$OPTARG;;
22040fd2682eSMark J. Nelson
2205ba44d8a2SVladimir Kotal	D)	Dflag=1;;
2206ba44d8a2SVladimir Kotal
2207daaffb31Sdp	i)	iflag=1
2208daaffb31Sdp		INCLUDE_FILE=$OPTARG;;
2209daaffb31Sdp
22100fd2682eSMark J. Nelson	I)	Iflag=1
22110fd2682eSMark J. Nelson		ITSREG=$OPTARG;;
22120fd2682eSMark J. Nelson
2213daaffb31Sdp	#
2214daaffb31Sdp	# If -l has been specified, we need to abort further options
2215daaffb31Sdp	# processing, because subsequent arguments are going to be
2216daaffb31Sdp	# arguments to 'putback -n'.
2217daaffb31Sdp	#
2218daaffb31Sdp	l)	lflag=1
2219daaffb31Sdp		break;;
2220daaffb31Sdp
222102d26c39SVladimir Kotal	N)	Nflag=1;;
222202d26c39SVladimir Kotal
222302d26c39SVladimir Kotal	n)	nflag=1;;
2224daaffb31Sdp
2225daaffb31Sdp	O)	Oflag=1;;
2226daaffb31Sdp
222702d26c39SVladimir Kotal	o)	oflag=1
22289d3952abSVladimir Kotal		# Strip the trailing slash to correctly form remote target.
22299d3952abSVladimir Kotal		WDIR=${OPTARG%/};;
223002d26c39SVladimir Kotal
223102d26c39SVladimir Kotal	p)	pflag=1
223202d26c39SVladimir Kotal		codemgr_parent=$OPTARG;;
223302d26c39SVladimir Kotal
223402d26c39SVladimir Kotal	t)	tflag=1
223502d26c39SVladimir Kotal		remote_target=$OPTARG;;
223602d26c39SVladimir Kotal
223702d26c39SVladimir Kotal	U)	Uflag=1;;
223802d26c39SVladimir Kotal
223902d26c39SVladimir Kotal	w)	wflag=1;;
22403df69ef3SDarren Moffat
2241daaffb31Sdp	?)	usage;;
2242daaffb31Sdp	esac
2243daaffb31Sdpdone
2244daaffb31Sdp
2245daaffb31SdpFLIST=/tmp/$$.flist
2246daaffb31Sdp
2247daaffb31Sdpif [[ -n $wflag && -n $lflag ]]; then
2248daaffb31Sdp	usage
2249daaffb31Sdpfi
2250daaffb31Sdp
225102d26c39SVladimir Kotal# more sanity checking
225202d26c39SVladimir Kotalif [[ -n $nflag && -z $Uflag ]]; then
2253ba44d8a2SVladimir Kotal	print "it does not make sense to skip webrev generation" \
2254ba44d8a2SVladimir Kotal	    "without -U"
225502d26c39SVladimir Kotal	exit 1
225602d26c39SVladimir Kotalfi
225702d26c39SVladimir Kotal
2258ba44d8a2SVladimir Kotalif [[ -n $tflag && -z $Uflag && -z $Dflag ]]; then
2259ba44d8a2SVladimir Kotal	echo "remote target has to be used only for upload or delete"
226002d26c39SVladimir Kotal	exit 1
226102d26c39SVladimir Kotalfi
226202d26c39SVladimir Kotal
2263daaffb31Sdp#
22642d9224a3SMark J. Nelson# For the invocation "webrev -n -U" with no other options, webrev will assume
22652d9224a3SMark J. Nelson# that the webrev exists in ${CWS}/webrev, but will upload it using the name
22662d9224a3SMark J. Nelson# $(basename ${CWS}).  So we need to get CWS set before we skip any remaining
22672d9224a3SMark J. Nelson# logic.
22682d9224a3SMark J. Nelson#
22692d9224a3SMark J. Nelson$WHICH_SCM | read SCM_MODE junk || exit 1
22702d9224a3SMark J. Nelsonif [[ $SCM_MODE == "teamware" ]]; then
22712d9224a3SMark J. Nelson	#
22722d9224a3SMark J. Nelson	# Teamware priorities:
22732d9224a3SMark J. Nelson	# 1. CODEMGR_WS from the environment
22742d9224a3SMark J. Nelson	# 2. workspace name
22752d9224a3SMark J. Nelson	#
22762d9224a3SMark J. Nelson	[[ -z $codemgr_ws && -n $CODEMGR_WS ]] && codemgr_ws=$CODEMGR_WS
22772d9224a3SMark J. Nelson	if [[ -n $codemgr_ws && ! -d $codemgr_ws ]]; then
22782d9224a3SMark J. Nelson		print -u2 "$codemgr_ws: no such workspace"
22792d9224a3SMark J. Nelson		exit 1
22802d9224a3SMark J. Nelson	fi
22812d9224a3SMark J. Nelson	[[ -z $codemgr_ws ]] && codemgr_ws=$(workspace name)
22822d9224a3SMark J. Nelson	codemgr_ws=$(cd $codemgr_ws;print $PWD)
22832d9224a3SMark J. Nelson	CODEMGR_WS=$codemgr_ws
22842d9224a3SMark J. Nelson	CWS=$codemgr_ws
22852d9224a3SMark J. Nelsonelif [[ $SCM_MODE == "mercurial" ]]; then
22862d9224a3SMark J. Nelson	#
22872d9224a3SMark J. Nelson	# Mercurial priorities:
22882d9224a3SMark J. Nelson	# 1. hg root from CODEMGR_WS environment variable
228978add226Sjmcp	# 1a. hg root from CODEMGR_WS/usr/closed if we're somewhere under
229078add226Sjmcp	#    usr/closed when we run webrev
22912d9224a3SMark J. Nelson	# 2. hg root from directory of invocation
22922d9224a3SMark J. Nelson	#
229378add226Sjmcp	if [[ ${PWD} =~ "usr/closed" ]]; then
229478add226Sjmcp		testparent=${CODEMGR_WS}/usr/closed
229578add226Sjmcp		# If we're in OpenSolaris mode, we enforce a minor policy:
229678add226Sjmcp		# help to make sure the reviewer doesn't accidentally publish
229778add226Sjmcp		# source which is under usr/closed
229878add226Sjmcp		if [[ -n "$Oflag" ]]; then
229978add226Sjmcp			print -u2 "OpenSolaris output not permitted with" \
230078add226Sjmcp			    "usr/closed changes"
230178add226Sjmcp			exit 1
230278add226Sjmcp		fi
230378add226Sjmcp	else
230478add226Sjmcp	        testparent=${CODEMGR_WS}
230578add226Sjmcp	fi
230678add226Sjmcp	[[ -z $codemgr_ws && -n $testparent ]] && \
230778add226Sjmcp	    codemgr_ws=$(hg root -R $testparent 2>/dev/null)
23082d9224a3SMark J. Nelson	[[ -z $codemgr_ws ]] && codemgr_ws=$(hg root 2>/dev/null)
23092d9224a3SMark J. Nelson	CWS=$codemgr_ws
23102d9224a3SMark J. Nelsonelif [[ $SCM_MODE == "subversion" ]]; then
23112d9224a3SMark J. Nelson	#
23122d9224a3SMark J. Nelson	# Subversion priorities:
23132d9224a3SMark J. Nelson	# 1. CODEMGR_WS from environment
23142d9224a3SMark J. Nelson	# 2. Relative path from current directory to SVN repository root
23152d9224a3SMark J. Nelson	#
23162d9224a3SMark J. Nelson	if [[ -n $CODEMGR_WS && -d $CODEMGR_WS/.svn ]]; then
23172d9224a3SMark J. Nelson		CWS=$CODEMGR_WS
23182d9224a3SMark J. Nelson	else
23192d9224a3SMark J. Nelson		svn info | while read line; do
23202d9224a3SMark J. Nelson			if [[ $line == "URL: "* ]]; then
23212d9224a3SMark J. Nelson				url=${line#URL: }
23222d9224a3SMark J. Nelson			elif [[ $line == "Repository Root: "* ]]; then
23232d9224a3SMark J. Nelson				repo=${line#Repository Root: }
23242d9224a3SMark J. Nelson			fi
23252d9224a3SMark J. Nelson		done
23262d9224a3SMark J. Nelson
23272d9224a3SMark J. Nelson		rel=${url#$repo}
23282d9224a3SMark J. Nelson		CWS=${PWD%$rel}
23292d9224a3SMark J. Nelson	fi
23302d9224a3SMark J. Nelsonfi
23312d9224a3SMark J. Nelson
23322d9224a3SMark J. Nelson#
23332d9224a3SMark J. Nelson# If no SCM has been determined, take either the environment setting
23342d9224a3SMark J. Nelson# setting for CODEMGR_WS, or the current directory if that wasn't set.
23352d9224a3SMark J. Nelson#
23362d9224a3SMark J. Nelsonif [[ -z ${CWS} ]]; then
23372d9224a3SMark J. Nelson	CWS=${CODEMGR_WS:-.}
23382d9224a3SMark J. Nelsonfi
23392d9224a3SMark J. Nelson
23402d9224a3SMark J. Nelson#
23410fd2682eSMark J. Nelson# If the command line options indicate no webrev generation, either
23420fd2682eSMark J. Nelson# explicitly (-n) or implicitly (-D but not -U), then there's a whole
23430fd2682eSMark J. Nelson# ton of logic we can skip.
23440fd2682eSMark J. Nelson#
23450fd2682eSMark J. Nelson# Instead of increasing indentation, we intentionally leave this loop
23460fd2682eSMark J. Nelson# body open here, and exit via break from multiple points within.
23470fd2682eSMark J. Nelson# Search for DO_EVERYTHING below to find the break points and closure.
23480fd2682eSMark J. Nelson#
23490fd2682eSMark J. Nelsonfor do_everything in 1; do
23500fd2682eSMark J. Nelson
23510fd2682eSMark J. Nelson# DO_EVERYTHING: break point
23520fd2682eSMark J. Nelsonif [[ -n $nflag || ( -z $Uflag && -n $Dflag ) ]]; then
23530fd2682eSMark J. Nelson	break
23540fd2682eSMark J. Nelsonfi
23550fd2682eSMark J. Nelson
23560fd2682eSMark J. Nelson#
2357daaffb31Sdp# If this manually set as the parent, and it appears to be an earlier webrev,
2358daaffb31Sdp# then note that fact and set the parent to the raw_files/new subdirectory.
2359daaffb31Sdp#
2360daaffb31Sdpif [[ -n $pflag && -d $codemgr_parent/raw_files/new ]]; then
2361daaffb31Sdp	parent_webrev="$codemgr_parent"
2362daaffb31Sdp	codemgr_parent="$codemgr_parent/raw_files/new"
2363daaffb31Sdpfi
2364daaffb31Sdp
2365daaffb31Sdpif [[ -z $wflag && -z $lflag ]]; then
2366daaffb31Sdp	shift $(($OPTIND - 1))
2367daaffb31Sdp
2368daaffb31Sdp	if [[ $1 == "-" ]]; then
2369daaffb31Sdp		cat > $FLIST
237014983201Sdp		flist_mode="stdin"
237114983201Sdp		flist_done=1
237214983201Sdp		shift
2373daaffb31Sdp	elif [[ -n $1 ]]; then
237414983201Sdp		if [[ ! -r $1 ]]; then
2375daaffb31Sdp			print -u2 "$1: no such file or not readable"
2376daaffb31Sdp			usage
2377daaffb31Sdp		fi
2378daaffb31Sdp		cat $1 > $FLIST
237914983201Sdp		flist_mode="file"
238014983201Sdp		flist_file=$1
238114983201Sdp		flist_done=1
238214983201Sdp		shift
2383daaffb31Sdp	else
238414983201Sdp		flist_mode="auto"
2385daaffb31Sdp	fi
2386daaffb31Sdpfi
2387daaffb31Sdp
2388daaffb31Sdp#
2389daaffb31Sdp# Before we go on to further consider -l and -w, work out which SCM we think
2390daaffb31Sdp# is in use.
2391daaffb31Sdp#
2392cdf0c1d5Smjnelsoncase "$SCM_MODE" in
2393cdf0c1d5Smjnelsonteamware|mercurial|subversion)
2394cdf0c1d5Smjnelson	;;
2395cdf0c1d5Smjnelsonunknown)
2396cdf0c1d5Smjnelson	if [[ $flist_mode == "auto" ]]; then
2397cdf0c1d5Smjnelson		print -u2 "Unable to determine SCM in use and file list not specified"
2398cdf0c1d5Smjnelson		print -u2 "See which_scm(1) for SCM detection information."
23997c478bd9Sstevel@tonic-gate		exit 1
24007c478bd9Sstevel@tonic-gate	fi
2401cdf0c1d5Smjnelson	;;
2402cdf0c1d5Smjnelson*)
2403cdf0c1d5Smjnelson	if [[ $flist_mode == "auto" ]]; then
2404cdf0c1d5Smjnelson		print -u2 "Unsupported SCM in use ($SCM_MODE) and file list not specified"
2405cdf0c1d5Smjnelson		exit 1
2406cdf0c1d5Smjnelson	fi
2407cdf0c1d5Smjnelson	;;
2408cdf0c1d5Smjnelsonesac
24097c478bd9Sstevel@tonic-gate
2410daaffb31Sdpprint -u2 "   SCM detected: $SCM_MODE"
2411daaffb31Sdp
2412daaffb31Sdpif [[ -n $lflag ]]; then
2413daaffb31Sdp	#
2414daaffb31Sdp	# If the -l flag is given instead of the name of a file list,
2415daaffb31Sdp	# then generate the file list by extracting file names from a
2416daaffb31Sdp	# putback -n.
2417daaffb31Sdp	#
2418daaffb31Sdp	shift $(($OPTIND - 1))
2419cdf0c1d5Smjnelson	if [[ $SCM_MODE == "teamware" ]]; then
2420daaffb31Sdp		flist_from_teamware "$*"
2421cdf0c1d5Smjnelson	else
2422cdf0c1d5Smjnelson		print -u2 -- "Error: -l option only applies to TeamWare"
2423cdf0c1d5Smjnelson		exit 1
2424cdf0c1d5Smjnelson	fi
2425daaffb31Sdp	flist_done=1
2426daaffb31Sdp	shift $#
2427daaffb31Sdpelif [[ -n $wflag ]]; then
2428daaffb31Sdp	#
2429daaffb31Sdp	# If the -w is given then assume the file list is in Bonwick's "wx"
2430daaffb31Sdp	# command format, i.e.  pathname lines alternating with SCCS comment
2431daaffb31Sdp	# lines with blank lines as separators.  Use the SCCS comments later
2432daaffb31Sdp	# in building the index.html file.
2433daaffb31Sdp	#
2434daaffb31Sdp	shift $(($OPTIND - 1))
2435daaffb31Sdp	wxfile=$1
2436daaffb31Sdp	if [[ -z $wxfile && -n $CODEMGR_WS ]]; then
2437daaffb31Sdp		if [[ -r $CODEMGR_WS/wx/active ]]; then
2438daaffb31Sdp			wxfile=$CODEMGR_WS/wx/active
2439daaffb31Sdp		fi
2440daaffb31Sdp	fi
2441daaffb31Sdp
2442daaffb31Sdp	[[ -z $wxfile ]] && print -u2 "wx file not specified, and could not " \
2443daaffb31Sdp	    "be auto-detected (check \$CODEMGR_WS)" && exit 1
2444daaffb31Sdp
2445cdf0c1d5Smjnelson	if [[ ! -r $wxfile ]]; then
2446cdf0c1d5Smjnelson		print -u2 "$wxfile: no such file or not readable"
2447cdf0c1d5Smjnelson		usage
2448cdf0c1d5Smjnelson	fi
2449cdf0c1d5Smjnelson
2450daaffb31Sdp	print -u2 " File list from: wx 'active' file '$wxfile' ... \c"
2451daaffb31Sdp	flist_from_wx $wxfile
2452daaffb31Sdp	flist_done=1
2453daaffb31Sdp	if [[ -n "$*" ]]; then
2454daaffb31Sdp		shift
2455daaffb31Sdp	fi
245614983201Sdpelif [[ $flist_mode == "stdin" ]]; then
245714983201Sdp	print -u2 " File list from: standard input"
245814983201Sdpelif [[ $flist_mode == "file" ]]; then
245914983201Sdp	print -u2 " File list from: $flist_file"
2460daaffb31Sdpfi
2461daaffb31Sdp
2462daaffb31Sdpif [[ $# -gt 0 ]]; then
246314983201Sdp	print -u2 "WARNING: unused arguments: $*"
2464daaffb31Sdpfi
2465daaffb31Sdp
24662d9224a3SMark J. Nelson#
24672d9224a3SMark J. Nelson# Before we entered the DO_EVERYTHING loop, we should have already set CWS
24682d9224a3SMark J. Nelson# and CODEMGR_WS as needed.  Here, we set the parent workspace.
24692d9224a3SMark J. Nelson#
24702d9224a3SMark J. Nelson
2471daaffb31Sdpif [[ $SCM_MODE == "teamware" ]]; then
24722d9224a3SMark J. Nelson
2473daaffb31Sdp	#
24742d9224a3SMark J. Nelson	# Teamware priorities:
2475daaffb31Sdp	#
24762d9224a3SMark J. Nelson	#      1) via -p command line option
2477daaffb31Sdp	#      2) in the user environment
2478daaffb31Sdp	#      3) in the flist
24792d9224a3SMark J. Nelson	#      4) automatically based on the workspace
2480daaffb31Sdp	#
2481daaffb31Sdp
2482daaffb31Sdp	#
24832d9224a3SMark J. Nelson	# For 1, codemgr_parent will already be set.  Here's 2:
2484daaffb31Sdp	#
2485daaffb31Sdp	[[ -z $codemgr_parent && -n $CODEMGR_PARENT ]] && \
2486daaffb31Sdp	    codemgr_parent=$CODEMGR_PARENT
2487daaffb31Sdp	if [[ -n $codemgr_parent && ! -d $codemgr_parent ]]; then
2488daaffb31Sdp		print -u2 "$codemgr_parent: no such directory"
24897c478bd9Sstevel@tonic-gate		exit 1
24907c478bd9Sstevel@tonic-gate	fi
24917c478bd9Sstevel@tonic-gate
2492daaffb31Sdp	#
2493daaffb31Sdp	# If we're in auto-detect mode and we haven't already gotten the file
2494daaffb31Sdp	# list, then see if we can get it by probing for wx.
2495daaffb31Sdp	#
249614983201Sdp	if [[ -z $flist_done && $flist_mode == "auto" && -n $codemgr_ws ]]; then
249714983201Sdp		if [[ ! -x $WX ]]; then
249814983201Sdp			print -u2 "WARNING: wx not found!"
2499daaffb31Sdp		fi
25007c478bd9Sstevel@tonic-gate
2501daaffb31Sdp		#
2502daaffb31Sdp		# We need to use wx list -w so that we get renamed files, etc.
2503daaffb31Sdp		# but only if a wx active file exists-- otherwise wx will
2504daaffb31Sdp		# hang asking us to initialize our wx information.
2505daaffb31Sdp		#
250614983201Sdp		if [[ -x $WX && -f $codemgr_ws/wx/active ]]; then
2507daaffb31Sdp			print -u2 " File list from: 'wx list -w' ... \c"
2508daaffb31Sdp			$WX list -w > $FLIST
2509daaffb31Sdp			$WX comments > /tmp/$$.wx_comments
2510daaffb31Sdp			wxfile=/tmp/$$.wx_comments
2511daaffb31Sdp			print -u2 "done"
2512daaffb31Sdp			flist_done=1
2513daaffb31Sdp		fi
2514daaffb31Sdp	fi
2515daaffb31Sdp
2516daaffb31Sdp	#
2517daaffb31Sdp	# If by hook or by crook we've gotten a file list by now (perhaps
2518daaffb31Sdp	# from the command line), eval it to extract environment variables from
25192d9224a3SMark J. Nelson	# it: This is method 3 for finding the parent.
2520daaffb31Sdp	#
2521daaffb31Sdp	if [[ -z $flist_done ]]; then
2522daaffb31Sdp		flist_from_teamware
2523daaffb31Sdp	fi
25242d9224a3SMark J. Nelson	env_from_flist
2525daaffb31Sdp
2526daaffb31Sdp	#
2527daaffb31Sdp	# (4) If we still don't have a value for codemgr_parent, get it
2528daaffb31Sdp	# from workspace.
2529daaffb31Sdp	#
2530daaffb31Sdp	[[ -z $codemgr_parent ]] && codemgr_parent=`workspace parent`
2531daaffb31Sdp	if [[ ! -d $codemgr_parent ]]; then
2532daaffb31Sdp		print -u2 "$CODEMGR_PARENT: no such parent workspace"
2533daaffb31Sdp		exit 1
2534daaffb31Sdp	fi
2535daaffb31Sdp
2536daaffb31Sdp	PWS=$codemgr_parent
2537cdf0c1d5Smjnelson
2538cdf0c1d5Smjnelson	[[ -n $parent_webrev ]] && RWS=$(workspace parent $CWS)
2539cdf0c1d5Smjnelson
2540cdf0c1d5Smjnelsonelif [[ $SCM_MODE == "mercurial" ]]; then
2541cdf0c1d5Smjnelson	#
2542cdf0c1d5Smjnelson	# Parent can either be specified with -p
2543cdf0c1d5Smjnelson	# Specified with CODEMGR_PARENT in the environment
2544cdf0c1d5Smjnelson	# or taken from hg's default path.
2545cdf0c1d5Smjnelson	#
2546cdf0c1d5Smjnelson
2547cdf0c1d5Smjnelson	if [[ -z $codemgr_parent && -n $CODEMGR_PARENT ]]; then
2548cdf0c1d5Smjnelson		codemgr_parent=$CODEMGR_PARENT
2549cdf0c1d5Smjnelson	fi
2550cdf0c1d5Smjnelson
2551cdf0c1d5Smjnelson	if [[ -z $codemgr_parent ]]; then
2552cdf0c1d5Smjnelson		codemgr_parent=`hg path -R $codemgr_ws default 2>/dev/null`
2553cdf0c1d5Smjnelson	fi
2554cdf0c1d5Smjnelson
2555cdf0c1d5Smjnelson	CWS_REV=`hg parent -R $codemgr_ws --template '{node|short}' 2>/dev/null`
2556cdf0c1d5Smjnelson	PWS=$codemgr_parent
2557cdf0c1d5Smjnelson
2558cdf0c1d5Smjnelson	#
2559cdf0c1d5Smjnelson	# If the parent is a webrev, we want to do some things against
2560cdf0c1d5Smjnelson	# the natural workspace parent (file list, comments, etc)
2561cdf0c1d5Smjnelson	#
2562cdf0c1d5Smjnelson	if [[ -n $parent_webrev ]]; then
2563cdf0c1d5Smjnelson		real_parent=$(hg path -R $codemgr_ws default 2>/dev/null)
2564cdf0c1d5Smjnelson	else
2565cdf0c1d5Smjnelson		real_parent=$PWS
2566cdf0c1d5Smjnelson	fi
2567cdf0c1d5Smjnelson
2568cdf0c1d5Smjnelson	#
2569cdf0c1d5Smjnelson	# If hg-active exists, then we run it.  In the case of no explicit
2570cdf0c1d5Smjnelson	# flist given, we'll use it for our comments.  In the case of an
2571cdf0c1d5Smjnelson	# explicit flist given we'll try to use it for comments for any
2572cdf0c1d5Smjnelson	# files mentioned in the flist.
2573cdf0c1d5Smjnelson	#
2574cdf0c1d5Smjnelson	if [[ -z $flist_done ]]; then
2575cdf0c1d5Smjnelson		flist_from_mercurial $CWS $real_parent
2576cdf0c1d5Smjnelson		flist_done=1
2577cdf0c1d5Smjnelson	fi
2578cdf0c1d5Smjnelson
2579cdf0c1d5Smjnelson	#
2580cdf0c1d5Smjnelson	# If we have a file list now, pull out any variables set
2581cdf0c1d5Smjnelson	# therein.  We do this now (rather than when we possibly use
2582cdf0c1d5Smjnelson	# hg-active to find comments) to avoid stomping specifications
2583cdf0c1d5Smjnelson	# in the user-specified flist.
2584cdf0c1d5Smjnelson	#
2585cdf0c1d5Smjnelson	if [[ -n $flist_done ]]; then
2586cdf0c1d5Smjnelson		env_from_flist
2587cdf0c1d5Smjnelson	fi
2588cdf0c1d5Smjnelson
2589cdf0c1d5Smjnelson	#
2590cdf0c1d5Smjnelson	# Only call hg-active if we don't have a wx formatted file already
2591cdf0c1d5Smjnelson	#
2592cdf0c1d5Smjnelson	if [[ -x $HG_ACTIVE && -z $wxfile ]]; then
2593cdf0c1d5Smjnelson		print "  Comments from: hg-active -p $real_parent ...\c"
2594cdf0c1d5Smjnelson		hg_active_wxfile $CWS $real_parent
2595cdf0c1d5Smjnelson		print " Done."
2596cdf0c1d5Smjnelson	fi
2597cdf0c1d5Smjnelson
2598cdf0c1d5Smjnelson	#
2599cdf0c1d5Smjnelson	# At this point we must have a wx flist either from hg-active,
2600cdf0c1d5Smjnelson	# or in general.  Use it to try and find our parent revision,
2601cdf0c1d5Smjnelson	# if we don't have one.
2602cdf0c1d5Smjnelson	#
2603cdf0c1d5Smjnelson	if [[ -z $HG_PARENT ]]; then
2604b0088928SVladimir Kotal		eval `$SED -e "s/#.*$//" $wxfile | $GREP HG_PARENT=`
2605cdf0c1d5Smjnelson	fi
2606cdf0c1d5Smjnelson
2607cdf0c1d5Smjnelson	#
2608cdf0c1d5Smjnelson	# If we still don't have a parent, we must have been given a
2609cdf0c1d5Smjnelson	# wx-style active list with no HG_PARENT specification, run
2610cdf0c1d5Smjnelson	# hg-active and pull an HG_PARENT out of it, ignore the rest.
2611cdf0c1d5Smjnelson	#
2612cdf0c1d5Smjnelson	if [[ -z $HG_PARENT && -x $HG_ACTIVE ]]; then
2613cdf0c1d5Smjnelson		$HG_ACTIVE -w $codemgr_ws -p $real_parent | \
2614b0088928SVladimir Kotal		    eval `$SED -e "s/#.*$//" | $GREP HG_PARENT=`
2615cdf0c1d5Smjnelson	elif [[ -z $HG_PARENT ]]; then
2616cdf0c1d5Smjnelson		print -u2 "Error: Cannot discover parent revision"
2617cdf0c1d5Smjnelson		exit 1
2618cdf0c1d5Smjnelson	fi
2619cdf0c1d5Smjnelsonelif [[ $SCM_MODE == "subversion" ]]; then
2620cdf0c1d5Smjnelson
2621cdf0c1d5Smjnelson	#
2622cdf0c1d5Smjnelson	# We only will have a real parent workspace in the case one
2623cdf0c1d5Smjnelson	# was specified (be it an older webrev, or another checkout).
2624cdf0c1d5Smjnelson	#
2625cdf0c1d5Smjnelson	[[ -n $codemgr_parent ]] && PWS=$codemgr_parent
2626cdf0c1d5Smjnelson
2627cdf0c1d5Smjnelson	if [[ -z $flist_done && $flist_mode == "auto" ]]; then
2628cdf0c1d5Smjnelson		flist_from_subversion $CWS $OLDPWD
2629cdf0c1d5Smjnelson	fi
2630cdf0c1d5Smjnelsonelse
2631cdf0c1d5Smjnelson    if [[ $SCM_MODE == "unknown" ]]; then
2632cdf0c1d5Smjnelson	print -u2 "    Unknown type of SCM in use"
2633cdf0c1d5Smjnelson    else
2634cdf0c1d5Smjnelson	print -u2 "    Unsupported SCM in use: $SCM_MODE"
2635cdf0c1d5Smjnelson    fi
2636cdf0c1d5Smjnelson
2637cdf0c1d5Smjnelson    env_from_flist
2638cdf0c1d5Smjnelson
2639cdf0c1d5Smjnelson    if [[ -z $CODEMGR_WS ]]; then
2640cdf0c1d5Smjnelson	print -u2 "SCM not detected/supported and CODEMGR_WS not specified"
2641cdf0c1d5Smjnelson	exit 1
2642cdf0c1d5Smjnelson    fi
2643cdf0c1d5Smjnelson
2644cdf0c1d5Smjnelson    if [[ -z $CODEMGR_PARENT ]]; then
2645cdf0c1d5Smjnelson	print -u2 "SCM not detected/supported and CODEMGR_PARENT not specified"
2646cdf0c1d5Smjnelson	exit 1
2647cdf0c1d5Smjnelson    fi
2648cdf0c1d5Smjnelson
2649cdf0c1d5Smjnelson    CWS=$CODEMGR_WS
2650cdf0c1d5Smjnelson    PWS=$CODEMGR_PARENT
2651daaffb31Sdpfi
2652daaffb31Sdp
2653daaffb31Sdp#
2654daaffb31Sdp# If the user didn't specify a -i option, check to see if there is a
2655daaffb31Sdp# webrev-info file in the workspace directory.
2656daaffb31Sdp#
2657daaffb31Sdpif [[ -z $iflag && -r "$CWS/webrev-info" ]]; then
2658daaffb31Sdp	iflag=1
2659daaffb31Sdp	INCLUDE_FILE="$CWS/webrev-info"
2660daaffb31Sdpfi
2661daaffb31Sdp
2662daaffb31Sdpif [[ -n $iflag ]]; then
2663daaffb31Sdp	if [[ ! -r $INCLUDE_FILE ]]; then
2664daaffb31Sdp		print -u2 "include file '$INCLUDE_FILE' does not exist or is" \
2665daaffb31Sdp		    "not readable."
2666daaffb31Sdp		exit 1
2667daaffb31Sdp	else
2668daaffb31Sdp		#
2669daaffb31Sdp		# $INCLUDE_FILE may be a relative path, and the script alters
2670daaffb31Sdp		# PWD, so we just stash a copy in /tmp.
2671daaffb31Sdp		#
2672daaffb31Sdp		cp $INCLUDE_FILE /tmp/$$.include
2673daaffb31Sdp	fi
2674daaffb31Sdpfi
2675daaffb31Sdp
26760fd2682eSMark J. Nelson# DO_EVERYTHING: break point
26770fd2682eSMark J. Nelsonif [[ -n $Nflag ]]; then
26780fd2682eSMark J. Nelson	break
26790fd2682eSMark J. Nelsonfi
26800fd2682eSMark J. Nelson
26810fd2682eSMark J. Nelsontypeset -A itsinfo
26820fd2682eSMark J. Nelsontypeset -r its_sed_script=/tmp/$$.its_sed
26830fd2682eSMark J. Nelsonvalid_prefixes=
26840fd2682eSMark J. Nelsonif [[ -z $nflag ]]; then
26850fd2682eSMark J. Nelson	DEFREGFILE="$(dirname $(whence $0))/../etc/its.reg"
26860fd2682eSMark J. Nelson	if [[ -n $Iflag ]]; then
26870fd2682eSMark J. Nelson		REGFILE=$ITSREG
26880fd2682eSMark J. Nelson	elif [[ -r $HOME/.its.reg ]]; then
26890fd2682eSMark J. Nelson		REGFILE=$HOME/.its.reg
26900fd2682eSMark J. Nelson	else
26910fd2682eSMark J. Nelson		REGFILE=$DEFREGFILE
26920fd2682eSMark J. Nelson	fi
26930fd2682eSMark J. Nelson	if [[ ! -r $REGFILE ]]; then
26940fd2682eSMark J. Nelson		print "ERROR: Unable to read database registry file $REGFILE"
26950fd2682eSMark J. Nelson		exit 1
26960fd2682eSMark J. Nelson	elif [[ $REGFILE != $DEFREGFILE ]]; then
26970fd2682eSMark J. Nelson		print "   its.reg from: $REGFILE"
26980fd2682eSMark J. Nelson	fi
26990fd2682eSMark J. Nelson
27000fd2682eSMark J. Nelson	$SED -e '/^#/d' -e '/^[ 	]*$/d' $REGFILE | while read LINE; do
27010fd2682eSMark J. Nelson
27020fd2682eSMark J. Nelson		name=${LINE%%=*}
27030fd2682eSMark J. Nelson		value="${LINE#*=}"
27040fd2682eSMark J. Nelson
27050fd2682eSMark J. Nelson		if [[ $name == PREFIX ]]; then
27060fd2682eSMark J. Nelson			p=${value}
27070fd2682eSMark J. Nelson			valid_prefixes="${p} ${valid_prefixes}"
27080fd2682eSMark J. Nelson		else
27090fd2682eSMark J. Nelson			itsinfo["${p}_${name}"]="${value}"
27100fd2682eSMark J. Nelson		fi
27110fd2682eSMark J. Nelson	done
27120fd2682eSMark J. Nelson
27130fd2682eSMark J. Nelson
27140fd2682eSMark J. Nelson	DEFCONFFILE="$(dirname $(whence $0))/../etc/its.conf"
27150fd2682eSMark J. Nelson	CONFFILES=$DEFCONFFILE
27160fd2682eSMark J. Nelson	if [[ -r $HOME/.its.conf ]]; then
27170fd2682eSMark J. Nelson		CONFFILES="${CONFFILES} $HOME/.its.conf"
27180fd2682eSMark J. Nelson	fi
27190fd2682eSMark J. Nelson	if [[ -n $Cflag ]]; then
27200fd2682eSMark J. Nelson		CONFFILES="${CONFFILES} ${ITSCONF}"
27210fd2682eSMark J. Nelson	fi
27220fd2682eSMark J. Nelson	its_domain=
27230fd2682eSMark J. Nelson	its_priority=
27240fd2682eSMark J. Nelson	for cf in ${CONFFILES}; do
27250fd2682eSMark J. Nelson		if [[ ! -r $cf ]]; then
27260fd2682eSMark J. Nelson			print "ERROR: Unable to read database configuration file $cf"
27270fd2682eSMark J. Nelson			exit 1
27280fd2682eSMark J. Nelson		elif [[ $cf != $DEFCONFFILE ]]; then
27290fd2682eSMark J. Nelson			print "       its.conf: reading $cf"
27300fd2682eSMark J. Nelson		fi
27310fd2682eSMark J. Nelson		$SED -e '/^#/d' -e '/^[ 	]*$/d' $cf | while read LINE; do
27320fd2682eSMark J. Nelson		    eval "${LINE}"
27330fd2682eSMark J. Nelson		done
27340fd2682eSMark J. Nelson	done
27350fd2682eSMark J. Nelson
27360fd2682eSMark J. Nelson	#
27370fd2682eSMark J. Nelson	# If an information tracking system is explicitly identified by prefix,
27380fd2682eSMark J. Nelson	# we want to disregard the specified priorities and resolve it accordingly.
27390fd2682eSMark J. Nelson	#
27400fd2682eSMark J. Nelson	# To that end, we'll build a sed script to do each valid prefix in turn.
27410fd2682eSMark J. Nelson	#
27420fd2682eSMark J. Nelson	for p in ${valid_prefixes}; do
27430fd2682eSMark J. Nelson		#
27440fd2682eSMark J. Nelson		# When an informational URL was provided, translate it to a
27450fd2682eSMark J. Nelson		# hyperlink.  When omitted, simply use the prefix text.
27460fd2682eSMark J. Nelson		#
27470fd2682eSMark J. Nelson		if [[ -z ${itsinfo["${p}_INFO"]} ]]; then
27480fd2682eSMark J. Nelson			itsinfo["${p}_INFO"]=${p}
27490fd2682eSMark J. Nelson		else
27500fd2682eSMark J. Nelson			itsinfo["${p}_INFO"]="<a href=\\\"${itsinfo["${p}_INFO"]}\\\">${p}</a>"
27510fd2682eSMark J. Nelson		fi
27520fd2682eSMark J. Nelson
27530fd2682eSMark J. Nelson		#
27540fd2682eSMark J. Nelson		# Assume that, for this invocation of webrev, all references
27550fd2682eSMark J. Nelson		# to this information tracking system should resolve through
27560fd2682eSMark J. Nelson		# the same URL.
27570fd2682eSMark J. Nelson		#
27580fd2682eSMark J. Nelson		# If the caller specified -O, then always use EXTERNAL_URL.
27590fd2682eSMark J. Nelson		#
27600fd2682eSMark J. Nelson		# Otherwise, look in the list of domains for a matching
27610fd2682eSMark J. Nelson		# INTERNAL_URL.
27620fd2682eSMark J. Nelson		#
27630fd2682eSMark J. Nelson		[[ -z $Oflag ]] && for d in ${its_domain}; do
27640fd2682eSMark J. Nelson			if [[ -n ${itsinfo["${p}_INTERNAL_URL_${d}"]} ]]; then
27650fd2682eSMark J. Nelson				itsinfo["${p}_URL"]="${itsinfo[${p}_INTERNAL_URL_${d}]}"
27660fd2682eSMark J. Nelson				break
27670fd2682eSMark J. Nelson			fi
27680fd2682eSMark J. Nelson		done
27690fd2682eSMark J. Nelson		if [[ -z ${itsinfo["${p}_URL"]} ]]; then
27700fd2682eSMark J. Nelson			itsinfo["${p}_URL"]="${itsinfo[${p}_EXTERNAL_URL]}"
27710fd2682eSMark J. Nelson		fi
27720fd2682eSMark J. Nelson
27730fd2682eSMark J. Nelson		#
27740fd2682eSMark J. Nelson		# Turn the destination URL into a hyperlink
27750fd2682eSMark J. Nelson		#
27760fd2682eSMark J. Nelson		itsinfo["${p}_URL"]="<a href=\\\"${itsinfo[${p}_URL]}\\\">&</a>"
27770fd2682eSMark J. Nelson
2778*2f54b716SRichard Lowe		# The character class below contains a literal tab
2779*2f54b716SRichard Lowe		print "/^${p}[: 	]/ {
27800fd2682eSMark J. Nelson				s;${itsinfo[${p}_REGEX]};${itsinfo[${p}_URL]};g
27810fd2682eSMark J. Nelson				s;^${p};${itsinfo[${p}_INFO]};
27820fd2682eSMark J. Nelson			}" >> ${its_sed_script}
27830fd2682eSMark J. Nelson	done
27840fd2682eSMark J. Nelson
27850fd2682eSMark J. Nelson	#
27860fd2682eSMark J. Nelson	# The previous loop took care of explicit specification.  Now use
27870fd2682eSMark J. Nelson	# the configured priorities to attempt implicit translations.
27880fd2682eSMark J. Nelson	#
27890fd2682eSMark J. Nelson	for p in ${its_priority}; do
27900fd2682eSMark J. Nelson		print "/^${itsinfo[${p}_REGEX]}[ 	]/ {
2791*2f54b716SRichard Lowe				s;^${itsinfo[${p}_REGEX]};${itsinfo[${p}_URL]};g
27920fd2682eSMark J. Nelson			}" >> ${its_sed_script}
27930fd2682eSMark J. Nelson	done
27940fd2682eSMark J. Nelsonfi
27950fd2682eSMark J. Nelson
27960fd2682eSMark J. Nelson#
27970fd2682eSMark J. Nelson# Search for DO_EVERYTHING above for matching "for" statement
27980fd2682eSMark J. Nelson# and explanation of this terminator.
27990fd2682eSMark J. Nelson#
28000fd2682eSMark J. Nelsondone
28010fd2682eSMark J. Nelson
2802daaffb31Sdp#
2803daaffb31Sdp# Output directory.
2804daaffb31Sdp#
2805daaffb31SdpWDIR=${WDIR:-$CWS/webrev}
2806daaffb31Sdp
2807daaffb31Sdp#
280802d26c39SVladimir Kotal# Name of the webrev, derived from the workspace name or output directory;
280902d26c39SVladimir Kotal# in the future this could potentially be an option.
2810daaffb31Sdp#
281102d26c39SVladimir Kotalif [[ -n $oflag ]]; then
281202d26c39SVladimir Kotal	WNAME=${WDIR##*/}
281302d26c39SVladimir Kotalelse
2814daaffb31Sdp	WNAME=${CWS##*/}
281502d26c39SVladimir Kotalfi
281602d26c39SVladimir Kotal
2817ba44d8a2SVladimir Kotal# Make sure remote target is well formed for remote upload/delete.
2818ba44d8a2SVladimir Kotalif [[ -n $Dflag || -n $Uflag ]]; then
2819b0088928SVladimir Kotal	#
2820ba44d8a2SVladimir Kotal	# If remote target is not specified, build it from scratch using
2821ba44d8a2SVladimir Kotal	# the default values.
2822b0088928SVladimir Kotal	#
2823ba44d8a2SVladimir Kotal	if [[ -z $tflag ]]; then
2824ba44d8a2SVladimir Kotal		remote_target=${DEFAULT_REMOTE_HOST}:${WNAME}
2825ba44d8a2SVladimir Kotal	else
2826b0088928SVladimir Kotal		#
2827b0088928SVladimir Kotal		# Check upload target prefix first.
2828b0088928SVladimir Kotal		#
2829b0088928SVladimir Kotal		if [[ "${remote_target}" != ${rsync_prefix}* &&
2830b0088928SVladimir Kotal		    "${remote_target}" != ${ssh_prefix}* ]]; then
2831b0088928SVladimir Kotal			print "ERROR: invalid prefix of upload URI" \
2832b0088928SVladimir Kotal			    "($remote_target)"
2833b0088928SVladimir Kotal			exit 1
2834b0088928SVladimir Kotal		fi
2835b0088928SVladimir Kotal		#
2836ba44d8a2SVladimir Kotal		# If destination specification is not in the form of
2837ba44d8a2SVladimir Kotal		# host_spec:remote_dir then assume it is just remote hostname
2838ba44d8a2SVladimir Kotal		# and append a colon and destination directory formed from
2839ba44d8a2SVladimir Kotal		# local webrev directory name.
2840b0088928SVladimir Kotal		#
2841b0088928SVladimir Kotal		typeset target_no_prefix=${remote_target##*://}
2842b0088928SVladimir Kotal		if [[ ${target_no_prefix} == *:* ]]; then
2843ba44d8a2SVladimir Kotal			if [[ "${remote_target}" == *: ]]; then
2844b0088928SVladimir Kotal				remote_target=${remote_target}${WNAME}
2845ba44d8a2SVladimir Kotal			fi
2846b0088928SVladimir Kotal		else
2847b0088928SVladimir Kotal			if [[ ${target_no_prefix} == */* ]]; then
2848b0088928SVladimir Kotal				print "ERROR: badly formed upload URI" \
2849b0088928SVladimir Kotal					"($remote_target)"
2850b0088928SVladimir Kotal				exit 1
2851b0088928SVladimir Kotal			else
2852b0088928SVladimir Kotal				remote_target=${remote_target}:${WNAME}
2853ba44d8a2SVladimir Kotal			fi
2854ba44d8a2SVladimir Kotal		fi
2855ba44d8a2SVladimir Kotal	fi
2856ba44d8a2SVladimir Kotal
2857b0088928SVladimir Kotal	#
2858b0088928SVladimir Kotal	# Strip trailing slash. Each upload method will deal with directory
2859b0088928SVladimir Kotal	# specification separately.
2860b0088928SVladimir Kotal	#
2861b0088928SVladimir Kotal	remote_target=${remote_target%/}
2862b0088928SVladimir Kotalfi
2863b0088928SVladimir Kotal
2864b0088928SVladimir Kotal#
2865ba44d8a2SVladimir Kotal# Option -D by itself (option -U not present) implies no webrev generation.
2866b0088928SVladimir Kotal#
2867ba44d8a2SVladimir Kotalif [[ -z $Uflag && -n $Dflag ]]; then
2868b0088928SVladimir Kotal	delete_webrev 1 1
2869ba44d8a2SVladimir Kotal	exit $?
2870ba44d8a2SVladimir Kotalfi
2871ba44d8a2SVladimir Kotal
2872b0088928SVladimir Kotal#
2873ba44d8a2SVladimir Kotal# Do not generate the webrev, just upload it or delete it.
2874b0088928SVladimir Kotal#
2875ba44d8a2SVladimir Kotalif [[ -n $nflag ]]; then
2876ba44d8a2SVladimir Kotal	if [[ -n $Dflag ]]; then
2877b0088928SVladimir Kotal		delete_webrev 1 1
2878ba44d8a2SVladimir Kotal		(( $? == 0 )) || exit $?
2879ba44d8a2SVladimir Kotal	fi
2880ba44d8a2SVladimir Kotal	if [[ -n $Uflag ]]; then
288102d26c39SVladimir Kotal		upload_webrev
288202d26c39SVladimir Kotal		exit $?
288302d26c39SVladimir Kotal	fi
2884ba44d8a2SVladimir Kotalfi
2885daaffb31Sdp
2886e0e0293aSjmcpif [ "${WDIR%%/*}" ]; then
28877c478bd9Sstevel@tonic-gate	WDIR=$PWD/$WDIR
28887c478bd9Sstevel@tonic-gatefi
2889daaffb31Sdp
2890daaffb31Sdpif [[ ! -d $WDIR ]]; then
2891daaffb31Sdp	mkdir -p $WDIR
2892ba44d8a2SVladimir Kotal	(( $? != 0 )) && exit 1
28937c478bd9Sstevel@tonic-gatefi
28947c478bd9Sstevel@tonic-gate
2895daaffb31Sdp#
2896daaffb31Sdp# Summarize what we're going to do.
2897daaffb31Sdp#
2898cdf0c1d5Smjnelsonif [[ -n $CWS_REV ]]; then
2899cdf0c1d5Smjnelson	print "      Workspace: $CWS (at $CWS_REV)"
2900cdf0c1d5Smjnelsonelse
2901daaffb31Sdp	print "      Workspace: $CWS"
2902cdf0c1d5Smjnelsonfi
2903daaffb31Sdpif [[ -n $parent_webrev ]]; then
2904daaffb31Sdp	print "Compare against: webrev at $parent_webrev"
2905daaffb31Sdpelse
2906cdf0c1d5Smjnelson	if [[ -n $HG_PARENT ]]; then
2907cdf0c1d5Smjnelson		hg_parent_short=`echo $HG_PARENT \
2908b0088928SVladimir Kotal			| $SED -e 's/\([0-9a-f]\{12\}\).*/\1/'`
2909cdf0c1d5Smjnelson		print "Compare against: $PWS (at $hg_parent_short)"
2910cdf0c1d5Smjnelson	else
2911daaffb31Sdp		print "Compare against: $PWS"
2912daaffb31Sdp	fi
2913cdf0c1d5Smjnelsonfi
2914daaffb31Sdp
2915daaffb31Sdp[[ -n $INCLUDE_FILE ]] && print "      Including: $INCLUDE_FILE"
2916daaffb31Sdpprint "      Output to: $WDIR"
2917daaffb31Sdp
2918daaffb31Sdp#
29197c478bd9Sstevel@tonic-gate# Save the file list in the webrev dir
2920daaffb31Sdp#
2921daaffb31Sdp[[ ! $FLIST -ef $WDIR/file.list ]] && cp $FLIST $WDIR/file.list
29227c478bd9Sstevel@tonic-gate
2923daaffb31Sdprm -f $WDIR/$WNAME.patch
2924daaffb31Sdprm -f $WDIR/$WNAME.ps
2925daaffb31Sdprm -f $WDIR/$WNAME.pdf
29267c478bd9Sstevel@tonic-gate
2927daaffb31Sdptouch $WDIR/$WNAME.patch
29287c478bd9Sstevel@tonic-gate
2929daaffb31Sdpprint "   Output Files:"
2930daaffb31Sdp
2931daaffb31Sdp#
2932daaffb31Sdp# Clean up the file list: Remove comments, blank lines and env variables.
2933daaffb31Sdp#
2934b0088928SVladimir Kotal$SED -e "s/#.*$//" -e "/=/d" -e "/^[   ]*$/d" $FLIST > /tmp/$$.flist.clean
2935daaffb31SdpFLIST=/tmp/$$.flist.clean
2936daaffb31Sdp
2937daaffb31Sdp#
2938cdf0c1d5Smjnelson# For Mercurial, create a cache of manifest entries.
2939cdf0c1d5Smjnelson#
2940cdf0c1d5Smjnelsonif [[ $SCM_MODE == "mercurial" ]]; then
2941cdf0c1d5Smjnelson	#
2942cdf0c1d5Smjnelson	# Transform the FLIST into a temporary sed script that matches
2943cdf0c1d5Smjnelson	# relevant entries in the Mercurial manifest as follows:
2944cdf0c1d5Smjnelson	# 1) The script will be used against the parent revision manifest,
2945cdf0c1d5Smjnelson	#    so for FLIST lines that have two filenames (a renamed file)
2946cdf0c1d5Smjnelson	#    keep only the old name.
2947cdf0c1d5Smjnelson	# 2) Escape all forward slashes the filename.
2948cdf0c1d5Smjnelson	# 3) Change the filename into another sed command that matches
2949cdf0c1d5Smjnelson	#    that file in "hg manifest -v" output:  start of line, three
2950cdf0c1d5Smjnelson	#    octal digits for file permissions, space, a file type flag
2951cdf0c1d5Smjnelson	#    character, space, the filename, end of line.
2952e6ccc173SEdward Pilatowicz	# 4) Eliminate any duplicate entries.  (This can occur if a
2953e6ccc173SEdward Pilatowicz	#    file has been used as the source of an hg cp and it's
2954e6ccc173SEdward Pilatowicz	#    also been modified in the same changeset.)
2955cdf0c1d5Smjnelson	#
2956cdf0c1d5Smjnelson	SEDFILE=/tmp/$$.manifest.sed
2957b0088928SVladimir Kotal	$SED '
2958cdf0c1d5Smjnelson		s#^[^ ]* ##
2959cdf0c1d5Smjnelson		s#/#\\\/#g
2960cdf0c1d5Smjnelson		s#^.*$#/^... . &$/p#
2961e6ccc173SEdward Pilatowicz	' < $FLIST | $SORT -u > $SEDFILE
2962cdf0c1d5Smjnelson
2963cdf0c1d5Smjnelson	#
2964cdf0c1d5Smjnelson	# Apply the generated script to the output of "hg manifest -v"
2965cdf0c1d5Smjnelson	# to get the relevant subset for this webrev.
2966cdf0c1d5Smjnelson	#
2967cdf0c1d5Smjnelson	HG_PARENT_MANIFEST=/tmp/$$.manifest
2968cdf0c1d5Smjnelson	hg -R $CWS manifest -v -r $HG_PARENT |
2969b0088928SVladimir Kotal	    $SED -n -f $SEDFILE > $HG_PARENT_MANIFEST
2970cdf0c1d5Smjnelsonfi
2971cdf0c1d5Smjnelson
2972cdf0c1d5Smjnelson#
2973daaffb31Sdp# First pass through the files: generate the per-file webrev HTML-files.
2974daaffb31Sdp#
2975daaffb31Sdpcat $FLIST | while read LINE
29767c478bd9Sstevel@tonic-gatedo
29777c478bd9Sstevel@tonic-gate	set - $LINE
29787c478bd9Sstevel@tonic-gate	P=$1
29797c478bd9Sstevel@tonic-gate
2980daaffb31Sdp	#
2981daaffb31Sdp	# Normally, each line in the file list is just a pathname of a
2982daaffb31Sdp	# file that has been modified or created in the child.  A file
2983daaffb31Sdp	# that is renamed in the child workspace has two names on the
2984daaffb31Sdp	# line: new name followed by the old name.
2985daaffb31Sdp	#
2986daaffb31Sdp	oldname=""
2987daaffb31Sdp	oldpath=""
2988daaffb31Sdp	rename=
2989daaffb31Sdp	if [[ $# -eq 2 ]]; then
29907c478bd9Sstevel@tonic-gate		PP=$2			# old filename
2991e6ccc173SEdward Pilatowicz		if [[ -f $PP ]]; then
2992e6ccc173SEdward Pilatowicz			oldname=" (copied from $PP)"
2993e6ccc173SEdward Pilatowicz		else
2994e6ccc173SEdward Pilatowicz			oldname=" (renamed from $PP)"
2995e6ccc173SEdward Pilatowicz		fi
2996daaffb31Sdp		oldpath="$PP"
2997daaffb31Sdp		rename=1
29987c478bd9Sstevel@tonic-gate		PDIR=${PP%/*}
2999daaffb31Sdp		if [[ $PDIR == $PP ]]; then
30007c478bd9Sstevel@tonic-gate			PDIR="."   # File at root of workspace
30017c478bd9Sstevel@tonic-gate		fi
30027c478bd9Sstevel@tonic-gate
30037c478bd9Sstevel@tonic-gate		PF=${PP##*/}
30047c478bd9Sstevel@tonic-gate
30057c478bd9Sstevel@tonic-gate		DIR=${P%/*}
3006daaffb31Sdp		if [[ $DIR == $P ]]; then
30077c478bd9Sstevel@tonic-gate			DIR="."   # File at root of workspace
30087c478bd9Sstevel@tonic-gate		fi
30097c478bd9Sstevel@tonic-gate
30107c478bd9Sstevel@tonic-gate		F=${P##*/}
3011daaffb31Sdp
30127c478bd9Sstevel@tonic-gate        else
30137c478bd9Sstevel@tonic-gate		DIR=${P%/*}
3014daaffb31Sdp		if [[ "$DIR" == "$P" ]]; then
30157c478bd9Sstevel@tonic-gate			DIR="."   # File at root of workspace
30167c478bd9Sstevel@tonic-gate		fi
30177c478bd9Sstevel@tonic-gate
30187c478bd9Sstevel@tonic-gate		F=${P##*/}
30197c478bd9Sstevel@tonic-gate
30207c478bd9Sstevel@tonic-gate		PP=$P
30217c478bd9Sstevel@tonic-gate		PDIR=$DIR
30227c478bd9Sstevel@tonic-gate		PF=$F
30237c478bd9Sstevel@tonic-gate	fi
30247c478bd9Sstevel@tonic-gate
3025daaffb31Sdp	COMM=`getcomments html $P $PP`
30267c478bd9Sstevel@tonic-gate
3027daaffb31Sdp	print "\t$P$oldname\n\t\t\c"
30287c478bd9Sstevel@tonic-gate
30297c478bd9Sstevel@tonic-gate	# Make the webrev mirror directory if necessary
30307c478bd9Sstevel@tonic-gate	mkdir -p $WDIR/$DIR
30317c478bd9Sstevel@tonic-gate
3032daaffb31Sdp	#
3033cdf0c1d5Smjnelson	# We stash old and new files into parallel directories in $WDIR
3034daaffb31Sdp	# and do our diffs there.  This makes it possible to generate
3035daaffb31Sdp	# clean looking diffs which don't have absolute paths present.
3036daaffb31Sdp	#
3037daaffb31Sdp
3038cdf0c1d5Smjnelson	build_old_new "$WDIR" "$PWS" "$PDIR" "$PF" "$CWS" "$DIR" "$F" || \
30397c478bd9Sstevel@tonic-gate	    continue
30407c478bd9Sstevel@tonic-gate
3041cdf0c1d5Smjnelson	#
3042cdf0c1d5Smjnelson	# Keep the old PWD around, so we can safely switch back after
3043cdf0c1d5Smjnelson	# diff generation, such that build_old_new runs in a
3044cdf0c1d5Smjnelson	# consistent environment.
3045cdf0c1d5Smjnelson	#
3046cdf0c1d5Smjnelson	OWD=$PWD
3047daaffb31Sdp	cd $WDIR/raw_files
3048daaffb31Sdp	ofile=old/$PDIR/$PF
3049daaffb31Sdp	nfile=new/$DIR/$F
30507c478bd9Sstevel@tonic-gate
3051daaffb31Sdp	mv_but_nodiff=
3052daaffb31Sdp	cmp $ofile $nfile > /dev/null 2>&1
3053daaffb31Sdp	if [[ $? == 0 && $rename == 1 ]]; then
3054daaffb31Sdp		mv_but_nodiff=1
3055daaffb31Sdp	fi
3056daaffb31Sdp
3057daaffb31Sdp	#
3058daaffb31Sdp	# If we have old and new versions of the file then run the appropriate
3059daaffb31Sdp	# diffs.  This is complicated by a couple of factors:
3060daaffb31Sdp	#
3061daaffb31Sdp	#	- renames must be handled specially: we emit a 'remove'
3062daaffb31Sdp	#	  diff and an 'add' diff
3063daaffb31Sdp	#	- new files and deleted files must be handled specially
3064daaffb31Sdp	#	- Solaris patch(1m) can't cope with file creation
3065daaffb31Sdp	#	  (and hence renames) as of this writing.
3066daaffb31Sdp	#       - To make matters worse, gnu patch doesn't interpret the
3067daaffb31Sdp	#	  output of Solaris diff properly when it comes to
3068daaffb31Sdp	#	  adds and deletes.  We need to do some "cleansing"
3069daaffb31Sdp	#         transformations:
3070daaffb31Sdp	#	    [to add a file] @@ -1,0 +X,Y @@  -->  @@ -0,0 +X,Y @@
3071daaffb31Sdp	#	    [to del a file] @@ -X,Y +1,0 @@  -->  @@ -X,Y +0,0 @@
3072daaffb31Sdp	#
3073b0088928SVladimir Kotal	cleanse_rmfile="$SED 's/^\(@@ [0-9+,-]*\) [0-9+,-]* @@$/\1 +0,0 @@/'"
3074b0088928SVladimir Kotal	cleanse_newfile="$SED 's/^@@ [0-9+,-]* \([0-9+,-]* @@\)$/@@ -0,0 \1/'"
3075daaffb31Sdp
3076daaffb31Sdp	rm -f $WDIR/$DIR/$F.patch
3077daaffb31Sdp	if [[ -z $rename ]]; then
3078e0e0293aSjmcp		if [ ! -f "$ofile" ]; then
3079daaffb31Sdp			diff -u /dev/null $nfile | sh -c "$cleanse_newfile" \
3080daaffb31Sdp			    > $WDIR/$DIR/$F.patch
3081e0e0293aSjmcp		elif [ ! -f "$nfile" ]; then
3082daaffb31Sdp			diff -u $ofile /dev/null | sh -c "$cleanse_rmfile" \
3083daaffb31Sdp			    > $WDIR/$DIR/$F.patch
3084daaffb31Sdp		else
3085daaffb31Sdp			diff -u $ofile $nfile > $WDIR/$DIR/$F.patch
3086daaffb31Sdp		fi
3087daaffb31Sdp	else
3088daaffb31Sdp		diff -u $ofile /dev/null | sh -c "$cleanse_rmfile" \
3089daaffb31Sdp		    > $WDIR/$DIR/$F.patch
3090daaffb31Sdp
3091daaffb31Sdp		diff -u /dev/null $nfile | sh -c "$cleanse_newfile" \
3092daaffb31Sdp		    >> $WDIR/$DIR/$F.patch
3093daaffb31Sdp	fi
3094daaffb31Sdp
3095daaffb31Sdp	#
3096daaffb31Sdp	# Tack the patch we just made onto the accumulated patch for the
3097daaffb31Sdp	# whole wad.
3098daaffb31Sdp	#
3099daaffb31Sdp	cat $WDIR/$DIR/$F.patch >> $WDIR/$WNAME.patch
3100daaffb31Sdp
3101daaffb31Sdp	print " patch\c"
3102daaffb31Sdp
3103daaffb31Sdp	if [[ -f $ofile && -f $nfile && -z $mv_but_nodiff ]]; then
3104daaffb31Sdp
3105daaffb31Sdp		${CDIFFCMD:-diff -bt -C 5} $ofile $nfile > $WDIR/$DIR/$F.cdiff
3106daaffb31Sdp		diff_to_html $F $DIR/$F "C" "$COMM" < $WDIR/$DIR/$F.cdiff \
3107daaffb31Sdp		    > $WDIR/$DIR/$F.cdiff.html
31087c478bd9Sstevel@tonic-gate		print " cdiffs\c"
31097c478bd9Sstevel@tonic-gate
3110daaffb31Sdp		${UDIFFCMD:-diff -bt -U 5} $ofile $nfile > $WDIR/$DIR/$F.udiff
3111daaffb31Sdp		diff_to_html $F $DIR/$F "U" "$COMM" < $WDIR/$DIR/$F.udiff \
3112daaffb31Sdp		    > $WDIR/$DIR/$F.udiff.html
3113daaffb31Sdp
31147c478bd9Sstevel@tonic-gate		print " udiffs\c"
31157c478bd9Sstevel@tonic-gate
31167c478bd9Sstevel@tonic-gate		if [[ -x $WDIFF ]]; then
3117daaffb31Sdp			$WDIFF -c "$COMM" \
3118daaffb31Sdp			    -t "$WNAME Wdiff $DIR/$F" $ofile $nfile > \
3119daaffb31Sdp			    $WDIR/$DIR/$F.wdiff.html 2>/dev/null
3120daaffb31Sdp			if [[ $? -eq 0 ]]; then
31217c478bd9Sstevel@tonic-gate				print " wdiffs\c"
3122daaffb31Sdp			else
3123daaffb31Sdp				print " wdiffs[fail]\c"
3124daaffb31Sdp			fi
31257c478bd9Sstevel@tonic-gate		fi
31267c478bd9Sstevel@tonic-gate
3127daaffb31Sdp		sdiff_to_html $ofile $nfile $F $DIR "$COMM" \
3128daaffb31Sdp		    > $WDIR/$DIR/$F.sdiff.html
31297c478bd9Sstevel@tonic-gate		print " sdiffs\c"
31307c478bd9Sstevel@tonic-gate
31317c478bd9Sstevel@tonic-gate		print " frames\c"
31327c478bd9Sstevel@tonic-gate
31337c478bd9Sstevel@tonic-gate		rm -f $WDIR/$DIR/$F.cdiff $WDIR/$DIR/$F.udiff
31347c478bd9Sstevel@tonic-gate
3135daaffb31Sdp		difflines $ofile $nfile > $WDIR/$DIR/$F.count
3136daaffb31Sdp
3137daaffb31Sdp	elif [[ -f $ofile && -f $nfile && -n $mv_but_nodiff ]]; then
3138daaffb31Sdp		# renamed file: may also have differences
3139daaffb31Sdp		difflines $ofile $nfile > $WDIR/$DIR/$F.count
3140daaffb31Sdp	elif [[ -f $nfile ]]; then
31417c478bd9Sstevel@tonic-gate		# new file: count added lines
3142daaffb31Sdp		difflines /dev/null $nfile > $WDIR/$DIR/$F.count
3143daaffb31Sdp	elif [[ -f $ofile ]]; then
31447c478bd9Sstevel@tonic-gate		# old file: count deleted lines
3145daaffb31Sdp		difflines $ofile /dev/null > $WDIR/$DIR/$F.count
31467c478bd9Sstevel@tonic-gate	fi
31477c478bd9Sstevel@tonic-gate
3148daaffb31Sdp	#
3149daaffb31Sdp	# Now we generate the postscript for this file.  We generate diffs
3150daaffb31Sdp	# only in the event that there is delta, or the file is new (it seems
3151daaffb31Sdp	# tree-killing to print out the contents of deleted files).
3152daaffb31Sdp	#
3153daaffb31Sdp	if [[ -f $nfile ]]; then
3154daaffb31Sdp		ocr=$ofile
3155daaffb31Sdp		[[ ! -f $ofile ]] && ocr=/dev/null
3156daaffb31Sdp
3157daaffb31Sdp		if [[ -z $mv_but_nodiff ]]; then
3158daaffb31Sdp			textcomm=`getcomments text $P $PP`
315914983201Sdp			if [[ -x $CODEREVIEW ]]; then
316014983201Sdp				$CODEREVIEW -y "$textcomm" \
316114983201Sdp				    -e $ocr $nfile \
316214983201Sdp				    > /tmp/$$.psfile 2>/dev/null &&
316314983201Sdp				    cat /tmp/$$.psfile >> $WDIR/$WNAME.ps
3164daaffb31Sdp				if [[ $? -eq 0 ]]; then
3165daaffb31Sdp					print " ps\c"
3166daaffb31Sdp				else
3167daaffb31Sdp					print " ps[fail]\c"
3168daaffb31Sdp				fi
3169daaffb31Sdp			fi
3170daaffb31Sdp		fi
317114983201Sdp	fi
3172daaffb31Sdp
3173cdf0c1d5Smjnelson	if [[ -f $ofile ]]; then
3174cdf0c1d5Smjnelson		source_to_html Old $PP < $ofile > $WDIR/$DIR/$F-.html
31757c478bd9Sstevel@tonic-gate		print " old\c"
31767c478bd9Sstevel@tonic-gate	fi
31777c478bd9Sstevel@tonic-gate
3178daaffb31Sdp	if [[ -f $nfile ]]; then
3179daaffb31Sdp		source_to_html New $P < $nfile > $WDIR/$DIR/$F.html
31807c478bd9Sstevel@tonic-gate		print " new\c"
31817c478bd9Sstevel@tonic-gate	fi
31827c478bd9Sstevel@tonic-gate
3183cdf0c1d5Smjnelson	cd $OWD
3184cdf0c1d5Smjnelson
3185daaffb31Sdp	print
31867c478bd9Sstevel@tonic-gatedone
31877c478bd9Sstevel@tonic-gate
3188daaffb31Sdpframe_nav_js > $WDIR/ancnav.js
31897c478bd9Sstevel@tonic-gateframe_navigation > $WDIR/ancnav.html
3190daaffb31Sdp
319114983201Sdpif [[ ! -f $WDIR/$WNAME.ps ]]; then
319214983201Sdp	print " Generating PDF: Skipped: no output available"
319314983201Sdpelif [[ -x $CODEREVIEW && -x $PS2PDF ]]; then
319414983201Sdp	print " Generating PDF: \c"
319514983201Sdp	fix_postscript $WDIR/$WNAME.ps | $PS2PDF - > $WDIR/$WNAME.pdf
3196daaffb31Sdp	print "Done."
319714983201Sdpelse
319814983201Sdp	print " Generating PDF: Skipped: missing 'ps2pdf' or 'codereview'"
319914983201Sdpfi
32007c478bd9Sstevel@tonic-gate
3201e0e0293aSjmcp# If we're in OpenSolaris mode and there's a closed dir under $WDIR,
3202e0e0293aSjmcp# delete it - prevent accidental publishing of closed source
3203e0e0293aSjmcp
3204e0e0293aSjmcpif [[ -n "$Oflag" ]]; then
3205ba44d8a2SVladimir Kotal	$FIND $WDIR -type d -name closed -exec /bin/rm -rf {} \;
3206e0e0293aSjmcpfi
3207e0e0293aSjmcp
32087c478bd9Sstevel@tonic-gate# Now build the index.html file that contains
32097c478bd9Sstevel@tonic-gate# links to the source files and their diffs.
32107c478bd9Sstevel@tonic-gate
32117c478bd9Sstevel@tonic-gatecd $CWS
32127c478bd9Sstevel@tonic-gate
32137c478bd9Sstevel@tonic-gate# Save total changed lines for Code Inspection.
3214daaffb31Sdpprint "$TOTL" > $WDIR/TotalChangedLines
32157c478bd9Sstevel@tonic-gate
3216daaffb31Sdpprint "     index.html: \c"
32177c478bd9Sstevel@tonic-gateINDEXFILE=$WDIR/index.html
32187c478bd9Sstevel@tonic-gateexec 3<&1			# duplicate stdout to FD3.
32197c478bd9Sstevel@tonic-gateexec 1<&-			# Close stdout.
32207c478bd9Sstevel@tonic-gateexec > $INDEXFILE		# Open stdout to index file.
32217c478bd9Sstevel@tonic-gate
3222daaffb31Sdpprint "$HTML<head>$STDHEAD"
3223daaffb31Sdpprint "<title>$WNAME</title>"
3224daaffb31Sdpprint "</head>"
3225daaffb31Sdpprint "<body id=\"SUNWwebrev\">"
3226daaffb31Sdpprint "<div class=\"summary\">"
3227daaffb31Sdpprint "<h2>Code Review for $WNAME</h2>"
32287c478bd9Sstevel@tonic-gate
3229daaffb31Sdpprint "<table>"
32307c478bd9Sstevel@tonic-gate
3231daaffb31Sdp#
3232cdf0c1d5Smjnelson# Get the preparer's name:
3233daaffb31Sdp#
3234cdf0c1d5Smjnelson# If the SCM detected is Mercurial, and the configuration property
3235cdf0c1d5Smjnelson# ui.username is available, use that, but be careful to properly escape
3236cdf0c1d5Smjnelson# angle brackets (HTML syntax characters) in the email address.
3237cdf0c1d5Smjnelson#
3238cdf0c1d5Smjnelson# Otherwise, use the current userid in the form "John Doe (jdoe)", but
3239cdf0c1d5Smjnelson# to maintain compatibility with passwd(4), we must support '&' substitutions.
3240cdf0c1d5Smjnelson#
3241cdf0c1d5Smjnelsonpreparer=
3242cdf0c1d5Smjnelsonif [[ "$SCM_MODE" == mercurial ]]; then
3243cdf0c1d5Smjnelson	preparer=`hg showconfig ui.username 2>/dev/null`
3244cdf0c1d5Smjnelson	if [[ -n "$preparer" ]]; then
3245cdf0c1d5Smjnelson		preparer="$(echo "$preparer" | html_quote)"
3246cdf0c1d5Smjnelson	fi
3247cdf0c1d5Smjnelsonfi
3248cdf0c1d5Smjnelsonif [[ -z "$preparer" ]]; then
3249cdf0c1d5Smjnelson	preparer=$(
3250cdf0c1d5Smjnelson	    $PERL -e '
3251cdf0c1d5Smjnelson	        ($login, $pw, $uid, $gid, $quota, $cmt, $gcos) = getpwuid($<);
3252cdf0c1d5Smjnelson	        if ($login) {
3253cdf0c1d5Smjnelson	            $gcos =~ s/\&/ucfirst($login)/e;
3254cdf0c1d5Smjnelson	            printf "%s (%s)\n", $gcos, $login;
3255cdf0c1d5Smjnelson	        } else {
3256cdf0c1d5Smjnelson	            printf "(unknown)\n";
3257cdf0c1d5Smjnelson	        }
3258cdf0c1d5Smjnelson	')
3259daaffb31Sdpfi
3260daaffb31Sdp
326148bc00d6SjmcpPREPDATE=$(LC_ALL=C /usr/bin/date +%Y-%b-%d\ %R\ %z\ %Z)
326248bc00d6Sjmcpprint "<tr><th>Prepared by:</th><td>$preparer on $PREPDATE</td></tr>"
3263cdf0c1d5Smjnelsonprint "<tr><th>Workspace:</th><td>$CWS"
3264cdf0c1d5Smjnelsonif [[ -n $CWS_REV ]]; then
3265cdf0c1d5Smjnelson	print "(at $CWS_REV)"
3266cdf0c1d5Smjnelsonfi
3267cdf0c1d5Smjnelsonprint "</td></tr>"
3268daaffb31Sdpprint "<tr><th>Compare against:</th><td>"
3269daaffb31Sdpif [[ -n $parent_webrev ]]; then
3270daaffb31Sdp	print "webrev at $parent_webrev"
3271daaffb31Sdpelse
3272daaffb31Sdp	print "$PWS"
3273cdf0c1d5Smjnelson	if [[ -n $hg_parent_short ]]; then
3274cdf0c1d5Smjnelson		print "(at $hg_parent_short)"
3275cdf0c1d5Smjnelson	fi
3276daaffb31Sdpfi
3277daaffb31Sdpprint "</td></tr>"
3278daaffb31Sdpprint "<tr><th>Summary of changes:</th><td>"
3279daaffb31SdpprintCI $TOTL $TINS $TDEL $TMOD $TUNC
3280daaffb31Sdpprint "</td></tr>"
3281daaffb31Sdp
3282daaffb31Sdpif [[ -f $WDIR/$WNAME.patch ]]; then
3283371d72daSLubomir Sedlacik	wpatch_url="$(print $WNAME.patch | url_encode)"
3284daaffb31Sdp	print "<tr><th>Patch of changes:</th><td>"
3285371d72daSLubomir Sedlacik	print "<a href=\"$wpatch_url\">$WNAME.patch</a></td></tr>"
3286daaffb31Sdpfi
3287daaffb31Sdpif [[ -f $WDIR/$WNAME.pdf ]]; then
3288371d72daSLubomir Sedlacik	wpdf_url="$(print $WNAME.pdf | url_encode)"
3289daaffb31Sdp	print "<tr><th>Printable review:</th><td>"
3290371d72daSLubomir Sedlacik	print "<a href=\"$wpdf_url\">$WNAME.pdf</a></td></tr>"
3291daaffb31Sdpfi
3292daaffb31Sdp
3293daaffb31Sdpif [[ -n "$iflag" ]]; then
3294daaffb31Sdp	print "<tr><th>Author comments:</th><td><div>"
3295daaffb31Sdp	cat /tmp/$$.include
3296daaffb31Sdp	print "</div></td></tr>"
3297daaffb31Sdpfi
3298daaffb31Sdpprint "</table>"
3299daaffb31Sdpprint "</div>"
3300daaffb31Sdp
3301daaffb31Sdp#
3302daaffb31Sdp# Second pass through the files: generate the rest of the index file
3303daaffb31Sdp#
3304daaffb31Sdpcat $FLIST | while read LINE
33057c478bd9Sstevel@tonic-gatedo
33067c478bd9Sstevel@tonic-gate	set - $LINE
33077c478bd9Sstevel@tonic-gate	P=$1
33087c478bd9Sstevel@tonic-gate
3309daaffb31Sdp	if [[ $# == 2 ]]; then
33107c478bd9Sstevel@tonic-gate		PP=$2
3311cdf0c1d5Smjnelson		oldname="$PP"
33127c478bd9Sstevel@tonic-gate	else
33137c478bd9Sstevel@tonic-gate		PP=$P
3314daaffb31Sdp		oldname=""
3315daaffb31Sdp	fi
3316daaffb31Sdp
3317cdf0c1d5Smjnelson	mv_but_nodiff=
3318cdf0c1d5Smjnelson	cmp $WDIR/raw_files/old/$PP $WDIR/raw_files/new/$P > /dev/null 2>&1
3319cdf0c1d5Smjnelson	if [[ $? == 0 && -n "$oldname" ]]; then
3320cdf0c1d5Smjnelson		mv_but_nodiff=1
3321cdf0c1d5Smjnelson	fi
3322cdf0c1d5Smjnelson
3323daaffb31Sdp	DIR=${P%/*}
3324daaffb31Sdp	if [[ $DIR == $P ]]; then
3325daaffb31Sdp		DIR="."   # File at root of workspace
33267c478bd9Sstevel@tonic-gate	fi
33277c478bd9Sstevel@tonic-gate
33287c478bd9Sstevel@tonic-gate	# Avoid processing the same file twice.
33297c478bd9Sstevel@tonic-gate	# It's possible for renamed files to
33307c478bd9Sstevel@tonic-gate	# appear twice in the file list
33317c478bd9Sstevel@tonic-gate
33327c478bd9Sstevel@tonic-gate	F=$WDIR/$P
33337c478bd9Sstevel@tonic-gate
3334daaffb31Sdp	print "<p>"
33357c478bd9Sstevel@tonic-gate
33367c478bd9Sstevel@tonic-gate	# If there's a diffs file, make diffs links
33377c478bd9Sstevel@tonic-gate
3338daaffb31Sdp	if [[ -f $F.cdiff.html ]]; then
3339371d72daSLubomir Sedlacik		cdiff_url="$(print $P.cdiff.html | url_encode)"
3340371d72daSLubomir Sedlacik		udiff_url="$(print $P.udiff.html | url_encode)"
3341371d72daSLubomir Sedlacik		print "<a href=\"$cdiff_url\">Cdiffs</a>"
3342371d72daSLubomir Sedlacik		print "<a href=\"$udiff_url\">Udiffs</a>"
33437c478bd9Sstevel@tonic-gate
3344daaffb31Sdp		if [[ -f $F.wdiff.html && -x $WDIFF ]]; then
3345371d72daSLubomir Sedlacik			wdiff_url="$(print $P.wdiff.html | url_encode)"
3346371d72daSLubomir Sedlacik			print "<a href=\"$wdiff_url\">Wdiffs</a>"
33477c478bd9Sstevel@tonic-gate		fi
33487c478bd9Sstevel@tonic-gate
3349371d72daSLubomir Sedlacik		sdiff_url="$(print $P.sdiff.html | url_encode)"
3350371d72daSLubomir Sedlacik		print "<a href=\"$sdiff_url\">Sdiffs</a>"
33517c478bd9Sstevel@tonic-gate
3352371d72daSLubomir Sedlacik		frames_url="$(print $P.frames.html | url_encode)"
3353371d72daSLubomir Sedlacik		print "<a href=\"$frames_url\">Frames</a>"
33547c478bd9Sstevel@tonic-gate	else
3355daaffb31Sdp		print " ------ ------ ------"
33567c478bd9Sstevel@tonic-gate
3357daaffb31Sdp		if [[ -x $WDIFF ]]; then
33587c478bd9Sstevel@tonic-gate			print " ------"
33597c478bd9Sstevel@tonic-gate		fi
3360daaffb31Sdp
3361daaffb31Sdp		print " ------"
33627c478bd9Sstevel@tonic-gate	fi
33637c478bd9Sstevel@tonic-gate
33647c478bd9Sstevel@tonic-gate	# If there's an old file, make the link
33657c478bd9Sstevel@tonic-gate
3366daaffb31Sdp	if [[ -f $F-.html ]]; then
3367371d72daSLubomir Sedlacik		oldfile_url="$(print $P-.html | url_encode)"
3368371d72daSLubomir Sedlacik		print "<a href=\"$oldfile_url\">Old</a>"
33697c478bd9Sstevel@tonic-gate	else
3370daaffb31Sdp		print " ---"
33717c478bd9Sstevel@tonic-gate	fi
33727c478bd9Sstevel@tonic-gate
33737c478bd9Sstevel@tonic-gate	# If there's an new file, make the link
33747c478bd9Sstevel@tonic-gate
3375daaffb31Sdp	if [[ -f $F.html ]]; then
3376371d72daSLubomir Sedlacik		newfile_url="$(print $P.html | url_encode)"
3377371d72daSLubomir Sedlacik		print "<a href=\"$newfile_url\">New</a>"
33787c478bd9Sstevel@tonic-gate	else
3379daaffb31Sdp		print " ---"
33807c478bd9Sstevel@tonic-gate	fi
33817c478bd9Sstevel@tonic-gate
3382daaffb31Sdp	if [[ -f $F.patch ]]; then
3383371d72daSLubomir Sedlacik		patch_url="$(print $P.patch | url_encode)"
3384371d72daSLubomir Sedlacik		print "<a href=\"$patch_url\">Patch</a>"
3385daaffb31Sdp	else
3386daaffb31Sdp		print " -----"
3387daaffb31Sdp	fi
3388daaffb31Sdp
3389daaffb31Sdp	if [[ -f $WDIR/raw_files/new/$P ]]; then
3390371d72daSLubomir Sedlacik		rawfiles_url="$(print raw_files/new/$P | url_encode)"
3391371d72daSLubomir Sedlacik		print "<a href=\"$rawfiles_url\">Raw</a>"
3392daaffb31Sdp	else
3393daaffb31Sdp		print " ---"
3394daaffb31Sdp	fi
3395daaffb31Sdp
3396cdf0c1d5Smjnelson	print "<b>$P</b>"
3397cdf0c1d5Smjnelson
3398cdf0c1d5Smjnelson	# For renamed files, clearly state whether or not they are modified
3399e6ccc173SEdward Pilatowicz	if [[ -f "$oldname" ]]; then
3400cdf0c1d5Smjnelson		if [[ -n "$mv_but_nodiff" ]]; then
3401e6ccc173SEdward Pilatowicz			print "<i>(copied from $oldname)</i>"
3402cdf0c1d5Smjnelson		else
3403e6ccc173SEdward Pilatowicz			print "<i>(copied and modified from $oldname)</i>"
3404e6ccc173SEdward Pilatowicz		fi
3405e6ccc173SEdward Pilatowicz	elif [[ -n "$oldname" ]]; then
3406e6ccc173SEdward Pilatowicz		if [[ -n "$mv_but_nodiff" ]]; then
3407e6ccc173SEdward Pilatowicz			print "<i>(renamed from $oldname)</i>"
3408e6ccc173SEdward Pilatowicz		else
3409e6ccc173SEdward Pilatowicz			print "<i>(renamed and modified from $oldname)</i>"
3410cdf0c1d5Smjnelson		fi
3411cdf0c1d5Smjnelson	fi
3412cdf0c1d5Smjnelson
3413cdf0c1d5Smjnelson	# If there's an old file, but no new file, the file was deleted
3414cdf0c1d5Smjnelson	if [[ -f $F-.html && ! -f $F.html ]]; then
3415cdf0c1d5Smjnelson		print " <i>(deleted)</i>"
3416cdf0c1d5Smjnelson	fi
3417daaffb31Sdp
3418daaffb31Sdp	#
3419e0e0293aSjmcp	# Check for usr/closed and deleted_files/usr/closed
3420daaffb31Sdp	#
3421daaffb31Sdp	if [ ! -z "$Oflag" ]; then
3422e0e0293aSjmcp		if [[ $P == usr/closed/* || \
3423e0e0293aSjmcp		    $P == deleted_files/usr/closed/* ]]; then
3424daaffb31Sdp			print "&nbsp;&nbsp;<i>Closed source: omitted from" \
3425daaffb31Sdp			    "this review</i>"
3426daaffb31Sdp		fi
3427daaffb31Sdp	fi
3428daaffb31Sdp
3429daaffb31Sdp	print "</p>"
34307c478bd9Sstevel@tonic-gate	# Insert delta comments
34317c478bd9Sstevel@tonic-gate
3432daaffb31Sdp	print "<blockquote><pre>"
3433daaffb31Sdp	getcomments html $P $PP
3434daaffb31Sdp	print "</pre>"
34357c478bd9Sstevel@tonic-gate
34367c478bd9Sstevel@tonic-gate	# Add additional comments comment
34377c478bd9Sstevel@tonic-gate
3438daaffb31Sdp	print "<!-- Add comments to explain changes in $P here -->"
34397c478bd9Sstevel@tonic-gate
34407c478bd9Sstevel@tonic-gate	# Add count of changes.
34417c478bd9Sstevel@tonic-gate
3442daaffb31Sdp	if [[ -f $F.count ]]; then
34437c478bd9Sstevel@tonic-gate	    cat $F.count
34447c478bd9Sstevel@tonic-gate	    rm $F.count
34457c478bd9Sstevel@tonic-gate	fi
3446cdf0c1d5Smjnelson
3447cdf0c1d5Smjnelson	if [[ $SCM_MODE == "teamware" ||
3448cdf0c1d5Smjnelson	    $SCM_MODE == "mercurial" ||
3449cdf0c1d5Smjnelson	    $SCM_MODE == "unknown" ]]; then
3450cdf0c1d5Smjnelson
3451cdf0c1d5Smjnelson		# Include warnings for important file mode situations:
3452cdf0c1d5Smjnelson		# 1) New executable files
3453cdf0c1d5Smjnelson		# 2) Permission changes of any kind
3454cdf0c1d5Smjnelson		# 3) Existing executable files
3455cdf0c1d5Smjnelson
3456cdf0c1d5Smjnelson		old_mode=
3457cdf0c1d5Smjnelson		if [[ -f $WDIR/raw_files/old/$PP ]]; then
3458cdf0c1d5Smjnelson			old_mode=`get_file_mode $WDIR/raw_files/old/$PP`
3459cdf0c1d5Smjnelson		fi
3460cdf0c1d5Smjnelson
3461cdf0c1d5Smjnelson		new_mode=
3462cdf0c1d5Smjnelson		if [[ -f $WDIR/raw_files/new/$P ]]; then
3463cdf0c1d5Smjnelson			new_mode=`get_file_mode $WDIR/raw_files/new/$P`
3464cdf0c1d5Smjnelson		fi
3465cdf0c1d5Smjnelson
3466cdf0c1d5Smjnelson		if [[ -z "$old_mode" && "$new_mode" = *[1357]* ]]; then
3467cdf0c1d5Smjnelson			print "<span class=\"chmod\">"
3468cdf0c1d5Smjnelson			print "<p>new executable file: mode $new_mode</p>"
3469cdf0c1d5Smjnelson			print "</span>"
3470cdf0c1d5Smjnelson		elif [[ -n "$old_mode" && -n "$new_mode" &&
3471cdf0c1d5Smjnelson		    "$old_mode" != "$new_mode" ]]; then
3472cdf0c1d5Smjnelson			print "<span class=\"chmod\">"
3473cdf0c1d5Smjnelson			print "<p>mode change: $old_mode to $new_mode</p>"
3474cdf0c1d5Smjnelson			print "</span>"
3475cdf0c1d5Smjnelson		elif [[ "$new_mode" = *[1357]* ]]; then
3476cdf0c1d5Smjnelson			print "<span class=\"chmod\">"
3477cdf0c1d5Smjnelson			print "<p>executable file: mode $new_mode</p>"
3478cdf0c1d5Smjnelson			print "</span>"
3479cdf0c1d5Smjnelson		fi
3480cdf0c1d5Smjnelson	fi
3481cdf0c1d5Smjnelson
3482daaffb31Sdp	print "</blockquote>"
34837c478bd9Sstevel@tonic-gatedone
34847c478bd9Sstevel@tonic-gate
3485daaffb31Sdpprint
3486daaffb31Sdpprint
3487cac38512Smjnelsonprint "<hr></hr>"
3488daaffb31Sdpprint "<p style=\"font-size: small\">"
34899a70fc3bSMark J. Nelsonprint "This code review page was prepared using <b>$0</b>."
3490daaffb31Sdpprint "Webrev is maintained by the <a href=\"http://www.opensolaris.org\">"
3491daaffb31Sdpprint "OpenSolaris</a> project.  The latest version may be obtained"
3492e9e2cfb2Sfr80241print "<a href=\"http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/tools/scripts/webrev.sh\">here</a>.</p>"
3493daaffb31Sdpprint "</body>"
3494daaffb31Sdpprint "</html>"
34957c478bd9Sstevel@tonic-gate
34967c478bd9Sstevel@tonic-gateexec 1<&-			# Close FD 1.
34977c478bd9Sstevel@tonic-gateexec 1<&3			# dup FD 3 to restore stdout.
34987c478bd9Sstevel@tonic-gateexec 3<&-			# close FD 3.
34997c478bd9Sstevel@tonic-gate
3500daaffb31Sdpprint "Done."
350102d26c39SVladimir Kotal
3502b0088928SVladimir Kotal#
3503ba44d8a2SVladimir Kotal# If remote deletion was specified and fails do not continue.
3504b0088928SVladimir Kotal#
3505ba44d8a2SVladimir Kotalif [[ -n $Dflag ]]; then
3506b0088928SVladimir Kotal	delete_webrev 1 1
3507ba44d8a2SVladimir Kotal	(( $? == 0 )) || exit $?
3508ba44d8a2SVladimir Kotalfi
3509ba44d8a2SVladimir Kotal
351002d26c39SVladimir Kotalif [[ -n $Uflag ]]; then
351102d26c39SVladimir Kotal	upload_webrev
351202d26c39SVladimir Kotal	exit $?
351302d26c39SVladimir Kotalfi
3514