17c478bd9Sstevel@tonic-gate#!/usr/bin/ksh -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# 24*371d72daSLubomir Sedlacik# Copyright 2009 Sun Microsystems, Inc. All rights reserved. 257c478bd9Sstevel@tonic-gate# Use is subject to license terms. 267c478bd9Sstevel@tonic-gate# 27cdf0c1d5Smjnelson 28cdf0c1d5Smjnelson# 29daaffb31Sdp# This script takes a file list and a workspace and builds a set of html files 30daaffb31Sdp# suitable for doing a code review of source changes via a web page. 31daaffb31Sdp# Documentation is available via the manual page, webrev.1, or just 32daaffb31Sdp# type 'webrev -h'. 337c478bd9Sstevel@tonic-gate# 34daaffb31Sdp# Acknowledgements to contributors to webrev are listed in the webrev(1) 35daaffb31Sdp# man page. 367c478bd9Sstevel@tonic-gate# 37daaffb31Sdp 387c478bd9Sstevel@tonic-gateREMOVED_COLOR=brown 397c478bd9Sstevel@tonic-gateCHANGED_COLOR=blue 407c478bd9Sstevel@tonic-gateNEW_COLOR=blue 417c478bd9Sstevel@tonic-gate 42daaffb31SdpHTML='<?xml version="1.0"?> 43daaffb31Sdp<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 44daaffb31Sdp "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 45daaffb31Sdp<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">\n' 46daaffb31Sdp 47daaffb31SdpFRAMEHTML='<?xml version="1.0"?> 48daaffb31Sdp<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" 49daaffb31Sdp "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd"> 50daaffb31Sdp<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">\n' 51daaffb31Sdp 52cac38512SmjnelsonSTDHEAD='<meta http-equiv="cache-control" content="no-cache"></meta> 53cac38512Smjnelson<meta http-equiv="Pragma" content="no-cache"></meta> 54cac38512Smjnelson<meta http-equiv="Expires" content="-1"></meta> 55daaffb31Sdp<!-- 56daaffb31Sdp Note to customizers: the body of the webrev is IDed as SUNWwebrev 57daaffb31Sdp to allow easy overriding by users of webrev via the userContent.css 58daaffb31Sdp mechanism available in some browsers. 59daaffb31Sdp 60daaffb31Sdp For example, to have all "removed" information be red instead of 61daaffb31Sdp brown, set a rule in your userContent.css file like: 62daaffb31Sdp 63daaffb31Sdp body#SUNWwebrev span.removed { color: red ! important; } 64daaffb31Sdp--> 65daaffb31Sdp<style type="text/css" media="screen"> 66daaffb31Sdpbody { 67daaffb31Sdp background-color: #eeeeee; 68daaffb31Sdp} 69daaffb31Sdphr { 70daaffb31Sdp border: none 0; 71daaffb31Sdp border-top: 1px solid #aaa; 72daaffb31Sdp height: 1px; 73daaffb31Sdp} 74daaffb31Sdpdiv.summary { 75daaffb31Sdp font-size: .8em; 76daaffb31Sdp border-bottom: 1px solid #aaa; 77daaffb31Sdp padding-left: 1em; 78daaffb31Sdp padding-right: 1em; 79daaffb31Sdp} 80daaffb31Sdpdiv.summary h2 { 81daaffb31Sdp margin-bottom: 0.3em; 82daaffb31Sdp} 83daaffb31Sdpdiv.summary table th { 84daaffb31Sdp text-align: right; 85daaffb31Sdp vertical-align: top; 86daaffb31Sdp white-space: nowrap; 87daaffb31Sdp} 88daaffb31Sdpspan.lineschanged { 89daaffb31Sdp font-size: 0.7em; 90daaffb31Sdp} 91daaffb31Sdpspan.oldmarker { 92daaffb31Sdp color: red; 93daaffb31Sdp font-size: large; 94daaffb31Sdp font-weight: bold; 95daaffb31Sdp} 96daaffb31Sdpspan.newmarker { 97daaffb31Sdp color: green; 98daaffb31Sdp font-size: large; 99daaffb31Sdp font-weight: bold; 100daaffb31Sdp} 101daaffb31Sdpspan.removed { 102daaffb31Sdp color: brown; 103daaffb31Sdp} 104daaffb31Sdpspan.changed { 105daaffb31Sdp color: blue; 106daaffb31Sdp} 107daaffb31Sdpspan.new { 108daaffb31Sdp color: blue; 109daaffb31Sdp font-weight: bold; 110daaffb31Sdp} 111cdf0c1d5Smjnelsonspan.chmod { 112cdf0c1d5Smjnelson font-size: 0.7em; 113cdf0c1d5Smjnelson color: #db7800; 114cdf0c1d5Smjnelson} 115daaffb31Sdpa.print { font-size: x-small; } 116daaffb31Sdpa:hover { background-color: #ffcc99; } 117daaffb31Sdp</style> 118daaffb31Sdp 119daaffb31Sdp<style type="text/css" media="print"> 120daaffb31Sdppre { font-size: 0.8em; font-family: courier, monospace; } 121daaffb31Sdpspan.removed { color: #444; font-style: italic } 122daaffb31Sdpspan.changed { font-weight: bold; } 123daaffb31Sdpspan.new { font-weight: bold; } 124daaffb31Sdpspan.newmarker { font-size: 1.2em; font-weight: bold; } 125daaffb31Sdpspan.oldmarker { font-size: 1.2em; font-weight: bold; } 126daaffb31Sdpa.print {display: none} 127daaffb31Sdphr { border: none 0; border-top: 1px solid #aaa; height: 1px; } 128daaffb31Sdp</style> 129daaffb31Sdp' 130daaffb31Sdp 131daaffb31Sdp# 132daaffb31Sdp# UDiffs need a slightly different CSS rule for 'new' items (we don't 133daaffb31Sdp# want them to be bolded as we do in cdiffs or sdiffs). 134daaffb31Sdp# 135daaffb31SdpUDIFFCSS=' 136daaffb31Sdp<style type="text/css" media="screen"> 137daaffb31Sdpspan.new { 138daaffb31Sdp color: blue; 139daaffb31Sdp font-weight: normal; 140daaffb31Sdp} 141daaffb31Sdp</style> 142daaffb31Sdp' 143daaffb31Sdp 14402d26c39SVladimir Kotal# Upload the webrev via rsync. Return 0 on success, 1 on error. 145ba44d8a2SVladimir Kotalfunction rsync_upload 14602d26c39SVladimir Kotal{ 14702d26c39SVladimir Kotal if (( $# != 1 )); then 14802d26c39SVladimir Kotal return 1 14902d26c39SVladimir Kotal fi 15002d26c39SVladimir Kotal 15102d26c39SVladimir Kotal typeset dst=$1 15202d26c39SVladimir Kotal 153ba44d8a2SVladimir Kotal print " Syncing: \c" 15402d26c39SVladimir Kotal # end source directory with a slash in order to copy just 15502d26c39SVladimir Kotal # directory contents, not the whole directory 15602d26c39SVladimir Kotal $RSYNC -r -q $WDIR/ $dst 15702d26c39SVladimir Kotal if (( $? != 0 )); then 15802d26c39SVladimir Kotal print "failed to sync webrev directory " \ 15902d26c39SVladimir Kotal "'$WDIR' to '$dst'" 16002d26c39SVladimir Kotal return 1 16102d26c39SVladimir Kotal fi 16202d26c39SVladimir Kotal 16302d26c39SVladimir Kotal print "Done." 16402d26c39SVladimir Kotal return 0 16502d26c39SVladimir Kotal} 16602d26c39SVladimir Kotal 16702d26c39SVladimir Kotal# Upload the webrev via SSH. Return 0 on success, 1 on error. 168ba44d8a2SVladimir Kotalfunction ssh_upload 16902d26c39SVladimir Kotal{ 17002d26c39SVladimir Kotal if (( $# != 1 )); then 171ba44d8a2SVladimir Kotal print "ssh_upload: wrong usage" 17202d26c39SVladimir Kotal return 1 17302d26c39SVladimir Kotal fi 17402d26c39SVladimir Kotal 17502d26c39SVladimir Kotal typeset dst=$1 17602d26c39SVladimir Kotal typeset -r host_spec=${dst%%:*} 177ba44d8a2SVladimir Kotal typeset -r dir_spec=${dst#*:} 17802d26c39SVladimir Kotal 179ba44d8a2SVladimir Kotal # if the deletion was explicitly requested there is no need 180ba44d8a2SVladimir Kotal # to perform it again 181ba44d8a2SVladimir Kotal if [[ -z $Dflag ]]; then 18202d26c39SVladimir Kotal # we do not care about return value because this might be 18302d26c39SVladimir Kotal # the first time this directory is uploaded 184ba44d8a2SVladimir Kotal delete_webrev 0 18502d26c39SVladimir Kotal fi 18602d26c39SVladimir Kotal 18702d26c39SVladimir Kotal # if the supplied path is absolute we assume all directories are 18802d26c39SVladimir Kotal # created, otherwise try to create all directories in the path 18902d26c39SVladimir Kotal # except the last one which will be created by scp 19002d26c39SVladimir Kotal if [[ "${dir_spec}" == */* && "${dir_spec}" != /* ]]; then 191ba44d8a2SVladimir Kotal print " Creating dirs: \c" 19202d26c39SVladimir Kotal typeset -r dirs_mk=${dir_spec%/*} 19302d26c39SVladimir Kotal typeset -r batch_file_mkdir=$( $MKTEMP /tmp/$webrev_mkdir.XXX ) 19402d26c39SVladimir Kotal OLDIFS=$IFS 19502d26c39SVladimir Kotal IFS=/ 19602d26c39SVladimir Kotal mk= 19702d26c39SVladimir Kotal for dir in $dirs_mk; do 19802d26c39SVladimir Kotal if [[ -z $mk ]]; then 19902d26c39SVladimir Kotal mk=$dir 20002d26c39SVladimir Kotal else 20102d26c39SVladimir Kotal mk=$mk/$dir 20202d26c39SVladimir Kotal fi 20302d26c39SVladimir Kotal echo "mkdir $mk" >> $batch_file_mkdir 20402d26c39SVladimir Kotal done 20502d26c39SVladimir Kotal IFS=$OLDIFS 20602d26c39SVladimir Kotal $SFTP -b $batch_file_mkdir $host_spec 2>/dev/null 1>&2 20702d26c39SVladimir Kotal if (( $? != 0 )); then 20802d26c39SVladimir Kotal echo "Failed to create remote directories" 20902d26c39SVladimir Kotal rm -f $batch_file_mkdir 21002d26c39SVladimir Kotal return 1 21102d26c39SVladimir Kotal fi 21202d26c39SVladimir Kotal rm -f $batch_file_mkdir 21302d26c39SVladimir Kotal print "Done." 21402d26c39SVladimir Kotal fi 21502d26c39SVladimir Kotal 216ba44d8a2SVladimir Kotal print " Uploading: \c" 21702d26c39SVladimir Kotal $SCP -q -C -B -o PreferredAuthentications=publickey -r \ 21802d26c39SVladimir Kotal $WDIR $dst 21902d26c39SVladimir Kotal if (( $? != 0 )); then 22002d26c39SVladimir Kotal print "failed to upload webrev directory" \ 22102d26c39SVladimir Kotal "'$WDIR' to '$dst'" 22202d26c39SVladimir Kotal return 1 22302d26c39SVladimir Kotal fi 22402d26c39SVladimir Kotal 22502d26c39SVladimir Kotal print "Done." 22602d26c39SVladimir Kotal return 0 22702d26c39SVladimir Kotal} 22802d26c39SVladimir Kotal 22902d26c39SVladimir Kotal# 230ba44d8a2SVladimir Kotal# Delete webrev at remote site. Return 0 on success, 1 or exit code from sftp 231ba44d8a2SVladimir Kotal# on failure. 232ba44d8a2SVladimir Kotal# 233ba44d8a2SVladimir Kotalfunction delete_webrev 234ba44d8a2SVladimir Kotal{ 235ba44d8a2SVladimir Kotal if (( $# != 1 )); then 236ba44d8a2SVladimir Kotal print "delete_webrev: wrong usage" 237ba44d8a2SVladimir Kotal return 1 238ba44d8a2SVladimir Kotal fi 239ba44d8a2SVladimir Kotal 240ba44d8a2SVladimir Kotal # Strip the transport specification part of remote target first. 241ba44d8a2SVladimir Kotal typeset -r stripped_target=${remote_target##*://} 242ba44d8a2SVladimir Kotal typeset -r host_spec=${stripped_target%%:*} 243ba44d8a2SVladimir Kotal typeset -r dir_spec=${stripped_target#*:} 244ba44d8a2SVladimir Kotal integer -r check=$1 245ba44d8a2SVladimir Kotal typeset dir_rm 246ba44d8a2SVladimir Kotal 247ba44d8a2SVladimir Kotal # Do not accept an absolute path. 248ba44d8a2SVladimir Kotal if [[ ${dir_spec} == /* ]]; then 249ba44d8a2SVladimir Kotal return 1 250ba44d8a2SVladimir Kotal fi 251ba44d8a2SVladimir Kotal 252ba44d8a2SVladimir Kotal # Strip the ending slash. 253ba44d8a2SVladimir Kotal if [[ ${dir_spec} == */ ]]; then 254ba44d8a2SVladimir Kotal dir_rm=${dir_spec%%/} 255ba44d8a2SVladimir Kotal else 256ba44d8a2SVladimir Kotal dir_rm=${dir_spec} 257ba44d8a2SVladimir Kotal fi 258ba44d8a2SVladimir Kotal 259ba44d8a2SVladimir Kotal print "Removing remote: \c" 260ba44d8a2SVladimir Kotal if [[ -z "$dir_rm" ]]; then 261ba44d8a2SVladimir Kotal print "empty directory for removal" 262ba44d8a2SVladimir Kotal return 1 263ba44d8a2SVladimir Kotal fi 264ba44d8a2SVladimir Kotal 265ba44d8a2SVladimir Kotal # Prepare batch file. 266ba44d8a2SVladimir Kotal typeset -r batch_file_rm=$( $MKTEMP /tmp/webrev_remove.XXX ) 267ba44d8a2SVladimir Kotal if [[ -z $batch_file_rm ]]; then 268ba44d8a2SVladimir Kotal print "Cannot create temporary file" 269ba44d8a2SVladimir Kotal return 1 270ba44d8a2SVladimir Kotal fi 271ba44d8a2SVladimir Kotal print "rename $dir_rm $TRASH_DIR/removed.$$" > $batch_file_rm 272ba44d8a2SVladimir Kotal 273ba44d8a2SVladimir Kotal # Perform remote deletion and remove the batch file. 274ba44d8a2SVladimir Kotal $SFTP -b $batch_file_rm $host_spec 2>/dev/null 1>&2 275ba44d8a2SVladimir Kotal integer -r ret=$? 276ba44d8a2SVladimir Kotal rm -f $batch_file_rm 277ba44d8a2SVladimir Kotal if (( $ret != 0 && $check > 0 )); then 278ba44d8a2SVladimir Kotal print "Failed" 279ba44d8a2SVladimir Kotal return $ret 280ba44d8a2SVladimir Kotal fi 281ba44d8a2SVladimir Kotal print "Done." 282ba44d8a2SVladimir Kotal 283ba44d8a2SVladimir Kotal return 0 284ba44d8a2SVladimir Kotal} 285ba44d8a2SVladimir Kotal 286ba44d8a2SVladimir Kotal# 28702d26c39SVladimir Kotal# Upload webrev to remote site 28802d26c39SVladimir Kotal# 289ba44d8a2SVladimir Kotalfunction upload_webrev 29002d26c39SVladimir Kotal{ 29102d26c39SVladimir Kotal typeset -r rsync_prefix="rsync://" 29202d26c39SVladimir Kotal typeset -r ssh_prefix="ssh://" 29302d26c39SVladimir Kotal 29402d26c39SVladimir Kotal if [[ ! -d "$WDIR" ]]; then 29502d26c39SVladimir Kotal echo "webrev directory '$WDIR' does not exist" 29602d26c39SVladimir Kotal return 1 29702d26c39SVladimir Kotal fi 29802d26c39SVladimir Kotal 29902d26c39SVladimir Kotal # Perform a late check to make sure we do not upload closed source 30002d26c39SVladimir Kotal # to remote target when -n is used. If the user used custom remote 30102d26c39SVladimir Kotal # target he probably knows what he is doing. 30202d26c39SVladimir Kotal if [[ -n $nflag && -z $tflag ]]; then 303ba44d8a2SVladimir Kotal $FIND $WDIR -type d -name closed \ 30402d26c39SVladimir Kotal | $GREP closed >/dev/null 30502d26c39SVladimir Kotal if (( $? == 0 )); then 30602d26c39SVladimir Kotal echo "directory '$WDIR' contains \"closed\" directory" 30702d26c39SVladimir Kotal return 1 30802d26c39SVladimir Kotal fi 30902d26c39SVladimir Kotal fi 31002d26c39SVladimir Kotal 31102d26c39SVladimir Kotal # we have the URI for remote destination now so let's start the upload 31202d26c39SVladimir Kotal if [[ -n $tflag ]]; then 31302d26c39SVladimir Kotal if [[ "${remote_target}" == ${rsync_prefix}?* ]]; then 31402d26c39SVladimir Kotal rsync_upload ${remote_target##$rsync_prefix} 31502d26c39SVladimir Kotal return $? 31602d26c39SVladimir Kotal elif [[ "${remote_target}" == ${ssh_prefix}?* ]]; then 31702d26c39SVladimir Kotal ssh_upload ${remote_target##$ssh_prefix} 31802d26c39SVladimir Kotal return $? 31902d26c39SVladimir Kotal else 32002d26c39SVladimir Kotal echo "invalid upload URI ($remote_target)" 32102d26c39SVladimir Kotal return 1 32202d26c39SVladimir Kotal fi 32302d26c39SVladimir Kotal else 32402d26c39SVladimir Kotal # try rsync first and fallback to SSH in case it fails 325ba44d8a2SVladimir Kotal rsync_upload ${remote_target} 32602d26c39SVladimir Kotal if (( $? != 0 )); then 32702d26c39SVladimir Kotal echo "rsync upload failed, falling back to SSH" 328ba44d8a2SVladimir Kotal ssh_upload ${remote_target} 32902d26c39SVladimir Kotal fi 33002d26c39SVladimir Kotal return $? 33102d26c39SVladimir Kotal fi 33202d26c39SVladimir Kotal 33302d26c39SVladimir Kotal return 0 33402d26c39SVladimir Kotal} 33502d26c39SVladimir Kotal 336daaffb31Sdp# 337*371d72daSLubomir Sedlacik# input_cmd | url_encode | output_cmd 338*371d72daSLubomir Sedlacik# 339*371d72daSLubomir Sedlacik# URL-encode (percent-encode) reserved characters as defined in RFC 3986. 340*371d72daSLubomir Sedlacik# 341*371d72daSLubomir Sedlacik# Reserved characters are: :/?#[]@!$&'()*+,;= 342*371d72daSLubomir Sedlacik# 343*371d72daSLubomir Sedlacik# While not a reserved character itself, percent '%' is reserved by definition 344*371d72daSLubomir Sedlacik# so encode it first to avoid recursive transformation, and skip '/' which is 345*371d72daSLubomir Sedlacik# a path delimiter. 346*371d72daSLubomir Sedlacik# 347*371d72daSLubomir Sedlacikfunction url_encode 348*371d72daSLubomir Sedlacik{ 349*371d72daSLubomir Sedlacik sed -e "s|%|%25|g" -e "s|:|%3A|g" -e "s|\&|%26|g" \ 350*371d72daSLubomir Sedlacik -e "s|?|%3F|g" -e "s|#|%23|g" -e "s|\[|%5B|g" \ 351*371d72daSLubomir Sedlacik -e "s|*|%2A|g" -e "s|@|%40|g" -e "s|\!|%21|g" \ 352*371d72daSLubomir Sedlacik -e "s|=|%3D|g" -e "s|;|%3B|g" -e "s|\]|%5D|g" \ 353*371d72daSLubomir Sedlacik -e "s|(|%28|g" -e "s|)|%29|g" -e "s|\'|%27|g" \ 354*371d72daSLubomir Sedlacik -e "s|+|%2B|g" -e "s|\,|%2C|g" -e "s|\\\$|%24|g" 355*371d72daSLubomir Sedlacik} 356*371d72daSLubomir Sedlacik 357*371d72daSLubomir Sedlacik# 358daaffb31Sdp# input_cmd | html_quote | output_cmd 359daaffb31Sdp# or 360daaffb31Sdp# html_quote filename | output_cmd 3617c478bd9Sstevel@tonic-gate# 3627c478bd9Sstevel@tonic-gate# Make a piece of source code safe for display in an HTML <pre> block. 3637c478bd9Sstevel@tonic-gate# 3647c478bd9Sstevel@tonic-gatehtml_quote() 3657c478bd9Sstevel@tonic-gate{ 3667c478bd9Sstevel@tonic-gate sed -e "s/&/\&/g" -e "s/</\</g" -e "s/>/\>/g" "$@" | expand 3677c478bd9Sstevel@tonic-gate} 3687c478bd9Sstevel@tonic-gate 369daaffb31Sdp# 370daaffb31Sdp# input_cmd | bug2url | output_cmd 371daaffb31Sdp# 372daaffb31Sdp# Scan for bugids and insert <a> links to the relevent bug database. 373daaffb31Sdp# 374daaffb31Sdpbug2url() 3757c478bd9Sstevel@tonic-gate{ 376daaffb31Sdp sed -e 's|[0-9]\{5,\}|<a href=\"'$BUGURL'&\">&</a>|g' 377daaffb31Sdp} 378daaffb31Sdp 3797c478bd9Sstevel@tonic-gate# 380daaffb31Sdp# input_cmd | sac2url | output_cmd 3817c478bd9Sstevel@tonic-gate# 382daaffb31Sdp# Scan for ARC cases and insert <a> links to the relevent SAC database. 383daaffb31Sdp# This is slightly complicated because inside the SWAN, SAC cases are 384daaffb31Sdp# grouped by ARC: PSARC/2006/123. But on OpenSolaris.org, they are 385daaffb31Sdp# referenced as 2006/123 (without labelling the ARC). 3867c478bd9Sstevel@tonic-gate# 387daaffb31Sdpsac2url() 388daaffb31Sdp{ 389e0e0293aSjmcp if [[ -z "$Oflag" ]]; then 3900a30ef2cSstevel sed -e 's|\([A-Z]\{1,2\}ARC\)[ /]\([0-9]\{4\}\)/\([0-9]\{3\}\)|<a href=\"'$SACURL'/\1/\2/\3\">\1 \2/\3</a>|g' 391daaffb31Sdp else 392daaffb31Sdp sed -e 's|\([A-Z]\{1,2\}ARC\)[ /]\([0-9]\{4\}\)/\([0-9]\{3\}\)|<a href=\"'$SACURL'/\2/\3\">\1 \2/\3</a>|g' 393daaffb31Sdp fi 394daaffb31Sdp} 395daaffb31Sdp 3967c478bd9Sstevel@tonic-gate# 397daaffb31Sdp# strip_unchanged <infile> | output_cmd 3987c478bd9Sstevel@tonic-gate# 399daaffb31Sdp# Removes chunks of sdiff documents that have not changed. This makes it 400daaffb31Sdp# easier for a code reviewer to find the bits that have changed. 4017c478bd9Sstevel@tonic-gate# 402daaffb31Sdp# Deleted lines of text are replaced by a horizontal rule. Some 403daaffb31Sdp# identical lines are retained before and after the changed lines to 404daaffb31Sdp# provide some context. The number of these lines is controlled by the 405cdf0c1d5Smjnelson# variable C in the $AWK script below. 406daaffb31Sdp# 407daaffb31Sdp# The script detects changed lines as any line that has a "<span class=" 408daaffb31Sdp# string embedded (unchanged lines have no particular class and are not 409daaffb31Sdp# part of a <span>). Blank lines (without a sequence number) are also 410daaffb31Sdp# detected since they flag lines that have been inserted or deleted. 411daaffb31Sdp# 412daaffb31Sdpstrip_unchanged() 413daaffb31Sdp{ 414cdf0c1d5Smjnelson $AWK ' 415daaffb31Sdp BEGIN { C = c = 20 } 416cdf0c1d5Smjnelson NF == 0 || /<span class="/ { 417daaffb31Sdp if (c > C) { 418daaffb31Sdp c -= C 419daaffb31Sdp inx = 0 420daaffb31Sdp if (c > C) { 421cac38512Smjnelson print "\n</pre><hr></hr><pre>" 422daaffb31Sdp inx = c % C 423daaffb31Sdp c = C 424daaffb31Sdp } 425daaffb31Sdp 426daaffb31Sdp for (i = 0; i < c; i++) 427daaffb31Sdp print ln[(inx + i) % C] 428daaffb31Sdp } 429daaffb31Sdp c = 0; 430daaffb31Sdp print 431daaffb31Sdp next 432daaffb31Sdp } 433daaffb31Sdp { if (c >= C) { 434daaffb31Sdp ln[c % C] = $0 435daaffb31Sdp c++; 436daaffb31Sdp next; 437daaffb31Sdp } 438daaffb31Sdp c++; 439daaffb31Sdp print 440daaffb31Sdp } 441cac38512Smjnelson END { if (c > (C * 2)) print "\n</pre><hr></hr>" } 442daaffb31Sdp 443daaffb31Sdp ' $1 444daaffb31Sdp} 445daaffb31Sdp 446daaffb31Sdp# 447daaffb31Sdp# sdiff_to_html 448daaffb31Sdp# 449daaffb31Sdp# This function takes two files as arguments, obtains their diff, and 450daaffb31Sdp# processes the diff output to present the files as an HTML document with 451daaffb31Sdp# the files displayed side-by-side, differences shown in color. It also 452daaffb31Sdp# takes a delta comment, rendered as an HTML snippet, as the third 453daaffb31Sdp# argument. The function takes two files as arguments, then the name of 454daaffb31Sdp# file, the path, and the comment. The HTML will be delivered on stdout, 455daaffb31Sdp# e.g. 456daaffb31Sdp# 457daaffb31Sdp# $ sdiff_to_html old/usr/src/tools/scripts/webrev.sh \ 458daaffb31Sdp# new/usr/src/tools/scripts/webrev.sh \ 459daaffb31Sdp# webrev.sh usr/src/tools/scripts \ 460daaffb31Sdp# '<a href="http://monaco.sfbay.sun.com/detail.jsp?cr=1234567"> 461daaffb31Sdp# 1234567</a> my bugid' > <file>.html 462daaffb31Sdp# 463daaffb31Sdp# framed_sdiff() is then called which creates $2.frames.html 464daaffb31Sdp# in the webrev tree. 465daaffb31Sdp# 466daaffb31Sdp# FYI: This function is rather unusual in its use of awk. The initial 467daaffb31Sdp# diff run produces conventional diff output showing changed lines mixed 468daaffb31Sdp# with editing codes. The changed lines are ignored - we're interested in 469daaffb31Sdp# the editing codes, e.g. 4707c478bd9Sstevel@tonic-gate# 4717c478bd9Sstevel@tonic-gate# 8c8 4727c478bd9Sstevel@tonic-gate# 57a61 4737c478bd9Sstevel@tonic-gate# 63c66,76 4747c478bd9Sstevel@tonic-gate# 68,93d80 4757c478bd9Sstevel@tonic-gate# 106d90 4767c478bd9Sstevel@tonic-gate# 108,110d91 4777c478bd9Sstevel@tonic-gate# 478daaffb31Sdp# These editing codes are parsed by the awk script and used to generate 479daaffb31Sdp# another awk script that generates HTML, e.g the above lines would turn 480daaffb31Sdp# into something like this: 4817c478bd9Sstevel@tonic-gate# 4827c478bd9Sstevel@tonic-gate# BEGIN { printf "<pre>\n" } 4837c478bd9Sstevel@tonic-gate# function sp(n) {for (i=0;i<n;i++)printf "\n"} 484daaffb31Sdp# function wl(n) {printf "<font color=%s>%4d %s </font>\n", n, NR, $0} 4857c478bd9Sstevel@tonic-gate# NR==8 {wl("#7A7ADD");next} 4867c478bd9Sstevel@tonic-gate# NR==54 {wl("#7A7ADD");sp(3);next} 4877c478bd9Sstevel@tonic-gate# NR==56 {wl("#7A7ADD");next} 4887c478bd9Sstevel@tonic-gate# NR==57 {wl("black");printf "\n"; next} 4897c478bd9Sstevel@tonic-gate# : : 4907c478bd9Sstevel@tonic-gate# 491daaffb31Sdp# This script is then run on the original source file to generate the 492daaffb31Sdp# HTML that corresponds to the source file. 4937c478bd9Sstevel@tonic-gate# 494daaffb31Sdp# The two HTML files are then combined into a single piece of HTML that 495daaffb31Sdp# uses an HTML table construct to present the files side by side. You'll 496daaffb31Sdp# notice that the changes are color-coded: 4977c478bd9Sstevel@tonic-gate# 4987c478bd9Sstevel@tonic-gate# black - unchanged lines 4997c478bd9Sstevel@tonic-gate# blue - changed lines 5007c478bd9Sstevel@tonic-gate# bold blue - new lines 5017c478bd9Sstevel@tonic-gate# brown - deleted lines 5027c478bd9Sstevel@tonic-gate# 503daaffb31Sdp# Blank lines are inserted in each file to keep unchanged lines in sync 504daaffb31Sdp# (side-by-side). This format is familiar to users of sdiff(1) or 505daaffb31Sdp# Teamware's filemerge tool. 506daaffb31Sdp# 507daaffb31Sdpsdiff_to_html() 508daaffb31Sdp{ 5097c478bd9Sstevel@tonic-gate diff -b $1 $2 > /tmp/$$.diffs 5107c478bd9Sstevel@tonic-gate 511daaffb31Sdp TNAME=$3 512daaffb31Sdp TPATH=$4 513daaffb31Sdp COMMENT=$5 514daaffb31Sdp 5157c478bd9Sstevel@tonic-gate # 5167c478bd9Sstevel@tonic-gate # Now we have the diffs, generate the HTML for the old file. 5177c478bd9Sstevel@tonic-gate # 518cdf0c1d5Smjnelson $AWK ' 5197c478bd9Sstevel@tonic-gate BEGIN { 5207c478bd9Sstevel@tonic-gate printf "function sp(n) {for (i=0;i<n;i++)printf \"\\n\"}\n" 521daaffb31Sdp printf "function removed() " 522daaffb31Sdp printf "{printf \"<span class=\\\"removed\\\">%%4d %%s</span>\\n\", NR, $0}\n" 523daaffb31Sdp printf "function changed() " 524daaffb31Sdp printf "{printf \"<span class=\\\"changed\\\">%%4d %%s</span>\\n\", NR, $0}\n" 525daaffb31Sdp printf "function bl() {printf \"%%4d %%s\\n\", NR, $0}\n" 5267c478bd9Sstevel@tonic-gate} 5277c478bd9Sstevel@tonic-gate /^</ {next} 5287c478bd9Sstevel@tonic-gate /^>/ {next} 5297c478bd9Sstevel@tonic-gate /^---/ {next} 530daaffb31Sdp 5317c478bd9Sstevel@tonic-gate { 5327c478bd9Sstevel@tonic-gate split($1, a, /[cad]/) ; 5337c478bd9Sstevel@tonic-gate if (index($1, "a")) { 5347c478bd9Sstevel@tonic-gate if (a[1] == 0) { 5357c478bd9Sstevel@tonic-gate n = split(a[2], r, /,/); 5367c478bd9Sstevel@tonic-gate if (n == 1) 5377c478bd9Sstevel@tonic-gate printf "BEGIN\t\t{sp(1)}\n" 5387c478bd9Sstevel@tonic-gate else 5397c478bd9Sstevel@tonic-gate printf "BEGIN\t\t{sp(%d)}\n",\ 5407c478bd9Sstevel@tonic-gate (r[2] - r[1]) + 1 5417c478bd9Sstevel@tonic-gate next 5427c478bd9Sstevel@tonic-gate } 5437c478bd9Sstevel@tonic-gate 5447c478bd9Sstevel@tonic-gate printf "NR==%s\t\t{", a[1] 5457c478bd9Sstevel@tonic-gate n = split(a[2], r, /,/); 5467c478bd9Sstevel@tonic-gate s = r[1]; 5477c478bd9Sstevel@tonic-gate if (n == 1) 5487c478bd9Sstevel@tonic-gate printf "bl();printf \"\\n\"; next}\n" 5497c478bd9Sstevel@tonic-gate else { 5507c478bd9Sstevel@tonic-gate n = r[2] - r[1] 5517c478bd9Sstevel@tonic-gate printf "bl();sp(%d);next}\n",\ 5527c478bd9Sstevel@tonic-gate (r[2] - r[1]) + 1 5537c478bd9Sstevel@tonic-gate } 5547c478bd9Sstevel@tonic-gate next 5557c478bd9Sstevel@tonic-gate } 5567c478bd9Sstevel@tonic-gate if (index($1, "d")) { 5577c478bd9Sstevel@tonic-gate n = split(a[1], r, /,/); 5587c478bd9Sstevel@tonic-gate n1 = r[1] 5597c478bd9Sstevel@tonic-gate n2 = r[2] 5607c478bd9Sstevel@tonic-gate if (n == 1) 561daaffb31Sdp printf "NR==%s\t\t{removed(); next}\n" , n1 5627c478bd9Sstevel@tonic-gate else 563daaffb31Sdp printf "NR==%s,NR==%s\t{removed(); next}\n" , n1, n2 5647c478bd9Sstevel@tonic-gate next 5657c478bd9Sstevel@tonic-gate } 5667c478bd9Sstevel@tonic-gate if (index($1, "c")) { 5677c478bd9Sstevel@tonic-gate n = split(a[1], r, /,/); 5687c478bd9Sstevel@tonic-gate n1 = r[1] 5697c478bd9Sstevel@tonic-gate n2 = r[2] 5707c478bd9Sstevel@tonic-gate final = n2 5717c478bd9Sstevel@tonic-gate d1 = 0 5727c478bd9Sstevel@tonic-gate if (n == 1) 573daaffb31Sdp printf "NR==%s\t\t{changed();" , n1 5747c478bd9Sstevel@tonic-gate else { 5757c478bd9Sstevel@tonic-gate d1 = n2 - n1 576daaffb31Sdp printf "NR==%s,NR==%s\t{changed();" , n1, n2 5777c478bd9Sstevel@tonic-gate } 5787c478bd9Sstevel@tonic-gate m = split(a[2], r, /,/); 5797c478bd9Sstevel@tonic-gate n1 = r[1] 5807c478bd9Sstevel@tonic-gate n2 = r[2] 5817c478bd9Sstevel@tonic-gate if (m > 1) { 5827c478bd9Sstevel@tonic-gate d2 = n2 - n1 5837c478bd9Sstevel@tonic-gate if (d2 > d1) { 5847c478bd9Sstevel@tonic-gate if (n > 1) printf "if (NR==%d)", final 5857c478bd9Sstevel@tonic-gate printf "sp(%d);", d2 - d1 5867c478bd9Sstevel@tonic-gate } 5877c478bd9Sstevel@tonic-gate } 5887c478bd9Sstevel@tonic-gate printf "next}\n" ; 5897c478bd9Sstevel@tonic-gate 5907c478bd9Sstevel@tonic-gate next 5917c478bd9Sstevel@tonic-gate } 5927c478bd9Sstevel@tonic-gate } 5937c478bd9Sstevel@tonic-gate 594daaffb31Sdp END { printf "{printf \"%%4d %%s\\n\", NR, $0 }\n" } 595daaffb31Sdp ' /tmp/$$.diffs > /tmp/$$.file1 5967c478bd9Sstevel@tonic-gate 5977c478bd9Sstevel@tonic-gate # 5987c478bd9Sstevel@tonic-gate # Now generate the HTML for the new file 5997c478bd9Sstevel@tonic-gate # 600cdf0c1d5Smjnelson $AWK ' 6017c478bd9Sstevel@tonic-gate BEGIN { 6027c478bd9Sstevel@tonic-gate printf "function sp(n) {for (i=0;i<n;i++)printf \"\\n\"}\n" 603daaffb31Sdp printf "function new() " 604daaffb31Sdp printf "{printf \"<span class=\\\"new\\\">%%4d %%s</span>\\n\", NR, $0}\n" 605daaffb31Sdp printf "function changed() " 606daaffb31Sdp printf "{printf \"<span class=\\\"changed\\\">%%4d %%s</span>\\n\", NR, $0}\n" 607daaffb31Sdp printf "function bl() {printf \"%%4d %%s\\n\", NR, $0}\n" 6087c478bd9Sstevel@tonic-gate } 609daaffb31Sdp 6107c478bd9Sstevel@tonic-gate /^</ {next} 6117c478bd9Sstevel@tonic-gate /^>/ {next} 6127c478bd9Sstevel@tonic-gate /^---/ {next} 613daaffb31Sdp 6147c478bd9Sstevel@tonic-gate { 6157c478bd9Sstevel@tonic-gate split($1, a, /[cad]/) ; 6167c478bd9Sstevel@tonic-gate if (index($1, "d")) { 6177c478bd9Sstevel@tonic-gate if (a[2] == 0) { 6187c478bd9Sstevel@tonic-gate n = split(a[1], r, /,/); 6197c478bd9Sstevel@tonic-gate if (n == 1) 6207c478bd9Sstevel@tonic-gate printf "BEGIN\t\t{sp(1)}\n" 6217c478bd9Sstevel@tonic-gate else 6227c478bd9Sstevel@tonic-gate printf "BEGIN\t\t{sp(%d)}\n",\ 6237c478bd9Sstevel@tonic-gate (r[2] - r[1]) + 1 6247c478bd9Sstevel@tonic-gate next 6257c478bd9Sstevel@tonic-gate } 6267c478bd9Sstevel@tonic-gate 6277c478bd9Sstevel@tonic-gate printf "NR==%s\t\t{", a[2] 6287c478bd9Sstevel@tonic-gate n = split(a[1], r, /,/); 6297c478bd9Sstevel@tonic-gate s = r[1]; 6307c478bd9Sstevel@tonic-gate if (n == 1) 6317c478bd9Sstevel@tonic-gate printf "bl();printf \"\\n\"; next}\n" 6327c478bd9Sstevel@tonic-gate else { 6337c478bd9Sstevel@tonic-gate n = r[2] - r[1] 6347c478bd9Sstevel@tonic-gate printf "bl();sp(%d);next}\n",\ 6357c478bd9Sstevel@tonic-gate (r[2] - r[1]) + 1 6367c478bd9Sstevel@tonic-gate } 6377c478bd9Sstevel@tonic-gate next 6387c478bd9Sstevel@tonic-gate } 6397c478bd9Sstevel@tonic-gate if (index($1, "a")) { 6407c478bd9Sstevel@tonic-gate n = split(a[2], r, /,/); 6417c478bd9Sstevel@tonic-gate n1 = r[1] 6427c478bd9Sstevel@tonic-gate n2 = r[2] 6437c478bd9Sstevel@tonic-gate if (n == 1) 644daaffb31Sdp printf "NR==%s\t\t{new() ; next}\n" , n1 6457c478bd9Sstevel@tonic-gate else 646daaffb31Sdp printf "NR==%s,NR==%s\t{new() ; next}\n" , n1, n2 6477c478bd9Sstevel@tonic-gate next 6487c478bd9Sstevel@tonic-gate } 6497c478bd9Sstevel@tonic-gate if (index($1, "c")) { 6507c478bd9Sstevel@tonic-gate n = split(a[2], r, /,/); 6517c478bd9Sstevel@tonic-gate n1 = r[1] 6527c478bd9Sstevel@tonic-gate n2 = r[2] 6537c478bd9Sstevel@tonic-gate final = n2 6547c478bd9Sstevel@tonic-gate d2 = 0; 6557c478bd9Sstevel@tonic-gate if (n == 1) { 6567c478bd9Sstevel@tonic-gate final = n1 657daaffb31Sdp printf "NR==%s\t\t{changed();" , n1 6587c478bd9Sstevel@tonic-gate } else { 6597c478bd9Sstevel@tonic-gate d2 = n2 - n1 660daaffb31Sdp printf "NR==%s,NR==%s\t{changed();" , n1, n2 6617c478bd9Sstevel@tonic-gate } 6627c478bd9Sstevel@tonic-gate m = split(a[1], r, /,/); 6637c478bd9Sstevel@tonic-gate n1 = r[1] 6647c478bd9Sstevel@tonic-gate n2 = r[2] 6657c478bd9Sstevel@tonic-gate if (m > 1) { 6667c478bd9Sstevel@tonic-gate d1 = n2 - n1 6677c478bd9Sstevel@tonic-gate if (d1 > d2) { 6687c478bd9Sstevel@tonic-gate if (n > 1) printf "if (NR==%d)", final 6697c478bd9Sstevel@tonic-gate printf "sp(%d);", d1 - d2 6707c478bd9Sstevel@tonic-gate } 6717c478bd9Sstevel@tonic-gate } 6727c478bd9Sstevel@tonic-gate printf "next}\n" ; 6737c478bd9Sstevel@tonic-gate next 6747c478bd9Sstevel@tonic-gate } 6757c478bd9Sstevel@tonic-gate } 676daaffb31Sdp END { printf "{printf \"%%4d %%s\\n\", NR, $0 }\n" } 6777c478bd9Sstevel@tonic-gate ' /tmp/$$.diffs > /tmp/$$.file2 6787c478bd9Sstevel@tonic-gate 679daaffb31Sdp # 680cdf0c1d5Smjnelson # Post-process the HTML files by running them back through $AWK 681daaffb31Sdp # 682cdf0c1d5Smjnelson html_quote < $1 | $AWK -f /tmp/$$.file1 > /tmp/$$.file1.html 6837c478bd9Sstevel@tonic-gate 684cdf0c1d5Smjnelson html_quote < $2 | $AWK -f /tmp/$$.file2 > /tmp/$$.file2.html 6857c478bd9Sstevel@tonic-gate 686daaffb31Sdp # 687daaffb31Sdp # Now combine into a valid HTML file and side-by-side into a table 688daaffb31Sdp # 689daaffb31Sdp print "$HTML<head>$STDHEAD" 690cdf0c1d5Smjnelson print "<title>$WNAME Sdiff $TPATH/$TNAME</title>" 691daaffb31Sdp print "</head><body id=\"SUNWwebrev\">" 692daaffb31Sdp print "<a class=\"print\" href=\"javascript:print()\">Print this page</a>" 693daaffb31Sdp print "<pre>$COMMENT</pre>\n" 694daaffb31Sdp print "<table><tr valign=\"top\">" 695daaffb31Sdp print "<td><pre>" 6967c478bd9Sstevel@tonic-gate 6977c478bd9Sstevel@tonic-gate strip_unchanged /tmp/$$.file1.html 6987c478bd9Sstevel@tonic-gate 699daaffb31Sdp print "</pre></td><td><pre>" 7007c478bd9Sstevel@tonic-gate 7017c478bd9Sstevel@tonic-gate strip_unchanged /tmp/$$.file2.html 7027c478bd9Sstevel@tonic-gate 703daaffb31Sdp print "</pre></td>" 704daaffb31Sdp print "</tr></table>" 705daaffb31Sdp print "</body></html>" 7067c478bd9Sstevel@tonic-gate 707daaffb31Sdp framed_sdiff $TNAME $TPATH /tmp/$$.file1.html /tmp/$$.file2.html \ 708daaffb31Sdp "$COMMENT" 7097c478bd9Sstevel@tonic-gate} 7107c478bd9Sstevel@tonic-gate 7117c478bd9Sstevel@tonic-gate 712daaffb31Sdp# 713daaffb31Sdp# framed_sdiff <filename> <filepath> <lhsfile> <rhsfile> <comment> 714daaffb31Sdp# 715daaffb31Sdp# Expects lefthand and righthand side html files created by sdiff_to_html. 716daaffb31Sdp# We use insert_anchors() to augment those with HTML navigation anchors, 717daaffb31Sdp# and then emit the main frame. Content is placed into: 718daaffb31Sdp# 719daaffb31Sdp# $WDIR/DIR/$TNAME.lhs.html 720daaffb31Sdp# $WDIR/DIR/$TNAME.rhs.html 721daaffb31Sdp# $WDIR/DIR/$TNAME.frames.html 722daaffb31Sdp# 723daaffb31Sdp# NOTE: We rely on standard usage of $WDIR and $DIR. 724daaffb31Sdp# 7257c478bd9Sstevel@tonic-gatefunction framed_sdiff 7267c478bd9Sstevel@tonic-gate{ 7277c478bd9Sstevel@tonic-gate typeset TNAME=$1 728daaffb31Sdp typeset TPATH=$2 729daaffb31Sdp typeset lhsfile=$3 730daaffb31Sdp typeset rhsfile=$4 731daaffb31Sdp typeset comments=$5 7327c478bd9Sstevel@tonic-gate typeset RTOP 733daaffb31Sdp 7347c478bd9Sstevel@tonic-gate # Enable html files to access WDIR via a relative path. 735daaffb31Sdp RTOP=$(relative_dir $TPATH $WDIR) 736daaffb31Sdp 737daaffb31Sdp # Make the rhs/lhs files and output the frameset file. 738daaffb31Sdp print "$HTML<head>$STDHEAD" > $WDIR/$DIR/$TNAME.lhs.html 739daaffb31Sdp 740daaffb31Sdp cat >> $WDIR/$DIR/$TNAME.lhs.html <<-EOF 741cac38512Smjnelson <script type="text/javascript" src="$RTOP/ancnav.js"></script> 7427c478bd9Sstevel@tonic-gate </head> 743daaffb31Sdp <body id="SUNWwebrev" onkeypress="keypress(event);"> 744cac38512Smjnelson <a name="0"></a> 745cac38512Smjnelson <pre>$comments</pre><hr></hr> 746daaffb31Sdp EOF 747daaffb31Sdp 748daaffb31Sdp cp $WDIR/$DIR/$TNAME.lhs.html $WDIR/$DIR/$TNAME.rhs.html 749daaffb31Sdp 750daaffb31Sdp insert_anchors $lhsfile >> $WDIR/$DIR/$TNAME.lhs.html 751daaffb31Sdp insert_anchors $rhsfile >> $WDIR/$DIR/$TNAME.rhs.html 752daaffb31Sdp 753daaffb31Sdp close='</body></html>' 754daaffb31Sdp 755daaffb31Sdp print $close >> $WDIR/$DIR/$TNAME.lhs.html 756daaffb31Sdp print $close >> $WDIR/$DIR/$TNAME.rhs.html 757daaffb31Sdp 758daaffb31Sdp print "$FRAMEHTML<head>$STDHEAD" > $WDIR/$DIR/$TNAME.frames.html 759daaffb31Sdp print "<title>$WNAME Framed-Sdiff " \ 760daaffb31Sdp "$TPATH/$TNAME</title> </head>" >> $WDIR/$DIR/$TNAME.frames.html 761daaffb31Sdp cat >> $WDIR/$DIR/$TNAME.frames.html <<-EOF 762daaffb31Sdp <frameset rows="*,60"> 763daaffb31Sdp <frameset cols="50%,50%"> 764cac38512Smjnelson <frame src="$TNAME.lhs.html" scrolling="auto" name="lhs"></frame> 765cac38512Smjnelson <frame src="$TNAME.rhs.html" scrolling="auto" name="rhs"></frame> 766daaffb31Sdp </frameset> 767daaffb31Sdp <frame src="$RTOP/ancnav.html" scrolling="no" marginwidth="0" 768cac38512Smjnelson marginheight="0" name="nav"></frame> 769daaffb31Sdp <noframes> 770daaffb31Sdp <body id="SUNWwebrev"> 771daaffb31Sdp Alas 'frames' webrev requires that your browser supports frames 7727c478bd9Sstevel@tonic-gate and has the feature enabled. 773daaffb31Sdp </body> 774daaffb31Sdp </noframes> 775daaffb31Sdp </frameset> 7767c478bd9Sstevel@tonic-gate </html> 7777c478bd9Sstevel@tonic-gate EOF 7787c478bd9Sstevel@tonic-gate} 7797c478bd9Sstevel@tonic-gate 7807c478bd9Sstevel@tonic-gate 781daaffb31Sdp# 782daaffb31Sdp# fix_postscript 783daaffb31Sdp# 784daaffb31Sdp# Merge codereview output files to a single conforming postscript file, by: 785daaffb31Sdp# - removing all extraneous headers/trailers 786daaffb31Sdp# - making the page numbers right 787daaffb31Sdp# - removing pages devoid of contents which confuse some 788daaffb31Sdp# postscript readers. 789daaffb31Sdp# 790daaffb31Sdp# From Casper. 791daaffb31Sdp# 792daaffb31Sdpfunction fix_postscript 7937c478bd9Sstevel@tonic-gate{ 794daaffb31Sdp infile=$1 7957c478bd9Sstevel@tonic-gate 796daaffb31Sdp cat > /tmp/$$.crmerge.pl << \EOF 7977c478bd9Sstevel@tonic-gate 798daaffb31Sdp print scalar(<>); # %!PS-Adobe--- 799daaffb31Sdp print "%%Orientation: Landscape\n"; 8007c478bd9Sstevel@tonic-gate 801daaffb31Sdp $pno = 0; 802daaffb31Sdp $doprint = 1; 803daaffb31Sdp 804daaffb31Sdp $page = ""; 805daaffb31Sdp 806daaffb31Sdp while (<>) { 807daaffb31Sdp next if (/^%%Pages:\s*\d+/); 808daaffb31Sdp 809daaffb31Sdp if (/^%%Page:/) { 810daaffb31Sdp if ($pno == 0 || $page =~ /\)S/) { 811daaffb31Sdp # Header or single page containing text 812daaffb31Sdp print "%%Page: ? $pno\n" if ($pno > 0); 813daaffb31Sdp print $page; 814daaffb31Sdp $pno++; 815daaffb31Sdp } else { 816daaffb31Sdp # Empty page, skip it. 8177c478bd9Sstevel@tonic-gate } 818daaffb31Sdp $page = ""; 819daaffb31Sdp $doprint = 1; 8207c478bd9Sstevel@tonic-gate next; 8217c478bd9Sstevel@tonic-gate } 8227c478bd9Sstevel@tonic-gate 823daaffb31Sdp # Skip from %%Trailer of one document to Endprolog 824daaffb31Sdp # %%Page of the next 825daaffb31Sdp $doprint = 0 if (/^%%Trailer/); 826daaffb31Sdp $page .= $_ if ($doprint); 8277c478bd9Sstevel@tonic-gate } 8287c478bd9Sstevel@tonic-gate 829daaffb31Sdp if ($page =~ /\)S/) { 830daaffb31Sdp print "%%Page: ? $pno\n"; 831daaffb31Sdp print $page; 832daaffb31Sdp } else { 833daaffb31Sdp $pno--; 834daaffb31Sdp } 835daaffb31Sdp print "%%Trailer\n%%Pages: $pno\n"; 836daaffb31SdpEOF 837daaffb31Sdp 83814983201Sdp $PERL /tmp/$$.crmerge.pl < $infile 839daaffb31Sdp} 840daaffb31Sdp 841daaffb31Sdp 842daaffb31Sdp# 843daaffb31Sdp# input_cmd | insert_anchors | output_cmd 844daaffb31Sdp# 8457c478bd9Sstevel@tonic-gate# Flag blocks of difference with sequentially numbered invisible 846daaffb31Sdp# anchors. These are used to drive the frames version of the 8477c478bd9Sstevel@tonic-gate# sdiffs output. 8487c478bd9Sstevel@tonic-gate# 8497c478bd9Sstevel@tonic-gate# NOTE: Anchor zero flags the top of the file irrespective of changes, 8507c478bd9Sstevel@tonic-gate# an additional anchor is also appended to flag the bottom. 8517c478bd9Sstevel@tonic-gate# 852daaffb31Sdp# The script detects changed lines as any line that has a "<span 853daaffb31Sdp# class=" string embedded (unchanged lines have no class set and are 854daaffb31Sdp# not part of a <span>. Blank lines (without a sequence number) 8557c478bd9Sstevel@tonic-gate# are also detected since they flag lines that have been inserted or 8567c478bd9Sstevel@tonic-gate# deleted. 8577c478bd9Sstevel@tonic-gate# 858daaffb31Sdpfunction insert_anchors 859daaffb31Sdp{ 860cdf0c1d5Smjnelson $AWK ' 8617c478bd9Sstevel@tonic-gate function ia() { 862daaffb31Sdp printf "<a name=\"%d\" id=\"anc%d\"></a>", anc, anc++; 8637c478bd9Sstevel@tonic-gate } 864daaffb31Sdp 8657c478bd9Sstevel@tonic-gate BEGIN { 866daaffb31Sdp anc=1; 8677c478bd9Sstevel@tonic-gate inblock=1; 868daaffb31Sdp printf "<pre>\n"; 8697c478bd9Sstevel@tonic-gate } 870daaffb31Sdp NF == 0 || /^<span class=/ { 8717c478bd9Sstevel@tonic-gate if (inblock == 0) { 8727c478bd9Sstevel@tonic-gate ia(); 8737c478bd9Sstevel@tonic-gate inblock=1; 8747c478bd9Sstevel@tonic-gate } 8757c478bd9Sstevel@tonic-gate print; 8767c478bd9Sstevel@tonic-gate next; 8777c478bd9Sstevel@tonic-gate } 8787c478bd9Sstevel@tonic-gate { 8797c478bd9Sstevel@tonic-gate inblock=0; 8807c478bd9Sstevel@tonic-gate print; 8817c478bd9Sstevel@tonic-gate } 8827c478bd9Sstevel@tonic-gate END { 8837c478bd9Sstevel@tonic-gate ia(); 884daaffb31Sdp 885daaffb31Sdp printf "<b style=\"font-size: large; color: red\">"; 886daaffb31Sdp printf "--- EOF ---</b>" 8877c478bd9Sstevel@tonic-gate for(i=0;i<8;i++) printf "\n\n\n\n\n\n\n\n\n\n"; 888daaffb31Sdp printf "</pre>" 889daaffb31Sdp printf "<form name=\"eof\">"; 890cac38512Smjnelson printf "<input name=\"value\" value=\"%d\" " \ 891cac38512Smjnelson "type=\"hidden\"></input>", anc - 1; 892daaffb31Sdp printf "</form>"; 8937c478bd9Sstevel@tonic-gate } 8947c478bd9Sstevel@tonic-gate ' $1 8957c478bd9Sstevel@tonic-gate} 8967c478bd9Sstevel@tonic-gate 8977c478bd9Sstevel@tonic-gate 898daaffb31Sdp# 899daaffb31Sdp# relative_dir 900daaffb31Sdp# 901daaffb31Sdp# Print a relative return path from $1 to $2. For example if 902daaffb31Sdp# $1=/tmp/myreview/raw_files/usr/src/tools/scripts and $2=/tmp/myreview, 903daaffb31Sdp# this function would print "../../../../". 904daaffb31Sdp# 905daaffb31Sdp# In the event that $1 is not in $2 a warning is printed to stderr, 906daaffb31Sdp# and $2 is returned-- the result of this is that the resulting webrev 907daaffb31Sdp# is not relocatable. 908daaffb31Sdp# 909daaffb31Sdpfunction relative_dir 9107c478bd9Sstevel@tonic-gate{ 911daaffb31Sdp typeset cur="${1##$2?(/)}" 912daaffb31Sdp typeset ret="" 913daaffb31Sdp if [[ $2 == $cur ]]; then # Should never happen. 914daaffb31Sdp # Should never happen. 91514983201Sdp print -u2 "\nWARNING: relative_dir: \"$1\" not relative " 916daaffb31Sdp print -u2 "to \"$2\". Check input paths. Framed webrev " 917daaffb31Sdp print -u2 "will not be relocatable!" 918daaffb31Sdp print $2 919daaffb31Sdp return 920daaffb31Sdp fi 921daaffb31Sdp 922daaffb31Sdp while [[ -n ${cur} ]]; 9237c478bd9Sstevel@tonic-gate do 9247c478bd9Sstevel@tonic-gate cur=${cur%%*(/)*([!/])} 925daaffb31Sdp if [[ -z $ret ]]; then 926daaffb31Sdp ret=".." 927daaffb31Sdp else 9287c478bd9Sstevel@tonic-gate ret="../$ret" 929daaffb31Sdp fi 9307c478bd9Sstevel@tonic-gate done 9317c478bd9Sstevel@tonic-gate print $ret 9327c478bd9Sstevel@tonic-gate} 9337c478bd9Sstevel@tonic-gate 9347c478bd9Sstevel@tonic-gate 935daaffb31Sdp# 936daaffb31Sdp# frame_nav_js 937daaffb31Sdp# 938daaffb31Sdp# Emit javascript for frame navigation 939daaffb31Sdp# 940daaffb31Sdpfunction frame_nav_js 9417c478bd9Sstevel@tonic-gate{ 9427c478bd9Sstevel@tonic-gatecat << \EOF 9437c478bd9Sstevel@tonic-gatevar myInt; 9447c478bd9Sstevel@tonic-gatevar scrolling=0; 945daaffb31Sdpvar sfactor = 3; 9467c478bd9Sstevel@tonic-gatevar scount=10; 9477c478bd9Sstevel@tonic-gate 9487c478bd9Sstevel@tonic-gatefunction scrollByPix() { 9497c478bd9Sstevel@tonic-gate if (scount<=0) { 9507c478bd9Sstevel@tonic-gate sfactor*=1.2; 9517c478bd9Sstevel@tonic-gate scount=10; 9527c478bd9Sstevel@tonic-gate } 9537c478bd9Sstevel@tonic-gate parent.lhs.scrollBy(0,sfactor); 9547c478bd9Sstevel@tonic-gate parent.rhs.scrollBy(0,sfactor); 9557c478bd9Sstevel@tonic-gate scount--; 9567c478bd9Sstevel@tonic-gate} 9577c478bd9Sstevel@tonic-gate 958daaffb31Sdpfunction scrollToAnc(num) { 959daaffb31Sdp 960daaffb31Sdp // Update the value of the anchor in the form which we use as 961daaffb31Sdp // storage for this value. setAncValue() will take care of 962daaffb31Sdp // correcting for overflow and underflow of the value and return 963daaffb31Sdp // us the new value. 964daaffb31Sdp num = setAncValue(num); 965daaffb31Sdp 966daaffb31Sdp // Set location and scroll back a little to expose previous 967daaffb31Sdp // lines. 968daaffb31Sdp // 969daaffb31Sdp // Note that this could be improved: it is possible although 970daaffb31Sdp // complex to compute the x and y position of an anchor, and to 971daaffb31Sdp // scroll to that location directly. 972daaffb31Sdp // 9737c478bd9Sstevel@tonic-gate parent.lhs.location.replace(parent.lhs.location.pathname + "#" + num); 9747c478bd9Sstevel@tonic-gate parent.rhs.location.replace(parent.rhs.location.pathname + "#" + num); 975daaffb31Sdp 9767c478bd9Sstevel@tonic-gate parent.lhs.scrollBy(0,-30); 9777c478bd9Sstevel@tonic-gate parent.rhs.scrollBy(0,-30); 9787c478bd9Sstevel@tonic-gate} 9797c478bd9Sstevel@tonic-gate 980daaffb31Sdpfunction getAncValue() 981daaffb31Sdp{ 982daaffb31Sdp return (parseInt(parent.nav.document.diff.real.value)); 983daaffb31Sdp} 984daaffb31Sdp 985daaffb31Sdpfunction setAncValue(val) 986daaffb31Sdp{ 987daaffb31Sdp if (val <= 0) { 988daaffb31Sdp val = 0; 989daaffb31Sdp parent.nav.document.diff.real.value = val; 990daaffb31Sdp parent.nav.document.diff.display.value = "BOF"; 991daaffb31Sdp return (val); 992daaffb31Sdp } 993daaffb31Sdp 994daaffb31Sdp // 995daaffb31Sdp // The way we compute the max anchor value is to stash it 996daaffb31Sdp // inline in the left and right hand side pages-- it's the same 997daaffb31Sdp // on each side, so we pluck from the left. 998daaffb31Sdp // 999daaffb31Sdp maxval = parent.lhs.document.eof.value.value; 1000daaffb31Sdp if (val < maxval) { 1001daaffb31Sdp parent.nav.document.diff.real.value = val; 1002daaffb31Sdp parent.nav.document.diff.display.value = val.toString(); 1003daaffb31Sdp return (val); 1004daaffb31Sdp } 1005daaffb31Sdp 1006daaffb31Sdp // this must be: val >= maxval 1007daaffb31Sdp val = maxval; 1008daaffb31Sdp parent.nav.document.diff.real.value = val; 1009daaffb31Sdp parent.nav.document.diff.display.value = "EOF"; 1010daaffb31Sdp return (val); 1011daaffb31Sdp} 1012daaffb31Sdp 10137c478bd9Sstevel@tonic-gatefunction stopScroll() { 10147c478bd9Sstevel@tonic-gate if (scrolling==1) { 10157c478bd9Sstevel@tonic-gate clearInterval(myInt); 10167c478bd9Sstevel@tonic-gate scrolling=0; 10177c478bd9Sstevel@tonic-gate } 10187c478bd9Sstevel@tonic-gate} 10197c478bd9Sstevel@tonic-gate 10207c478bd9Sstevel@tonic-gatefunction startScroll() { 10217c478bd9Sstevel@tonic-gate stopScroll(); 10227c478bd9Sstevel@tonic-gate scrolling=1; 10237c478bd9Sstevel@tonic-gate myInt=setInterval("scrollByPix()",10); 10247c478bd9Sstevel@tonic-gate} 10257c478bd9Sstevel@tonic-gate 10267c478bd9Sstevel@tonic-gatefunction handlePress(b) { 1027daaffb31Sdp 10287c478bd9Sstevel@tonic-gate switch (b) { 10297c478bd9Sstevel@tonic-gate case 1 : 1030daaffb31Sdp scrollToAnc(-1); 10317c478bd9Sstevel@tonic-gate break; 10327c478bd9Sstevel@tonic-gate case 2 : 1033daaffb31Sdp scrollToAnc(getAncValue() - 1); 10347c478bd9Sstevel@tonic-gate break; 10357c478bd9Sstevel@tonic-gate case 3 : 10367c478bd9Sstevel@tonic-gate sfactor=-3; 10377c478bd9Sstevel@tonic-gate startScroll(); 10387c478bd9Sstevel@tonic-gate break; 10397c478bd9Sstevel@tonic-gate case 4 : 10407c478bd9Sstevel@tonic-gate sfactor=3; 10417c478bd9Sstevel@tonic-gate startScroll(); 10427c478bd9Sstevel@tonic-gate break; 10437c478bd9Sstevel@tonic-gate case 5 : 1044daaffb31Sdp scrollToAnc(getAncValue() + 1); 10457c478bd9Sstevel@tonic-gate break; 10467c478bd9Sstevel@tonic-gate case 6 : 1047daaffb31Sdp scrollToAnc(999999); 10487c478bd9Sstevel@tonic-gate break; 10497c478bd9Sstevel@tonic-gate } 10507c478bd9Sstevel@tonic-gate} 10517c478bd9Sstevel@tonic-gate 10527c478bd9Sstevel@tonic-gatefunction handleRelease(b) { 10537c478bd9Sstevel@tonic-gate stopScroll(); 10547c478bd9Sstevel@tonic-gate} 10557c478bd9Sstevel@tonic-gate 1056daaffb31Sdpfunction keypress(ev) { 1057daaffb31Sdp var keynum; 1058daaffb31Sdp var keychar; 1059daaffb31Sdp 1060daaffb31Sdp if (window.event) { // IE 1061daaffb31Sdp keynum = ev.keyCode; 1062daaffb31Sdp } else if (ev.which) { // non-IE 1063daaffb31Sdp keynum = ev.which; 1064daaffb31Sdp } 1065daaffb31Sdp 1066daaffb31Sdp keychar = String.fromCharCode(keynum); 1067daaffb31Sdp 1068daaffb31Sdp if (keychar == "k") { 1069daaffb31Sdp handlePress(2); 1070daaffb31Sdp return (0); 1071daaffb31Sdp } else if (keychar == "j" || keychar == " ") { 1072daaffb31Sdp handlePress(5); 1073daaffb31Sdp return (0); 1074daaffb31Sdp } 1075daaffb31Sdp return (1); 1076daaffb31Sdp} 1077daaffb31Sdp 10787c478bd9Sstevel@tonic-gatefunction ValidateDiffNum(){ 1079daaffb31Sdp val = parent.nav.document.diff.display.value; 1080daaffb31Sdp if (val == "EOF") { 1081daaffb31Sdp scrollToAnc(999999); 1082daaffb31Sdp return; 1083daaffb31Sdp } 1084daaffb31Sdp 1085daaffb31Sdp if (val == "BOF") { 1086daaffb31Sdp scrollToAnc(0); 1087daaffb31Sdp return; 1088daaffb31Sdp } 1089daaffb31Sdp 1090daaffb31Sdp i=parseInt(val); 10917c478bd9Sstevel@tonic-gate if (isNaN(i)) { 1092daaffb31Sdp parent.nav.document.diff.display.value = getAncValue(); 10937c478bd9Sstevel@tonic-gate } else { 1094daaffb31Sdp scrollToAnc(i); 10957c478bd9Sstevel@tonic-gate } 10967c478bd9Sstevel@tonic-gate return false; 10977c478bd9Sstevel@tonic-gate} 10987c478bd9Sstevel@tonic-gate 1099daaffb31SdpEOF 1100daaffb31Sdp} 1101daaffb31Sdp 1102daaffb31Sdp# 1103daaffb31Sdp# frame_navigation 1104daaffb31Sdp# 1105daaffb31Sdp# Output anchor navigation file for framed sdiffs. 1106daaffb31Sdp# 1107daaffb31Sdpfunction frame_navigation 1108daaffb31Sdp{ 1109daaffb31Sdp print "$HTML<head>$STDHEAD" 1110daaffb31Sdp 1111daaffb31Sdp cat << \EOF 1112daaffb31Sdp<title>Anchor Navigation</title> 1113daaffb31Sdp<meta http-equiv="Content-Script-Type" content="text/javascript"> 1114daaffb31Sdp<meta http-equiv="Content-Type" content="text/html"> 1115daaffb31Sdp 1116daaffb31Sdp<style type="text/css"> 1117daaffb31Sdp div.button td { padding-left: 5px; padding-right: 5px; 1118daaffb31Sdp background-color: #eee; text-align: center; 1119daaffb31Sdp border: 1px #444 outset; cursor: pointer; } 1120daaffb31Sdp div.button a { font-weight: bold; color: black } 1121daaffb31Sdp div.button td:hover { background: #ffcc99; } 1122daaffb31Sdp</style> 1123daaffb31SdpEOF 1124daaffb31Sdp 1125cac38512Smjnelson print "<script type=\"text/javascript\" src=\"ancnav.js\"></script>" 1126daaffb31Sdp 1127daaffb31Sdp cat << \EOF 11287c478bd9Sstevel@tonic-gate</head> 1129daaffb31Sdp<body id="SUNWwebrev" bgcolor="#eeeeee" onload="document.diff.real.focus();" 1130daaffb31Sdp onkeypress="keypress(event);"> 11317c478bd9Sstevel@tonic-gate <noscript lang="javascript"> 11327c478bd9Sstevel@tonic-gate <center> 1133cac38512Smjnelson <p><big>Framed Navigation controls require Javascript</big><br></br> 11347c478bd9Sstevel@tonic-gate Either this browser is incompatable or javascript is not enabled</p> 11357c478bd9Sstevel@tonic-gate </center> 11367c478bd9Sstevel@tonic-gate </noscript> 11377c478bd9Sstevel@tonic-gate <table width="100%" border="0" align="center"> 1138daaffb31Sdp <tr> 1139daaffb31Sdp <td valign="middle" width="25%">Diff navigation: 1140daaffb31Sdp Use 'j' and 'k' for next and previous diffs; or use buttons 1141daaffb31Sdp at right</td> 1142daaffb31Sdp <td align="center" valign="top" width="50%"> 11437c478bd9Sstevel@tonic-gate <div class="button"> 1144daaffb31Sdp <table border="0" align="center"> 1145daaffb31Sdp <tr> 1146daaffb31Sdp <td> 11477c478bd9Sstevel@tonic-gate <a onMouseDown="handlePress(1);return true;" 11487c478bd9Sstevel@tonic-gate onMouseUp="handleRelease(1);return true;" 11497c478bd9Sstevel@tonic-gate onMouseOut="handleRelease(1);return true;" 11507c478bd9Sstevel@tonic-gate onClick="return false;" 11517c478bd9Sstevel@tonic-gate title="Go to Beginning Of file">BOF</a></td> 1152daaffb31Sdp <td> 11537c478bd9Sstevel@tonic-gate <a onMouseDown="handlePress(3);return true;" 11547c478bd9Sstevel@tonic-gate onMouseUp="handleRelease(3);return true;" 11557c478bd9Sstevel@tonic-gate onMouseOut="handleRelease(3);return true;" 11567c478bd9Sstevel@tonic-gate title="Scroll Up: Press and Hold to accelerate" 1157daaffb31Sdp onClick="return false;">Scroll Up</a></td> 1158daaffb31Sdp <td> 11597c478bd9Sstevel@tonic-gate <a onMouseDown="handlePress(2);return true;" 11607c478bd9Sstevel@tonic-gate onMouseUp="handleRelease(2);return true;" 11617c478bd9Sstevel@tonic-gate onMouseOut="handleRelease(2);return true;" 11627c478bd9Sstevel@tonic-gate title="Go to previous Diff" 11637c478bd9Sstevel@tonic-gate onClick="return false;">Prev Diff</a> 11647c478bd9Sstevel@tonic-gate </td></tr> 1165daaffb31Sdp 11667c478bd9Sstevel@tonic-gate <tr> 1167daaffb31Sdp <td> 11687c478bd9Sstevel@tonic-gate <a onMouseDown="handlePress(6);return true;" 11697c478bd9Sstevel@tonic-gate onMouseUp="handleRelease(6);return true;" 11707c478bd9Sstevel@tonic-gate onMouseOut="handleRelease(6);return true;" 11717c478bd9Sstevel@tonic-gate onClick="return false;" 11727c478bd9Sstevel@tonic-gate title="Go to End Of File">EOF</a></td> 1173daaffb31Sdp <td> 11747c478bd9Sstevel@tonic-gate <a onMouseDown="handlePress(4);return true;" 11757c478bd9Sstevel@tonic-gate onMouseUp="handleRelease(4);return true;" 11767c478bd9Sstevel@tonic-gate onMouseOut="handleRelease(4);return true;" 11777c478bd9Sstevel@tonic-gate title="Scroll Down: Press and Hold to accelerate" 1178daaffb31Sdp onClick="return false;">Scroll Down</a></td> 1179daaffb31Sdp <td> 11807c478bd9Sstevel@tonic-gate <a onMouseDown="handlePress(5);return true;" 11817c478bd9Sstevel@tonic-gate onMouseUp="handleRelease(5);return true;" 11827c478bd9Sstevel@tonic-gate onMouseOut="handleRelease(5);return true;" 11837c478bd9Sstevel@tonic-gate title="Go to next Diff" 11847c478bd9Sstevel@tonic-gate onClick="return false;">Next Diff</a></td> 1185daaffb31Sdp </tr> 1186daaffb31Sdp </table> 1187daaffb31Sdp </div> 1188daaffb31Sdp </td> 11897c478bd9Sstevel@tonic-gate <th valign="middle" width="25%"> 1190daaffb31Sdp <form action="" name="diff" onsubmit="return ValidateDiffNum();"> 1191cac38512Smjnelson <input name="display" value="BOF" size="8" type="text"></input> 1192cac38512Smjnelson <input name="real" value="0" size="8" type="hidden"></input> 11937c478bd9Sstevel@tonic-gate </form> 11947c478bd9Sstevel@tonic-gate </th> 1195daaffb31Sdp </tr> 11967c478bd9Sstevel@tonic-gate </table> 11977c478bd9Sstevel@tonic-gate </body> 11987c478bd9Sstevel@tonic-gate</html> 11997c478bd9Sstevel@tonic-gateEOF 12007c478bd9Sstevel@tonic-gate} 12017c478bd9Sstevel@tonic-gate 12027c478bd9Sstevel@tonic-gate 1203daaffb31Sdp 1204daaffb31Sdp# 1205daaffb31Sdp# diff_to_html <filename> <filepath> { U | C } <comment> 1206daaffb31Sdp# 1207daaffb31Sdp# Processes the output of diff to produce an HTML file representing either 1208daaffb31Sdp# context or unified diffs. 1209daaffb31Sdp# 12107c478bd9Sstevel@tonic-gatediff_to_html() 12117c478bd9Sstevel@tonic-gate{ 12127c478bd9Sstevel@tonic-gate TNAME=$1 1213daaffb31Sdp TPATH=$2 1214daaffb31Sdp DIFFTYPE=$3 1215daaffb31Sdp COMMENT=$4 1216daaffb31Sdp 1217daaffb31Sdp print "$HTML<head>$STDHEAD" 1218daaffb31Sdp print "<title>$WNAME ${DIFFTYPE}diff $TPATH</title>" 1219daaffb31Sdp 1220daaffb31Sdp if [[ $DIFFTYPE == "U" ]]; then 1221daaffb31Sdp print "$UDIFFCSS" 1222daaffb31Sdp fi 1223daaffb31Sdp 1224daaffb31Sdp cat <<-EOF 1225daaffb31Sdp </head> 1226daaffb31Sdp <body id="SUNWwebrev"> 1227daaffb31Sdp <a class="print" href="javascript:print()">Print this page</a> 1228daaffb31Sdp <pre>$COMMENT</pre> 1229daaffb31Sdp <pre> 1230daaffb31Sdp EOF 12317c478bd9Sstevel@tonic-gate 1232cdf0c1d5Smjnelson html_quote | $AWK ' 1233daaffb31Sdp /^--- new/ { next } 1234daaffb31Sdp /^\+\+\+ new/ { next } 1235daaffb31Sdp /^--- old/ { next } 1236daaffb31Sdp /^\*\*\* old/ { next } 1237daaffb31Sdp /^\*\*\*\*/ { next } 12387c478bd9Sstevel@tonic-gate /^-------/ { printf "<center><h1>%s</h1></center>\n", $0; next } 1239cac38512Smjnelson /^\@\@.*\@\@$/ { printf "</pre><hr></hr><pre>\n"; 1240daaffb31Sdp printf "<span class=\"newmarker\">%s</span>\n", $0; 1241daaffb31Sdp next} 1242daaffb31Sdp 1243cac38512Smjnelson /^\*\*\*/ { printf "<hr></hr><span class=\"oldmarker\">%s</span>\n", $0; 1244daaffb31Sdp next} 1245daaffb31Sdp /^---/ { printf "<span class=\"newmarker\">%s</span>\n", $0; 1246daaffb31Sdp next} 1247daaffb31Sdp /^\+/ {printf "<span class=\"new\">%s</span>\n", $0; next} 1248daaffb31Sdp /^!/ {printf "<span class=\"changed\">%s</span>\n", $0; next} 1249daaffb31Sdp /^-/ {printf "<span class=\"removed\">%s</span>\n", $0; next} 1250daaffb31Sdp {printf "%s\n", $0; next} 12517c478bd9Sstevel@tonic-gate ' 1252daaffb31Sdp 1253daaffb31Sdp print "</pre></body></html>\n" 12547c478bd9Sstevel@tonic-gate} 12557c478bd9Sstevel@tonic-gate 12567c478bd9Sstevel@tonic-gate 1257daaffb31Sdp# 1258daaffb31Sdp# source_to_html { new | old } <filename> 1259daaffb31Sdp# 1260daaffb31Sdp# Process a plain vanilla source file to transform it into an HTML file. 1261daaffb31Sdp# 12627c478bd9Sstevel@tonic-gatesource_to_html() 12637c478bd9Sstevel@tonic-gate{ 12647c478bd9Sstevel@tonic-gate WHICH=$1 12657c478bd9Sstevel@tonic-gate TNAME=$2 12667c478bd9Sstevel@tonic-gate 1267daaffb31Sdp print "$HTML<head>$STDHEAD" 1268cdf0c1d5Smjnelson print "<title>$WNAME $WHICH $TNAME</title>" 1269daaffb31Sdp print "<body id=\"SUNWwebrev\">" 1270daaffb31Sdp print "<pre>" 1271cdf0c1d5Smjnelson html_quote | $AWK '{line += 1 ; printf "%4d %s\n", line, $0 }' 1272daaffb31Sdp print "</pre></body></html>" 12737c478bd9Sstevel@tonic-gate} 12747c478bd9Sstevel@tonic-gate 1275daaffb31Sdp# 1276cdf0c1d5Smjnelson# comments_from_teamware {text|html} parent-file child-file 1277daaffb31Sdp# 1278daaffb31Sdp# Find the first delta in the child that's not in the parent. Get the 1279daaffb31Sdp# newest delta from the parent, get all deltas from the child starting 1280daaffb31Sdp# with that delta, and then get all info starting with the second oldest 1281daaffb31Sdp# delta in that list (the first delta unique to the child). 12827c478bd9Sstevel@tonic-gate# 12837c478bd9Sstevel@tonic-gate# This code adapted from Bill Shannon's "spc" script 1284daaffb31Sdp# 1285daaffb31Sdpcomments_from_teamware() 12867c478bd9Sstevel@tonic-gate{ 1287daaffb31Sdp fmt=$1 1288daaffb31Sdp pfile=$PWS/$2 1289daaffb31Sdp cfile=$CWS/$3 12907c478bd9Sstevel@tonic-gate 1291cdf0c1d5Smjnelson if [[ ! -f $PWS/${2%/*}/SCCS/s.${2##*/} && -n $RWS ]]; then 1292cdf0c1d5Smjnelson pfile=$RWS/$2 1293cdf0c1d5Smjnelson fi 1294cdf0c1d5Smjnelson 1295daaffb31Sdp if [[ -f $pfile ]]; then 1296cdf0c1d5Smjnelson psid=$($SCCS prs -d:I: $pfile 2>/dev/null) 12977c478bd9Sstevel@tonic-gate else 12987c478bd9Sstevel@tonic-gate psid=1.1 12997c478bd9Sstevel@tonic-gate fi 13007c478bd9Sstevel@tonic-gate 1301cdf0c1d5Smjnelson set -A sids $($SCCS prs -l -r$psid -d:I: $cfile 2>/dev/null) 13027c478bd9Sstevel@tonic-gate N=${#sids[@]} 13037c478bd9Sstevel@tonic-gate 1304daaffb31Sdp nawkprg=' 1305daaffb31Sdp /^COMMENTS:/ {p=1; continue} 1306daaffb31Sdp /^D [0-9]+\.[0-9]+/ {printf "--- %s ---\n", $2; p=0; } 1307daaffb31Sdp NF == 0u { continue } 1308daaffb31Sdp {if (p==0) continue; print $0 }' 1309daaffb31Sdp 13107c478bd9Sstevel@tonic-gate if [[ $N -ge 2 ]]; then 13117c478bd9Sstevel@tonic-gate sid1=${sids[$((N-2))]} # Gets 2nd to last sid 13127c478bd9Sstevel@tonic-gate 1313daaffb31Sdp if [[ $fmt == "text" ]]; then 1314cdf0c1d5Smjnelson $SCCS prs -l -r$sid1 $cfile 2>/dev/null | \ 1315cdf0c1d5Smjnelson $AWK "$nawkprg" 1316daaffb31Sdp return 1317daaffb31Sdp fi 1318daaffb31Sdp 1319cdf0c1d5Smjnelson $SCCS prs -l -r$sid1 $cfile 2>/dev/null | \ 1320cdf0c1d5Smjnelson html_quote | bug2url | sac2url | $AWK "$nawkprg" 13217c478bd9Sstevel@tonic-gate fi 13227c478bd9Sstevel@tonic-gate} 13237c478bd9Sstevel@tonic-gate 1324daaffb31Sdp# 1325cdf0c1d5Smjnelson# comments_from_wx {text|html} filepath 1326daaffb31Sdp# 1327cdf0c1d5Smjnelson# Given the pathname of a file, find its location in a "wx" active 1328cdf0c1d5Smjnelson# file list and print the following comment. Output is either text or 1329cdf0c1d5Smjnelson# HTML; if the latter, embedded bugids (sequence of 5 or more digits) 1330cdf0c1d5Smjnelson# are turned into URLs. 1331cdf0c1d5Smjnelson# 1332cdf0c1d5Smjnelson# This is also used with Mercurial and the file list provided by hg-active. 1333daaffb31Sdp# 1334daaffb31Sdpcomments_from_wx() 13357c478bd9Sstevel@tonic-gate{ 1336daaffb31Sdp typeset fmt=$1 1337daaffb31Sdp typeset p=$2 13387c478bd9Sstevel@tonic-gate 1339cdf0c1d5Smjnelson comm=`$AWK ' 1340daaffb31Sdp $1 == "'$p'" { 13417c478bd9Sstevel@tonic-gate do getline ; while (NF > 0) 13427c478bd9Sstevel@tonic-gate getline 13437c478bd9Sstevel@tonic-gate while (NF > 0) { print ; getline } 13447c478bd9Sstevel@tonic-gate exit 1345daaffb31Sdp }' < $wxfile` 1346daaffb31Sdp 1347cdf0c1d5Smjnelson if [[ -z $comm ]]; then 1348cdf0c1d5Smjnelson comm="*** NO COMMENTS ***" 1349cdf0c1d5Smjnelson fi 1350cdf0c1d5Smjnelson 1351daaffb31Sdp if [[ $fmt == "text" ]]; then 1352cdf0c1d5Smjnelson print -- "$comm" 1353daaffb31Sdp return 1354daaffb31Sdp fi 1355daaffb31Sdp 1356cdf0c1d5Smjnelson print -- "$comm" | html_quote | bug2url | sac2url 1357cdf0c1d5Smjnelson 13587c478bd9Sstevel@tonic-gate} 13597c478bd9Sstevel@tonic-gate 13607c478bd9Sstevel@tonic-gate# 1361daaffb31Sdp# getcomments {text|html} filepath parentpath 1362daaffb31Sdp# 1363daaffb31Sdp# Fetch the comments depending on what SCM mode we're in. 1364daaffb31Sdp# 1365daaffb31Sdpgetcomments() 1366daaffb31Sdp{ 1367daaffb31Sdp typeset fmt=$1 1368daaffb31Sdp typeset p=$2 1369daaffb31Sdp typeset pp=$3 13707c478bd9Sstevel@tonic-gate 13713df69ef3SDarren Moffat if [[ -n $Nflag ]]; then 13723df69ef3SDarren Moffat return 13733df69ef3SDarren Moffat fi 1374cdf0c1d5Smjnelson # 1375cdf0c1d5Smjnelson # Mercurial support uses a file list in wx format, so this 1376cdf0c1d5Smjnelson # will be used there, too 1377cdf0c1d5Smjnelson # 1378daaffb31Sdp if [[ -n $wxfile ]]; then 1379daaffb31Sdp comments_from_wx $fmt $p 1380daaffb31Sdp else 1381daaffb31Sdp if [[ $SCM_MODE == "teamware" ]]; then 1382daaffb31Sdp comments_from_teamware $fmt $pp $p 1383daaffb31Sdp fi 1384daaffb31Sdp fi 1385daaffb31Sdp} 1386daaffb31Sdp 1387daaffb31Sdp# 1388daaffb31Sdp# printCI <total-changed> <inserted> <deleted> <modified> <unchanged> 1389daaffb31Sdp# 1390daaffb31Sdp# Print out Code Inspection figures similar to sccs-prt(1) format. 1391daaffb31Sdp# 1392daaffb31Sdpfunction printCI 1393daaffb31Sdp{ 1394daaffb31Sdp integer tot=$1 ins=$2 del=$3 mod=$4 unc=$5 1395daaffb31Sdp typeset str 1396daaffb31Sdp if (( tot == 1 )); then 1397daaffb31Sdp str="line" 1398daaffb31Sdp else 1399daaffb31Sdp str="lines" 1400daaffb31Sdp fi 1401daaffb31Sdp printf '%d %s changed: %d ins; %d del; %d mod; %d unchg\n' \ 1402daaffb31Sdp $tot $str $ins $del $mod $unc 1403daaffb31Sdp} 1404daaffb31Sdp 1405daaffb31Sdp 1406daaffb31Sdp# 1407daaffb31Sdp# difflines <oldfile> <newfile> 1408daaffb31Sdp# 1409daaffb31Sdp# Calculate and emit number of added, removed, modified and unchanged lines, 1410daaffb31Sdp# and total lines changed, the sum of added + removed + modified. 1411daaffb31Sdp# 14127c478bd9Sstevel@tonic-gatefunction difflines 14137c478bd9Sstevel@tonic-gate{ 1414daaffb31Sdp integer tot mod del ins unc err 14157c478bd9Sstevel@tonic-gate typeset filename 14167c478bd9Sstevel@tonic-gate 1417cdf0c1d5Smjnelson eval $( diff -e $1 $2 | $AWK ' 1418daaffb31Sdp # Change range of lines: N,Nc 14197c478bd9Sstevel@tonic-gate /^[0-9]*,[0-9]*c$/ { 14207c478bd9Sstevel@tonic-gate n=split(substr($1,1,length($1)-1), counts, ","); 14217c478bd9Sstevel@tonic-gate if (n != 2) { 14227c478bd9Sstevel@tonic-gate error=2 14237c478bd9Sstevel@tonic-gate exit; 14247c478bd9Sstevel@tonic-gate } 1425daaffb31Sdp # 1426daaffb31Sdp # 3,5c means lines 3 , 4 and 5 are changed, a total of 3 lines. 1427daaffb31Sdp # following would be 5 - 3 = 2! Hence +1 for correction. 1428daaffb31Sdp # 14297c478bd9Sstevel@tonic-gate r=(counts[2]-counts[1])+1; 1430daaffb31Sdp 1431daaffb31Sdp # 1432daaffb31Sdp # Now count replacement lines: each represents a change instead 1433daaffb31Sdp # of a delete, so increment c and decrement r. 1434daaffb31Sdp # 14357c478bd9Sstevel@tonic-gate while (getline != /^\.$/) { 14367c478bd9Sstevel@tonic-gate c++; 14377c478bd9Sstevel@tonic-gate r--; 14387c478bd9Sstevel@tonic-gate } 1439daaffb31Sdp # 1440daaffb31Sdp # If there were more replacement lines than original lines, 1441daaffb31Sdp # then r will be negative; in this case there are no deletions, 1442daaffb31Sdp # but there are r changes that should be counted as adds, and 1443daaffb31Sdp # since r is negative, subtract it from a and add it to c. 1444daaffb31Sdp # 14457c478bd9Sstevel@tonic-gate if (r < 0) { 14467c478bd9Sstevel@tonic-gate a-=r; 14477c478bd9Sstevel@tonic-gate c+=r; 14487c478bd9Sstevel@tonic-gate } 1449daaffb31Sdp 1450daaffb31Sdp # 1451daaffb31Sdp # If there were more original lines than replacement lines, then 1452daaffb31Sdp # r will be positive; in this case, increment d by that much. 1453daaffb31Sdp # 14547c478bd9Sstevel@tonic-gate if (r > 0) { 14557c478bd9Sstevel@tonic-gate d+=r; 14567c478bd9Sstevel@tonic-gate } 14577c478bd9Sstevel@tonic-gate next; 14587c478bd9Sstevel@tonic-gate } 14597c478bd9Sstevel@tonic-gate 1460daaffb31Sdp # Change lines: Nc 14617c478bd9Sstevel@tonic-gate /^[0-9].*c$/ { 1462daaffb31Sdp # The first line is a replacement; any more are additions. 14637c478bd9Sstevel@tonic-gate if (getline != /^\.$/) { 14647c478bd9Sstevel@tonic-gate c++; 14657c478bd9Sstevel@tonic-gate while (getline != /^\.$/) a++; 14667c478bd9Sstevel@tonic-gate } 14677c478bd9Sstevel@tonic-gate next; 14687c478bd9Sstevel@tonic-gate } 14697c478bd9Sstevel@tonic-gate 1470daaffb31Sdp # Add lines: both Na and N,Na 14717c478bd9Sstevel@tonic-gate /^[0-9].*a$/ { 14727c478bd9Sstevel@tonic-gate while (getline != /^\.$/) a++; 14737c478bd9Sstevel@tonic-gate next; 14747c478bd9Sstevel@tonic-gate } 14757c478bd9Sstevel@tonic-gate 1476daaffb31Sdp # Delete range of lines: N,Nd 14777c478bd9Sstevel@tonic-gate /^[0-9]*,[0-9]*d$/ { 14787c478bd9Sstevel@tonic-gate n=split(substr($1,1,length($1)-1), counts, ","); 14797c478bd9Sstevel@tonic-gate if (n != 2) { 14807c478bd9Sstevel@tonic-gate error=2 14817c478bd9Sstevel@tonic-gate exit; 14827c478bd9Sstevel@tonic-gate } 1483daaffb31Sdp # 1484daaffb31Sdp # 3,5d means lines 3 , 4 and 5 are deleted, a total of 3 lines. 1485daaffb31Sdp # following would be 5 - 3 = 2! Hence +1 for correction. 1486daaffb31Sdp # 14877c478bd9Sstevel@tonic-gate r=(counts[2]-counts[1])+1; 14887c478bd9Sstevel@tonic-gate d+=r; 14897c478bd9Sstevel@tonic-gate next; 14907c478bd9Sstevel@tonic-gate } 14917c478bd9Sstevel@tonic-gate 1492daaffb31Sdp # Delete line: Nd. For example 10d says line 10 is deleted. 14937c478bd9Sstevel@tonic-gate /^[0-9]*d$/ {d++; next} 14947c478bd9Sstevel@tonic-gate 1495daaffb31Sdp # Should not get here! 14967c478bd9Sstevel@tonic-gate { 14977c478bd9Sstevel@tonic-gate error=1; 14987c478bd9Sstevel@tonic-gate exit; 14997c478bd9Sstevel@tonic-gate } 15007c478bd9Sstevel@tonic-gate 1501daaffb31Sdp # Finish off - print results 15027c478bd9Sstevel@tonic-gate END { 1503daaffb31Sdp printf("tot=%d;mod=%d;del=%d;ins=%d;err=%d\n", 15047c478bd9Sstevel@tonic-gate (c+d+a), c, d, a, error); 15057c478bd9Sstevel@tonic-gate }' ) 15067c478bd9Sstevel@tonic-gate 1507cdf0c1d5Smjnelson # End of $AWK, Check to see if any trouble occurred. 15087c478bd9Sstevel@tonic-gate if (( $? > 0 || err > 0 )); then 1509daaffb31Sdp print "Unexpected Error occurred reading" \ 1510daaffb31Sdp "\`diff -e $1 $2\`: \$?=$?, err=" $err 1511daaffb31Sdp return 1512daaffb31Sdp fi 1513daaffb31Sdp 15147c478bd9Sstevel@tonic-gate # Accumulate totals 15157c478bd9Sstevel@tonic-gate (( TOTL += tot )) 1516daaffb31Sdp (( TMOD += mod )) 15177c478bd9Sstevel@tonic-gate (( TDEL += del )) 15187c478bd9Sstevel@tonic-gate (( TINS += ins )) 15197c478bd9Sstevel@tonic-gate # Calculate unchanged lines 1520cdf0c1d5Smjnelson unc=`wc -l < $1` 15217c478bd9Sstevel@tonic-gate if (( unc > 0 )); then 1522daaffb31Sdp (( unc -= del + mod )) 15237c478bd9Sstevel@tonic-gate (( TUNC += unc )) 15247c478bd9Sstevel@tonic-gate fi 15257c478bd9Sstevel@tonic-gate # print summary 1526daaffb31Sdp print "<span class=\"lineschanged\">" 1527daaffb31Sdp printCI $tot $ins $del $mod $unc 1528daaffb31Sdp print "</span>" 15297c478bd9Sstevel@tonic-gate} 15307c478bd9Sstevel@tonic-gate 1531daaffb31Sdp 15327c478bd9Sstevel@tonic-gate# 1533daaffb31Sdp# flist_from_wx 1534daaffb31Sdp# 1535daaffb31Sdp# Sets up webrev to source its information from a wx-formatted file. 1536daaffb31Sdp# Sets the global 'wxfile' variable. 1537daaffb31Sdp# 1538daaffb31Sdpfunction flist_from_wx 15397c478bd9Sstevel@tonic-gate{ 1540daaffb31Sdp typeset argfile=$1 1541daaffb31Sdp if [[ -n ${argfile%%/*} ]]; then 1542daaffb31Sdp # 1543daaffb31Sdp # If the wx file pathname is relative then make it absolute 1544daaffb31Sdp # because the webrev does a "cd" later on. 1545daaffb31Sdp # 1546daaffb31Sdp wxfile=$PWD/$argfile 15477c478bd9Sstevel@tonic-gate else 1548daaffb31Sdp wxfile=$argfile 15497c478bd9Sstevel@tonic-gate fi 15507c478bd9Sstevel@tonic-gate 1551cdf0c1d5Smjnelson $AWK '{ c = 1; print; 15527c478bd9Sstevel@tonic-gate while (getline) { 15537c478bd9Sstevel@tonic-gate if (NF == 0) { c = -c; continue } 15547c478bd9Sstevel@tonic-gate if (c > 0) print 15557c478bd9Sstevel@tonic-gate } 1556daaffb31Sdp }' $wxfile > $FLIST 15577c478bd9Sstevel@tonic-gate 1558daaffb31Sdp print " Done." 1559daaffb31Sdp} 15607c478bd9Sstevel@tonic-gate 1561daaffb31Sdp# 1562daaffb31Sdp# flist_from_teamware [ <args-to-putback-n> ] 1563daaffb31Sdp# 1564daaffb31Sdp# Generate the file list by extracting file names from a putback -n. Some 1565daaffb31Sdp# names may come from the "update/create" messages and others from the 1566daaffb31Sdp# "currently checked out" warning. Renames are detected here too. Extract 1567daaffb31Sdp# values for CODEMGR_WS and CODEMGR_PARENT from the output of the putback 1568daaffb31Sdp# -n as well, but remove them if they are already defined. 1569daaffb31Sdp# 1570daaffb31Sdpfunction flist_from_teamware 1571daaffb31Sdp{ 1572cdf0c1d5Smjnelson if [[ -n $codemgr_parent && -z $parent_webrev ]]; then 1573daaffb31Sdp if [[ ! -d $codemgr_parent/Codemgr_wsdata ]]; then 1574daaffb31Sdp print -u2 "parent $codemgr_parent doesn't look like a" \ 1575daaffb31Sdp "valid teamware workspace" 15767c478bd9Sstevel@tonic-gate exit 1 15777c478bd9Sstevel@tonic-gate fi 1578daaffb31Sdp parent_args="-p $codemgr_parent" 15797c478bd9Sstevel@tonic-gate fi 15807c478bd9Sstevel@tonic-gate 1581daaffb31Sdp print " File list from: 'putback -n $parent_args $*' ... \c" 15827c478bd9Sstevel@tonic-gate 1583daaffb31Sdp putback -n $parent_args $* 2>&1 | 1584cdf0c1d5Smjnelson $AWK ' 1585daaffb31Sdp /^update:|^create:/ {print $2} 1586daaffb31Sdp /^Parent workspace:/ {printf("CODEMGR_PARENT=%s\n",$3)} 1587daaffb31Sdp /^Child workspace:/ {printf("CODEMGR_WS=%s\n",$3)} 1588daaffb31Sdp /^The following files are currently checked out/ {p = 1; continue} 1589daaffb31Sdp NF == 0 {p=0 ; continue} 1590daaffb31Sdp /^rename/ {old=$3} 1591daaffb31Sdp $1 == "to:" {print $2, old} 1592daaffb31Sdp /^"/ {continue} 1593daaffb31Sdp p == 1 {print $1}' | 1594daaffb31Sdp sort -r -k 1,1 -u | sort > $FLIST 15957c478bd9Sstevel@tonic-gate 1596daaffb31Sdp print " Done." 1597daaffb31Sdp} 1598daaffb31Sdp 1599cdf0c1d5Smjnelson# 1600cdf0c1d5Smjnelson# Call hg-active to get the active list output in the wx active list format 1601cdf0c1d5Smjnelson# 1602cdf0c1d5Smjnelsonfunction hg_active_wxfile 1603cdf0c1d5Smjnelson{ 1604cdf0c1d5Smjnelson typeset child=$1 1605cdf0c1d5Smjnelson typeset parent=$2 1606cdf0c1d5Smjnelson 1607cdf0c1d5Smjnelson TMPFLIST=/tmp/$$.active 16089a70fc3bSMark J. Nelson $HG_ACTIVE -w $child -p $parent -o $TMPFLIST 1609cdf0c1d5Smjnelson wxfile=$TMPFLIST 1610cdf0c1d5Smjnelson} 1611cdf0c1d5Smjnelson 1612cdf0c1d5Smjnelson# 1613cdf0c1d5Smjnelson# flist_from_mercurial 1614cdf0c1d5Smjnelson# Call hg-active to get a wx-style active list, and hand it off to 1615cdf0c1d5Smjnelson# flist_from_wx 1616cdf0c1d5Smjnelson# 1617cdf0c1d5Smjnelsonfunction flist_from_mercurial 1618cdf0c1d5Smjnelson{ 1619cdf0c1d5Smjnelson typeset child=$1 1620cdf0c1d5Smjnelson typeset parent=$2 1621cdf0c1d5Smjnelson 1622cdf0c1d5Smjnelson print " File list from: hg-active -p $parent ...\c" 1623cdf0c1d5Smjnelson 1624cdf0c1d5Smjnelson if [[ ! -x $HG_ACTIVE ]]; then 1625cdf0c1d5Smjnelson print # Blank line for the \c above 1626cdf0c1d5Smjnelson print -u2 "Error: hg-active tool not found. Exiting" 1627cdf0c1d5Smjnelson exit 1 1628cdf0c1d5Smjnelson fi 1629cdf0c1d5Smjnelson hg_active_wxfile $child $parent 1630cdf0c1d5Smjnelson 1631cdf0c1d5Smjnelson # flist_from_wx prints the Done, so we don't have to. 1632cdf0c1d5Smjnelson flist_from_wx $TMPFLIST 1633cdf0c1d5Smjnelson} 1634cdf0c1d5Smjnelson 1635cdf0c1d5Smjnelson# 1636cdf0c1d5Smjnelson# flist_from_subversion 1637cdf0c1d5Smjnelson# 1638cdf0c1d5Smjnelson# Generate the file list by extracting file names from svn status. 1639cdf0c1d5Smjnelson# 1640cdf0c1d5Smjnelsonfunction flist_from_subversion 1641cdf0c1d5Smjnelson{ 1642cdf0c1d5Smjnelson CWS=$1 1643cdf0c1d5Smjnelson OLDPWD=$2 1644cdf0c1d5Smjnelson 1645cdf0c1d5Smjnelson cd $CWS 1646cdf0c1d5Smjnelson print -u2 " File list from: svn status ... \c" 1647cdf0c1d5Smjnelson svn status | $AWK '/^[ACDMR]/ { print $NF }' > $FLIST 1648cdf0c1d5Smjnelson print -u2 " Done." 1649cdf0c1d5Smjnelson cd $OLDPWD 1650cdf0c1d5Smjnelson} 1651cdf0c1d5Smjnelson 1652daaffb31Sdpfunction env_from_flist 1653daaffb31Sdp{ 1654daaffb31Sdp [[ -r $FLIST ]] || return 1655daaffb31Sdp 1656daaffb31Sdp # 1657daaffb31Sdp # Use "eval" to set env variables that are listed in the file 1658daaffb31Sdp # list. Then copy those into our local versions of those 1659daaffb31Sdp # variables if they have not been set already. 1660daaffb31Sdp # 166102d26c39SVladimir Kotal eval `sed -e "s/#.*$//" $FLIST | $GREP = ` 16627c478bd9Sstevel@tonic-gate 1663cdf0c1d5Smjnelson if [[ -z $codemgr_ws && -n $CODEMGR_WS ]]; then 1664cdf0c1d5Smjnelson codemgr_ws=$CODEMGR_WS 1665cdf0c1d5Smjnelson export CODEMGR_WS 1666cdf0c1d5Smjnelson fi 16677c478bd9Sstevel@tonic-gate 1668daaffb31Sdp # 1669daaffb31Sdp # Check to see if CODEMGR_PARENT is set in the flist file. 1670daaffb31Sdp # 1671cdf0c1d5Smjnelson if [[ -z $codemgr_parent && -n $CODEMGR_PARENT ]]; then 1672daaffb31Sdp codemgr_parent=$CODEMGR_PARENT 1673cdf0c1d5Smjnelson export CODEMGR_PARENT 1674daaffb31Sdp fi 1675daaffb31Sdp} 1676daaffb31Sdp 167714983201Sdpfunction look_for_prog 167814983201Sdp{ 167914983201Sdp typeset path 168014983201Sdp typeset ppath 168114983201Sdp typeset progname=$1 168214983201Sdp 168314983201Sdp ppath=$PATH 168414983201Sdp ppath=$ppath:/usr/sfw/bin:/usr/bin:/usr/sbin 168514983201Sdp ppath=$ppath:/opt/teamware/bin:/opt/onbld/bin 1686cdf0c1d5Smjnelson ppath=$ppath:/opt/onbld/bin/`uname -p` 168714983201Sdp 168814983201Sdp PATH=$ppath prog=`whence $progname` 168914983201Sdp if [[ -n $prog ]]; then 169014983201Sdp print $prog 169114983201Sdp fi 169214983201Sdp} 169314983201Sdp 1694cdf0c1d5Smjnelsonfunction get_file_mode 1695cdf0c1d5Smjnelson{ 1696cdf0c1d5Smjnelson $PERL -e ' 1697cdf0c1d5Smjnelson if (@stat = stat($ARGV[0])) { 1698cdf0c1d5Smjnelson $mode = $stat[2] & 0777; 1699cdf0c1d5Smjnelson printf "%03o\n", $mode; 1700cdf0c1d5Smjnelson exit 0; 1701cdf0c1d5Smjnelson } else { 1702cdf0c1d5Smjnelson exit 1; 1703cdf0c1d5Smjnelson } 1704cdf0c1d5Smjnelson ' $1 1705cdf0c1d5Smjnelson} 1706cdf0c1d5Smjnelson 1707cdf0c1d5Smjnelsonfunction build_old_new_teamware 1708cdf0c1d5Smjnelson{ 1709cdf0c1d5Smjnelson typeset olddir="$1" 1710cdf0c1d5Smjnelson typeset newdir="$2" 1711cdf0c1d5Smjnelson 1712cdf0c1d5Smjnelson # If the child's version doesn't exist then 1713cdf0c1d5Smjnelson # get a readonly copy. 1714cdf0c1d5Smjnelson 1715cdf0c1d5Smjnelson if [[ ! -f $CWS/$DIR/$F && -f $CWS/$DIR/SCCS/s.$F ]]; then 1716cdf0c1d5Smjnelson $SCCS get -s -p $CWS/$DIR/$F > $CWS/$DIR/$F 1717cdf0c1d5Smjnelson fi 1718cdf0c1d5Smjnelson 1719cdf0c1d5Smjnelson # The following two sections propagate file permissions the 1720cdf0c1d5Smjnelson # same way SCCS does. If the file is already under version 1721cdf0c1d5Smjnelson # control, always use permissions from the SCCS/s.file. If 1722cdf0c1d5Smjnelson # the file is not under SCCS control, use permissions from the 1723cdf0c1d5Smjnelson # working copy. In all cases, the file copied to the webrev 1724cdf0c1d5Smjnelson # is set to read only, and group/other permissions are set to 1725cdf0c1d5Smjnelson # match those of the file owner. This way, even if the file 1726cdf0c1d5Smjnelson # is currently checked out, the webrev will display the final 1727cdf0c1d5Smjnelson # permissions that would result after check in. 1728cdf0c1d5Smjnelson 1729cdf0c1d5Smjnelson # 1730cdf0c1d5Smjnelson # Snag new version of file. 1731cdf0c1d5Smjnelson # 1732cdf0c1d5Smjnelson rm -f $newdir/$DIR/$F 1733cdf0c1d5Smjnelson cp $CWS/$DIR/$F $newdir/$DIR/$F 1734cdf0c1d5Smjnelson if [[ -f $CWS/$DIR/SCCS/s.$F ]]; then 1735cdf0c1d5Smjnelson chmod `get_file_mode $CWS/$DIR/SCCS/s.$F` \ 1736cdf0c1d5Smjnelson $newdir/$DIR/$F 1737cdf0c1d5Smjnelson fi 1738cdf0c1d5Smjnelson chmod u-w,go=u $newdir/$DIR/$F 1739cdf0c1d5Smjnelson 1740cdf0c1d5Smjnelson # 1741cdf0c1d5Smjnelson # Get the parent's version of the file. First see whether the 1742cdf0c1d5Smjnelson # child's version is checked out and get the parent's version 1743cdf0c1d5Smjnelson # with keywords expanded or unexpanded as appropriate. 1744cdf0c1d5Smjnelson # 1745cdf0c1d5Smjnelson if [[ -f $PWS/$PDIR/$PF && ! -f $PWS/$PDIR/SCCS/s.$PF && \ 1746cdf0c1d5Smjnelson ! -f $PWS/$PDIR/SCCS/p.$PF ]]; then 1747cdf0c1d5Smjnelson # Parent is not a real workspace, but just a raw 1748cdf0c1d5Smjnelson # directory tree - use the file that's there as 1749cdf0c1d5Smjnelson # the old file. 1750cdf0c1d5Smjnelson 1751cdf0c1d5Smjnelson rm -f $olddir/$PDIR/$PF 1752cdf0c1d5Smjnelson cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF 1753cdf0c1d5Smjnelson else 1754cdf0c1d5Smjnelson if [[ -f $PWS/$PDIR/SCCS/s.$PF ]]; then 1755cdf0c1d5Smjnelson real_parent=$PWS 1756cdf0c1d5Smjnelson else 1757cdf0c1d5Smjnelson real_parent=$RWS 1758cdf0c1d5Smjnelson fi 1759cdf0c1d5Smjnelson 1760cdf0c1d5Smjnelson rm -f $olddir/$PDIR/$PF 1761cdf0c1d5Smjnelson 1762cdf0c1d5Smjnelson if [[ -f $real_parent/$PDIR/$PF ]]; then 1763cdf0c1d5Smjnelson if [ -f $CWS/$DIR/SCCS/p.$F ]; then 1764cdf0c1d5Smjnelson $SCCS get -s -p -k $real_parent/$PDIR/$PF > \ 1765cdf0c1d5Smjnelson $olddir/$PDIR/$PF 1766cdf0c1d5Smjnelson else 1767cdf0c1d5Smjnelson $SCCS get -s -p $real_parent/$PDIR/$PF > \ 1768cdf0c1d5Smjnelson $olddir/$PDIR/$PF 1769cdf0c1d5Smjnelson fi 1770cdf0c1d5Smjnelson chmod `get_file_mode $real_parent/$PDIR/SCCS/s.$PF` \ 1771cdf0c1d5Smjnelson $olddir/$PDIR/$PF 1772cdf0c1d5Smjnelson fi 1773cdf0c1d5Smjnelson fi 1774cdf0c1d5Smjnelson if [[ -f $olddir/$PDIR/$PF ]]; then 1775cdf0c1d5Smjnelson chmod u-w,go=u $olddir/$PDIR/$PF 1776cdf0c1d5Smjnelson fi 1777cdf0c1d5Smjnelson} 1778cdf0c1d5Smjnelson 1779cdf0c1d5Smjnelsonfunction build_old_new_mercurial 1780cdf0c1d5Smjnelson{ 1781cdf0c1d5Smjnelson typeset olddir="$1" 1782cdf0c1d5Smjnelson typeset newdir="$2" 1783cdf0c1d5Smjnelson typeset old_mode= 1784cdf0c1d5Smjnelson typeset new_mode= 1785cdf0c1d5Smjnelson typeset file 1786cdf0c1d5Smjnelson 1787cdf0c1d5Smjnelson # 1788cdf0c1d5Smjnelson # Get old file mode, from the parent revision manifest entry. 1789cdf0c1d5Smjnelson # Mercurial only stores a "file is executable" flag, but the 1790cdf0c1d5Smjnelson # manifest will display an octal mode "644" or "755". 1791cdf0c1d5Smjnelson # 1792cdf0c1d5Smjnelson if [[ "$PDIR" == "." ]]; then 1793cdf0c1d5Smjnelson file="$PF" 1794cdf0c1d5Smjnelson else 1795cdf0c1d5Smjnelson file="$PDIR/$PF" 1796cdf0c1d5Smjnelson fi 1797cdf0c1d5Smjnelson file=`echo $file | sed 's#/#\\\/#g'` 1798cdf0c1d5Smjnelson # match the exact filename, and return only the permission digits 1799cdf0c1d5Smjnelson old_mode=`sed -n -e "/^\\(...\\) . ${file}$/s//\\1/p" \ 1800cdf0c1d5Smjnelson < $HG_PARENT_MANIFEST` 1801cdf0c1d5Smjnelson 1802cdf0c1d5Smjnelson # 1803cdf0c1d5Smjnelson # Get new file mode, directly from the filesystem. 1804cdf0c1d5Smjnelson # Normalize the mode to match Mercurial's behavior. 1805cdf0c1d5Smjnelson # 1806cdf0c1d5Smjnelson new_mode=`get_file_mode $CWS/$DIR/$F` 1807cdf0c1d5Smjnelson if [[ -n "$new_mode" ]]; then 1808cdf0c1d5Smjnelson if [[ "$new_mode" = *[1357]* ]]; then 1809cdf0c1d5Smjnelson new_mode=755 1810cdf0c1d5Smjnelson else 1811cdf0c1d5Smjnelson new_mode=644 1812cdf0c1d5Smjnelson fi 1813cdf0c1d5Smjnelson fi 1814cdf0c1d5Smjnelson 1815cdf0c1d5Smjnelson # 1816cdf0c1d5Smjnelson # new version of the file. 1817cdf0c1d5Smjnelson # 1818cdf0c1d5Smjnelson rm -rf $newdir/$DIR/$F 1819cdf0c1d5Smjnelson if [[ -e $CWS/$DIR/$F ]]; then 1820cdf0c1d5Smjnelson cp $CWS/$DIR/$F $newdir/$DIR/$F 1821cdf0c1d5Smjnelson if [[ -n $new_mode ]]; then 1822cdf0c1d5Smjnelson chmod $new_mode $newdir/$DIR/$F 1823cdf0c1d5Smjnelson else 1824cdf0c1d5Smjnelson # should never happen 1825cdf0c1d5Smjnelson print -u2 "ERROR: set mode of $newdir/$DIR/$F" 1826cdf0c1d5Smjnelson fi 1827cdf0c1d5Smjnelson fi 1828cdf0c1d5Smjnelson 1829cdf0c1d5Smjnelson # 1830cdf0c1d5Smjnelson # parent's version of the file 1831cdf0c1d5Smjnelson # 1832cdf0c1d5Smjnelson # Note that we get this from the last version common to both 1833cdf0c1d5Smjnelson # ourselves and the parent. References are via $CWS since we have no 1834cdf0c1d5Smjnelson # guarantee that the parent workspace is reachable via the filesystem. 1835cdf0c1d5Smjnelson # 1836cdf0c1d5Smjnelson if [[ -n $parent_webrev && -e $PWS/$PDIR/$PF ]]; then 1837cdf0c1d5Smjnelson cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF 1838cdf0c1d5Smjnelson elif [[ -n $HG_PARENT ]]; then 1839cdf0c1d5Smjnelson hg cat -R $CWS -r $HG_PARENT $CWS/$PDIR/$PF > \ 1840cdf0c1d5Smjnelson $olddir/$PDIR/$PF 2>/dev/null 1841cdf0c1d5Smjnelson 184202d26c39SVladimir Kotal if (( $? != 0 )); then 1843cdf0c1d5Smjnelson rm -f $olddir/$PDIR/$PF 1844cdf0c1d5Smjnelson else 1845cdf0c1d5Smjnelson if [[ -n $old_mode ]]; then 1846cdf0c1d5Smjnelson chmod $old_mode $olddir/$PDIR/$PF 1847cdf0c1d5Smjnelson else 1848cdf0c1d5Smjnelson # should never happen 1849cdf0c1d5Smjnelson print -u2 "ERROR: set mode of $olddir/$PDIR/$PF" 1850cdf0c1d5Smjnelson fi 1851cdf0c1d5Smjnelson fi 1852cdf0c1d5Smjnelson fi 1853cdf0c1d5Smjnelson} 1854cdf0c1d5Smjnelson 1855cdf0c1d5Smjnelsonfunction build_old_new_subversion 1856cdf0c1d5Smjnelson{ 1857cdf0c1d5Smjnelson typeset olddir="$1" 1858cdf0c1d5Smjnelson typeset newdir="$2" 1859cdf0c1d5Smjnelson 1860cdf0c1d5Smjnelson # Snag new version of file. 1861cdf0c1d5Smjnelson rm -f $newdir/$DIR/$F 1862cdf0c1d5Smjnelson [[ -e $CWS/$DIR/$F ]] && cp $CWS/$DIR/$F $newdir/$DIR/$F 1863cdf0c1d5Smjnelson 1864cdf0c1d5Smjnelson if [[ -n $PWS && -e $PWS/$PDIR/$PF ]]; then 1865cdf0c1d5Smjnelson cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF 1866cdf0c1d5Smjnelson else 1867cdf0c1d5Smjnelson # Get the parent's version of the file. 1868cdf0c1d5Smjnelson svn status $CWS/$DIR/$F | read stat file 1869cdf0c1d5Smjnelson if [[ $stat != "A" ]]; then 1870cdf0c1d5Smjnelson svn cat -r BASE $CWS/$DIR/$F > $olddir/$PDIR/$PF 1871cdf0c1d5Smjnelson fi 1872cdf0c1d5Smjnelson fi 1873cdf0c1d5Smjnelson} 1874cdf0c1d5Smjnelson 1875cdf0c1d5Smjnelsonfunction build_old_new_unknown 1876cdf0c1d5Smjnelson{ 1877cdf0c1d5Smjnelson typeset olddir="$1" 1878cdf0c1d5Smjnelson typeset newdir="$2" 1879cdf0c1d5Smjnelson 1880cdf0c1d5Smjnelson # 1881cdf0c1d5Smjnelson # Snag new version of file. 1882cdf0c1d5Smjnelson # 1883cdf0c1d5Smjnelson rm -f $newdir/$DIR/$F 1884cdf0c1d5Smjnelson [[ -e $CWS/$DIR/$F ]] && cp $CWS/$DIR/$F $newdir/$DIR/$F 1885cdf0c1d5Smjnelson 1886cdf0c1d5Smjnelson # 1887cdf0c1d5Smjnelson # Snag the parent's version of the file. 1888cdf0c1d5Smjnelson # 1889cdf0c1d5Smjnelson if [[ -f $PWS/$PDIR/$PF ]]; then 1890cdf0c1d5Smjnelson rm -f $olddir/$PDIR/$PF 1891cdf0c1d5Smjnelson cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF 1892cdf0c1d5Smjnelson fi 1893cdf0c1d5Smjnelson} 1894cdf0c1d5Smjnelson 1895cdf0c1d5Smjnelsonfunction build_old_new 1896cdf0c1d5Smjnelson{ 1897cdf0c1d5Smjnelson typeset WDIR=$1 1898cdf0c1d5Smjnelson typeset PWS=$2 1899cdf0c1d5Smjnelson typeset PDIR=$3 1900cdf0c1d5Smjnelson typeset PF=$4 1901cdf0c1d5Smjnelson typeset CWS=$5 1902cdf0c1d5Smjnelson typeset DIR=$6 1903cdf0c1d5Smjnelson typeset F=$7 1904cdf0c1d5Smjnelson 1905cdf0c1d5Smjnelson typeset olddir="$WDIR/raw_files/old" 1906cdf0c1d5Smjnelson typeset newdir="$WDIR/raw_files/new" 1907cdf0c1d5Smjnelson 1908cdf0c1d5Smjnelson mkdir -p $olddir/$PDIR 1909cdf0c1d5Smjnelson mkdir -p $newdir/$DIR 1910cdf0c1d5Smjnelson 1911cdf0c1d5Smjnelson if [[ $SCM_MODE == "teamware" ]]; then 1912cdf0c1d5Smjnelson build_old_new_teamware "$olddir" "$newdir" 1913cdf0c1d5Smjnelson elif [[ $SCM_MODE == "mercurial" ]]; then 1914cdf0c1d5Smjnelson build_old_new_mercurial "$olddir" "$newdir" 1915cdf0c1d5Smjnelson elif [[ $SCM_MODE == "subversion" ]]; then 1916cdf0c1d5Smjnelson build_old_new_subversion "$olddir" "$newdir" 1917cdf0c1d5Smjnelson elif [[ $SCM_MODE == "unknown" ]]; then 1918cdf0c1d5Smjnelson build_old_new_unknown "$olddir" "$newdir" 1919cdf0c1d5Smjnelson fi 1920cdf0c1d5Smjnelson 1921cdf0c1d5Smjnelson if [[ ! -f $olddir/$PDIR/$PF && ! -f $newdir/$DIR/$F ]]; then 1922cdf0c1d5Smjnelson print "*** Error: file not in parent or child" 1923cdf0c1d5Smjnelson return 1 1924cdf0c1d5Smjnelson fi 1925cdf0c1d5Smjnelson return 0 1926cdf0c1d5Smjnelson} 1927cdf0c1d5Smjnelson 1928cdf0c1d5Smjnelson 1929daaffb31Sdp# 1930daaffb31Sdp# Usage message. 1931daaffb31Sdp# 1932daaffb31Sdpfunction usage 1933daaffb31Sdp{ 1934daaffb31Sdp print 'Usage:\twebrev [common-options] 1935daaffb31Sdp webrev [common-options] ( <file> | - ) 1936daaffb31Sdp webrev [common-options] -w <wx file> 1937daaffb31Sdp 1938daaffb31SdpOptions: 1939ba44d8a2SVladimir Kotal -D: delete remote webrev 1940daaffb31Sdp -i <filename>: Include <filename> in the index.html file. 1941ba44d8a2SVladimir Kotal -n: do not generate the webrev (useful with -U) 1942ba44d8a2SVladimir Kotal -O: Print bugids/arc cases suitable for OpenSolaris. 1943daaffb31Sdp -o <outdir>: Output webrev to specified directory. 1944daaffb31Sdp -p <compare-against>: Use specified parent wkspc or basis for comparison 194502d26c39SVladimir Kotal -t <remote_target>: Specify remote destination for webrev upload 194602d26c39SVladimir Kotal -U: upload the webrev to remote destination 1947daaffb31Sdp -w <wxfile>: Use specified wx active file. 1948daaffb31Sdp 1949daaffb31SdpEnvironment: 1950daaffb31Sdp WDIR: Control the output directory. 1951daaffb31Sdp WEBREV_BUGURL: Control the URL prefix for bugids. 1952daaffb31Sdp WEBREV_SACURL: Control the URL prefix for ARC cases. 1953ba44d8a2SVladimir Kotal WEBREV_TRASH_DIR: Set directory for webrev delete. 1954daaffb31Sdp 1955cdf0c1d5SmjnelsonSCM Specific Options: 1956cdf0c1d5Smjnelson TeamWare: webrev [common-options] -l [arguments to 'putback'] 1957cdf0c1d5Smjnelson 1958daaffb31SdpSCM Environment: 1959cdf0c1d5Smjnelson CODEMGR_WS: Workspace location. 1960cdf0c1d5Smjnelson CODEMGR_PARENT: Parent workspace location. 1961daaffb31Sdp' 1962daaffb31Sdp 1963daaffb31Sdp exit 2 1964daaffb31Sdp} 1965daaffb31Sdp 1966daaffb31Sdp# 1967daaffb31Sdp# 1968daaffb31Sdp# Main program starts here 1969daaffb31Sdp# 1970daaffb31Sdp# 1971daaffb31Sdp 1972daaffb31Sdptrap "rm -f /tmp/$$.* ; exit" 0 1 2 3 15 1973daaffb31Sdp 1974daaffb31Sdpset +o noclobber 1975daaffb31Sdp 1976cdf0c1d5SmjnelsonPATH=$(dirname $(whence $0)):$PATH 1977cdf0c1d5Smjnelson 197814983201Sdp[[ -z $WDIFF ]] && WDIFF=`look_for_prog wdiff` 197914983201Sdp[[ -z $WX ]] && WX=`look_for_prog wx` 1980cdf0c1d5Smjnelson[[ -z $HG_ACTIVE ]] && HG_ACTIVE=`look_for_prog hg-active` 1981cdf0c1d5Smjnelson[[ -z $WHICH_SCM ]] && WHICH_SCM=`look_for_prog which_scm` 198214983201Sdp[[ -z $CODEREVIEW ]] && CODEREVIEW=`look_for_prog codereview` 198314983201Sdp[[ -z $PS2PDF ]] && PS2PDF=`look_for_prog ps2pdf` 198414983201Sdp[[ -z $PERL ]] && PERL=`look_for_prog perl` 198502d26c39SVladimir Kotal[[ -z $RSYNC ]] && RSYNC=`look_for_prog rsync` 1986cdf0c1d5Smjnelson[[ -z $SCCS ]] && SCCS=`look_for_prog sccs` 1987cdf0c1d5Smjnelson[[ -z $AWK ]] && AWK=`look_for_prog nawk` 1988cdf0c1d5Smjnelson[[ -z $AWK ]] && AWK=`look_for_prog gawk` 1989cdf0c1d5Smjnelson[[ -z $AWK ]] && AWK=`look_for_prog awk` 199002d26c39SVladimir Kotal[[ -z $SCP ]] && SCP=`look_for_prog scp` 199102d26c39SVladimir Kotal[[ -z $SFTP ]] && SFTP=`look_for_prog sftp` 199202d26c39SVladimir Kotal[[ -z $MKTEMP ]] && MKTEMP=`look_for_prog mktemp` 199302d26c39SVladimir Kotal[[ -z $GREP ]] && GREP=`look_for_prog grep` 1994ba44d8a2SVladimir Kotal[[ -z $FIND ]] && FIND=`look_for_prog find` 1995cdf0c1d5Smjnelson 1996ba44d8a2SVladimir Kotal# set name of trash directory for remote webrev deletion 1997ba44d8a2SVladimir KotalTRASH_DIR=".trash" 1998ba44d8a2SVladimir Kotal[[ -n $WEBREV_TRASH_DIR ]] && TRASH_DIR=$WEBREV_TRASH_DIR 199914983201Sdp 200014983201Sdpif [[ ! -x $PERL ]]; then 200114983201Sdp print -u2 "Error: No perl interpreter found. Exiting." 200214983201Sdp exit 1 2003daaffb31Sdpfi 200414983201Sdp 2005cdf0c1d5Smjnelsonif [[ ! -x $WHICH_SCM ]]; then 2006cdf0c1d5Smjnelson print -u2 "Error: Could not find which_scm. Exiting." 2007cdf0c1d5Smjnelson exit 1 2008cdf0c1d5Smjnelsonfi 2009cdf0c1d5Smjnelson 201014983201Sdp# 201114983201Sdp# These aren't fatal, but we want to note them to the user. 201214983201Sdp# We don't warn on the absence of 'wx' until later when we've 201314983201Sdp# determined that we actually need to try to invoke it. 201414983201Sdp# 201514983201Sdp[[ ! -x $CODEREVIEW ]] && print -u2 "WARNING: codereview(1) not found." 201614983201Sdp[[ ! -x $PS2PDF ]] && print -u2 "WARNING: ps2pdf(1) not found." 201714983201Sdp[[ ! -x $WDIFF ]] && print -u2 "WARNING: wdiff not found." 2018daaffb31Sdp 2019daaffb31Sdp# Declare global total counters. 2020daaffb31Sdpinteger TOTL TINS TDEL TMOD TUNC 2021daaffb31Sdp 2022ba44d8a2SVladimir Kotal# default remote host for upload/delete 2023ba44d8a2SVladimir Kotaltypeset -r DEFAULT_REMOTE_HOST="cr.opensolaris.org" 2024ba44d8a2SVladimir Kotal 2025ba44d8a2SVladimir KotalDflag= 202614983201Sdpflist_mode= 202714983201Sdpflist_file= 2028daaffb31Sdpiflag= 202902d26c39SVladimir Kotallflag= 203002d26c39SVladimir KotalNflag= 203102d26c39SVladimir Kotalnflag= 203202d26c39SVladimir KotalOflag= 2033daaffb31Sdpoflag= 2034daaffb31Sdppflag= 203502d26c39SVladimir Kotaltflag= 203602d26c39SVladimir Kotaluflag= 203702d26c39SVladimir KotalUflag= 2038daaffb31Sdpwflag= 203902d26c39SVladimir Kotalremote_target= 2040ba44d8a2SVladimir Kotal 2041ba44d8a2SVladimir Kotal# 2042ba44d8a2SVladimir Kotal# NOTE: when adding/removing options it is necessary to sync the list 2043ba44d8a2SVladimir Kotal# with usr/src/tools/onbld/hgext/cdm.py 2044ba44d8a2SVladimir Kotal# 2045ba44d8a2SVladimir Kotalwhile getopts "i:o:p:lwONnt:UD" opt 2046daaffb31Sdpdo 2047daaffb31Sdp case $opt in 2048ba44d8a2SVladimir Kotal D) Dflag=1;; 2049ba44d8a2SVladimir Kotal 2050daaffb31Sdp i) iflag=1 2051daaffb31Sdp INCLUDE_FILE=$OPTARG;; 2052daaffb31Sdp 2053daaffb31Sdp # 2054daaffb31Sdp # If -l has been specified, we need to abort further options 2055daaffb31Sdp # processing, because subsequent arguments are going to be 2056daaffb31Sdp # arguments to 'putback -n'. 2057daaffb31Sdp # 2058daaffb31Sdp l) lflag=1 2059daaffb31Sdp break;; 2060daaffb31Sdp 206102d26c39SVladimir Kotal N) Nflag=1;; 206202d26c39SVladimir Kotal 206302d26c39SVladimir Kotal n) nflag=1;; 2064daaffb31Sdp 2065daaffb31Sdp O) Oflag=1;; 2066daaffb31Sdp 206702d26c39SVladimir Kotal o) oflag=1 206802d26c39SVladimir Kotal WDIR=$OPTARG;; 206902d26c39SVladimir Kotal 207002d26c39SVladimir Kotal p) pflag=1 207102d26c39SVladimir Kotal codemgr_parent=$OPTARG;; 207202d26c39SVladimir Kotal 207302d26c39SVladimir Kotal t) tflag=1 207402d26c39SVladimir Kotal remote_target=$OPTARG;; 207502d26c39SVladimir Kotal 207602d26c39SVladimir Kotal U) Uflag=1;; 207702d26c39SVladimir Kotal 207802d26c39SVladimir Kotal w) wflag=1;; 20793df69ef3SDarren Moffat 2080daaffb31Sdp ?) usage;; 2081daaffb31Sdp esac 2082daaffb31Sdpdone 2083daaffb31Sdp 2084daaffb31SdpFLIST=/tmp/$$.flist 2085daaffb31Sdp 2086daaffb31Sdpif [[ -n $wflag && -n $lflag ]]; then 2087daaffb31Sdp usage 2088daaffb31Sdpfi 2089daaffb31Sdp 209002d26c39SVladimir Kotal# more sanity checking 209102d26c39SVladimir Kotalif [[ -n $nflag && -z $Uflag ]]; then 2092ba44d8a2SVladimir Kotal print "it does not make sense to skip webrev generation" \ 2093ba44d8a2SVladimir Kotal "without -U" 209402d26c39SVladimir Kotal exit 1 209502d26c39SVladimir Kotalfi 209602d26c39SVladimir Kotal 2097ba44d8a2SVladimir Kotalif [[ -n $tflag && -z $Uflag && -z $Dflag ]]; then 2098ba44d8a2SVladimir Kotal echo "remote target has to be used only for upload or delete" 209902d26c39SVladimir Kotal exit 1 210002d26c39SVladimir Kotalfi 210102d26c39SVladimir Kotal 2102daaffb31Sdp# 2103daaffb31Sdp# If this manually set as the parent, and it appears to be an earlier webrev, 2104daaffb31Sdp# then note that fact and set the parent to the raw_files/new subdirectory. 2105daaffb31Sdp# 2106daaffb31Sdpif [[ -n $pflag && -d $codemgr_parent/raw_files/new ]]; then 2107daaffb31Sdp parent_webrev="$codemgr_parent" 2108daaffb31Sdp codemgr_parent="$codemgr_parent/raw_files/new" 2109daaffb31Sdpfi 2110daaffb31Sdp 2111daaffb31Sdpif [[ -z $wflag && -z $lflag ]]; then 2112daaffb31Sdp shift $(($OPTIND - 1)) 2113daaffb31Sdp 2114daaffb31Sdp if [[ $1 == "-" ]]; then 2115daaffb31Sdp cat > $FLIST 211614983201Sdp flist_mode="stdin" 211714983201Sdp flist_done=1 211814983201Sdp shift 2119daaffb31Sdp elif [[ -n $1 ]]; then 212014983201Sdp if [[ ! -r $1 ]]; then 2121daaffb31Sdp print -u2 "$1: no such file or not readable" 2122daaffb31Sdp usage 2123daaffb31Sdp fi 2124daaffb31Sdp cat $1 > $FLIST 212514983201Sdp flist_mode="file" 212614983201Sdp flist_file=$1 212714983201Sdp flist_done=1 212814983201Sdp shift 2129daaffb31Sdp else 213014983201Sdp flist_mode="auto" 2131daaffb31Sdp fi 2132daaffb31Sdpfi 2133daaffb31Sdp 2134daaffb31Sdp# 2135daaffb31Sdp# Before we go on to further consider -l and -w, work out which SCM we think 2136daaffb31Sdp# is in use. 2137daaffb31Sdp# 2138cdf0c1d5Smjnelson$WHICH_SCM | read SCM_MODE junk || exit 1 2139cdf0c1d5Smjnelsoncase "$SCM_MODE" in 2140cdf0c1d5Smjnelsonteamware|mercurial|subversion) 2141cdf0c1d5Smjnelson ;; 2142cdf0c1d5Smjnelsonunknown) 2143cdf0c1d5Smjnelson if [[ $flist_mode == "auto" ]]; then 2144cdf0c1d5Smjnelson print -u2 "Unable to determine SCM in use and file list not specified" 2145cdf0c1d5Smjnelson print -u2 "See which_scm(1) for SCM detection information." 21467c478bd9Sstevel@tonic-gate exit 1 21477c478bd9Sstevel@tonic-gate fi 2148cdf0c1d5Smjnelson ;; 2149cdf0c1d5Smjnelson*) 2150cdf0c1d5Smjnelson if [[ $flist_mode == "auto" ]]; then 2151cdf0c1d5Smjnelson print -u2 "Unsupported SCM in use ($SCM_MODE) and file list not specified" 2152cdf0c1d5Smjnelson exit 1 2153cdf0c1d5Smjnelson fi 2154cdf0c1d5Smjnelson ;; 2155cdf0c1d5Smjnelsonesac 21567c478bd9Sstevel@tonic-gate 2157daaffb31Sdpprint -u2 " SCM detected: $SCM_MODE" 2158daaffb31Sdp 2159daaffb31Sdpif [[ -n $lflag ]]; then 2160daaffb31Sdp # 2161daaffb31Sdp # If the -l flag is given instead of the name of a file list, 2162daaffb31Sdp # then generate the file list by extracting file names from a 2163daaffb31Sdp # putback -n. 2164daaffb31Sdp # 2165daaffb31Sdp shift $(($OPTIND - 1)) 2166cdf0c1d5Smjnelson if [[ $SCM_MODE == "teamware" ]]; then 2167daaffb31Sdp flist_from_teamware "$*" 2168cdf0c1d5Smjnelson else 2169cdf0c1d5Smjnelson print -u2 -- "Error: -l option only applies to TeamWare" 2170cdf0c1d5Smjnelson exit 1 2171cdf0c1d5Smjnelson fi 2172daaffb31Sdp flist_done=1 2173daaffb31Sdp shift $# 2174daaffb31Sdpelif [[ -n $wflag ]]; then 2175daaffb31Sdp # 2176daaffb31Sdp # If the -w is given then assume the file list is in Bonwick's "wx" 2177daaffb31Sdp # command format, i.e. pathname lines alternating with SCCS comment 2178daaffb31Sdp # lines with blank lines as separators. Use the SCCS comments later 2179daaffb31Sdp # in building the index.html file. 2180daaffb31Sdp # 2181daaffb31Sdp shift $(($OPTIND - 1)) 2182daaffb31Sdp wxfile=$1 2183daaffb31Sdp if [[ -z $wxfile && -n $CODEMGR_WS ]]; then 2184daaffb31Sdp if [[ -r $CODEMGR_WS/wx/active ]]; then 2185daaffb31Sdp wxfile=$CODEMGR_WS/wx/active 2186daaffb31Sdp fi 2187daaffb31Sdp fi 2188daaffb31Sdp 2189daaffb31Sdp [[ -z $wxfile ]] && print -u2 "wx file not specified, and could not " \ 2190daaffb31Sdp "be auto-detected (check \$CODEMGR_WS)" && exit 1 2191daaffb31Sdp 2192cdf0c1d5Smjnelson if [[ ! -r $wxfile ]]; then 2193cdf0c1d5Smjnelson print -u2 "$wxfile: no such file or not readable" 2194cdf0c1d5Smjnelson usage 2195cdf0c1d5Smjnelson fi 2196cdf0c1d5Smjnelson 2197daaffb31Sdp print -u2 " File list from: wx 'active' file '$wxfile' ... \c" 2198daaffb31Sdp flist_from_wx $wxfile 2199daaffb31Sdp flist_done=1 2200daaffb31Sdp if [[ -n "$*" ]]; then 2201daaffb31Sdp shift 2202daaffb31Sdp fi 220314983201Sdpelif [[ $flist_mode == "stdin" ]]; then 220414983201Sdp print -u2 " File list from: standard input" 220514983201Sdpelif [[ $flist_mode == "file" ]]; then 220614983201Sdp print -u2 " File list from: $flist_file" 2207daaffb31Sdpfi 2208daaffb31Sdp 2209daaffb31Sdpif [[ $# -gt 0 ]]; then 221014983201Sdp print -u2 "WARNING: unused arguments: $*" 2211daaffb31Sdpfi 2212daaffb31Sdp 2213daaffb31Sdpif [[ $SCM_MODE == "teamware" ]]; then 2214daaffb31Sdp # 2215daaffb31Sdp # Parent (internally $codemgr_parent) and workspace ($codemgr_ws) can 2216daaffb31Sdp # be set in a number of ways, in decreasing precedence: 2217daaffb31Sdp # 2218daaffb31Sdp # 1) on the command line (only for the parent) 2219daaffb31Sdp # 2) in the user environment 2220daaffb31Sdp # 3) in the flist 2221daaffb31Sdp # 4) automatically based on the workspace (only for the parent) 2222daaffb31Sdp # 2223daaffb31Sdp 2224daaffb31Sdp # 2225daaffb31Sdp # Here is case (2): the user environment 2226daaffb31Sdp # 2227daaffb31Sdp [[ -z $codemgr_ws && -n $CODEMGR_WS ]] && codemgr_ws=$CODEMGR_WS 2228daaffb31Sdp if [[ -n $codemgr_ws && ! -d $codemgr_ws ]]; then 2229daaffb31Sdp print -u2 "$codemgr_ws: no such workspace" 22307c478bd9Sstevel@tonic-gate exit 1 22317c478bd9Sstevel@tonic-gate fi 22327c478bd9Sstevel@tonic-gate 2233daaffb31Sdp [[ -z $codemgr_parent && -n $CODEMGR_PARENT ]] && \ 2234daaffb31Sdp codemgr_parent=$CODEMGR_PARENT 2235daaffb31Sdp if [[ -n $codemgr_parent && ! -d $codemgr_parent ]]; then 2236daaffb31Sdp print -u2 "$codemgr_parent: no such directory" 22377c478bd9Sstevel@tonic-gate exit 1 22387c478bd9Sstevel@tonic-gate fi 22397c478bd9Sstevel@tonic-gate 2240daaffb31Sdp # 2241daaffb31Sdp # If we're in auto-detect mode and we haven't already gotten the file 2242daaffb31Sdp # list, then see if we can get it by probing for wx. 2243daaffb31Sdp # 224414983201Sdp if [[ -z $flist_done && $flist_mode == "auto" && -n $codemgr_ws ]]; then 224514983201Sdp if [[ ! -x $WX ]]; then 224614983201Sdp print -u2 "WARNING: wx not found!" 2247daaffb31Sdp fi 22487c478bd9Sstevel@tonic-gate 2249daaffb31Sdp # 2250daaffb31Sdp # We need to use wx list -w so that we get renamed files, etc. 2251daaffb31Sdp # but only if a wx active file exists-- otherwise wx will 2252daaffb31Sdp # hang asking us to initialize our wx information. 2253daaffb31Sdp # 225414983201Sdp if [[ -x $WX && -f $codemgr_ws/wx/active ]]; then 2255daaffb31Sdp print -u2 " File list from: 'wx list -w' ... \c" 2256daaffb31Sdp $WX list -w > $FLIST 2257daaffb31Sdp $WX comments > /tmp/$$.wx_comments 2258daaffb31Sdp wxfile=/tmp/$$.wx_comments 2259daaffb31Sdp print -u2 "done" 2260daaffb31Sdp flist_done=1 2261daaffb31Sdp fi 2262daaffb31Sdp fi 2263daaffb31Sdp 2264daaffb31Sdp # 2265daaffb31Sdp # If by hook or by crook we've gotten a file list by now (perhaps 2266daaffb31Sdp # from the command line), eval it to extract environment variables from 2267daaffb31Sdp # it: This is step (3). 2268daaffb31Sdp # 2269daaffb31Sdp env_from_flist 2270daaffb31Sdp 2271daaffb31Sdp # 2272daaffb31Sdp # Continuing step (3): If we still have no file list, we'll try to get 2273daaffb31Sdp # it from teamware. 2274daaffb31Sdp # 2275daaffb31Sdp if [[ -z $flist_done ]]; then 2276daaffb31Sdp flist_from_teamware 2277daaffb31Sdp env_from_flist 2278daaffb31Sdp fi 2279daaffb31Sdp 2280daaffb31Sdp # 2281daaffb31Sdp # (4) If we still don't have a value for codemgr_parent, get it 2282daaffb31Sdp # from workspace. 2283daaffb31Sdp # 2284cdf0c1d5Smjnelson [[ -z $codemgr_ws ]] && codemgr_ws=`workspace name` 2285daaffb31Sdp [[ -z $codemgr_parent ]] && codemgr_parent=`workspace parent` 2286daaffb31Sdp if [[ ! -d $codemgr_parent ]]; then 2287daaffb31Sdp print -u2 "$CODEMGR_PARENT: no such parent workspace" 2288daaffb31Sdp exit 1 2289daaffb31Sdp fi 2290daaffb31Sdp 2291daaffb31Sdp # 2292cdf0c1d5Smjnelson # Observe true directory name of CODEMGR_WS, as used later in 2293cdf0c1d5Smjnelson # webrev title. 2294cdf0c1d5Smjnelson # 2295cdf0c1d5Smjnelson codemgr_ws=$(cd $codemgr_ws;print $PWD) 2296cdf0c1d5Smjnelson 2297cdf0c1d5Smjnelson # 2298daaffb31Sdp # Reset CODEMGR_WS to make sure teamware commands are happy. 2299daaffb31Sdp # 2300daaffb31Sdp CODEMGR_WS=$codemgr_ws 2301daaffb31Sdp CWS=$codemgr_ws 2302daaffb31Sdp PWS=$codemgr_parent 2303cdf0c1d5Smjnelson 2304cdf0c1d5Smjnelson [[ -n $parent_webrev ]] && RWS=$(workspace parent $CWS) 2305cdf0c1d5Smjnelson 2306cdf0c1d5Smjnelsonelif [[ $SCM_MODE == "mercurial" ]]; then 2307cdf0c1d5Smjnelson [[ -z $codemgr_ws && -n $CODEMGR_WS ]] && \ 2308cdf0c1d5Smjnelson codemgr_ws=`hg root -R $CODEMGR_WS 2>/dev/null` 2309cdf0c1d5Smjnelson 2310cdf0c1d5Smjnelson [[ -z $codemgr_ws ]] && codemgr_ws=`hg root 2>/dev/null` 2311cdf0c1d5Smjnelson 2312cdf0c1d5Smjnelson # 2313cdf0c1d5Smjnelson # Parent can either be specified with -p 2314cdf0c1d5Smjnelson # Specified with CODEMGR_PARENT in the environment 2315cdf0c1d5Smjnelson # or taken from hg's default path. 2316cdf0c1d5Smjnelson # 2317cdf0c1d5Smjnelson 2318cdf0c1d5Smjnelson if [[ -z $codemgr_parent && -n $CODEMGR_PARENT ]]; then 2319cdf0c1d5Smjnelson codemgr_parent=$CODEMGR_PARENT 2320cdf0c1d5Smjnelson fi 2321cdf0c1d5Smjnelson 2322cdf0c1d5Smjnelson if [[ -z $codemgr_parent ]]; then 2323cdf0c1d5Smjnelson codemgr_parent=`hg path -R $codemgr_ws default 2>/dev/null` 2324cdf0c1d5Smjnelson fi 2325cdf0c1d5Smjnelson 2326cdf0c1d5Smjnelson CWS_REV=`hg parent -R $codemgr_ws --template '{node|short}' 2>/dev/null` 2327cdf0c1d5Smjnelson CWS=$codemgr_ws 2328cdf0c1d5Smjnelson PWS=$codemgr_parent 2329cdf0c1d5Smjnelson 2330cdf0c1d5Smjnelson # 2331cdf0c1d5Smjnelson # If the parent is a webrev, we want to do some things against 2332cdf0c1d5Smjnelson # the natural workspace parent (file list, comments, etc) 2333cdf0c1d5Smjnelson # 2334cdf0c1d5Smjnelson if [[ -n $parent_webrev ]]; then 2335cdf0c1d5Smjnelson real_parent=$(hg path -R $codemgr_ws default 2>/dev/null) 2336cdf0c1d5Smjnelson else 2337cdf0c1d5Smjnelson real_parent=$PWS 2338cdf0c1d5Smjnelson fi 2339cdf0c1d5Smjnelson 2340cdf0c1d5Smjnelson # 2341cdf0c1d5Smjnelson # If hg-active exists, then we run it. In the case of no explicit 2342cdf0c1d5Smjnelson # flist given, we'll use it for our comments. In the case of an 2343cdf0c1d5Smjnelson # explicit flist given we'll try to use it for comments for any 2344cdf0c1d5Smjnelson # files mentioned in the flist. 2345cdf0c1d5Smjnelson # 2346cdf0c1d5Smjnelson if [[ -z $flist_done ]]; then 2347cdf0c1d5Smjnelson flist_from_mercurial $CWS $real_parent 2348cdf0c1d5Smjnelson flist_done=1 2349cdf0c1d5Smjnelson fi 2350cdf0c1d5Smjnelson 2351cdf0c1d5Smjnelson # 2352cdf0c1d5Smjnelson # If we have a file list now, pull out any variables set 2353cdf0c1d5Smjnelson # therein. We do this now (rather than when we possibly use 2354cdf0c1d5Smjnelson # hg-active to find comments) to avoid stomping specifications 2355cdf0c1d5Smjnelson # in the user-specified flist. 2356cdf0c1d5Smjnelson # 2357cdf0c1d5Smjnelson if [[ -n $flist_done ]]; then 2358cdf0c1d5Smjnelson env_from_flist 2359cdf0c1d5Smjnelson fi 2360cdf0c1d5Smjnelson 2361cdf0c1d5Smjnelson # 2362cdf0c1d5Smjnelson # Only call hg-active if we don't have a wx formatted file already 2363cdf0c1d5Smjnelson # 2364cdf0c1d5Smjnelson if [[ -x $HG_ACTIVE && -z $wxfile ]]; then 2365cdf0c1d5Smjnelson print " Comments from: hg-active -p $real_parent ...\c" 2366cdf0c1d5Smjnelson hg_active_wxfile $CWS $real_parent 2367cdf0c1d5Smjnelson print " Done." 2368cdf0c1d5Smjnelson fi 2369cdf0c1d5Smjnelson 2370cdf0c1d5Smjnelson # 2371cdf0c1d5Smjnelson # At this point we must have a wx flist either from hg-active, 2372cdf0c1d5Smjnelson # or in general. Use it to try and find our parent revision, 2373cdf0c1d5Smjnelson # if we don't have one. 2374cdf0c1d5Smjnelson # 2375cdf0c1d5Smjnelson if [[ -z $HG_PARENT ]]; then 237602d26c39SVladimir Kotal eval `sed -e "s/#.*$//" $wxfile | $GREP HG_PARENT=` 2377cdf0c1d5Smjnelson fi 2378cdf0c1d5Smjnelson 2379cdf0c1d5Smjnelson # 2380cdf0c1d5Smjnelson # If we still don't have a parent, we must have been given a 2381cdf0c1d5Smjnelson # wx-style active list with no HG_PARENT specification, run 2382cdf0c1d5Smjnelson # hg-active and pull an HG_PARENT out of it, ignore the rest. 2383cdf0c1d5Smjnelson # 2384cdf0c1d5Smjnelson if [[ -z $HG_PARENT && -x $HG_ACTIVE ]]; then 2385cdf0c1d5Smjnelson $HG_ACTIVE -w $codemgr_ws -p $real_parent | \ 238602d26c39SVladimir Kotal eval `sed -e "s/#.*$//" | $GREP HG_PARENT=` 2387cdf0c1d5Smjnelson elif [[ -z $HG_PARENT ]]; then 2388cdf0c1d5Smjnelson print -u2 "Error: Cannot discover parent revision" 2389cdf0c1d5Smjnelson exit 1 2390cdf0c1d5Smjnelson fi 2391cdf0c1d5Smjnelsonelif [[ $SCM_MODE == "subversion" ]]; then 2392cdf0c1d5Smjnelson if [[ -n $CODEMGR_WS && -d $CODEMGR_WS/.svn ]]; then 2393cdf0c1d5Smjnelson CWS=$CODEMGR_WS 2394cdf0c1d5Smjnelson else 2395cdf0c1d5Smjnelson svn info | while read line; do 2396cdf0c1d5Smjnelson if [[ $line == "URL: "* ]]; then 2397cdf0c1d5Smjnelson url=${line#URL: } 2398cdf0c1d5Smjnelson elif [[ $line == "Repository Root: "* ]]; then 2399cdf0c1d5Smjnelson repo=${line#Repository Root: } 2400cdf0c1d5Smjnelson fi 2401cdf0c1d5Smjnelson done 2402cdf0c1d5Smjnelson 2403cdf0c1d5Smjnelson rel=${url#$repo} 2404cdf0c1d5Smjnelson CWS=${PWD%$rel} 2405cdf0c1d5Smjnelson fi 2406cdf0c1d5Smjnelson 2407cdf0c1d5Smjnelson # 2408cdf0c1d5Smjnelson # We only will have a real parent workspace in the case one 2409cdf0c1d5Smjnelson # was specified (be it an older webrev, or another checkout). 2410cdf0c1d5Smjnelson # 2411cdf0c1d5Smjnelson [[ -n $codemgr_parent ]] && PWS=$codemgr_parent 2412cdf0c1d5Smjnelson 2413cdf0c1d5Smjnelson if [[ -z $flist_done && $flist_mode == "auto" ]]; then 2414cdf0c1d5Smjnelson flist_from_subversion $CWS $OLDPWD 2415cdf0c1d5Smjnelson fi 2416cdf0c1d5Smjnelsonelse 2417cdf0c1d5Smjnelson if [[ $SCM_MODE == "unknown" ]]; then 2418cdf0c1d5Smjnelson print -u2 " Unknown type of SCM in use" 2419cdf0c1d5Smjnelson else 2420cdf0c1d5Smjnelson print -u2 " Unsupported SCM in use: $SCM_MODE" 2421cdf0c1d5Smjnelson fi 2422cdf0c1d5Smjnelson 2423cdf0c1d5Smjnelson env_from_flist 2424cdf0c1d5Smjnelson 2425cdf0c1d5Smjnelson if [[ -z $CODEMGR_WS ]]; then 2426cdf0c1d5Smjnelson print -u2 "SCM not detected/supported and CODEMGR_WS not specified" 2427cdf0c1d5Smjnelson exit 1 2428cdf0c1d5Smjnelson fi 2429cdf0c1d5Smjnelson 2430cdf0c1d5Smjnelson if [[ -z $CODEMGR_PARENT ]]; then 2431cdf0c1d5Smjnelson print -u2 "SCM not detected/supported and CODEMGR_PARENT not specified" 2432cdf0c1d5Smjnelson exit 1 2433cdf0c1d5Smjnelson fi 2434cdf0c1d5Smjnelson 2435cdf0c1d5Smjnelson CWS=$CODEMGR_WS 2436cdf0c1d5Smjnelson PWS=$CODEMGR_PARENT 2437daaffb31Sdpfi 2438daaffb31Sdp 2439daaffb31Sdp# 2440daaffb31Sdp# If the user didn't specify a -i option, check to see if there is a 2441daaffb31Sdp# webrev-info file in the workspace directory. 2442daaffb31Sdp# 2443daaffb31Sdpif [[ -z $iflag && -r "$CWS/webrev-info" ]]; then 2444daaffb31Sdp iflag=1 2445daaffb31Sdp INCLUDE_FILE="$CWS/webrev-info" 2446daaffb31Sdpfi 2447daaffb31Sdp 2448daaffb31Sdpif [[ -n $iflag ]]; then 2449daaffb31Sdp if [[ ! -r $INCLUDE_FILE ]]; then 2450daaffb31Sdp print -u2 "include file '$INCLUDE_FILE' does not exist or is" \ 2451daaffb31Sdp "not readable." 2452daaffb31Sdp exit 1 2453daaffb31Sdp else 2454daaffb31Sdp # 2455daaffb31Sdp # $INCLUDE_FILE may be a relative path, and the script alters 2456daaffb31Sdp # PWD, so we just stash a copy in /tmp. 2457daaffb31Sdp # 2458daaffb31Sdp cp $INCLUDE_FILE /tmp/$$.include 2459daaffb31Sdp fi 2460daaffb31Sdpfi 2461daaffb31Sdp 2462daaffb31Sdp# 2463daaffb31Sdp# Output directory. 2464daaffb31Sdp# 2465daaffb31SdpWDIR=${WDIR:-$CWS/webrev} 2466daaffb31Sdp 2467daaffb31Sdp# 246802d26c39SVladimir Kotal# Name of the webrev, derived from the workspace name or output directory; 246902d26c39SVladimir Kotal# in the future this could potentially be an option. 2470daaffb31Sdp# 247102d26c39SVladimir Kotalif [[ -n $oflag ]]; then 247202d26c39SVladimir Kotal WNAME=${WDIR##*/} 247302d26c39SVladimir Kotalelse 2474daaffb31Sdp WNAME=${CWS##*/} 247502d26c39SVladimir Kotalfi 247602d26c39SVladimir Kotal 2477ba44d8a2SVladimir Kotal# Make sure remote target is well formed for remote upload/delete. 2478ba44d8a2SVladimir Kotalif [[ -n $Dflag || -n $Uflag ]]; then 2479ba44d8a2SVladimir Kotal # If remote target is not specified, build it from scratch using 2480ba44d8a2SVladimir Kotal # the default values. 2481ba44d8a2SVladimir Kotal if [[ -z $tflag ]]; then 2482ba44d8a2SVladimir Kotal remote_target=${DEFAULT_REMOTE_HOST}:${WNAME} 2483ba44d8a2SVladimir Kotal else 2484ba44d8a2SVladimir Kotal # If destination specification is not in the form of 2485ba44d8a2SVladimir Kotal # host_spec:remote_dir then assume it is just remote hostname 2486ba44d8a2SVladimir Kotal # and append a colon and destination directory formed from 2487ba44d8a2SVladimir Kotal # local webrev directory name. 2488ba44d8a2SVladimir Kotal if [[ -z ${remote_target##*:} ]]; then 2489ba44d8a2SVladimir Kotal if [[ "${remote_target}" == *: ]]; then 2490ba44d8a2SVladimir Kotal dst=${remote_target}${WNAME} 2491ba44d8a2SVladimir Kotal else 2492ba44d8a2SVladimir Kotal dst=${remote_target}:${WNAME} 2493ba44d8a2SVladimir Kotal fi 2494ba44d8a2SVladimir Kotal fi 2495ba44d8a2SVladimir Kotal fi 2496ba44d8a2SVladimir Kotalfi 2497ba44d8a2SVladimir Kotal 2498ba44d8a2SVladimir Kotal# Option -D by itself (option -U not present) implies no webrev generation. 2499ba44d8a2SVladimir Kotalif [[ -z $Uflag && -n $Dflag ]]; then 2500ba44d8a2SVladimir Kotal delete_webrev 1 2501ba44d8a2SVladimir Kotal exit $? 2502ba44d8a2SVladimir Kotalfi 2503ba44d8a2SVladimir Kotal 2504ba44d8a2SVladimir Kotal# Do not generate the webrev, just upload it or delete it. 2505ba44d8a2SVladimir Kotalif [[ -n $nflag ]]; then 2506ba44d8a2SVladimir Kotal if [[ -n $Dflag ]]; then 2507ba44d8a2SVladimir Kotal delete_webrev 1 2508ba44d8a2SVladimir Kotal (( $? == 0 )) || exit $? 2509ba44d8a2SVladimir Kotal fi 2510ba44d8a2SVladimir Kotal if [[ -n $Uflag ]]; then 251102d26c39SVladimir Kotal upload_webrev 251202d26c39SVladimir Kotal exit $? 251302d26c39SVladimir Kotal fi 2514ba44d8a2SVladimir Kotalfi 2515daaffb31Sdp 2516e0e0293aSjmcpif [ "${WDIR%%/*}" ]; then 25177c478bd9Sstevel@tonic-gate WDIR=$PWD/$WDIR 25187c478bd9Sstevel@tonic-gatefi 2519daaffb31Sdp 2520daaffb31Sdpif [[ ! -d $WDIR ]]; then 2521daaffb31Sdp mkdir -p $WDIR 2522ba44d8a2SVladimir Kotal (( $? != 0 )) && exit 1 25237c478bd9Sstevel@tonic-gatefi 25247c478bd9Sstevel@tonic-gate 2525daaffb31Sdp# 2526daaffb31Sdp# Summarize what we're going to do. 2527daaffb31Sdp# 2528cdf0c1d5Smjnelsonif [[ -n $CWS_REV ]]; then 2529cdf0c1d5Smjnelson print " Workspace: $CWS (at $CWS_REV)" 2530cdf0c1d5Smjnelsonelse 2531daaffb31Sdp print " Workspace: $CWS" 2532cdf0c1d5Smjnelsonfi 2533daaffb31Sdpif [[ -n $parent_webrev ]]; then 2534daaffb31Sdp print "Compare against: webrev at $parent_webrev" 2535daaffb31Sdpelse 2536cdf0c1d5Smjnelson if [[ -n $HG_PARENT ]]; then 2537cdf0c1d5Smjnelson hg_parent_short=`echo $HG_PARENT \ 2538cdf0c1d5Smjnelson | sed -e 's/\([0-9a-f]\{12\}\).*/\1/'` 2539cdf0c1d5Smjnelson print "Compare against: $PWS (at $hg_parent_short)" 2540cdf0c1d5Smjnelson else 2541daaffb31Sdp print "Compare against: $PWS" 2542daaffb31Sdp fi 2543cdf0c1d5Smjnelsonfi 2544daaffb31Sdp 2545daaffb31Sdp[[ -n $INCLUDE_FILE ]] && print " Including: $INCLUDE_FILE" 2546daaffb31Sdpprint " Output to: $WDIR" 2547daaffb31Sdp 2548daaffb31Sdp# 25497c478bd9Sstevel@tonic-gate# Save the file list in the webrev dir 2550daaffb31Sdp# 2551daaffb31Sdp[[ ! $FLIST -ef $WDIR/file.list ]] && cp $FLIST $WDIR/file.list 25527c478bd9Sstevel@tonic-gate 2553daaffb31Sdp# 2554daaffb31Sdp# Bug IDs will be replaced by a URL. Order of precedence 2555daaffb31Sdp# is: default location, $WEBREV_BUGURL, the -O flag. 2556daaffb31Sdp# 2557daaffb31SdpBUGURL='http://monaco.sfbay.sun.com/detail.jsp?cr=' 2558daaffb31Sdp[[ -n $WEBREV_BUGURL ]] && BUGURL="$WEBREV_BUGURL" 2559daaffb31Sdp[[ -n "$Oflag" ]] && \ 2560daaffb31Sdp BUGURL='http://bugs.opensolaris.org/bugdatabase/view_bug.do?bug_id=' 25617c478bd9Sstevel@tonic-gate 2562daaffb31Sdp# 2563daaffb31Sdp# Likewise, ARC cases will be replaced by a URL. Order of precedence 2564daaffb31Sdp# is: default, $WEBREV_SACURL, the -O flag. 2565daaffb31Sdp# 2566daaffb31Sdp# Note that -O also triggers different substitution behavior for 2567daaffb31Sdp# SACURL. See sac2url(). 2568daaffb31Sdp# 2569daaffb31SdpSACURL='http://sac.eng.sun.com' 2570daaffb31Sdp[[ -n $WEBREV_SACURL ]] && SACURL="$WEBREV_SACURL" 2571e0e0293aSjmcp[[ -n "$Oflag" ]] && \ 2572daaffb31Sdp SACURL='http://www.opensolaris.org/os/community/arc/caselog' 25737c478bd9Sstevel@tonic-gate 2574daaffb31Sdprm -f $WDIR/$WNAME.patch 2575daaffb31Sdprm -f $WDIR/$WNAME.ps 2576daaffb31Sdprm -f $WDIR/$WNAME.pdf 25777c478bd9Sstevel@tonic-gate 2578daaffb31Sdptouch $WDIR/$WNAME.patch 25797c478bd9Sstevel@tonic-gate 2580daaffb31Sdpprint " Output Files:" 2581daaffb31Sdp 2582daaffb31Sdp# 2583daaffb31Sdp# Clean up the file list: Remove comments, blank lines and env variables. 2584daaffb31Sdp# 2585daaffb31Sdpsed -e "s/#.*$//" -e "/=/d" -e "/^[ ]*$/d" $FLIST > /tmp/$$.flist.clean 2586daaffb31SdpFLIST=/tmp/$$.flist.clean 2587daaffb31Sdp 2588daaffb31Sdp# 2589cdf0c1d5Smjnelson# For Mercurial, create a cache of manifest entries. 2590cdf0c1d5Smjnelson# 2591cdf0c1d5Smjnelsonif [[ $SCM_MODE == "mercurial" ]]; then 2592cdf0c1d5Smjnelson # 2593cdf0c1d5Smjnelson # Transform the FLIST into a temporary sed script that matches 2594cdf0c1d5Smjnelson # relevant entries in the Mercurial manifest as follows: 2595cdf0c1d5Smjnelson # 1) The script will be used against the parent revision manifest, 2596cdf0c1d5Smjnelson # so for FLIST lines that have two filenames (a renamed file) 2597cdf0c1d5Smjnelson # keep only the old name. 2598cdf0c1d5Smjnelson # 2) Escape all forward slashes the filename. 2599cdf0c1d5Smjnelson # 3) Change the filename into another sed command that matches 2600cdf0c1d5Smjnelson # that file in "hg manifest -v" output: start of line, three 2601cdf0c1d5Smjnelson # octal digits for file permissions, space, a file type flag 2602cdf0c1d5Smjnelson # character, space, the filename, end of line. 2603cdf0c1d5Smjnelson # 2604cdf0c1d5Smjnelson SEDFILE=/tmp/$$.manifest.sed 2605cdf0c1d5Smjnelson sed ' 2606cdf0c1d5Smjnelson s#^[^ ]* ## 2607cdf0c1d5Smjnelson s#/#\\\/#g 2608cdf0c1d5Smjnelson s#^.*$#/^... . &$/p# 2609cdf0c1d5Smjnelson ' < $FLIST > $SEDFILE 2610cdf0c1d5Smjnelson 2611cdf0c1d5Smjnelson # 2612cdf0c1d5Smjnelson # Apply the generated script to the output of "hg manifest -v" 2613cdf0c1d5Smjnelson # to get the relevant subset for this webrev. 2614cdf0c1d5Smjnelson # 2615cdf0c1d5Smjnelson HG_PARENT_MANIFEST=/tmp/$$.manifest 2616cdf0c1d5Smjnelson hg -R $CWS manifest -v -r $HG_PARENT | 2617cdf0c1d5Smjnelson sed -n -f $SEDFILE > $HG_PARENT_MANIFEST 2618cdf0c1d5Smjnelsonfi 2619cdf0c1d5Smjnelson 2620cdf0c1d5Smjnelson# 2621daaffb31Sdp# First pass through the files: generate the per-file webrev HTML-files. 2622daaffb31Sdp# 2623daaffb31Sdpcat $FLIST | while read LINE 26247c478bd9Sstevel@tonic-gatedo 26257c478bd9Sstevel@tonic-gate set - $LINE 26267c478bd9Sstevel@tonic-gate P=$1 26277c478bd9Sstevel@tonic-gate 2628daaffb31Sdp # 2629daaffb31Sdp # Normally, each line in the file list is just a pathname of a 2630daaffb31Sdp # file that has been modified or created in the child. A file 2631daaffb31Sdp # that is renamed in the child workspace has two names on the 2632daaffb31Sdp # line: new name followed by the old name. 2633daaffb31Sdp # 2634daaffb31Sdp oldname="" 2635daaffb31Sdp oldpath="" 2636daaffb31Sdp rename= 2637daaffb31Sdp if [[ $# -eq 2 ]]; then 26387c478bd9Sstevel@tonic-gate PP=$2 # old filename 2639daaffb31Sdp oldname=" (was $PP)" 2640daaffb31Sdp oldpath="$PP" 2641daaffb31Sdp rename=1 26427c478bd9Sstevel@tonic-gate PDIR=${PP%/*} 2643daaffb31Sdp if [[ $PDIR == $PP ]]; then 26447c478bd9Sstevel@tonic-gate PDIR="." # File at root of workspace 26457c478bd9Sstevel@tonic-gate fi 26467c478bd9Sstevel@tonic-gate 26477c478bd9Sstevel@tonic-gate PF=${PP##*/} 26487c478bd9Sstevel@tonic-gate 26497c478bd9Sstevel@tonic-gate DIR=${P%/*} 2650daaffb31Sdp if [[ $DIR == $P ]]; then 26517c478bd9Sstevel@tonic-gate DIR="." # File at root of workspace 26527c478bd9Sstevel@tonic-gate fi 26537c478bd9Sstevel@tonic-gate 26547c478bd9Sstevel@tonic-gate F=${P##*/} 2655daaffb31Sdp 26567c478bd9Sstevel@tonic-gate else 26577c478bd9Sstevel@tonic-gate DIR=${P%/*} 2658daaffb31Sdp if [[ "$DIR" == "$P" ]]; then 26597c478bd9Sstevel@tonic-gate DIR="." # File at root of workspace 26607c478bd9Sstevel@tonic-gate fi 26617c478bd9Sstevel@tonic-gate 26627c478bd9Sstevel@tonic-gate F=${P##*/} 26637c478bd9Sstevel@tonic-gate 26647c478bd9Sstevel@tonic-gate PP=$P 26657c478bd9Sstevel@tonic-gate PDIR=$DIR 26667c478bd9Sstevel@tonic-gate PF=$F 26677c478bd9Sstevel@tonic-gate fi 26687c478bd9Sstevel@tonic-gate 2669daaffb31Sdp COMM=`getcomments html $P $PP` 26707c478bd9Sstevel@tonic-gate 2671daaffb31Sdp print "\t$P$oldname\n\t\t\c" 26727c478bd9Sstevel@tonic-gate 26737c478bd9Sstevel@tonic-gate # Make the webrev mirror directory if necessary 26747c478bd9Sstevel@tonic-gate mkdir -p $WDIR/$DIR 26757c478bd9Sstevel@tonic-gate 2676daaffb31Sdp # 2677daaffb31Sdp # If we're in OpenSolaris mode, we enforce a minor policy: 2678daaffb31Sdp # help to make sure the reviewer doesn't accidentally publish 2679e0e0293aSjmcp # source which is in usr/closed/* or deleted_files/usr/closed/* 2680daaffb31Sdp # 2681e0e0293aSjmcp if [[ -n "$Oflag" ]]; then 2682daaffb31Sdp pclosed=${P##usr/closed/} 2683e0e0293aSjmcp pdeleted=${P##deleted_files/usr/closed/} 2684e0e0293aSjmcp if [[ "$pclosed" != "$P" || "$pdeleted" != "$P" ]]; then 2685daaffb31Sdp print "*** Omitting closed source for OpenSolaris" \ 2686daaffb31Sdp "mode review" 2687daaffb31Sdp continue 2688daaffb31Sdp fi 2689daaffb31Sdp fi 2690daaffb31Sdp 2691daaffb31Sdp # 2692cdf0c1d5Smjnelson # We stash old and new files into parallel directories in $WDIR 2693daaffb31Sdp # and do our diffs there. This makes it possible to generate 2694daaffb31Sdp # clean looking diffs which don't have absolute paths present. 2695daaffb31Sdp # 2696daaffb31Sdp 2697cdf0c1d5Smjnelson build_old_new "$WDIR" "$PWS" "$PDIR" "$PF" "$CWS" "$DIR" "$F" || \ 26987c478bd9Sstevel@tonic-gate continue 26997c478bd9Sstevel@tonic-gate 2700cdf0c1d5Smjnelson # 2701cdf0c1d5Smjnelson # Keep the old PWD around, so we can safely switch back after 2702cdf0c1d5Smjnelson # diff generation, such that build_old_new runs in a 2703cdf0c1d5Smjnelson # consistent environment. 2704cdf0c1d5Smjnelson # 2705cdf0c1d5Smjnelson OWD=$PWD 2706daaffb31Sdp cd $WDIR/raw_files 2707daaffb31Sdp ofile=old/$PDIR/$PF 2708daaffb31Sdp nfile=new/$DIR/$F 27097c478bd9Sstevel@tonic-gate 2710daaffb31Sdp mv_but_nodiff= 2711daaffb31Sdp cmp $ofile $nfile > /dev/null 2>&1 2712daaffb31Sdp if [[ $? == 0 && $rename == 1 ]]; then 2713daaffb31Sdp mv_but_nodiff=1 2714daaffb31Sdp fi 2715daaffb31Sdp 2716daaffb31Sdp # 2717daaffb31Sdp # If we have old and new versions of the file then run the appropriate 2718daaffb31Sdp # diffs. This is complicated by a couple of factors: 2719daaffb31Sdp # 2720daaffb31Sdp # - renames must be handled specially: we emit a 'remove' 2721daaffb31Sdp # diff and an 'add' diff 2722daaffb31Sdp # - new files and deleted files must be handled specially 2723daaffb31Sdp # - Solaris patch(1m) can't cope with file creation 2724daaffb31Sdp # (and hence renames) as of this writing. 2725daaffb31Sdp # - To make matters worse, gnu patch doesn't interpret the 2726daaffb31Sdp # output of Solaris diff properly when it comes to 2727daaffb31Sdp # adds and deletes. We need to do some "cleansing" 2728daaffb31Sdp # transformations: 2729daaffb31Sdp # [to add a file] @@ -1,0 +X,Y @@ --> @@ -0,0 +X,Y @@ 2730daaffb31Sdp # [to del a file] @@ -X,Y +1,0 @@ --> @@ -X,Y +0,0 @@ 2731daaffb31Sdp # 2732daaffb31Sdp cleanse_rmfile="sed 's/^\(@@ [0-9+,-]*\) [0-9+,-]* @@$/\1 +0,0 @@/'" 2733daaffb31Sdp cleanse_newfile="sed 's/^@@ [0-9+,-]* \([0-9+,-]* @@\)$/@@ -0,0 \1/'" 2734daaffb31Sdp 2735daaffb31Sdp rm -f $WDIR/$DIR/$F.patch 2736daaffb31Sdp if [[ -z $rename ]]; then 2737e0e0293aSjmcp if [ ! -f "$ofile" ]; then 2738daaffb31Sdp diff -u /dev/null $nfile | sh -c "$cleanse_newfile" \ 2739daaffb31Sdp > $WDIR/$DIR/$F.patch 2740e0e0293aSjmcp elif [ ! -f "$nfile" ]; then 2741daaffb31Sdp diff -u $ofile /dev/null | sh -c "$cleanse_rmfile" \ 2742daaffb31Sdp > $WDIR/$DIR/$F.patch 2743daaffb31Sdp else 2744daaffb31Sdp diff -u $ofile $nfile > $WDIR/$DIR/$F.patch 2745daaffb31Sdp fi 2746daaffb31Sdp else 2747daaffb31Sdp diff -u $ofile /dev/null | sh -c "$cleanse_rmfile" \ 2748daaffb31Sdp > $WDIR/$DIR/$F.patch 2749daaffb31Sdp 2750daaffb31Sdp diff -u /dev/null $nfile | sh -c "$cleanse_newfile" \ 2751daaffb31Sdp >> $WDIR/$DIR/$F.patch 2752daaffb31Sdp 2753daaffb31Sdp fi 2754daaffb31Sdp 2755daaffb31Sdp # 2756daaffb31Sdp # Tack the patch we just made onto the accumulated patch for the 2757daaffb31Sdp # whole wad. 2758daaffb31Sdp # 2759daaffb31Sdp cat $WDIR/$DIR/$F.patch >> $WDIR/$WNAME.patch 2760daaffb31Sdp 2761daaffb31Sdp print " patch\c" 2762daaffb31Sdp 2763daaffb31Sdp if [[ -f $ofile && -f $nfile && -z $mv_but_nodiff ]]; then 2764daaffb31Sdp 2765daaffb31Sdp ${CDIFFCMD:-diff -bt -C 5} $ofile $nfile > $WDIR/$DIR/$F.cdiff 2766daaffb31Sdp diff_to_html $F $DIR/$F "C" "$COMM" < $WDIR/$DIR/$F.cdiff \ 2767daaffb31Sdp > $WDIR/$DIR/$F.cdiff.html 27687c478bd9Sstevel@tonic-gate print " cdiffs\c" 27697c478bd9Sstevel@tonic-gate 2770daaffb31Sdp ${UDIFFCMD:-diff -bt -U 5} $ofile $nfile > $WDIR/$DIR/$F.udiff 2771daaffb31Sdp diff_to_html $F $DIR/$F "U" "$COMM" < $WDIR/$DIR/$F.udiff \ 2772daaffb31Sdp > $WDIR/$DIR/$F.udiff.html 2773daaffb31Sdp 27747c478bd9Sstevel@tonic-gate print " udiffs\c" 27757c478bd9Sstevel@tonic-gate 27767c478bd9Sstevel@tonic-gate if [[ -x $WDIFF ]]; then 2777daaffb31Sdp $WDIFF -c "$COMM" \ 2778daaffb31Sdp -t "$WNAME Wdiff $DIR/$F" $ofile $nfile > \ 2779daaffb31Sdp $WDIR/$DIR/$F.wdiff.html 2>/dev/null 2780daaffb31Sdp if [[ $? -eq 0 ]]; then 27817c478bd9Sstevel@tonic-gate print " wdiffs\c" 2782daaffb31Sdp else 2783daaffb31Sdp print " wdiffs[fail]\c" 2784daaffb31Sdp fi 27857c478bd9Sstevel@tonic-gate fi 27867c478bd9Sstevel@tonic-gate 2787daaffb31Sdp sdiff_to_html $ofile $nfile $F $DIR "$COMM" \ 2788daaffb31Sdp > $WDIR/$DIR/$F.sdiff.html 27897c478bd9Sstevel@tonic-gate print " sdiffs\c" 27907c478bd9Sstevel@tonic-gate 27917c478bd9Sstevel@tonic-gate print " frames\c" 27927c478bd9Sstevel@tonic-gate 27937c478bd9Sstevel@tonic-gate rm -f $WDIR/$DIR/$F.cdiff $WDIR/$DIR/$F.udiff 27947c478bd9Sstevel@tonic-gate 2795daaffb31Sdp difflines $ofile $nfile > $WDIR/$DIR/$F.count 2796daaffb31Sdp 2797daaffb31Sdp elif [[ -f $ofile && -f $nfile && -n $mv_but_nodiff ]]; then 2798daaffb31Sdp # renamed file: may also have differences 2799daaffb31Sdp difflines $ofile $nfile > $WDIR/$DIR/$F.count 2800daaffb31Sdp elif [[ -f $nfile ]]; then 28017c478bd9Sstevel@tonic-gate # new file: count added lines 2802daaffb31Sdp difflines /dev/null $nfile > $WDIR/$DIR/$F.count 2803daaffb31Sdp elif [[ -f $ofile ]]; then 28047c478bd9Sstevel@tonic-gate # old file: count deleted lines 2805daaffb31Sdp difflines $ofile /dev/null > $WDIR/$DIR/$F.count 28067c478bd9Sstevel@tonic-gate fi 28077c478bd9Sstevel@tonic-gate 2808daaffb31Sdp # 2809daaffb31Sdp # Now we generate the postscript for this file. We generate diffs 2810daaffb31Sdp # only in the event that there is delta, or the file is new (it seems 2811daaffb31Sdp # tree-killing to print out the contents of deleted files). 2812daaffb31Sdp # 2813daaffb31Sdp if [[ -f $nfile ]]; then 2814daaffb31Sdp ocr=$ofile 2815daaffb31Sdp [[ ! -f $ofile ]] && ocr=/dev/null 2816daaffb31Sdp 2817daaffb31Sdp if [[ -z $mv_but_nodiff ]]; then 2818daaffb31Sdp textcomm=`getcomments text $P $PP` 281914983201Sdp if [[ -x $CODEREVIEW ]]; then 282014983201Sdp $CODEREVIEW -y "$textcomm" \ 282114983201Sdp -e $ocr $nfile \ 282214983201Sdp > /tmp/$$.psfile 2>/dev/null && 282314983201Sdp cat /tmp/$$.psfile >> $WDIR/$WNAME.ps 2824daaffb31Sdp if [[ $? -eq 0 ]]; then 2825daaffb31Sdp print " ps\c" 2826daaffb31Sdp else 2827daaffb31Sdp print " ps[fail]\c" 2828daaffb31Sdp fi 2829daaffb31Sdp fi 2830daaffb31Sdp fi 283114983201Sdp fi 2832daaffb31Sdp 2833cdf0c1d5Smjnelson if [[ -f $ofile ]]; then 2834cdf0c1d5Smjnelson source_to_html Old $PP < $ofile > $WDIR/$DIR/$F-.html 28357c478bd9Sstevel@tonic-gate print " old\c" 28367c478bd9Sstevel@tonic-gate fi 28377c478bd9Sstevel@tonic-gate 2838daaffb31Sdp if [[ -f $nfile ]]; then 2839daaffb31Sdp source_to_html New $P < $nfile > $WDIR/$DIR/$F.html 28407c478bd9Sstevel@tonic-gate print " new\c" 28417c478bd9Sstevel@tonic-gate fi 28427c478bd9Sstevel@tonic-gate 2843cdf0c1d5Smjnelson cd $OWD 2844cdf0c1d5Smjnelson 2845daaffb31Sdp print 28467c478bd9Sstevel@tonic-gatedone 28477c478bd9Sstevel@tonic-gate 2848daaffb31Sdpframe_nav_js > $WDIR/ancnav.js 28497c478bd9Sstevel@tonic-gateframe_navigation > $WDIR/ancnav.html 2850daaffb31Sdp 285114983201Sdpif [[ ! -f $WDIR/$WNAME.ps ]]; then 285214983201Sdp print " Generating PDF: Skipped: no output available" 285314983201Sdpelif [[ -x $CODEREVIEW && -x $PS2PDF ]]; then 285414983201Sdp print " Generating PDF: \c" 285514983201Sdp fix_postscript $WDIR/$WNAME.ps | $PS2PDF - > $WDIR/$WNAME.pdf 2856daaffb31Sdp print "Done." 285714983201Sdpelse 285814983201Sdp print " Generating PDF: Skipped: missing 'ps2pdf' or 'codereview'" 285914983201Sdpfi 28607c478bd9Sstevel@tonic-gate 2861e0e0293aSjmcp# If we're in OpenSolaris mode and there's a closed dir under $WDIR, 2862e0e0293aSjmcp# delete it - prevent accidental publishing of closed source 2863e0e0293aSjmcp 2864e0e0293aSjmcpif [[ -n "$Oflag" ]]; then 2865ba44d8a2SVladimir Kotal $FIND $WDIR -type d -name closed -exec /bin/rm -rf {} \; 2866e0e0293aSjmcpfi 2867e0e0293aSjmcp 28687c478bd9Sstevel@tonic-gate# Now build the index.html file that contains 28697c478bd9Sstevel@tonic-gate# links to the source files and their diffs. 28707c478bd9Sstevel@tonic-gate 28717c478bd9Sstevel@tonic-gatecd $CWS 28727c478bd9Sstevel@tonic-gate 28737c478bd9Sstevel@tonic-gate# Save total changed lines for Code Inspection. 2874daaffb31Sdpprint "$TOTL" > $WDIR/TotalChangedLines 28757c478bd9Sstevel@tonic-gate 2876daaffb31Sdpprint " index.html: \c" 28777c478bd9Sstevel@tonic-gateINDEXFILE=$WDIR/index.html 28787c478bd9Sstevel@tonic-gateexec 3<&1 # duplicate stdout to FD3. 28797c478bd9Sstevel@tonic-gateexec 1<&- # Close stdout. 28807c478bd9Sstevel@tonic-gateexec > $INDEXFILE # Open stdout to index file. 28817c478bd9Sstevel@tonic-gate 2882daaffb31Sdpprint "$HTML<head>$STDHEAD" 2883daaffb31Sdpprint "<title>$WNAME</title>" 2884daaffb31Sdpprint "</head>" 2885daaffb31Sdpprint "<body id=\"SUNWwebrev\">" 2886daaffb31Sdpprint "<div class=\"summary\">" 2887daaffb31Sdpprint "<h2>Code Review for $WNAME</h2>" 28887c478bd9Sstevel@tonic-gate 2889daaffb31Sdpprint "<table>" 28907c478bd9Sstevel@tonic-gate 2891daaffb31Sdp# 2892cdf0c1d5Smjnelson# Get the preparer's name: 2893daaffb31Sdp# 2894cdf0c1d5Smjnelson# If the SCM detected is Mercurial, and the configuration property 2895cdf0c1d5Smjnelson# ui.username is available, use that, but be careful to properly escape 2896cdf0c1d5Smjnelson# angle brackets (HTML syntax characters) in the email address. 2897cdf0c1d5Smjnelson# 2898cdf0c1d5Smjnelson# Otherwise, use the current userid in the form "John Doe (jdoe)", but 2899cdf0c1d5Smjnelson# to maintain compatibility with passwd(4), we must support '&' substitutions. 2900cdf0c1d5Smjnelson# 2901cdf0c1d5Smjnelsonpreparer= 2902cdf0c1d5Smjnelsonif [[ "$SCM_MODE" == mercurial ]]; then 2903cdf0c1d5Smjnelson preparer=`hg showconfig ui.username 2>/dev/null` 2904cdf0c1d5Smjnelson if [[ -n "$preparer" ]]; then 2905cdf0c1d5Smjnelson preparer="$(echo "$preparer" | html_quote)" 2906cdf0c1d5Smjnelson fi 2907cdf0c1d5Smjnelsonfi 2908cdf0c1d5Smjnelsonif [[ -z "$preparer" ]]; then 2909cdf0c1d5Smjnelson preparer=$( 2910cdf0c1d5Smjnelson $PERL -e ' 2911cdf0c1d5Smjnelson ($login, $pw, $uid, $gid, $quota, $cmt, $gcos) = getpwuid($<); 2912cdf0c1d5Smjnelson if ($login) { 2913cdf0c1d5Smjnelson $gcos =~ s/\&/ucfirst($login)/e; 2914cdf0c1d5Smjnelson printf "%s (%s)\n", $gcos, $login; 2915cdf0c1d5Smjnelson } else { 2916cdf0c1d5Smjnelson printf "(unknown)\n"; 2917cdf0c1d5Smjnelson } 2918cdf0c1d5Smjnelson ') 2919daaffb31Sdpfi 2920daaffb31Sdp 2921cdf0c1d5Smjnelsonprint "<tr><th>Prepared by:</th><td>$preparer on `date`</td></tr>" 2922cdf0c1d5Smjnelsonprint "<tr><th>Workspace:</th><td>$CWS" 2923cdf0c1d5Smjnelsonif [[ -n $CWS_REV ]]; then 2924cdf0c1d5Smjnelson print "(at $CWS_REV)" 2925cdf0c1d5Smjnelsonfi 2926cdf0c1d5Smjnelsonprint "</td></tr>" 2927daaffb31Sdpprint "<tr><th>Compare against:</th><td>" 2928daaffb31Sdpif [[ -n $parent_webrev ]]; then 2929daaffb31Sdp print "webrev at $parent_webrev" 2930daaffb31Sdpelse 2931daaffb31Sdp print "$PWS" 2932cdf0c1d5Smjnelson if [[ -n $hg_parent_short ]]; then 2933cdf0c1d5Smjnelson print "(at $hg_parent_short)" 2934cdf0c1d5Smjnelson fi 2935daaffb31Sdpfi 2936daaffb31Sdpprint "</td></tr>" 2937daaffb31Sdpprint "<tr><th>Summary of changes:</th><td>" 2938daaffb31SdpprintCI $TOTL $TINS $TDEL $TMOD $TUNC 2939daaffb31Sdpprint "</td></tr>" 2940daaffb31Sdp 2941daaffb31Sdpif [[ -f $WDIR/$WNAME.patch ]]; then 2942*371d72daSLubomir Sedlacik wpatch_url="$(print $WNAME.patch | url_encode)" 2943daaffb31Sdp print "<tr><th>Patch of changes:</th><td>" 2944*371d72daSLubomir Sedlacik print "<a href=\"$wpatch_url\">$WNAME.patch</a></td></tr>" 2945daaffb31Sdpfi 2946daaffb31Sdpif [[ -f $WDIR/$WNAME.pdf ]]; then 2947*371d72daSLubomir Sedlacik wpdf_url="$(print $WNAME.pdf | url_encode)" 2948daaffb31Sdp print "<tr><th>Printable review:</th><td>" 2949*371d72daSLubomir Sedlacik print "<a href=\"$wpdf_url\">$WNAME.pdf</a></td></tr>" 2950daaffb31Sdpfi 2951daaffb31Sdp 2952daaffb31Sdpif [[ -n "$iflag" ]]; then 2953daaffb31Sdp print "<tr><th>Author comments:</th><td><div>" 2954daaffb31Sdp cat /tmp/$$.include 2955daaffb31Sdp print "</div></td></tr>" 2956daaffb31Sdpfi 2957daaffb31Sdpprint "</table>" 2958daaffb31Sdpprint "</div>" 2959daaffb31Sdp 2960daaffb31Sdp# 2961daaffb31Sdp# Second pass through the files: generate the rest of the index file 2962daaffb31Sdp# 2963daaffb31Sdpcat $FLIST | while read LINE 29647c478bd9Sstevel@tonic-gatedo 29657c478bd9Sstevel@tonic-gate set - $LINE 29667c478bd9Sstevel@tonic-gate P=$1 29677c478bd9Sstevel@tonic-gate 2968daaffb31Sdp if [[ $# == 2 ]]; then 29697c478bd9Sstevel@tonic-gate PP=$2 2970cdf0c1d5Smjnelson oldname="$PP" 29717c478bd9Sstevel@tonic-gate else 29727c478bd9Sstevel@tonic-gate PP=$P 2973daaffb31Sdp oldname="" 2974daaffb31Sdp fi 2975daaffb31Sdp 2976cdf0c1d5Smjnelson mv_but_nodiff= 2977cdf0c1d5Smjnelson cmp $WDIR/raw_files/old/$PP $WDIR/raw_files/new/$P > /dev/null 2>&1 2978cdf0c1d5Smjnelson if [[ $? == 0 && -n "$oldname" ]]; then 2979cdf0c1d5Smjnelson mv_but_nodiff=1 2980cdf0c1d5Smjnelson fi 2981cdf0c1d5Smjnelson 2982daaffb31Sdp DIR=${P%/*} 2983daaffb31Sdp if [[ $DIR == $P ]]; then 2984daaffb31Sdp DIR="." # File at root of workspace 29857c478bd9Sstevel@tonic-gate fi 29867c478bd9Sstevel@tonic-gate 29877c478bd9Sstevel@tonic-gate # Avoid processing the same file twice. 29887c478bd9Sstevel@tonic-gate # It's possible for renamed files to 29897c478bd9Sstevel@tonic-gate # appear twice in the file list 29907c478bd9Sstevel@tonic-gate 29917c478bd9Sstevel@tonic-gate F=$WDIR/$P 29927c478bd9Sstevel@tonic-gate 2993daaffb31Sdp print "<p>" 29947c478bd9Sstevel@tonic-gate 29957c478bd9Sstevel@tonic-gate # If there's a diffs file, make diffs links 29967c478bd9Sstevel@tonic-gate 2997daaffb31Sdp if [[ -f $F.cdiff.html ]]; then 2998*371d72daSLubomir Sedlacik cdiff_url="$(print $P.cdiff.html | url_encode)" 2999*371d72daSLubomir Sedlacik udiff_url="$(print $P.udiff.html | url_encode)" 3000*371d72daSLubomir Sedlacik print "<a href=\"$cdiff_url\">Cdiffs</a>" 3001*371d72daSLubomir Sedlacik print "<a href=\"$udiff_url\">Udiffs</a>" 30027c478bd9Sstevel@tonic-gate 3003daaffb31Sdp if [[ -f $F.wdiff.html && -x $WDIFF ]]; then 3004*371d72daSLubomir Sedlacik wdiff_url="$(print $P.wdiff.html | url_encode)" 3005*371d72daSLubomir Sedlacik print "<a href=\"$wdiff_url\">Wdiffs</a>" 30067c478bd9Sstevel@tonic-gate fi 30077c478bd9Sstevel@tonic-gate 3008*371d72daSLubomir Sedlacik sdiff_url="$(print $P.sdiff.html | url_encode)" 3009*371d72daSLubomir Sedlacik print "<a href=\"$sdiff_url\">Sdiffs</a>" 30107c478bd9Sstevel@tonic-gate 3011*371d72daSLubomir Sedlacik frames_url="$(print $P.frames.html | url_encode)" 3012*371d72daSLubomir Sedlacik print "<a href=\"$frames_url\">Frames</a>" 30137c478bd9Sstevel@tonic-gate else 3014daaffb31Sdp print " ------ ------ ------" 30157c478bd9Sstevel@tonic-gate 3016daaffb31Sdp if [[ -x $WDIFF ]]; then 30177c478bd9Sstevel@tonic-gate print " ------" 30187c478bd9Sstevel@tonic-gate fi 3019daaffb31Sdp 3020daaffb31Sdp print " ------" 30217c478bd9Sstevel@tonic-gate fi 30227c478bd9Sstevel@tonic-gate 30237c478bd9Sstevel@tonic-gate # If there's an old file, make the link 30247c478bd9Sstevel@tonic-gate 3025daaffb31Sdp if [[ -f $F-.html ]]; then 3026*371d72daSLubomir Sedlacik oldfile_url="$(print $P-.html | url_encode)" 3027*371d72daSLubomir Sedlacik print "<a href=\"$oldfile_url\">Old</a>" 30287c478bd9Sstevel@tonic-gate else 3029daaffb31Sdp print " ---" 30307c478bd9Sstevel@tonic-gate fi 30317c478bd9Sstevel@tonic-gate 30327c478bd9Sstevel@tonic-gate # If there's an new file, make the link 30337c478bd9Sstevel@tonic-gate 3034daaffb31Sdp if [[ -f $F.html ]]; then 3035*371d72daSLubomir Sedlacik newfile_url="$(print $P.html | url_encode)" 3036*371d72daSLubomir Sedlacik print "<a href=\"$newfile_url\">New</a>" 30377c478bd9Sstevel@tonic-gate else 3038daaffb31Sdp print " ---" 30397c478bd9Sstevel@tonic-gate fi 30407c478bd9Sstevel@tonic-gate 3041daaffb31Sdp if [[ -f $F.patch ]]; then 3042*371d72daSLubomir Sedlacik patch_url="$(print $P.patch | url_encode)" 3043*371d72daSLubomir Sedlacik print "<a href=\"$patch_url\">Patch</a>" 3044daaffb31Sdp else 3045daaffb31Sdp print " -----" 3046daaffb31Sdp fi 3047daaffb31Sdp 3048daaffb31Sdp if [[ -f $WDIR/raw_files/new/$P ]]; then 3049*371d72daSLubomir Sedlacik rawfiles_url="$(print raw_files/new/$P | url_encode)" 3050*371d72daSLubomir Sedlacik print "<a href=\"$rawfiles_url\">Raw</a>" 3051daaffb31Sdp else 3052daaffb31Sdp print " ---" 3053daaffb31Sdp fi 3054daaffb31Sdp 3055cdf0c1d5Smjnelson print "<b>$P</b>" 3056cdf0c1d5Smjnelson 3057cdf0c1d5Smjnelson # For renamed files, clearly state whether or not they are modified 3058cdf0c1d5Smjnelson if [[ -n "$oldname" ]]; then 3059cdf0c1d5Smjnelson if [[ -n "$mv_but_nodiff" ]]; then 3060cdf0c1d5Smjnelson print "<i>(renamed only, was $oldname)</i>" 3061cdf0c1d5Smjnelson else 3062cdf0c1d5Smjnelson print "<i>(modified and renamed, was $oldname)</i>" 3063cdf0c1d5Smjnelson fi 3064cdf0c1d5Smjnelson fi 3065cdf0c1d5Smjnelson 3066cdf0c1d5Smjnelson # If there's an old file, but no new file, the file was deleted 3067cdf0c1d5Smjnelson if [[ -f $F-.html && ! -f $F.html ]]; then 3068cdf0c1d5Smjnelson print " <i>(deleted)</i>" 3069cdf0c1d5Smjnelson fi 3070daaffb31Sdp 3071daaffb31Sdp # 3072e0e0293aSjmcp # Check for usr/closed and deleted_files/usr/closed 3073daaffb31Sdp # 3074daaffb31Sdp if [ ! -z "$Oflag" ]; then 3075e0e0293aSjmcp if [[ $P == usr/closed/* || \ 3076e0e0293aSjmcp $P == deleted_files/usr/closed/* ]]; then 3077daaffb31Sdp print " <i>Closed source: omitted from" \ 3078daaffb31Sdp "this review</i>" 3079daaffb31Sdp fi 3080daaffb31Sdp fi 3081daaffb31Sdp 3082daaffb31Sdp print "</p>" 30837c478bd9Sstevel@tonic-gate # Insert delta comments 30847c478bd9Sstevel@tonic-gate 3085daaffb31Sdp print "<blockquote><pre>" 3086daaffb31Sdp getcomments html $P $PP 3087daaffb31Sdp print "</pre>" 30887c478bd9Sstevel@tonic-gate 30897c478bd9Sstevel@tonic-gate # Add additional comments comment 30907c478bd9Sstevel@tonic-gate 3091daaffb31Sdp print "<!-- Add comments to explain changes in $P here -->" 30927c478bd9Sstevel@tonic-gate 30937c478bd9Sstevel@tonic-gate # Add count of changes. 30947c478bd9Sstevel@tonic-gate 3095daaffb31Sdp if [[ -f $F.count ]]; then 30967c478bd9Sstevel@tonic-gate cat $F.count 30977c478bd9Sstevel@tonic-gate rm $F.count 30987c478bd9Sstevel@tonic-gate fi 3099cdf0c1d5Smjnelson 3100cdf0c1d5Smjnelson if [[ $SCM_MODE == "teamware" || 3101cdf0c1d5Smjnelson $SCM_MODE == "mercurial" || 3102cdf0c1d5Smjnelson $SCM_MODE == "unknown" ]]; then 3103cdf0c1d5Smjnelson 3104cdf0c1d5Smjnelson # Include warnings for important file mode situations: 3105cdf0c1d5Smjnelson # 1) New executable files 3106cdf0c1d5Smjnelson # 2) Permission changes of any kind 3107cdf0c1d5Smjnelson # 3) Existing executable files 3108cdf0c1d5Smjnelson 3109cdf0c1d5Smjnelson old_mode= 3110cdf0c1d5Smjnelson if [[ -f $WDIR/raw_files/old/$PP ]]; then 3111cdf0c1d5Smjnelson old_mode=`get_file_mode $WDIR/raw_files/old/$PP` 3112cdf0c1d5Smjnelson fi 3113cdf0c1d5Smjnelson 3114cdf0c1d5Smjnelson new_mode= 3115cdf0c1d5Smjnelson if [[ -f $WDIR/raw_files/new/$P ]]; then 3116cdf0c1d5Smjnelson new_mode=`get_file_mode $WDIR/raw_files/new/$P` 3117cdf0c1d5Smjnelson fi 3118cdf0c1d5Smjnelson 3119cdf0c1d5Smjnelson if [[ -z "$old_mode" && "$new_mode" = *[1357]* ]]; then 3120cdf0c1d5Smjnelson print "<span class=\"chmod\">" 3121cdf0c1d5Smjnelson print "<p>new executable file: mode $new_mode</p>" 3122cdf0c1d5Smjnelson print "</span>" 3123cdf0c1d5Smjnelson elif [[ -n "$old_mode" && -n "$new_mode" && 3124cdf0c1d5Smjnelson "$old_mode" != "$new_mode" ]]; then 3125cdf0c1d5Smjnelson print "<span class=\"chmod\">" 3126cdf0c1d5Smjnelson print "<p>mode change: $old_mode to $new_mode</p>" 3127cdf0c1d5Smjnelson print "</span>" 3128cdf0c1d5Smjnelson elif [[ "$new_mode" = *[1357]* ]]; then 3129cdf0c1d5Smjnelson print "<span class=\"chmod\">" 3130cdf0c1d5Smjnelson print "<p>executable file: mode $new_mode</p>" 3131cdf0c1d5Smjnelson print "</span>" 3132cdf0c1d5Smjnelson fi 3133cdf0c1d5Smjnelson fi 3134cdf0c1d5Smjnelson 3135daaffb31Sdp print "</blockquote>" 31367c478bd9Sstevel@tonic-gatedone 31377c478bd9Sstevel@tonic-gate 3138daaffb31Sdpprint 3139daaffb31Sdpprint 3140cac38512Smjnelsonprint "<hr></hr>" 3141daaffb31Sdpprint "<p style=\"font-size: small\">" 31429a70fc3bSMark J. Nelsonprint "This code review page was prepared using <b>$0</b>." 3143daaffb31Sdpprint "Webrev is maintained by the <a href=\"http://www.opensolaris.org\">" 3144daaffb31Sdpprint "OpenSolaris</a> project. The latest version may be obtained" 3145e9e2cfb2Sfr80241print "<a href=\"http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/tools/scripts/webrev.sh\">here</a>.</p>" 3146daaffb31Sdpprint "</body>" 3147daaffb31Sdpprint "</html>" 31487c478bd9Sstevel@tonic-gate 31497c478bd9Sstevel@tonic-gateexec 1<&- # Close FD 1. 31507c478bd9Sstevel@tonic-gateexec 1<&3 # dup FD 3 to restore stdout. 31517c478bd9Sstevel@tonic-gateexec 3<&- # close FD 3. 31527c478bd9Sstevel@tonic-gate 3153daaffb31Sdpprint "Done." 315402d26c39SVladimir Kotal 3155ba44d8a2SVladimir Kotal# If remote deletion was specified and fails do not continue. 3156ba44d8a2SVladimir Kotalif [[ -n $Dflag ]]; then 3157ba44d8a2SVladimir Kotal delete_webrev 1 3158ba44d8a2SVladimir Kotal (( $? == 0 )) || exit $? 3159ba44d8a2SVladimir Kotalfi 3160ba44d8a2SVladimir Kotal 316102d26c39SVladimir Kotalif [[ -n $Uflag ]]; then 316202d26c39SVladimir Kotal upload_webrev 316302d26c39SVladimir Kotal exit $? 316402d26c39SVladimir Kotalfi 3165