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# 24cac38512Smjnelson# Copyright 2008 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. 145*ba44d8a2SVladimir 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 153*ba44d8a2SVladimir 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. 168*ba44d8a2SVladimir Kotalfunction ssh_upload 16902d26c39SVladimir Kotal{ 17002d26c39SVladimir Kotal if (( $# != 1 )); then 171*ba44d8a2SVladimir 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%%:*} 177*ba44d8a2SVladimir Kotal typeset -r dir_spec=${dst#*:} 17802d26c39SVladimir Kotal 179*ba44d8a2SVladimir Kotal # if the deletion was explicitly requested there is no need 180*ba44d8a2SVladimir Kotal # to perform it again 181*ba44d8a2SVladimir 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 184*ba44d8a2SVladimir 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 191*ba44d8a2SVladimir 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 216*ba44d8a2SVladimir 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# 230*ba44d8a2SVladimir Kotal# Delete webrev at remote site. Return 0 on success, 1 or exit code from sftp 231*ba44d8a2SVladimir Kotal# on failure. 232*ba44d8a2SVladimir Kotal# 233*ba44d8a2SVladimir Kotalfunction delete_webrev 234*ba44d8a2SVladimir Kotal{ 235*ba44d8a2SVladimir Kotal if (( $# != 1 )); then 236*ba44d8a2SVladimir Kotal print "delete_webrev: wrong usage" 237*ba44d8a2SVladimir Kotal return 1 238*ba44d8a2SVladimir Kotal fi 239*ba44d8a2SVladimir Kotal 240*ba44d8a2SVladimir Kotal # Strip the transport specification part of remote target first. 241*ba44d8a2SVladimir Kotal typeset -r stripped_target=${remote_target##*://} 242*ba44d8a2SVladimir Kotal typeset -r host_spec=${stripped_target%%:*} 243*ba44d8a2SVladimir Kotal typeset -r dir_spec=${stripped_target#*:} 244*ba44d8a2SVladimir Kotal integer -r check=$1 245*ba44d8a2SVladimir Kotal typeset dir_rm 246*ba44d8a2SVladimir Kotal 247*ba44d8a2SVladimir Kotal # Do not accept an absolute path. 248*ba44d8a2SVladimir Kotal if [[ ${dir_spec} == /* ]]; then 249*ba44d8a2SVladimir Kotal return 1 250*ba44d8a2SVladimir Kotal fi 251*ba44d8a2SVladimir Kotal 252*ba44d8a2SVladimir Kotal # Strip the ending slash. 253*ba44d8a2SVladimir Kotal if [[ ${dir_spec} == */ ]]; then 254*ba44d8a2SVladimir Kotal dir_rm=${dir_spec%%/} 255*ba44d8a2SVladimir Kotal else 256*ba44d8a2SVladimir Kotal dir_rm=${dir_spec} 257*ba44d8a2SVladimir Kotal fi 258*ba44d8a2SVladimir Kotal 259*ba44d8a2SVladimir Kotal print "Removing remote: \c" 260*ba44d8a2SVladimir Kotal if [[ -z "$dir_rm" ]]; then 261*ba44d8a2SVladimir Kotal print "empty directory for removal" 262*ba44d8a2SVladimir Kotal return 1 263*ba44d8a2SVladimir Kotal fi 264*ba44d8a2SVladimir Kotal 265*ba44d8a2SVladimir Kotal # Prepare batch file. 266*ba44d8a2SVladimir Kotal typeset -r batch_file_rm=$( $MKTEMP /tmp/webrev_remove.XXX ) 267*ba44d8a2SVladimir Kotal if [[ -z $batch_file_rm ]]; then 268*ba44d8a2SVladimir Kotal print "Cannot create temporary file" 269*ba44d8a2SVladimir Kotal return 1 270*ba44d8a2SVladimir Kotal fi 271*ba44d8a2SVladimir Kotal print "rename $dir_rm $TRASH_DIR/removed.$$" > $batch_file_rm 272*ba44d8a2SVladimir Kotal 273*ba44d8a2SVladimir Kotal # Perform remote deletion and remove the batch file. 274*ba44d8a2SVladimir Kotal $SFTP -b $batch_file_rm $host_spec 2>/dev/null 1>&2 275*ba44d8a2SVladimir Kotal integer -r ret=$? 276*ba44d8a2SVladimir Kotal rm -f $batch_file_rm 277*ba44d8a2SVladimir Kotal if (( $ret != 0 && $check > 0 )); then 278*ba44d8a2SVladimir Kotal print "Failed" 279*ba44d8a2SVladimir Kotal return $ret 280*ba44d8a2SVladimir Kotal fi 281*ba44d8a2SVladimir Kotal print "Done." 282*ba44d8a2SVladimir Kotal 283*ba44d8a2SVladimir Kotal return 0 284*ba44d8a2SVladimir Kotal} 285*ba44d8a2SVladimir Kotal 286*ba44d8a2SVladimir Kotal# 28702d26c39SVladimir Kotal# Upload webrev to remote site 28802d26c39SVladimir Kotal# 289*ba44d8a2SVladimir 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 303*ba44d8a2SVladimir 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 325*ba44d8a2SVladimir Kotal rsync_upload ${remote_target} 32602d26c39SVladimir Kotal if (( $? != 0 )); then 32702d26c39SVladimir Kotal echo "rsync upload failed, falling back to SSH" 328*ba44d8a2SVladimir 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# 337daaffb31Sdp# input_cmd | html_quote | output_cmd 338daaffb31Sdp# or 339daaffb31Sdp# html_quote filename | output_cmd 3407c478bd9Sstevel@tonic-gate# 3417c478bd9Sstevel@tonic-gate# Make a piece of source code safe for display in an HTML <pre> block. 3427c478bd9Sstevel@tonic-gate# 3437c478bd9Sstevel@tonic-gatehtml_quote() 3447c478bd9Sstevel@tonic-gate{ 3457c478bd9Sstevel@tonic-gate sed -e "s/&/\&/g" -e "s/</\</g" -e "s/>/\>/g" "$@" | expand 3467c478bd9Sstevel@tonic-gate} 3477c478bd9Sstevel@tonic-gate 348daaffb31Sdp# 349daaffb31Sdp# input_cmd | bug2url | output_cmd 350daaffb31Sdp# 351daaffb31Sdp# Scan for bugids and insert <a> links to the relevent bug database. 352daaffb31Sdp# 353daaffb31Sdpbug2url() 3547c478bd9Sstevel@tonic-gate{ 355daaffb31Sdp sed -e 's|[0-9]\{5,\}|<a href=\"'$BUGURL'&\">&</a>|g' 356daaffb31Sdp} 357daaffb31Sdp 3587c478bd9Sstevel@tonic-gate# 359daaffb31Sdp# input_cmd | sac2url | output_cmd 3607c478bd9Sstevel@tonic-gate# 361daaffb31Sdp# Scan for ARC cases and insert <a> links to the relevent SAC database. 362daaffb31Sdp# This is slightly complicated because inside the SWAN, SAC cases are 363daaffb31Sdp# grouped by ARC: PSARC/2006/123. But on OpenSolaris.org, they are 364daaffb31Sdp# referenced as 2006/123 (without labelling the ARC). 3657c478bd9Sstevel@tonic-gate# 366daaffb31Sdpsac2url() 367daaffb31Sdp{ 368e0e0293aSjmcp if [[ -z "$Oflag" ]]; then 3690a30ef2cSstevel 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' 370daaffb31Sdp else 371daaffb31Sdp sed -e 's|\([A-Z]\{1,2\}ARC\)[ /]\([0-9]\{4\}\)/\([0-9]\{3\}\)|<a href=\"'$SACURL'/\2/\3\">\1 \2/\3</a>|g' 372daaffb31Sdp fi 373daaffb31Sdp} 374daaffb31Sdp 3757c478bd9Sstevel@tonic-gate# 376daaffb31Sdp# strip_unchanged <infile> | output_cmd 3777c478bd9Sstevel@tonic-gate# 378daaffb31Sdp# Removes chunks of sdiff documents that have not changed. This makes it 379daaffb31Sdp# easier for a code reviewer to find the bits that have changed. 3807c478bd9Sstevel@tonic-gate# 381daaffb31Sdp# Deleted lines of text are replaced by a horizontal rule. Some 382daaffb31Sdp# identical lines are retained before and after the changed lines to 383daaffb31Sdp# provide some context. The number of these lines is controlled by the 384cdf0c1d5Smjnelson# variable C in the $AWK script below. 385daaffb31Sdp# 386daaffb31Sdp# The script detects changed lines as any line that has a "<span class=" 387daaffb31Sdp# string embedded (unchanged lines have no particular class and are not 388daaffb31Sdp# part of a <span>). Blank lines (without a sequence number) are also 389daaffb31Sdp# detected since they flag lines that have been inserted or deleted. 390daaffb31Sdp# 391daaffb31Sdpstrip_unchanged() 392daaffb31Sdp{ 393cdf0c1d5Smjnelson $AWK ' 394daaffb31Sdp BEGIN { C = c = 20 } 395cdf0c1d5Smjnelson NF == 0 || /<span class="/ { 396daaffb31Sdp if (c > C) { 397daaffb31Sdp c -= C 398daaffb31Sdp inx = 0 399daaffb31Sdp if (c > C) { 400cac38512Smjnelson print "\n</pre><hr></hr><pre>" 401daaffb31Sdp inx = c % C 402daaffb31Sdp c = C 403daaffb31Sdp } 404daaffb31Sdp 405daaffb31Sdp for (i = 0; i < c; i++) 406daaffb31Sdp print ln[(inx + i) % C] 407daaffb31Sdp } 408daaffb31Sdp c = 0; 409daaffb31Sdp print 410daaffb31Sdp next 411daaffb31Sdp } 412daaffb31Sdp { if (c >= C) { 413daaffb31Sdp ln[c % C] = $0 414daaffb31Sdp c++; 415daaffb31Sdp next; 416daaffb31Sdp } 417daaffb31Sdp c++; 418daaffb31Sdp print 419daaffb31Sdp } 420cac38512Smjnelson END { if (c > (C * 2)) print "\n</pre><hr></hr>" } 421daaffb31Sdp 422daaffb31Sdp ' $1 423daaffb31Sdp} 424daaffb31Sdp 425daaffb31Sdp# 426daaffb31Sdp# sdiff_to_html 427daaffb31Sdp# 428daaffb31Sdp# This function takes two files as arguments, obtains their diff, and 429daaffb31Sdp# processes the diff output to present the files as an HTML document with 430daaffb31Sdp# the files displayed side-by-side, differences shown in color. It also 431daaffb31Sdp# takes a delta comment, rendered as an HTML snippet, as the third 432daaffb31Sdp# argument. The function takes two files as arguments, then the name of 433daaffb31Sdp# file, the path, and the comment. The HTML will be delivered on stdout, 434daaffb31Sdp# e.g. 435daaffb31Sdp# 436daaffb31Sdp# $ sdiff_to_html old/usr/src/tools/scripts/webrev.sh \ 437daaffb31Sdp# new/usr/src/tools/scripts/webrev.sh \ 438daaffb31Sdp# webrev.sh usr/src/tools/scripts \ 439daaffb31Sdp# '<a href="http://monaco.sfbay.sun.com/detail.jsp?cr=1234567"> 440daaffb31Sdp# 1234567</a> my bugid' > <file>.html 441daaffb31Sdp# 442daaffb31Sdp# framed_sdiff() is then called which creates $2.frames.html 443daaffb31Sdp# in the webrev tree. 444daaffb31Sdp# 445daaffb31Sdp# FYI: This function is rather unusual in its use of awk. The initial 446daaffb31Sdp# diff run produces conventional diff output showing changed lines mixed 447daaffb31Sdp# with editing codes. The changed lines are ignored - we're interested in 448daaffb31Sdp# the editing codes, e.g. 4497c478bd9Sstevel@tonic-gate# 4507c478bd9Sstevel@tonic-gate# 8c8 4517c478bd9Sstevel@tonic-gate# 57a61 4527c478bd9Sstevel@tonic-gate# 63c66,76 4537c478bd9Sstevel@tonic-gate# 68,93d80 4547c478bd9Sstevel@tonic-gate# 106d90 4557c478bd9Sstevel@tonic-gate# 108,110d91 4567c478bd9Sstevel@tonic-gate# 457daaffb31Sdp# These editing codes are parsed by the awk script and used to generate 458daaffb31Sdp# another awk script that generates HTML, e.g the above lines would turn 459daaffb31Sdp# into something like this: 4607c478bd9Sstevel@tonic-gate# 4617c478bd9Sstevel@tonic-gate# BEGIN { printf "<pre>\n" } 4627c478bd9Sstevel@tonic-gate# function sp(n) {for (i=0;i<n;i++)printf "\n"} 463daaffb31Sdp# function wl(n) {printf "<font color=%s>%4d %s </font>\n", n, NR, $0} 4647c478bd9Sstevel@tonic-gate# NR==8 {wl("#7A7ADD");next} 4657c478bd9Sstevel@tonic-gate# NR==54 {wl("#7A7ADD");sp(3);next} 4667c478bd9Sstevel@tonic-gate# NR==56 {wl("#7A7ADD");next} 4677c478bd9Sstevel@tonic-gate# NR==57 {wl("black");printf "\n"; next} 4687c478bd9Sstevel@tonic-gate# : : 4697c478bd9Sstevel@tonic-gate# 470daaffb31Sdp# This script is then run on the original source file to generate the 471daaffb31Sdp# HTML that corresponds to the source file. 4727c478bd9Sstevel@tonic-gate# 473daaffb31Sdp# The two HTML files are then combined into a single piece of HTML that 474daaffb31Sdp# uses an HTML table construct to present the files side by side. You'll 475daaffb31Sdp# notice that the changes are color-coded: 4767c478bd9Sstevel@tonic-gate# 4777c478bd9Sstevel@tonic-gate# black - unchanged lines 4787c478bd9Sstevel@tonic-gate# blue - changed lines 4797c478bd9Sstevel@tonic-gate# bold blue - new lines 4807c478bd9Sstevel@tonic-gate# brown - deleted lines 4817c478bd9Sstevel@tonic-gate# 482daaffb31Sdp# Blank lines are inserted in each file to keep unchanged lines in sync 483daaffb31Sdp# (side-by-side). This format is familiar to users of sdiff(1) or 484daaffb31Sdp# Teamware's filemerge tool. 485daaffb31Sdp# 486daaffb31Sdpsdiff_to_html() 487daaffb31Sdp{ 4887c478bd9Sstevel@tonic-gate diff -b $1 $2 > /tmp/$$.diffs 4897c478bd9Sstevel@tonic-gate 490daaffb31Sdp TNAME=$3 491daaffb31Sdp TPATH=$4 492daaffb31Sdp COMMENT=$5 493daaffb31Sdp 4947c478bd9Sstevel@tonic-gate # 4957c478bd9Sstevel@tonic-gate # Now we have the diffs, generate the HTML for the old file. 4967c478bd9Sstevel@tonic-gate # 497cdf0c1d5Smjnelson $AWK ' 4987c478bd9Sstevel@tonic-gate BEGIN { 4997c478bd9Sstevel@tonic-gate printf "function sp(n) {for (i=0;i<n;i++)printf \"\\n\"}\n" 500daaffb31Sdp printf "function removed() " 501daaffb31Sdp printf "{printf \"<span class=\\\"removed\\\">%%4d %%s</span>\\n\", NR, $0}\n" 502daaffb31Sdp printf "function changed() " 503daaffb31Sdp printf "{printf \"<span class=\\\"changed\\\">%%4d %%s</span>\\n\", NR, $0}\n" 504daaffb31Sdp printf "function bl() {printf \"%%4d %%s\\n\", NR, $0}\n" 5057c478bd9Sstevel@tonic-gate} 5067c478bd9Sstevel@tonic-gate /^</ {next} 5077c478bd9Sstevel@tonic-gate /^>/ {next} 5087c478bd9Sstevel@tonic-gate /^---/ {next} 509daaffb31Sdp 5107c478bd9Sstevel@tonic-gate { 5117c478bd9Sstevel@tonic-gate split($1, a, /[cad]/) ; 5127c478bd9Sstevel@tonic-gate if (index($1, "a")) { 5137c478bd9Sstevel@tonic-gate if (a[1] == 0) { 5147c478bd9Sstevel@tonic-gate n = split(a[2], r, /,/); 5157c478bd9Sstevel@tonic-gate if (n == 1) 5167c478bd9Sstevel@tonic-gate printf "BEGIN\t\t{sp(1)}\n" 5177c478bd9Sstevel@tonic-gate else 5187c478bd9Sstevel@tonic-gate printf "BEGIN\t\t{sp(%d)}\n",\ 5197c478bd9Sstevel@tonic-gate (r[2] - r[1]) + 1 5207c478bd9Sstevel@tonic-gate next 5217c478bd9Sstevel@tonic-gate } 5227c478bd9Sstevel@tonic-gate 5237c478bd9Sstevel@tonic-gate printf "NR==%s\t\t{", a[1] 5247c478bd9Sstevel@tonic-gate n = split(a[2], r, /,/); 5257c478bd9Sstevel@tonic-gate s = r[1]; 5267c478bd9Sstevel@tonic-gate if (n == 1) 5277c478bd9Sstevel@tonic-gate printf "bl();printf \"\\n\"; next}\n" 5287c478bd9Sstevel@tonic-gate else { 5297c478bd9Sstevel@tonic-gate n = r[2] - r[1] 5307c478bd9Sstevel@tonic-gate printf "bl();sp(%d);next}\n",\ 5317c478bd9Sstevel@tonic-gate (r[2] - r[1]) + 1 5327c478bd9Sstevel@tonic-gate } 5337c478bd9Sstevel@tonic-gate next 5347c478bd9Sstevel@tonic-gate } 5357c478bd9Sstevel@tonic-gate if (index($1, "d")) { 5367c478bd9Sstevel@tonic-gate n = split(a[1], r, /,/); 5377c478bd9Sstevel@tonic-gate n1 = r[1] 5387c478bd9Sstevel@tonic-gate n2 = r[2] 5397c478bd9Sstevel@tonic-gate if (n == 1) 540daaffb31Sdp printf "NR==%s\t\t{removed(); next}\n" , n1 5417c478bd9Sstevel@tonic-gate else 542daaffb31Sdp printf "NR==%s,NR==%s\t{removed(); next}\n" , n1, n2 5437c478bd9Sstevel@tonic-gate next 5447c478bd9Sstevel@tonic-gate } 5457c478bd9Sstevel@tonic-gate if (index($1, "c")) { 5467c478bd9Sstevel@tonic-gate n = split(a[1], r, /,/); 5477c478bd9Sstevel@tonic-gate n1 = r[1] 5487c478bd9Sstevel@tonic-gate n2 = r[2] 5497c478bd9Sstevel@tonic-gate final = n2 5507c478bd9Sstevel@tonic-gate d1 = 0 5517c478bd9Sstevel@tonic-gate if (n == 1) 552daaffb31Sdp printf "NR==%s\t\t{changed();" , n1 5537c478bd9Sstevel@tonic-gate else { 5547c478bd9Sstevel@tonic-gate d1 = n2 - n1 555daaffb31Sdp printf "NR==%s,NR==%s\t{changed();" , n1, n2 5567c478bd9Sstevel@tonic-gate } 5577c478bd9Sstevel@tonic-gate m = split(a[2], r, /,/); 5587c478bd9Sstevel@tonic-gate n1 = r[1] 5597c478bd9Sstevel@tonic-gate n2 = r[2] 5607c478bd9Sstevel@tonic-gate if (m > 1) { 5617c478bd9Sstevel@tonic-gate d2 = n2 - n1 5627c478bd9Sstevel@tonic-gate if (d2 > d1) { 5637c478bd9Sstevel@tonic-gate if (n > 1) printf "if (NR==%d)", final 5647c478bd9Sstevel@tonic-gate printf "sp(%d);", d2 - d1 5657c478bd9Sstevel@tonic-gate } 5667c478bd9Sstevel@tonic-gate } 5677c478bd9Sstevel@tonic-gate printf "next}\n" ; 5687c478bd9Sstevel@tonic-gate 5697c478bd9Sstevel@tonic-gate next 5707c478bd9Sstevel@tonic-gate } 5717c478bd9Sstevel@tonic-gate } 5727c478bd9Sstevel@tonic-gate 573daaffb31Sdp END { printf "{printf \"%%4d %%s\\n\", NR, $0 }\n" } 574daaffb31Sdp ' /tmp/$$.diffs > /tmp/$$.file1 5757c478bd9Sstevel@tonic-gate 5767c478bd9Sstevel@tonic-gate # 5777c478bd9Sstevel@tonic-gate # Now generate the HTML for the new file 5787c478bd9Sstevel@tonic-gate # 579cdf0c1d5Smjnelson $AWK ' 5807c478bd9Sstevel@tonic-gate BEGIN { 5817c478bd9Sstevel@tonic-gate printf "function sp(n) {for (i=0;i<n;i++)printf \"\\n\"}\n" 582daaffb31Sdp printf "function new() " 583daaffb31Sdp printf "{printf \"<span class=\\\"new\\\">%%4d %%s</span>\\n\", NR, $0}\n" 584daaffb31Sdp printf "function changed() " 585daaffb31Sdp printf "{printf \"<span class=\\\"changed\\\">%%4d %%s</span>\\n\", NR, $0}\n" 586daaffb31Sdp printf "function bl() {printf \"%%4d %%s\\n\", NR, $0}\n" 5877c478bd9Sstevel@tonic-gate } 588daaffb31Sdp 5897c478bd9Sstevel@tonic-gate /^</ {next} 5907c478bd9Sstevel@tonic-gate /^>/ {next} 5917c478bd9Sstevel@tonic-gate /^---/ {next} 592daaffb31Sdp 5937c478bd9Sstevel@tonic-gate { 5947c478bd9Sstevel@tonic-gate split($1, a, /[cad]/) ; 5957c478bd9Sstevel@tonic-gate if (index($1, "d")) { 5967c478bd9Sstevel@tonic-gate if (a[2] == 0) { 5977c478bd9Sstevel@tonic-gate n = split(a[1], r, /,/); 5987c478bd9Sstevel@tonic-gate if (n == 1) 5997c478bd9Sstevel@tonic-gate printf "BEGIN\t\t{sp(1)}\n" 6007c478bd9Sstevel@tonic-gate else 6017c478bd9Sstevel@tonic-gate printf "BEGIN\t\t{sp(%d)}\n",\ 6027c478bd9Sstevel@tonic-gate (r[2] - r[1]) + 1 6037c478bd9Sstevel@tonic-gate next 6047c478bd9Sstevel@tonic-gate } 6057c478bd9Sstevel@tonic-gate 6067c478bd9Sstevel@tonic-gate printf "NR==%s\t\t{", a[2] 6077c478bd9Sstevel@tonic-gate n = split(a[1], r, /,/); 6087c478bd9Sstevel@tonic-gate s = r[1]; 6097c478bd9Sstevel@tonic-gate if (n == 1) 6107c478bd9Sstevel@tonic-gate printf "bl();printf \"\\n\"; next}\n" 6117c478bd9Sstevel@tonic-gate else { 6127c478bd9Sstevel@tonic-gate n = r[2] - r[1] 6137c478bd9Sstevel@tonic-gate printf "bl();sp(%d);next}\n",\ 6147c478bd9Sstevel@tonic-gate (r[2] - r[1]) + 1 6157c478bd9Sstevel@tonic-gate } 6167c478bd9Sstevel@tonic-gate next 6177c478bd9Sstevel@tonic-gate } 6187c478bd9Sstevel@tonic-gate if (index($1, "a")) { 6197c478bd9Sstevel@tonic-gate n = split(a[2], r, /,/); 6207c478bd9Sstevel@tonic-gate n1 = r[1] 6217c478bd9Sstevel@tonic-gate n2 = r[2] 6227c478bd9Sstevel@tonic-gate if (n == 1) 623daaffb31Sdp printf "NR==%s\t\t{new() ; next}\n" , n1 6247c478bd9Sstevel@tonic-gate else 625daaffb31Sdp printf "NR==%s,NR==%s\t{new() ; next}\n" , n1, n2 6267c478bd9Sstevel@tonic-gate next 6277c478bd9Sstevel@tonic-gate } 6287c478bd9Sstevel@tonic-gate if (index($1, "c")) { 6297c478bd9Sstevel@tonic-gate n = split(a[2], r, /,/); 6307c478bd9Sstevel@tonic-gate n1 = r[1] 6317c478bd9Sstevel@tonic-gate n2 = r[2] 6327c478bd9Sstevel@tonic-gate final = n2 6337c478bd9Sstevel@tonic-gate d2 = 0; 6347c478bd9Sstevel@tonic-gate if (n == 1) { 6357c478bd9Sstevel@tonic-gate final = n1 636daaffb31Sdp printf "NR==%s\t\t{changed();" , n1 6377c478bd9Sstevel@tonic-gate } else { 6387c478bd9Sstevel@tonic-gate d2 = n2 - n1 639daaffb31Sdp printf "NR==%s,NR==%s\t{changed();" , n1, n2 6407c478bd9Sstevel@tonic-gate } 6417c478bd9Sstevel@tonic-gate m = split(a[1], r, /,/); 6427c478bd9Sstevel@tonic-gate n1 = r[1] 6437c478bd9Sstevel@tonic-gate n2 = r[2] 6447c478bd9Sstevel@tonic-gate if (m > 1) { 6457c478bd9Sstevel@tonic-gate d1 = n2 - n1 6467c478bd9Sstevel@tonic-gate if (d1 > d2) { 6477c478bd9Sstevel@tonic-gate if (n > 1) printf "if (NR==%d)", final 6487c478bd9Sstevel@tonic-gate printf "sp(%d);", d1 - d2 6497c478bd9Sstevel@tonic-gate } 6507c478bd9Sstevel@tonic-gate } 6517c478bd9Sstevel@tonic-gate printf "next}\n" ; 6527c478bd9Sstevel@tonic-gate next 6537c478bd9Sstevel@tonic-gate } 6547c478bd9Sstevel@tonic-gate } 655daaffb31Sdp END { printf "{printf \"%%4d %%s\\n\", NR, $0 }\n" } 6567c478bd9Sstevel@tonic-gate ' /tmp/$$.diffs > /tmp/$$.file2 6577c478bd9Sstevel@tonic-gate 658daaffb31Sdp # 659cdf0c1d5Smjnelson # Post-process the HTML files by running them back through $AWK 660daaffb31Sdp # 661cdf0c1d5Smjnelson html_quote < $1 | $AWK -f /tmp/$$.file1 > /tmp/$$.file1.html 6627c478bd9Sstevel@tonic-gate 663cdf0c1d5Smjnelson html_quote < $2 | $AWK -f /tmp/$$.file2 > /tmp/$$.file2.html 6647c478bd9Sstevel@tonic-gate 665daaffb31Sdp # 666daaffb31Sdp # Now combine into a valid HTML file and side-by-side into a table 667daaffb31Sdp # 668daaffb31Sdp print "$HTML<head>$STDHEAD" 669cdf0c1d5Smjnelson print "<title>$WNAME Sdiff $TPATH/$TNAME</title>" 670daaffb31Sdp print "</head><body id=\"SUNWwebrev\">" 671daaffb31Sdp print "<a class=\"print\" href=\"javascript:print()\">Print this page</a>" 672daaffb31Sdp print "<pre>$COMMENT</pre>\n" 673daaffb31Sdp print "<table><tr valign=\"top\">" 674daaffb31Sdp print "<td><pre>" 6757c478bd9Sstevel@tonic-gate 6767c478bd9Sstevel@tonic-gate strip_unchanged /tmp/$$.file1.html 6777c478bd9Sstevel@tonic-gate 678daaffb31Sdp print "</pre></td><td><pre>" 6797c478bd9Sstevel@tonic-gate 6807c478bd9Sstevel@tonic-gate strip_unchanged /tmp/$$.file2.html 6817c478bd9Sstevel@tonic-gate 682daaffb31Sdp print "</pre></td>" 683daaffb31Sdp print "</tr></table>" 684daaffb31Sdp print "</body></html>" 6857c478bd9Sstevel@tonic-gate 686daaffb31Sdp framed_sdiff $TNAME $TPATH /tmp/$$.file1.html /tmp/$$.file2.html \ 687daaffb31Sdp "$COMMENT" 6887c478bd9Sstevel@tonic-gate} 6897c478bd9Sstevel@tonic-gate 6907c478bd9Sstevel@tonic-gate 691daaffb31Sdp# 692daaffb31Sdp# framed_sdiff <filename> <filepath> <lhsfile> <rhsfile> <comment> 693daaffb31Sdp# 694daaffb31Sdp# Expects lefthand and righthand side html files created by sdiff_to_html. 695daaffb31Sdp# We use insert_anchors() to augment those with HTML navigation anchors, 696daaffb31Sdp# and then emit the main frame. Content is placed into: 697daaffb31Sdp# 698daaffb31Sdp# $WDIR/DIR/$TNAME.lhs.html 699daaffb31Sdp# $WDIR/DIR/$TNAME.rhs.html 700daaffb31Sdp# $WDIR/DIR/$TNAME.frames.html 701daaffb31Sdp# 702daaffb31Sdp# NOTE: We rely on standard usage of $WDIR and $DIR. 703daaffb31Sdp# 7047c478bd9Sstevel@tonic-gatefunction framed_sdiff 7057c478bd9Sstevel@tonic-gate{ 7067c478bd9Sstevel@tonic-gate typeset TNAME=$1 707daaffb31Sdp typeset TPATH=$2 708daaffb31Sdp typeset lhsfile=$3 709daaffb31Sdp typeset rhsfile=$4 710daaffb31Sdp typeset comments=$5 7117c478bd9Sstevel@tonic-gate typeset RTOP 712daaffb31Sdp 7137c478bd9Sstevel@tonic-gate # Enable html files to access WDIR via a relative path. 714daaffb31Sdp RTOP=$(relative_dir $TPATH $WDIR) 715daaffb31Sdp 716daaffb31Sdp # Make the rhs/lhs files and output the frameset file. 717daaffb31Sdp print "$HTML<head>$STDHEAD" > $WDIR/$DIR/$TNAME.lhs.html 718daaffb31Sdp 719daaffb31Sdp cat >> $WDIR/$DIR/$TNAME.lhs.html <<-EOF 720cac38512Smjnelson <script type="text/javascript" src="$RTOP/ancnav.js"></script> 7217c478bd9Sstevel@tonic-gate </head> 722daaffb31Sdp <body id="SUNWwebrev" onkeypress="keypress(event);"> 723cac38512Smjnelson <a name="0"></a> 724cac38512Smjnelson <pre>$comments</pre><hr></hr> 725daaffb31Sdp EOF 726daaffb31Sdp 727daaffb31Sdp cp $WDIR/$DIR/$TNAME.lhs.html $WDIR/$DIR/$TNAME.rhs.html 728daaffb31Sdp 729daaffb31Sdp insert_anchors $lhsfile >> $WDIR/$DIR/$TNAME.lhs.html 730daaffb31Sdp insert_anchors $rhsfile >> $WDIR/$DIR/$TNAME.rhs.html 731daaffb31Sdp 732daaffb31Sdp close='</body></html>' 733daaffb31Sdp 734daaffb31Sdp print $close >> $WDIR/$DIR/$TNAME.lhs.html 735daaffb31Sdp print $close >> $WDIR/$DIR/$TNAME.rhs.html 736daaffb31Sdp 737daaffb31Sdp print "$FRAMEHTML<head>$STDHEAD" > $WDIR/$DIR/$TNAME.frames.html 738daaffb31Sdp print "<title>$WNAME Framed-Sdiff " \ 739daaffb31Sdp "$TPATH/$TNAME</title> </head>" >> $WDIR/$DIR/$TNAME.frames.html 740daaffb31Sdp cat >> $WDIR/$DIR/$TNAME.frames.html <<-EOF 741daaffb31Sdp <frameset rows="*,60"> 742daaffb31Sdp <frameset cols="50%,50%"> 743cac38512Smjnelson <frame src="$TNAME.lhs.html" scrolling="auto" name="lhs"></frame> 744cac38512Smjnelson <frame src="$TNAME.rhs.html" scrolling="auto" name="rhs"></frame> 745daaffb31Sdp </frameset> 746daaffb31Sdp <frame src="$RTOP/ancnav.html" scrolling="no" marginwidth="0" 747cac38512Smjnelson marginheight="0" name="nav"></frame> 748daaffb31Sdp <noframes> 749daaffb31Sdp <body id="SUNWwebrev"> 750daaffb31Sdp Alas 'frames' webrev requires that your browser supports frames 7517c478bd9Sstevel@tonic-gate and has the feature enabled. 752daaffb31Sdp </body> 753daaffb31Sdp </noframes> 754daaffb31Sdp </frameset> 7557c478bd9Sstevel@tonic-gate </html> 7567c478bd9Sstevel@tonic-gate EOF 7577c478bd9Sstevel@tonic-gate} 7587c478bd9Sstevel@tonic-gate 7597c478bd9Sstevel@tonic-gate 760daaffb31Sdp# 761daaffb31Sdp# fix_postscript 762daaffb31Sdp# 763daaffb31Sdp# Merge codereview output files to a single conforming postscript file, by: 764daaffb31Sdp# - removing all extraneous headers/trailers 765daaffb31Sdp# - making the page numbers right 766daaffb31Sdp# - removing pages devoid of contents which confuse some 767daaffb31Sdp# postscript readers. 768daaffb31Sdp# 769daaffb31Sdp# From Casper. 770daaffb31Sdp# 771daaffb31Sdpfunction fix_postscript 7727c478bd9Sstevel@tonic-gate{ 773daaffb31Sdp infile=$1 7747c478bd9Sstevel@tonic-gate 775daaffb31Sdp cat > /tmp/$$.crmerge.pl << \EOF 7767c478bd9Sstevel@tonic-gate 777daaffb31Sdp print scalar(<>); # %!PS-Adobe--- 778daaffb31Sdp print "%%Orientation: Landscape\n"; 7797c478bd9Sstevel@tonic-gate 780daaffb31Sdp $pno = 0; 781daaffb31Sdp $doprint = 1; 782daaffb31Sdp 783daaffb31Sdp $page = ""; 784daaffb31Sdp 785daaffb31Sdp while (<>) { 786daaffb31Sdp next if (/^%%Pages:\s*\d+/); 787daaffb31Sdp 788daaffb31Sdp if (/^%%Page:/) { 789daaffb31Sdp if ($pno == 0 || $page =~ /\)S/) { 790daaffb31Sdp # Header or single page containing text 791daaffb31Sdp print "%%Page: ? $pno\n" if ($pno > 0); 792daaffb31Sdp print $page; 793daaffb31Sdp $pno++; 794daaffb31Sdp } else { 795daaffb31Sdp # Empty page, skip it. 7967c478bd9Sstevel@tonic-gate } 797daaffb31Sdp $page = ""; 798daaffb31Sdp $doprint = 1; 7997c478bd9Sstevel@tonic-gate next; 8007c478bd9Sstevel@tonic-gate } 8017c478bd9Sstevel@tonic-gate 802daaffb31Sdp # Skip from %%Trailer of one document to Endprolog 803daaffb31Sdp # %%Page of the next 804daaffb31Sdp $doprint = 0 if (/^%%Trailer/); 805daaffb31Sdp $page .= $_ if ($doprint); 8067c478bd9Sstevel@tonic-gate } 8077c478bd9Sstevel@tonic-gate 808daaffb31Sdp if ($page =~ /\)S/) { 809daaffb31Sdp print "%%Page: ? $pno\n"; 810daaffb31Sdp print $page; 811daaffb31Sdp } else { 812daaffb31Sdp $pno--; 813daaffb31Sdp } 814daaffb31Sdp print "%%Trailer\n%%Pages: $pno\n"; 815daaffb31SdpEOF 816daaffb31Sdp 81714983201Sdp $PERL /tmp/$$.crmerge.pl < $infile 818daaffb31Sdp} 819daaffb31Sdp 820daaffb31Sdp 821daaffb31Sdp# 822daaffb31Sdp# input_cmd | insert_anchors | output_cmd 823daaffb31Sdp# 8247c478bd9Sstevel@tonic-gate# Flag blocks of difference with sequentially numbered invisible 825daaffb31Sdp# anchors. These are used to drive the frames version of the 8267c478bd9Sstevel@tonic-gate# sdiffs output. 8277c478bd9Sstevel@tonic-gate# 8287c478bd9Sstevel@tonic-gate# NOTE: Anchor zero flags the top of the file irrespective of changes, 8297c478bd9Sstevel@tonic-gate# an additional anchor is also appended to flag the bottom. 8307c478bd9Sstevel@tonic-gate# 831daaffb31Sdp# The script detects changed lines as any line that has a "<span 832daaffb31Sdp# class=" string embedded (unchanged lines have no class set and are 833daaffb31Sdp# not part of a <span>. Blank lines (without a sequence number) 8347c478bd9Sstevel@tonic-gate# are also detected since they flag lines that have been inserted or 8357c478bd9Sstevel@tonic-gate# deleted. 8367c478bd9Sstevel@tonic-gate# 837daaffb31Sdpfunction insert_anchors 838daaffb31Sdp{ 839cdf0c1d5Smjnelson $AWK ' 8407c478bd9Sstevel@tonic-gate function ia() { 841daaffb31Sdp printf "<a name=\"%d\" id=\"anc%d\"></a>", anc, anc++; 8427c478bd9Sstevel@tonic-gate } 843daaffb31Sdp 8447c478bd9Sstevel@tonic-gate BEGIN { 845daaffb31Sdp anc=1; 8467c478bd9Sstevel@tonic-gate inblock=1; 847daaffb31Sdp printf "<pre>\n"; 8487c478bd9Sstevel@tonic-gate } 849daaffb31Sdp NF == 0 || /^<span class=/ { 8507c478bd9Sstevel@tonic-gate if (inblock == 0) { 8517c478bd9Sstevel@tonic-gate ia(); 8527c478bd9Sstevel@tonic-gate inblock=1; 8537c478bd9Sstevel@tonic-gate } 8547c478bd9Sstevel@tonic-gate print; 8557c478bd9Sstevel@tonic-gate next; 8567c478bd9Sstevel@tonic-gate } 8577c478bd9Sstevel@tonic-gate { 8587c478bd9Sstevel@tonic-gate inblock=0; 8597c478bd9Sstevel@tonic-gate print; 8607c478bd9Sstevel@tonic-gate } 8617c478bd9Sstevel@tonic-gate END { 8627c478bd9Sstevel@tonic-gate ia(); 863daaffb31Sdp 864daaffb31Sdp printf "<b style=\"font-size: large; color: red\">"; 865daaffb31Sdp printf "--- EOF ---</b>" 8667c478bd9Sstevel@tonic-gate for(i=0;i<8;i++) printf "\n\n\n\n\n\n\n\n\n\n"; 867daaffb31Sdp printf "</pre>" 868daaffb31Sdp printf "<form name=\"eof\">"; 869cac38512Smjnelson printf "<input name=\"value\" value=\"%d\" " \ 870cac38512Smjnelson "type=\"hidden\"></input>", anc - 1; 871daaffb31Sdp printf "</form>"; 8727c478bd9Sstevel@tonic-gate } 8737c478bd9Sstevel@tonic-gate ' $1 8747c478bd9Sstevel@tonic-gate} 8757c478bd9Sstevel@tonic-gate 8767c478bd9Sstevel@tonic-gate 877daaffb31Sdp# 878daaffb31Sdp# relative_dir 879daaffb31Sdp# 880daaffb31Sdp# Print a relative return path from $1 to $2. For example if 881daaffb31Sdp# $1=/tmp/myreview/raw_files/usr/src/tools/scripts and $2=/tmp/myreview, 882daaffb31Sdp# this function would print "../../../../". 883daaffb31Sdp# 884daaffb31Sdp# In the event that $1 is not in $2 a warning is printed to stderr, 885daaffb31Sdp# and $2 is returned-- the result of this is that the resulting webrev 886daaffb31Sdp# is not relocatable. 887daaffb31Sdp# 888daaffb31Sdpfunction relative_dir 8897c478bd9Sstevel@tonic-gate{ 890daaffb31Sdp typeset cur="${1##$2?(/)}" 891daaffb31Sdp typeset ret="" 892daaffb31Sdp if [[ $2 == $cur ]]; then # Should never happen. 893daaffb31Sdp # Should never happen. 89414983201Sdp print -u2 "\nWARNING: relative_dir: \"$1\" not relative " 895daaffb31Sdp print -u2 "to \"$2\". Check input paths. Framed webrev " 896daaffb31Sdp print -u2 "will not be relocatable!" 897daaffb31Sdp print $2 898daaffb31Sdp return 899daaffb31Sdp fi 900daaffb31Sdp 901daaffb31Sdp while [[ -n ${cur} ]]; 9027c478bd9Sstevel@tonic-gate do 9037c478bd9Sstevel@tonic-gate cur=${cur%%*(/)*([!/])} 904daaffb31Sdp if [[ -z $ret ]]; then 905daaffb31Sdp ret=".." 906daaffb31Sdp else 9077c478bd9Sstevel@tonic-gate ret="../$ret" 908daaffb31Sdp fi 9097c478bd9Sstevel@tonic-gate done 9107c478bd9Sstevel@tonic-gate print $ret 9117c478bd9Sstevel@tonic-gate} 9127c478bd9Sstevel@tonic-gate 9137c478bd9Sstevel@tonic-gate 914daaffb31Sdp# 915daaffb31Sdp# frame_nav_js 916daaffb31Sdp# 917daaffb31Sdp# Emit javascript for frame navigation 918daaffb31Sdp# 919daaffb31Sdpfunction frame_nav_js 9207c478bd9Sstevel@tonic-gate{ 9217c478bd9Sstevel@tonic-gatecat << \EOF 9227c478bd9Sstevel@tonic-gatevar myInt; 9237c478bd9Sstevel@tonic-gatevar scrolling=0; 924daaffb31Sdpvar sfactor = 3; 9257c478bd9Sstevel@tonic-gatevar scount=10; 9267c478bd9Sstevel@tonic-gate 9277c478bd9Sstevel@tonic-gatefunction scrollByPix() { 9287c478bd9Sstevel@tonic-gate if (scount<=0) { 9297c478bd9Sstevel@tonic-gate sfactor*=1.2; 9307c478bd9Sstevel@tonic-gate scount=10; 9317c478bd9Sstevel@tonic-gate } 9327c478bd9Sstevel@tonic-gate parent.lhs.scrollBy(0,sfactor); 9337c478bd9Sstevel@tonic-gate parent.rhs.scrollBy(0,sfactor); 9347c478bd9Sstevel@tonic-gate scount--; 9357c478bd9Sstevel@tonic-gate} 9367c478bd9Sstevel@tonic-gate 937daaffb31Sdpfunction scrollToAnc(num) { 938daaffb31Sdp 939daaffb31Sdp // Update the value of the anchor in the form which we use as 940daaffb31Sdp // storage for this value. setAncValue() will take care of 941daaffb31Sdp // correcting for overflow and underflow of the value and return 942daaffb31Sdp // us the new value. 943daaffb31Sdp num = setAncValue(num); 944daaffb31Sdp 945daaffb31Sdp // Set location and scroll back a little to expose previous 946daaffb31Sdp // lines. 947daaffb31Sdp // 948daaffb31Sdp // Note that this could be improved: it is possible although 949daaffb31Sdp // complex to compute the x and y position of an anchor, and to 950daaffb31Sdp // scroll to that location directly. 951daaffb31Sdp // 9527c478bd9Sstevel@tonic-gate parent.lhs.location.replace(parent.lhs.location.pathname + "#" + num); 9537c478bd9Sstevel@tonic-gate parent.rhs.location.replace(parent.rhs.location.pathname + "#" + num); 954daaffb31Sdp 9557c478bd9Sstevel@tonic-gate parent.lhs.scrollBy(0,-30); 9567c478bd9Sstevel@tonic-gate parent.rhs.scrollBy(0,-30); 9577c478bd9Sstevel@tonic-gate} 9587c478bd9Sstevel@tonic-gate 959daaffb31Sdpfunction getAncValue() 960daaffb31Sdp{ 961daaffb31Sdp return (parseInt(parent.nav.document.diff.real.value)); 962daaffb31Sdp} 963daaffb31Sdp 964daaffb31Sdpfunction setAncValue(val) 965daaffb31Sdp{ 966daaffb31Sdp if (val <= 0) { 967daaffb31Sdp val = 0; 968daaffb31Sdp parent.nav.document.diff.real.value = val; 969daaffb31Sdp parent.nav.document.diff.display.value = "BOF"; 970daaffb31Sdp return (val); 971daaffb31Sdp } 972daaffb31Sdp 973daaffb31Sdp // 974daaffb31Sdp // The way we compute the max anchor value is to stash it 975daaffb31Sdp // inline in the left and right hand side pages-- it's the same 976daaffb31Sdp // on each side, so we pluck from the left. 977daaffb31Sdp // 978daaffb31Sdp maxval = parent.lhs.document.eof.value.value; 979daaffb31Sdp if (val < maxval) { 980daaffb31Sdp parent.nav.document.diff.real.value = val; 981daaffb31Sdp parent.nav.document.diff.display.value = val.toString(); 982daaffb31Sdp return (val); 983daaffb31Sdp } 984daaffb31Sdp 985daaffb31Sdp // this must be: val >= maxval 986daaffb31Sdp val = maxval; 987daaffb31Sdp parent.nav.document.diff.real.value = val; 988daaffb31Sdp parent.nav.document.diff.display.value = "EOF"; 989daaffb31Sdp return (val); 990daaffb31Sdp} 991daaffb31Sdp 9927c478bd9Sstevel@tonic-gatefunction stopScroll() { 9937c478bd9Sstevel@tonic-gate if (scrolling==1) { 9947c478bd9Sstevel@tonic-gate clearInterval(myInt); 9957c478bd9Sstevel@tonic-gate scrolling=0; 9967c478bd9Sstevel@tonic-gate } 9977c478bd9Sstevel@tonic-gate} 9987c478bd9Sstevel@tonic-gate 9997c478bd9Sstevel@tonic-gatefunction startScroll() { 10007c478bd9Sstevel@tonic-gate stopScroll(); 10017c478bd9Sstevel@tonic-gate scrolling=1; 10027c478bd9Sstevel@tonic-gate myInt=setInterval("scrollByPix()",10); 10037c478bd9Sstevel@tonic-gate} 10047c478bd9Sstevel@tonic-gate 10057c478bd9Sstevel@tonic-gatefunction handlePress(b) { 1006daaffb31Sdp 10077c478bd9Sstevel@tonic-gate switch (b) { 10087c478bd9Sstevel@tonic-gate case 1 : 1009daaffb31Sdp scrollToAnc(-1); 10107c478bd9Sstevel@tonic-gate break; 10117c478bd9Sstevel@tonic-gate case 2 : 1012daaffb31Sdp scrollToAnc(getAncValue() - 1); 10137c478bd9Sstevel@tonic-gate break; 10147c478bd9Sstevel@tonic-gate case 3 : 10157c478bd9Sstevel@tonic-gate sfactor=-3; 10167c478bd9Sstevel@tonic-gate startScroll(); 10177c478bd9Sstevel@tonic-gate break; 10187c478bd9Sstevel@tonic-gate case 4 : 10197c478bd9Sstevel@tonic-gate sfactor=3; 10207c478bd9Sstevel@tonic-gate startScroll(); 10217c478bd9Sstevel@tonic-gate break; 10227c478bd9Sstevel@tonic-gate case 5 : 1023daaffb31Sdp scrollToAnc(getAncValue() + 1); 10247c478bd9Sstevel@tonic-gate break; 10257c478bd9Sstevel@tonic-gate case 6 : 1026daaffb31Sdp scrollToAnc(999999); 10277c478bd9Sstevel@tonic-gate break; 10287c478bd9Sstevel@tonic-gate } 10297c478bd9Sstevel@tonic-gate} 10307c478bd9Sstevel@tonic-gate 10317c478bd9Sstevel@tonic-gatefunction handleRelease(b) { 10327c478bd9Sstevel@tonic-gate stopScroll(); 10337c478bd9Sstevel@tonic-gate} 10347c478bd9Sstevel@tonic-gate 1035daaffb31Sdpfunction keypress(ev) { 1036daaffb31Sdp var keynum; 1037daaffb31Sdp var keychar; 1038daaffb31Sdp 1039daaffb31Sdp if (window.event) { // IE 1040daaffb31Sdp keynum = ev.keyCode; 1041daaffb31Sdp } else if (ev.which) { // non-IE 1042daaffb31Sdp keynum = ev.which; 1043daaffb31Sdp } 1044daaffb31Sdp 1045daaffb31Sdp keychar = String.fromCharCode(keynum); 1046daaffb31Sdp 1047daaffb31Sdp if (keychar == "k") { 1048daaffb31Sdp handlePress(2); 1049daaffb31Sdp return (0); 1050daaffb31Sdp } else if (keychar == "j" || keychar == " ") { 1051daaffb31Sdp handlePress(5); 1052daaffb31Sdp return (0); 1053daaffb31Sdp } 1054daaffb31Sdp return (1); 1055daaffb31Sdp} 1056daaffb31Sdp 10577c478bd9Sstevel@tonic-gatefunction ValidateDiffNum(){ 1058daaffb31Sdp val = parent.nav.document.diff.display.value; 1059daaffb31Sdp if (val == "EOF") { 1060daaffb31Sdp scrollToAnc(999999); 1061daaffb31Sdp return; 1062daaffb31Sdp } 1063daaffb31Sdp 1064daaffb31Sdp if (val == "BOF") { 1065daaffb31Sdp scrollToAnc(0); 1066daaffb31Sdp return; 1067daaffb31Sdp } 1068daaffb31Sdp 1069daaffb31Sdp i=parseInt(val); 10707c478bd9Sstevel@tonic-gate if (isNaN(i)) { 1071daaffb31Sdp parent.nav.document.diff.display.value = getAncValue(); 10727c478bd9Sstevel@tonic-gate } else { 1073daaffb31Sdp scrollToAnc(i); 10747c478bd9Sstevel@tonic-gate } 10757c478bd9Sstevel@tonic-gate return false; 10767c478bd9Sstevel@tonic-gate} 10777c478bd9Sstevel@tonic-gate 1078daaffb31SdpEOF 1079daaffb31Sdp} 1080daaffb31Sdp 1081daaffb31Sdp# 1082daaffb31Sdp# frame_navigation 1083daaffb31Sdp# 1084daaffb31Sdp# Output anchor navigation file for framed sdiffs. 1085daaffb31Sdp# 1086daaffb31Sdpfunction frame_navigation 1087daaffb31Sdp{ 1088daaffb31Sdp print "$HTML<head>$STDHEAD" 1089daaffb31Sdp 1090daaffb31Sdp cat << \EOF 1091daaffb31Sdp<title>Anchor Navigation</title> 1092daaffb31Sdp<meta http-equiv="Content-Script-Type" content="text/javascript"> 1093daaffb31Sdp<meta http-equiv="Content-Type" content="text/html"> 1094daaffb31Sdp 1095daaffb31Sdp<style type="text/css"> 1096daaffb31Sdp div.button td { padding-left: 5px; padding-right: 5px; 1097daaffb31Sdp background-color: #eee; text-align: center; 1098daaffb31Sdp border: 1px #444 outset; cursor: pointer; } 1099daaffb31Sdp div.button a { font-weight: bold; color: black } 1100daaffb31Sdp div.button td:hover { background: #ffcc99; } 1101daaffb31Sdp</style> 1102daaffb31SdpEOF 1103daaffb31Sdp 1104cac38512Smjnelson print "<script type=\"text/javascript\" src=\"ancnav.js\"></script>" 1105daaffb31Sdp 1106daaffb31Sdp cat << \EOF 11077c478bd9Sstevel@tonic-gate</head> 1108daaffb31Sdp<body id="SUNWwebrev" bgcolor="#eeeeee" onload="document.diff.real.focus();" 1109daaffb31Sdp onkeypress="keypress(event);"> 11107c478bd9Sstevel@tonic-gate <noscript lang="javascript"> 11117c478bd9Sstevel@tonic-gate <center> 1112cac38512Smjnelson <p><big>Framed Navigation controls require Javascript</big><br></br> 11137c478bd9Sstevel@tonic-gate Either this browser is incompatable or javascript is not enabled</p> 11147c478bd9Sstevel@tonic-gate </center> 11157c478bd9Sstevel@tonic-gate </noscript> 11167c478bd9Sstevel@tonic-gate <table width="100%" border="0" align="center"> 1117daaffb31Sdp <tr> 1118daaffb31Sdp <td valign="middle" width="25%">Diff navigation: 1119daaffb31Sdp Use 'j' and 'k' for next and previous diffs; or use buttons 1120daaffb31Sdp at right</td> 1121daaffb31Sdp <td align="center" valign="top" width="50%"> 11227c478bd9Sstevel@tonic-gate <div class="button"> 1123daaffb31Sdp <table border="0" align="center"> 1124daaffb31Sdp <tr> 1125daaffb31Sdp <td> 11267c478bd9Sstevel@tonic-gate <a onMouseDown="handlePress(1);return true;" 11277c478bd9Sstevel@tonic-gate onMouseUp="handleRelease(1);return true;" 11287c478bd9Sstevel@tonic-gate onMouseOut="handleRelease(1);return true;" 11297c478bd9Sstevel@tonic-gate onClick="return false;" 11307c478bd9Sstevel@tonic-gate title="Go to Beginning Of file">BOF</a></td> 1131daaffb31Sdp <td> 11327c478bd9Sstevel@tonic-gate <a onMouseDown="handlePress(3);return true;" 11337c478bd9Sstevel@tonic-gate onMouseUp="handleRelease(3);return true;" 11347c478bd9Sstevel@tonic-gate onMouseOut="handleRelease(3);return true;" 11357c478bd9Sstevel@tonic-gate title="Scroll Up: Press and Hold to accelerate" 1136daaffb31Sdp onClick="return false;">Scroll Up</a></td> 1137daaffb31Sdp <td> 11387c478bd9Sstevel@tonic-gate <a onMouseDown="handlePress(2);return true;" 11397c478bd9Sstevel@tonic-gate onMouseUp="handleRelease(2);return true;" 11407c478bd9Sstevel@tonic-gate onMouseOut="handleRelease(2);return true;" 11417c478bd9Sstevel@tonic-gate title="Go to previous Diff" 11427c478bd9Sstevel@tonic-gate onClick="return false;">Prev Diff</a> 11437c478bd9Sstevel@tonic-gate </td></tr> 1144daaffb31Sdp 11457c478bd9Sstevel@tonic-gate <tr> 1146daaffb31Sdp <td> 11477c478bd9Sstevel@tonic-gate <a onMouseDown="handlePress(6);return true;" 11487c478bd9Sstevel@tonic-gate onMouseUp="handleRelease(6);return true;" 11497c478bd9Sstevel@tonic-gate onMouseOut="handleRelease(6);return true;" 11507c478bd9Sstevel@tonic-gate onClick="return false;" 11517c478bd9Sstevel@tonic-gate title="Go to End Of File">EOF</a></td> 1152daaffb31Sdp <td> 11537c478bd9Sstevel@tonic-gate <a onMouseDown="handlePress(4);return true;" 11547c478bd9Sstevel@tonic-gate onMouseUp="handleRelease(4);return true;" 11557c478bd9Sstevel@tonic-gate onMouseOut="handleRelease(4);return true;" 11567c478bd9Sstevel@tonic-gate title="Scroll Down: Press and Hold to accelerate" 1157daaffb31Sdp onClick="return false;">Scroll Down</a></td> 1158daaffb31Sdp <td> 11597c478bd9Sstevel@tonic-gate <a onMouseDown="handlePress(5);return true;" 11607c478bd9Sstevel@tonic-gate onMouseUp="handleRelease(5);return true;" 11617c478bd9Sstevel@tonic-gate onMouseOut="handleRelease(5);return true;" 11627c478bd9Sstevel@tonic-gate title="Go to next Diff" 11637c478bd9Sstevel@tonic-gate onClick="return false;">Next Diff</a></td> 1164daaffb31Sdp </tr> 1165daaffb31Sdp </table> 1166daaffb31Sdp </div> 1167daaffb31Sdp </td> 11687c478bd9Sstevel@tonic-gate <th valign="middle" width="25%"> 1169daaffb31Sdp <form action="" name="diff" onsubmit="return ValidateDiffNum();"> 1170cac38512Smjnelson <input name="display" value="BOF" size="8" type="text"></input> 1171cac38512Smjnelson <input name="real" value="0" size="8" type="hidden"></input> 11727c478bd9Sstevel@tonic-gate </form> 11737c478bd9Sstevel@tonic-gate </th> 1174daaffb31Sdp </tr> 11757c478bd9Sstevel@tonic-gate </table> 11767c478bd9Sstevel@tonic-gate </body> 11777c478bd9Sstevel@tonic-gate</html> 11787c478bd9Sstevel@tonic-gateEOF 11797c478bd9Sstevel@tonic-gate} 11807c478bd9Sstevel@tonic-gate 11817c478bd9Sstevel@tonic-gate 1182daaffb31Sdp 1183daaffb31Sdp# 1184daaffb31Sdp# diff_to_html <filename> <filepath> { U | C } <comment> 1185daaffb31Sdp# 1186daaffb31Sdp# Processes the output of diff to produce an HTML file representing either 1187daaffb31Sdp# context or unified diffs. 1188daaffb31Sdp# 11897c478bd9Sstevel@tonic-gatediff_to_html() 11907c478bd9Sstevel@tonic-gate{ 11917c478bd9Sstevel@tonic-gate TNAME=$1 1192daaffb31Sdp TPATH=$2 1193daaffb31Sdp DIFFTYPE=$3 1194daaffb31Sdp COMMENT=$4 1195daaffb31Sdp 1196daaffb31Sdp print "$HTML<head>$STDHEAD" 1197daaffb31Sdp print "<title>$WNAME ${DIFFTYPE}diff $TPATH</title>" 1198daaffb31Sdp 1199daaffb31Sdp if [[ $DIFFTYPE == "U" ]]; then 1200daaffb31Sdp print "$UDIFFCSS" 1201daaffb31Sdp fi 1202daaffb31Sdp 1203daaffb31Sdp cat <<-EOF 1204daaffb31Sdp </head> 1205daaffb31Sdp <body id="SUNWwebrev"> 1206daaffb31Sdp <a class="print" href="javascript:print()">Print this page</a> 1207daaffb31Sdp <pre>$COMMENT</pre> 1208daaffb31Sdp <pre> 1209daaffb31Sdp EOF 12107c478bd9Sstevel@tonic-gate 1211cdf0c1d5Smjnelson html_quote | $AWK ' 1212daaffb31Sdp /^--- new/ { next } 1213daaffb31Sdp /^\+\+\+ new/ { next } 1214daaffb31Sdp /^--- old/ { next } 1215daaffb31Sdp /^\*\*\* old/ { next } 1216daaffb31Sdp /^\*\*\*\*/ { next } 12177c478bd9Sstevel@tonic-gate /^-------/ { printf "<center><h1>%s</h1></center>\n", $0; next } 1218cac38512Smjnelson /^\@\@.*\@\@$/ { printf "</pre><hr></hr><pre>\n"; 1219daaffb31Sdp printf "<span class=\"newmarker\">%s</span>\n", $0; 1220daaffb31Sdp next} 1221daaffb31Sdp 1222cac38512Smjnelson /^\*\*\*/ { printf "<hr></hr><span class=\"oldmarker\">%s</span>\n", $0; 1223daaffb31Sdp next} 1224daaffb31Sdp /^---/ { printf "<span class=\"newmarker\">%s</span>\n", $0; 1225daaffb31Sdp next} 1226daaffb31Sdp /^\+/ {printf "<span class=\"new\">%s</span>\n", $0; next} 1227daaffb31Sdp /^!/ {printf "<span class=\"changed\">%s</span>\n", $0; next} 1228daaffb31Sdp /^-/ {printf "<span class=\"removed\">%s</span>\n", $0; next} 1229daaffb31Sdp {printf "%s\n", $0; next} 12307c478bd9Sstevel@tonic-gate ' 1231daaffb31Sdp 1232daaffb31Sdp print "</pre></body></html>\n" 12337c478bd9Sstevel@tonic-gate} 12347c478bd9Sstevel@tonic-gate 12357c478bd9Sstevel@tonic-gate 1236daaffb31Sdp# 1237daaffb31Sdp# source_to_html { new | old } <filename> 1238daaffb31Sdp# 1239daaffb31Sdp# Process a plain vanilla source file to transform it into an HTML file. 1240daaffb31Sdp# 12417c478bd9Sstevel@tonic-gatesource_to_html() 12427c478bd9Sstevel@tonic-gate{ 12437c478bd9Sstevel@tonic-gate WHICH=$1 12447c478bd9Sstevel@tonic-gate TNAME=$2 12457c478bd9Sstevel@tonic-gate 1246daaffb31Sdp print "$HTML<head>$STDHEAD" 1247cdf0c1d5Smjnelson print "<title>$WNAME $WHICH $TNAME</title>" 1248daaffb31Sdp print "<body id=\"SUNWwebrev\">" 1249daaffb31Sdp print "<pre>" 1250cdf0c1d5Smjnelson html_quote | $AWK '{line += 1 ; printf "%4d %s\n", line, $0 }' 1251daaffb31Sdp print "</pre></body></html>" 12527c478bd9Sstevel@tonic-gate} 12537c478bd9Sstevel@tonic-gate 1254daaffb31Sdp# 1255cdf0c1d5Smjnelson# comments_from_teamware {text|html} parent-file child-file 1256daaffb31Sdp# 1257daaffb31Sdp# Find the first delta in the child that's not in the parent. Get the 1258daaffb31Sdp# newest delta from the parent, get all deltas from the child starting 1259daaffb31Sdp# with that delta, and then get all info starting with the second oldest 1260daaffb31Sdp# delta in that list (the first delta unique to the child). 12617c478bd9Sstevel@tonic-gate# 12627c478bd9Sstevel@tonic-gate# This code adapted from Bill Shannon's "spc" script 1263daaffb31Sdp# 1264daaffb31Sdpcomments_from_teamware() 12657c478bd9Sstevel@tonic-gate{ 1266daaffb31Sdp fmt=$1 1267daaffb31Sdp pfile=$PWS/$2 1268daaffb31Sdp cfile=$CWS/$3 12697c478bd9Sstevel@tonic-gate 1270cdf0c1d5Smjnelson if [[ ! -f $PWS/${2%/*}/SCCS/s.${2##*/} && -n $RWS ]]; then 1271cdf0c1d5Smjnelson pfile=$RWS/$2 1272cdf0c1d5Smjnelson fi 1273cdf0c1d5Smjnelson 1274daaffb31Sdp if [[ -f $pfile ]]; then 1275cdf0c1d5Smjnelson psid=$($SCCS prs -d:I: $pfile 2>/dev/null) 12767c478bd9Sstevel@tonic-gate else 12777c478bd9Sstevel@tonic-gate psid=1.1 12787c478bd9Sstevel@tonic-gate fi 12797c478bd9Sstevel@tonic-gate 1280cdf0c1d5Smjnelson set -A sids $($SCCS prs -l -r$psid -d:I: $cfile 2>/dev/null) 12817c478bd9Sstevel@tonic-gate N=${#sids[@]} 12827c478bd9Sstevel@tonic-gate 1283daaffb31Sdp nawkprg=' 1284daaffb31Sdp /^COMMENTS:/ {p=1; continue} 1285daaffb31Sdp /^D [0-9]+\.[0-9]+/ {printf "--- %s ---\n", $2; p=0; } 1286daaffb31Sdp NF == 0u { continue } 1287daaffb31Sdp {if (p==0) continue; print $0 }' 1288daaffb31Sdp 12897c478bd9Sstevel@tonic-gate if [[ $N -ge 2 ]]; then 12907c478bd9Sstevel@tonic-gate sid1=${sids[$((N-2))]} # Gets 2nd to last sid 12917c478bd9Sstevel@tonic-gate 1292daaffb31Sdp if [[ $fmt == "text" ]]; then 1293cdf0c1d5Smjnelson $SCCS prs -l -r$sid1 $cfile 2>/dev/null | \ 1294cdf0c1d5Smjnelson $AWK "$nawkprg" 1295daaffb31Sdp return 1296daaffb31Sdp fi 1297daaffb31Sdp 1298cdf0c1d5Smjnelson $SCCS prs -l -r$sid1 $cfile 2>/dev/null | \ 1299cdf0c1d5Smjnelson html_quote | bug2url | sac2url | $AWK "$nawkprg" 13007c478bd9Sstevel@tonic-gate fi 13017c478bd9Sstevel@tonic-gate} 13027c478bd9Sstevel@tonic-gate 1303daaffb31Sdp# 1304cdf0c1d5Smjnelson# comments_from_wx {text|html} filepath 1305daaffb31Sdp# 1306cdf0c1d5Smjnelson# Given the pathname of a file, find its location in a "wx" active 1307cdf0c1d5Smjnelson# file list and print the following comment. Output is either text or 1308cdf0c1d5Smjnelson# HTML; if the latter, embedded bugids (sequence of 5 or more digits) 1309cdf0c1d5Smjnelson# are turned into URLs. 1310cdf0c1d5Smjnelson# 1311cdf0c1d5Smjnelson# This is also used with Mercurial and the file list provided by hg-active. 1312daaffb31Sdp# 1313daaffb31Sdpcomments_from_wx() 13147c478bd9Sstevel@tonic-gate{ 1315daaffb31Sdp typeset fmt=$1 1316daaffb31Sdp typeset p=$2 13177c478bd9Sstevel@tonic-gate 1318cdf0c1d5Smjnelson comm=`$AWK ' 1319daaffb31Sdp $1 == "'$p'" { 13207c478bd9Sstevel@tonic-gate do getline ; while (NF > 0) 13217c478bd9Sstevel@tonic-gate getline 13227c478bd9Sstevel@tonic-gate while (NF > 0) { print ; getline } 13237c478bd9Sstevel@tonic-gate exit 1324daaffb31Sdp }' < $wxfile` 1325daaffb31Sdp 1326cdf0c1d5Smjnelson if [[ -z $comm ]]; then 1327cdf0c1d5Smjnelson comm="*** NO COMMENTS ***" 1328cdf0c1d5Smjnelson fi 1329cdf0c1d5Smjnelson 1330daaffb31Sdp if [[ $fmt == "text" ]]; then 1331cdf0c1d5Smjnelson print -- "$comm" 1332daaffb31Sdp return 1333daaffb31Sdp fi 1334daaffb31Sdp 1335cdf0c1d5Smjnelson print -- "$comm" | html_quote | bug2url | sac2url 1336cdf0c1d5Smjnelson 13377c478bd9Sstevel@tonic-gate} 13387c478bd9Sstevel@tonic-gate 13397c478bd9Sstevel@tonic-gate# 1340daaffb31Sdp# getcomments {text|html} filepath parentpath 1341daaffb31Sdp# 1342daaffb31Sdp# Fetch the comments depending on what SCM mode we're in. 1343daaffb31Sdp# 1344daaffb31Sdpgetcomments() 1345daaffb31Sdp{ 1346daaffb31Sdp typeset fmt=$1 1347daaffb31Sdp typeset p=$2 1348daaffb31Sdp typeset pp=$3 13497c478bd9Sstevel@tonic-gate 13503df69ef3SDarren Moffat if [[ -n $Nflag ]]; then 13513df69ef3SDarren Moffat return 13523df69ef3SDarren Moffat fi 1353cdf0c1d5Smjnelson # 1354cdf0c1d5Smjnelson # Mercurial support uses a file list in wx format, so this 1355cdf0c1d5Smjnelson # will be used there, too 1356cdf0c1d5Smjnelson # 1357daaffb31Sdp if [[ -n $wxfile ]]; then 1358daaffb31Sdp comments_from_wx $fmt $p 1359daaffb31Sdp else 1360daaffb31Sdp if [[ $SCM_MODE == "teamware" ]]; then 1361daaffb31Sdp comments_from_teamware $fmt $pp $p 1362daaffb31Sdp fi 1363daaffb31Sdp fi 1364daaffb31Sdp} 1365daaffb31Sdp 1366daaffb31Sdp# 1367daaffb31Sdp# printCI <total-changed> <inserted> <deleted> <modified> <unchanged> 1368daaffb31Sdp# 1369daaffb31Sdp# Print out Code Inspection figures similar to sccs-prt(1) format. 1370daaffb31Sdp# 1371daaffb31Sdpfunction printCI 1372daaffb31Sdp{ 1373daaffb31Sdp integer tot=$1 ins=$2 del=$3 mod=$4 unc=$5 1374daaffb31Sdp typeset str 1375daaffb31Sdp if (( tot == 1 )); then 1376daaffb31Sdp str="line" 1377daaffb31Sdp else 1378daaffb31Sdp str="lines" 1379daaffb31Sdp fi 1380daaffb31Sdp printf '%d %s changed: %d ins; %d del; %d mod; %d unchg\n' \ 1381daaffb31Sdp $tot $str $ins $del $mod $unc 1382daaffb31Sdp} 1383daaffb31Sdp 1384daaffb31Sdp 1385daaffb31Sdp# 1386daaffb31Sdp# difflines <oldfile> <newfile> 1387daaffb31Sdp# 1388daaffb31Sdp# Calculate and emit number of added, removed, modified and unchanged lines, 1389daaffb31Sdp# and total lines changed, the sum of added + removed + modified. 1390daaffb31Sdp# 13917c478bd9Sstevel@tonic-gatefunction difflines 13927c478bd9Sstevel@tonic-gate{ 1393daaffb31Sdp integer tot mod del ins unc err 13947c478bd9Sstevel@tonic-gate typeset filename 13957c478bd9Sstevel@tonic-gate 1396cdf0c1d5Smjnelson eval $( diff -e $1 $2 | $AWK ' 1397daaffb31Sdp # Change range of lines: N,Nc 13987c478bd9Sstevel@tonic-gate /^[0-9]*,[0-9]*c$/ { 13997c478bd9Sstevel@tonic-gate n=split(substr($1,1,length($1)-1), counts, ","); 14007c478bd9Sstevel@tonic-gate if (n != 2) { 14017c478bd9Sstevel@tonic-gate error=2 14027c478bd9Sstevel@tonic-gate exit; 14037c478bd9Sstevel@tonic-gate } 1404daaffb31Sdp # 1405daaffb31Sdp # 3,5c means lines 3 , 4 and 5 are changed, a total of 3 lines. 1406daaffb31Sdp # following would be 5 - 3 = 2! Hence +1 for correction. 1407daaffb31Sdp # 14087c478bd9Sstevel@tonic-gate r=(counts[2]-counts[1])+1; 1409daaffb31Sdp 1410daaffb31Sdp # 1411daaffb31Sdp # Now count replacement lines: each represents a change instead 1412daaffb31Sdp # of a delete, so increment c and decrement r. 1413daaffb31Sdp # 14147c478bd9Sstevel@tonic-gate while (getline != /^\.$/) { 14157c478bd9Sstevel@tonic-gate c++; 14167c478bd9Sstevel@tonic-gate r--; 14177c478bd9Sstevel@tonic-gate } 1418daaffb31Sdp # 1419daaffb31Sdp # If there were more replacement lines than original lines, 1420daaffb31Sdp # then r will be negative; in this case there are no deletions, 1421daaffb31Sdp # but there are r changes that should be counted as adds, and 1422daaffb31Sdp # since r is negative, subtract it from a and add it to c. 1423daaffb31Sdp # 14247c478bd9Sstevel@tonic-gate if (r < 0) { 14257c478bd9Sstevel@tonic-gate a-=r; 14267c478bd9Sstevel@tonic-gate c+=r; 14277c478bd9Sstevel@tonic-gate } 1428daaffb31Sdp 1429daaffb31Sdp # 1430daaffb31Sdp # If there were more original lines than replacement lines, then 1431daaffb31Sdp # r will be positive; in this case, increment d by that much. 1432daaffb31Sdp # 14337c478bd9Sstevel@tonic-gate if (r > 0) { 14347c478bd9Sstevel@tonic-gate d+=r; 14357c478bd9Sstevel@tonic-gate } 14367c478bd9Sstevel@tonic-gate next; 14377c478bd9Sstevel@tonic-gate } 14387c478bd9Sstevel@tonic-gate 1439daaffb31Sdp # Change lines: Nc 14407c478bd9Sstevel@tonic-gate /^[0-9].*c$/ { 1441daaffb31Sdp # The first line is a replacement; any more are additions. 14427c478bd9Sstevel@tonic-gate if (getline != /^\.$/) { 14437c478bd9Sstevel@tonic-gate c++; 14447c478bd9Sstevel@tonic-gate while (getline != /^\.$/) a++; 14457c478bd9Sstevel@tonic-gate } 14467c478bd9Sstevel@tonic-gate next; 14477c478bd9Sstevel@tonic-gate } 14487c478bd9Sstevel@tonic-gate 1449daaffb31Sdp # Add lines: both Na and N,Na 14507c478bd9Sstevel@tonic-gate /^[0-9].*a$/ { 14517c478bd9Sstevel@tonic-gate while (getline != /^\.$/) a++; 14527c478bd9Sstevel@tonic-gate next; 14537c478bd9Sstevel@tonic-gate } 14547c478bd9Sstevel@tonic-gate 1455daaffb31Sdp # Delete range of lines: N,Nd 14567c478bd9Sstevel@tonic-gate /^[0-9]*,[0-9]*d$/ { 14577c478bd9Sstevel@tonic-gate n=split(substr($1,1,length($1)-1), counts, ","); 14587c478bd9Sstevel@tonic-gate if (n != 2) { 14597c478bd9Sstevel@tonic-gate error=2 14607c478bd9Sstevel@tonic-gate exit; 14617c478bd9Sstevel@tonic-gate } 1462daaffb31Sdp # 1463daaffb31Sdp # 3,5d means lines 3 , 4 and 5 are deleted, a total of 3 lines. 1464daaffb31Sdp # following would be 5 - 3 = 2! Hence +1 for correction. 1465daaffb31Sdp # 14667c478bd9Sstevel@tonic-gate r=(counts[2]-counts[1])+1; 14677c478bd9Sstevel@tonic-gate d+=r; 14687c478bd9Sstevel@tonic-gate next; 14697c478bd9Sstevel@tonic-gate } 14707c478bd9Sstevel@tonic-gate 1471daaffb31Sdp # Delete line: Nd. For example 10d says line 10 is deleted. 14727c478bd9Sstevel@tonic-gate /^[0-9]*d$/ {d++; next} 14737c478bd9Sstevel@tonic-gate 1474daaffb31Sdp # Should not get here! 14757c478bd9Sstevel@tonic-gate { 14767c478bd9Sstevel@tonic-gate error=1; 14777c478bd9Sstevel@tonic-gate exit; 14787c478bd9Sstevel@tonic-gate } 14797c478bd9Sstevel@tonic-gate 1480daaffb31Sdp # Finish off - print results 14817c478bd9Sstevel@tonic-gate END { 1482daaffb31Sdp printf("tot=%d;mod=%d;del=%d;ins=%d;err=%d\n", 14837c478bd9Sstevel@tonic-gate (c+d+a), c, d, a, error); 14847c478bd9Sstevel@tonic-gate }' ) 14857c478bd9Sstevel@tonic-gate 1486cdf0c1d5Smjnelson # End of $AWK, Check to see if any trouble occurred. 14877c478bd9Sstevel@tonic-gate if (( $? > 0 || err > 0 )); then 1488daaffb31Sdp print "Unexpected Error occurred reading" \ 1489daaffb31Sdp "\`diff -e $1 $2\`: \$?=$?, err=" $err 1490daaffb31Sdp return 1491daaffb31Sdp fi 1492daaffb31Sdp 14937c478bd9Sstevel@tonic-gate # Accumulate totals 14947c478bd9Sstevel@tonic-gate (( TOTL += tot )) 1495daaffb31Sdp (( TMOD += mod )) 14967c478bd9Sstevel@tonic-gate (( TDEL += del )) 14977c478bd9Sstevel@tonic-gate (( TINS += ins )) 14987c478bd9Sstevel@tonic-gate # Calculate unchanged lines 1499cdf0c1d5Smjnelson unc=`wc -l < $1` 15007c478bd9Sstevel@tonic-gate if (( unc > 0 )); then 1501daaffb31Sdp (( unc -= del + mod )) 15027c478bd9Sstevel@tonic-gate (( TUNC += unc )) 15037c478bd9Sstevel@tonic-gate fi 15047c478bd9Sstevel@tonic-gate # print summary 1505daaffb31Sdp print "<span class=\"lineschanged\">" 1506daaffb31Sdp printCI $tot $ins $del $mod $unc 1507daaffb31Sdp print "</span>" 15087c478bd9Sstevel@tonic-gate} 15097c478bd9Sstevel@tonic-gate 1510daaffb31Sdp 15117c478bd9Sstevel@tonic-gate# 1512daaffb31Sdp# flist_from_wx 1513daaffb31Sdp# 1514daaffb31Sdp# Sets up webrev to source its information from a wx-formatted file. 1515daaffb31Sdp# Sets the global 'wxfile' variable. 1516daaffb31Sdp# 1517daaffb31Sdpfunction flist_from_wx 15187c478bd9Sstevel@tonic-gate{ 1519daaffb31Sdp typeset argfile=$1 1520daaffb31Sdp if [[ -n ${argfile%%/*} ]]; then 1521daaffb31Sdp # 1522daaffb31Sdp # If the wx file pathname is relative then make it absolute 1523daaffb31Sdp # because the webrev does a "cd" later on. 1524daaffb31Sdp # 1525daaffb31Sdp wxfile=$PWD/$argfile 15267c478bd9Sstevel@tonic-gate else 1527daaffb31Sdp wxfile=$argfile 15287c478bd9Sstevel@tonic-gate fi 15297c478bd9Sstevel@tonic-gate 1530cdf0c1d5Smjnelson $AWK '{ c = 1; print; 15317c478bd9Sstevel@tonic-gate while (getline) { 15327c478bd9Sstevel@tonic-gate if (NF == 0) { c = -c; continue } 15337c478bd9Sstevel@tonic-gate if (c > 0) print 15347c478bd9Sstevel@tonic-gate } 1535daaffb31Sdp }' $wxfile > $FLIST 15367c478bd9Sstevel@tonic-gate 1537daaffb31Sdp print " Done." 1538daaffb31Sdp} 15397c478bd9Sstevel@tonic-gate 1540daaffb31Sdp# 1541daaffb31Sdp# flist_from_teamware [ <args-to-putback-n> ] 1542daaffb31Sdp# 1543daaffb31Sdp# Generate the file list by extracting file names from a putback -n. Some 1544daaffb31Sdp# names may come from the "update/create" messages and others from the 1545daaffb31Sdp# "currently checked out" warning. Renames are detected here too. Extract 1546daaffb31Sdp# values for CODEMGR_WS and CODEMGR_PARENT from the output of the putback 1547daaffb31Sdp# -n as well, but remove them if they are already defined. 1548daaffb31Sdp# 1549daaffb31Sdpfunction flist_from_teamware 1550daaffb31Sdp{ 1551cdf0c1d5Smjnelson if [[ -n $codemgr_parent && -z $parent_webrev ]]; then 1552daaffb31Sdp if [[ ! -d $codemgr_parent/Codemgr_wsdata ]]; then 1553daaffb31Sdp print -u2 "parent $codemgr_parent doesn't look like a" \ 1554daaffb31Sdp "valid teamware workspace" 15557c478bd9Sstevel@tonic-gate exit 1 15567c478bd9Sstevel@tonic-gate fi 1557daaffb31Sdp parent_args="-p $codemgr_parent" 15587c478bd9Sstevel@tonic-gate fi 15597c478bd9Sstevel@tonic-gate 1560daaffb31Sdp print " File list from: 'putback -n $parent_args $*' ... \c" 15617c478bd9Sstevel@tonic-gate 1562daaffb31Sdp putback -n $parent_args $* 2>&1 | 1563cdf0c1d5Smjnelson $AWK ' 1564daaffb31Sdp /^update:|^create:/ {print $2} 1565daaffb31Sdp /^Parent workspace:/ {printf("CODEMGR_PARENT=%s\n",$3)} 1566daaffb31Sdp /^Child workspace:/ {printf("CODEMGR_WS=%s\n",$3)} 1567daaffb31Sdp /^The following files are currently checked out/ {p = 1; continue} 1568daaffb31Sdp NF == 0 {p=0 ; continue} 1569daaffb31Sdp /^rename/ {old=$3} 1570daaffb31Sdp $1 == "to:" {print $2, old} 1571daaffb31Sdp /^"/ {continue} 1572daaffb31Sdp p == 1 {print $1}' | 1573daaffb31Sdp sort -r -k 1,1 -u | sort > $FLIST 15747c478bd9Sstevel@tonic-gate 1575daaffb31Sdp print " Done." 1576daaffb31Sdp} 1577daaffb31Sdp 1578cdf0c1d5Smjnelson# 1579cdf0c1d5Smjnelson# Call hg-active to get the active list output in the wx active list format 1580cdf0c1d5Smjnelson# 1581cdf0c1d5Smjnelsonfunction hg_active_wxfile 1582cdf0c1d5Smjnelson{ 1583cdf0c1d5Smjnelson typeset child=$1 1584cdf0c1d5Smjnelson typeset parent=$2 1585cdf0c1d5Smjnelson 1586cdf0c1d5Smjnelson TMPFLIST=/tmp/$$.active 15879a70fc3bSMark J. Nelson $HG_ACTIVE -w $child -p $parent -o $TMPFLIST 1588cdf0c1d5Smjnelson wxfile=$TMPFLIST 1589cdf0c1d5Smjnelson} 1590cdf0c1d5Smjnelson 1591cdf0c1d5Smjnelson# 1592cdf0c1d5Smjnelson# flist_from_mercurial 1593cdf0c1d5Smjnelson# Call hg-active to get a wx-style active list, and hand it off to 1594cdf0c1d5Smjnelson# flist_from_wx 1595cdf0c1d5Smjnelson# 1596cdf0c1d5Smjnelsonfunction flist_from_mercurial 1597cdf0c1d5Smjnelson{ 1598cdf0c1d5Smjnelson typeset child=$1 1599cdf0c1d5Smjnelson typeset parent=$2 1600cdf0c1d5Smjnelson 1601cdf0c1d5Smjnelson print " File list from: hg-active -p $parent ...\c" 1602cdf0c1d5Smjnelson 1603cdf0c1d5Smjnelson if [[ ! -x $HG_ACTIVE ]]; then 1604cdf0c1d5Smjnelson print # Blank line for the \c above 1605cdf0c1d5Smjnelson print -u2 "Error: hg-active tool not found. Exiting" 1606cdf0c1d5Smjnelson exit 1 1607cdf0c1d5Smjnelson fi 1608cdf0c1d5Smjnelson hg_active_wxfile $child $parent 1609cdf0c1d5Smjnelson 1610cdf0c1d5Smjnelson # flist_from_wx prints the Done, so we don't have to. 1611cdf0c1d5Smjnelson flist_from_wx $TMPFLIST 1612cdf0c1d5Smjnelson} 1613cdf0c1d5Smjnelson 1614cdf0c1d5Smjnelson# 1615cdf0c1d5Smjnelson# flist_from_subversion 1616cdf0c1d5Smjnelson# 1617cdf0c1d5Smjnelson# Generate the file list by extracting file names from svn status. 1618cdf0c1d5Smjnelson# 1619cdf0c1d5Smjnelsonfunction flist_from_subversion 1620cdf0c1d5Smjnelson{ 1621cdf0c1d5Smjnelson CWS=$1 1622cdf0c1d5Smjnelson OLDPWD=$2 1623cdf0c1d5Smjnelson 1624cdf0c1d5Smjnelson cd $CWS 1625cdf0c1d5Smjnelson print -u2 " File list from: svn status ... \c" 1626cdf0c1d5Smjnelson svn status | $AWK '/^[ACDMR]/ { print $NF }' > $FLIST 1627cdf0c1d5Smjnelson print -u2 " Done." 1628cdf0c1d5Smjnelson cd $OLDPWD 1629cdf0c1d5Smjnelson} 1630cdf0c1d5Smjnelson 1631daaffb31Sdpfunction env_from_flist 1632daaffb31Sdp{ 1633daaffb31Sdp [[ -r $FLIST ]] || return 1634daaffb31Sdp 1635daaffb31Sdp # 1636daaffb31Sdp # Use "eval" to set env variables that are listed in the file 1637daaffb31Sdp # list. Then copy those into our local versions of those 1638daaffb31Sdp # variables if they have not been set already. 1639daaffb31Sdp # 164002d26c39SVladimir Kotal eval `sed -e "s/#.*$//" $FLIST | $GREP = ` 16417c478bd9Sstevel@tonic-gate 1642cdf0c1d5Smjnelson if [[ -z $codemgr_ws && -n $CODEMGR_WS ]]; then 1643cdf0c1d5Smjnelson codemgr_ws=$CODEMGR_WS 1644cdf0c1d5Smjnelson export CODEMGR_WS 1645cdf0c1d5Smjnelson fi 16467c478bd9Sstevel@tonic-gate 1647daaffb31Sdp # 1648daaffb31Sdp # Check to see if CODEMGR_PARENT is set in the flist file. 1649daaffb31Sdp # 1650cdf0c1d5Smjnelson if [[ -z $codemgr_parent && -n $CODEMGR_PARENT ]]; then 1651daaffb31Sdp codemgr_parent=$CODEMGR_PARENT 1652cdf0c1d5Smjnelson export CODEMGR_PARENT 1653daaffb31Sdp fi 1654daaffb31Sdp} 1655daaffb31Sdp 165614983201Sdpfunction look_for_prog 165714983201Sdp{ 165814983201Sdp typeset path 165914983201Sdp typeset ppath 166014983201Sdp typeset progname=$1 166114983201Sdp 166214983201Sdp ppath=$PATH 166314983201Sdp ppath=$ppath:/usr/sfw/bin:/usr/bin:/usr/sbin 166414983201Sdp ppath=$ppath:/opt/teamware/bin:/opt/onbld/bin 1665cdf0c1d5Smjnelson ppath=$ppath:/opt/onbld/bin/`uname -p` 166614983201Sdp 166714983201Sdp PATH=$ppath prog=`whence $progname` 166814983201Sdp if [[ -n $prog ]]; then 166914983201Sdp print $prog 167014983201Sdp fi 167114983201Sdp} 167214983201Sdp 1673cdf0c1d5Smjnelsonfunction get_file_mode 1674cdf0c1d5Smjnelson{ 1675cdf0c1d5Smjnelson $PERL -e ' 1676cdf0c1d5Smjnelson if (@stat = stat($ARGV[0])) { 1677cdf0c1d5Smjnelson $mode = $stat[2] & 0777; 1678cdf0c1d5Smjnelson printf "%03o\n", $mode; 1679cdf0c1d5Smjnelson exit 0; 1680cdf0c1d5Smjnelson } else { 1681cdf0c1d5Smjnelson exit 1; 1682cdf0c1d5Smjnelson } 1683cdf0c1d5Smjnelson ' $1 1684cdf0c1d5Smjnelson} 1685cdf0c1d5Smjnelson 1686cdf0c1d5Smjnelsonfunction build_old_new_teamware 1687cdf0c1d5Smjnelson{ 1688cdf0c1d5Smjnelson typeset olddir="$1" 1689cdf0c1d5Smjnelson typeset newdir="$2" 1690cdf0c1d5Smjnelson 1691cdf0c1d5Smjnelson # If the child's version doesn't exist then 1692cdf0c1d5Smjnelson # get a readonly copy. 1693cdf0c1d5Smjnelson 1694cdf0c1d5Smjnelson if [[ ! -f $CWS/$DIR/$F && -f $CWS/$DIR/SCCS/s.$F ]]; then 1695cdf0c1d5Smjnelson $SCCS get -s -p $CWS/$DIR/$F > $CWS/$DIR/$F 1696cdf0c1d5Smjnelson fi 1697cdf0c1d5Smjnelson 1698cdf0c1d5Smjnelson # The following two sections propagate file permissions the 1699cdf0c1d5Smjnelson # same way SCCS does. If the file is already under version 1700cdf0c1d5Smjnelson # control, always use permissions from the SCCS/s.file. If 1701cdf0c1d5Smjnelson # the file is not under SCCS control, use permissions from the 1702cdf0c1d5Smjnelson # working copy. In all cases, the file copied to the webrev 1703cdf0c1d5Smjnelson # is set to read only, and group/other permissions are set to 1704cdf0c1d5Smjnelson # match those of the file owner. This way, even if the file 1705cdf0c1d5Smjnelson # is currently checked out, the webrev will display the final 1706cdf0c1d5Smjnelson # permissions that would result after check in. 1707cdf0c1d5Smjnelson 1708cdf0c1d5Smjnelson # 1709cdf0c1d5Smjnelson # Snag new version of file. 1710cdf0c1d5Smjnelson # 1711cdf0c1d5Smjnelson rm -f $newdir/$DIR/$F 1712cdf0c1d5Smjnelson cp $CWS/$DIR/$F $newdir/$DIR/$F 1713cdf0c1d5Smjnelson if [[ -f $CWS/$DIR/SCCS/s.$F ]]; then 1714cdf0c1d5Smjnelson chmod `get_file_mode $CWS/$DIR/SCCS/s.$F` \ 1715cdf0c1d5Smjnelson $newdir/$DIR/$F 1716cdf0c1d5Smjnelson fi 1717cdf0c1d5Smjnelson chmod u-w,go=u $newdir/$DIR/$F 1718cdf0c1d5Smjnelson 1719cdf0c1d5Smjnelson # 1720cdf0c1d5Smjnelson # Get the parent's version of the file. First see whether the 1721cdf0c1d5Smjnelson # child's version is checked out and get the parent's version 1722cdf0c1d5Smjnelson # with keywords expanded or unexpanded as appropriate. 1723cdf0c1d5Smjnelson # 1724cdf0c1d5Smjnelson if [[ -f $PWS/$PDIR/$PF && ! -f $PWS/$PDIR/SCCS/s.$PF && \ 1725cdf0c1d5Smjnelson ! -f $PWS/$PDIR/SCCS/p.$PF ]]; then 1726cdf0c1d5Smjnelson # Parent is not a real workspace, but just a raw 1727cdf0c1d5Smjnelson # directory tree - use the file that's there as 1728cdf0c1d5Smjnelson # the old file. 1729cdf0c1d5Smjnelson 1730cdf0c1d5Smjnelson rm -f $olddir/$PDIR/$PF 1731cdf0c1d5Smjnelson cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF 1732cdf0c1d5Smjnelson else 1733cdf0c1d5Smjnelson if [[ -f $PWS/$PDIR/SCCS/s.$PF ]]; then 1734cdf0c1d5Smjnelson real_parent=$PWS 1735cdf0c1d5Smjnelson else 1736cdf0c1d5Smjnelson real_parent=$RWS 1737cdf0c1d5Smjnelson fi 1738cdf0c1d5Smjnelson 1739cdf0c1d5Smjnelson rm -f $olddir/$PDIR/$PF 1740cdf0c1d5Smjnelson 1741cdf0c1d5Smjnelson if [[ -f $real_parent/$PDIR/$PF ]]; then 1742cdf0c1d5Smjnelson if [ -f $CWS/$DIR/SCCS/p.$F ]; then 1743cdf0c1d5Smjnelson $SCCS get -s -p -k $real_parent/$PDIR/$PF > \ 1744cdf0c1d5Smjnelson $olddir/$PDIR/$PF 1745cdf0c1d5Smjnelson else 1746cdf0c1d5Smjnelson $SCCS get -s -p $real_parent/$PDIR/$PF > \ 1747cdf0c1d5Smjnelson $olddir/$PDIR/$PF 1748cdf0c1d5Smjnelson fi 1749cdf0c1d5Smjnelson chmod `get_file_mode $real_parent/$PDIR/SCCS/s.$PF` \ 1750cdf0c1d5Smjnelson $olddir/$PDIR/$PF 1751cdf0c1d5Smjnelson fi 1752cdf0c1d5Smjnelson fi 1753cdf0c1d5Smjnelson if [[ -f $olddir/$PDIR/$PF ]]; then 1754cdf0c1d5Smjnelson chmod u-w,go=u $olddir/$PDIR/$PF 1755cdf0c1d5Smjnelson fi 1756cdf0c1d5Smjnelson} 1757cdf0c1d5Smjnelson 1758cdf0c1d5Smjnelsonfunction build_old_new_mercurial 1759cdf0c1d5Smjnelson{ 1760cdf0c1d5Smjnelson typeset olddir="$1" 1761cdf0c1d5Smjnelson typeset newdir="$2" 1762cdf0c1d5Smjnelson typeset old_mode= 1763cdf0c1d5Smjnelson typeset new_mode= 1764cdf0c1d5Smjnelson typeset file 1765cdf0c1d5Smjnelson 1766cdf0c1d5Smjnelson # 1767cdf0c1d5Smjnelson # Get old file mode, from the parent revision manifest entry. 1768cdf0c1d5Smjnelson # Mercurial only stores a "file is executable" flag, but the 1769cdf0c1d5Smjnelson # manifest will display an octal mode "644" or "755". 1770cdf0c1d5Smjnelson # 1771cdf0c1d5Smjnelson if [[ "$PDIR" == "." ]]; then 1772cdf0c1d5Smjnelson file="$PF" 1773cdf0c1d5Smjnelson else 1774cdf0c1d5Smjnelson file="$PDIR/$PF" 1775cdf0c1d5Smjnelson fi 1776cdf0c1d5Smjnelson file=`echo $file | sed 's#/#\\\/#g'` 1777cdf0c1d5Smjnelson # match the exact filename, and return only the permission digits 1778cdf0c1d5Smjnelson old_mode=`sed -n -e "/^\\(...\\) . ${file}$/s//\\1/p" \ 1779cdf0c1d5Smjnelson < $HG_PARENT_MANIFEST` 1780cdf0c1d5Smjnelson 1781cdf0c1d5Smjnelson # 1782cdf0c1d5Smjnelson # Get new file mode, directly from the filesystem. 1783cdf0c1d5Smjnelson # Normalize the mode to match Mercurial's behavior. 1784cdf0c1d5Smjnelson # 1785cdf0c1d5Smjnelson new_mode=`get_file_mode $CWS/$DIR/$F` 1786cdf0c1d5Smjnelson if [[ -n "$new_mode" ]]; then 1787cdf0c1d5Smjnelson if [[ "$new_mode" = *[1357]* ]]; then 1788cdf0c1d5Smjnelson new_mode=755 1789cdf0c1d5Smjnelson else 1790cdf0c1d5Smjnelson new_mode=644 1791cdf0c1d5Smjnelson fi 1792cdf0c1d5Smjnelson fi 1793cdf0c1d5Smjnelson 1794cdf0c1d5Smjnelson # 1795cdf0c1d5Smjnelson # new version of the file. 1796cdf0c1d5Smjnelson # 1797cdf0c1d5Smjnelson rm -rf $newdir/$DIR/$F 1798cdf0c1d5Smjnelson if [[ -e $CWS/$DIR/$F ]]; then 1799cdf0c1d5Smjnelson cp $CWS/$DIR/$F $newdir/$DIR/$F 1800cdf0c1d5Smjnelson if [[ -n $new_mode ]]; then 1801cdf0c1d5Smjnelson chmod $new_mode $newdir/$DIR/$F 1802cdf0c1d5Smjnelson else 1803cdf0c1d5Smjnelson # should never happen 1804cdf0c1d5Smjnelson print -u2 "ERROR: set mode of $newdir/$DIR/$F" 1805cdf0c1d5Smjnelson fi 1806cdf0c1d5Smjnelson fi 1807cdf0c1d5Smjnelson 1808cdf0c1d5Smjnelson # 1809cdf0c1d5Smjnelson # parent's version of the file 1810cdf0c1d5Smjnelson # 1811cdf0c1d5Smjnelson # Note that we get this from the last version common to both 1812cdf0c1d5Smjnelson # ourselves and the parent. References are via $CWS since we have no 1813cdf0c1d5Smjnelson # guarantee that the parent workspace is reachable via the filesystem. 1814cdf0c1d5Smjnelson # 1815cdf0c1d5Smjnelson if [[ -n $parent_webrev && -e $PWS/$PDIR/$PF ]]; then 1816cdf0c1d5Smjnelson cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF 1817cdf0c1d5Smjnelson elif [[ -n $HG_PARENT ]]; then 1818cdf0c1d5Smjnelson hg cat -R $CWS -r $HG_PARENT $CWS/$PDIR/$PF > \ 1819cdf0c1d5Smjnelson $olddir/$PDIR/$PF 2>/dev/null 1820cdf0c1d5Smjnelson 182102d26c39SVladimir Kotal if (( $? != 0 )); then 1822cdf0c1d5Smjnelson rm -f $olddir/$PDIR/$PF 1823cdf0c1d5Smjnelson else 1824cdf0c1d5Smjnelson if [[ -n $old_mode ]]; then 1825cdf0c1d5Smjnelson chmod $old_mode $olddir/$PDIR/$PF 1826cdf0c1d5Smjnelson else 1827cdf0c1d5Smjnelson # should never happen 1828cdf0c1d5Smjnelson print -u2 "ERROR: set mode of $olddir/$PDIR/$PF" 1829cdf0c1d5Smjnelson fi 1830cdf0c1d5Smjnelson fi 1831cdf0c1d5Smjnelson fi 1832cdf0c1d5Smjnelson} 1833cdf0c1d5Smjnelson 1834cdf0c1d5Smjnelsonfunction build_old_new_subversion 1835cdf0c1d5Smjnelson{ 1836cdf0c1d5Smjnelson typeset olddir="$1" 1837cdf0c1d5Smjnelson typeset newdir="$2" 1838cdf0c1d5Smjnelson 1839cdf0c1d5Smjnelson # Snag new version of file. 1840cdf0c1d5Smjnelson rm -f $newdir/$DIR/$F 1841cdf0c1d5Smjnelson [[ -e $CWS/$DIR/$F ]] && cp $CWS/$DIR/$F $newdir/$DIR/$F 1842cdf0c1d5Smjnelson 1843cdf0c1d5Smjnelson if [[ -n $PWS && -e $PWS/$PDIR/$PF ]]; then 1844cdf0c1d5Smjnelson cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF 1845cdf0c1d5Smjnelson else 1846cdf0c1d5Smjnelson # Get the parent's version of the file. 1847cdf0c1d5Smjnelson svn status $CWS/$DIR/$F | read stat file 1848cdf0c1d5Smjnelson if [[ $stat != "A" ]]; then 1849cdf0c1d5Smjnelson svn cat -r BASE $CWS/$DIR/$F > $olddir/$PDIR/$PF 1850cdf0c1d5Smjnelson fi 1851cdf0c1d5Smjnelson fi 1852cdf0c1d5Smjnelson} 1853cdf0c1d5Smjnelson 1854cdf0c1d5Smjnelsonfunction build_old_new_unknown 1855cdf0c1d5Smjnelson{ 1856cdf0c1d5Smjnelson typeset olddir="$1" 1857cdf0c1d5Smjnelson typeset newdir="$2" 1858cdf0c1d5Smjnelson 1859cdf0c1d5Smjnelson # 1860cdf0c1d5Smjnelson # Snag new version of file. 1861cdf0c1d5Smjnelson # 1862cdf0c1d5Smjnelson rm -f $newdir/$DIR/$F 1863cdf0c1d5Smjnelson [[ -e $CWS/$DIR/$F ]] && cp $CWS/$DIR/$F $newdir/$DIR/$F 1864cdf0c1d5Smjnelson 1865cdf0c1d5Smjnelson # 1866cdf0c1d5Smjnelson # Snag the parent's version of the file. 1867cdf0c1d5Smjnelson # 1868cdf0c1d5Smjnelson if [[ -f $PWS/$PDIR/$PF ]]; then 1869cdf0c1d5Smjnelson rm -f $olddir/$PDIR/$PF 1870cdf0c1d5Smjnelson cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF 1871cdf0c1d5Smjnelson fi 1872cdf0c1d5Smjnelson} 1873cdf0c1d5Smjnelson 1874cdf0c1d5Smjnelsonfunction build_old_new 1875cdf0c1d5Smjnelson{ 1876cdf0c1d5Smjnelson typeset WDIR=$1 1877cdf0c1d5Smjnelson typeset PWS=$2 1878cdf0c1d5Smjnelson typeset PDIR=$3 1879cdf0c1d5Smjnelson typeset PF=$4 1880cdf0c1d5Smjnelson typeset CWS=$5 1881cdf0c1d5Smjnelson typeset DIR=$6 1882cdf0c1d5Smjnelson typeset F=$7 1883cdf0c1d5Smjnelson 1884cdf0c1d5Smjnelson typeset olddir="$WDIR/raw_files/old" 1885cdf0c1d5Smjnelson typeset newdir="$WDIR/raw_files/new" 1886cdf0c1d5Smjnelson 1887cdf0c1d5Smjnelson mkdir -p $olddir/$PDIR 1888cdf0c1d5Smjnelson mkdir -p $newdir/$DIR 1889cdf0c1d5Smjnelson 1890cdf0c1d5Smjnelson if [[ $SCM_MODE == "teamware" ]]; then 1891cdf0c1d5Smjnelson build_old_new_teamware "$olddir" "$newdir" 1892cdf0c1d5Smjnelson elif [[ $SCM_MODE == "mercurial" ]]; then 1893cdf0c1d5Smjnelson build_old_new_mercurial "$olddir" "$newdir" 1894cdf0c1d5Smjnelson elif [[ $SCM_MODE == "subversion" ]]; then 1895cdf0c1d5Smjnelson build_old_new_subversion "$olddir" "$newdir" 1896cdf0c1d5Smjnelson elif [[ $SCM_MODE == "unknown" ]]; then 1897cdf0c1d5Smjnelson build_old_new_unknown "$olddir" "$newdir" 1898cdf0c1d5Smjnelson fi 1899cdf0c1d5Smjnelson 1900cdf0c1d5Smjnelson if [[ ! -f $olddir/$PDIR/$PF && ! -f $newdir/$DIR/$F ]]; then 1901cdf0c1d5Smjnelson print "*** Error: file not in parent or child" 1902cdf0c1d5Smjnelson return 1 1903cdf0c1d5Smjnelson fi 1904cdf0c1d5Smjnelson return 0 1905cdf0c1d5Smjnelson} 1906cdf0c1d5Smjnelson 1907cdf0c1d5Smjnelson 1908daaffb31Sdp# 1909daaffb31Sdp# Usage message. 1910daaffb31Sdp# 1911daaffb31Sdpfunction usage 1912daaffb31Sdp{ 1913daaffb31Sdp print 'Usage:\twebrev [common-options] 1914daaffb31Sdp webrev [common-options] ( <file> | - ) 1915daaffb31Sdp webrev [common-options] -w <wx file> 1916daaffb31Sdp 1917daaffb31SdpOptions: 1918*ba44d8a2SVladimir Kotal -D: delete remote webrev 1919daaffb31Sdp -i <filename>: Include <filename> in the index.html file. 1920*ba44d8a2SVladimir Kotal -n: do not generate the webrev (useful with -U) 1921*ba44d8a2SVladimir Kotal -O: Print bugids/arc cases suitable for OpenSolaris. 1922daaffb31Sdp -o <outdir>: Output webrev to specified directory. 1923daaffb31Sdp -p <compare-against>: Use specified parent wkspc or basis for comparison 192402d26c39SVladimir Kotal -t <remote_target>: Specify remote destination for webrev upload 192502d26c39SVladimir Kotal -U: upload the webrev to remote destination 1926daaffb31Sdp -w <wxfile>: Use specified wx active file. 1927daaffb31Sdp 1928daaffb31SdpEnvironment: 1929daaffb31Sdp WDIR: Control the output directory. 1930daaffb31Sdp WEBREV_BUGURL: Control the URL prefix for bugids. 1931daaffb31Sdp WEBREV_SACURL: Control the URL prefix for ARC cases. 1932*ba44d8a2SVladimir Kotal WEBREV_TRASH_DIR: Set directory for webrev delete. 1933daaffb31Sdp 1934cdf0c1d5SmjnelsonSCM Specific Options: 1935cdf0c1d5Smjnelson TeamWare: webrev [common-options] -l [arguments to 'putback'] 1936cdf0c1d5Smjnelson 1937daaffb31SdpSCM Environment: 1938cdf0c1d5Smjnelson CODEMGR_WS: Workspace location. 1939cdf0c1d5Smjnelson CODEMGR_PARENT: Parent workspace location. 1940daaffb31Sdp' 1941daaffb31Sdp 1942daaffb31Sdp exit 2 1943daaffb31Sdp} 1944daaffb31Sdp 1945daaffb31Sdp# 1946daaffb31Sdp# 1947daaffb31Sdp# Main program starts here 1948daaffb31Sdp# 1949daaffb31Sdp# 1950daaffb31Sdp 1951daaffb31Sdptrap "rm -f /tmp/$$.* ; exit" 0 1 2 3 15 1952daaffb31Sdp 1953daaffb31Sdpset +o noclobber 1954daaffb31Sdp 1955cdf0c1d5SmjnelsonPATH=$(dirname $(whence $0)):$PATH 1956cdf0c1d5Smjnelson 195714983201Sdp[[ -z $WDIFF ]] && WDIFF=`look_for_prog wdiff` 195814983201Sdp[[ -z $WX ]] && WX=`look_for_prog wx` 1959cdf0c1d5Smjnelson[[ -z $HG_ACTIVE ]] && HG_ACTIVE=`look_for_prog hg-active` 1960cdf0c1d5Smjnelson[[ -z $WHICH_SCM ]] && WHICH_SCM=`look_for_prog which_scm` 196114983201Sdp[[ -z $CODEREVIEW ]] && CODEREVIEW=`look_for_prog codereview` 196214983201Sdp[[ -z $PS2PDF ]] && PS2PDF=`look_for_prog ps2pdf` 196314983201Sdp[[ -z $PERL ]] && PERL=`look_for_prog perl` 196402d26c39SVladimir Kotal[[ -z $RSYNC ]] && RSYNC=`look_for_prog rsync` 1965cdf0c1d5Smjnelson[[ -z $SCCS ]] && SCCS=`look_for_prog sccs` 1966cdf0c1d5Smjnelson[[ -z $AWK ]] && AWK=`look_for_prog nawk` 1967cdf0c1d5Smjnelson[[ -z $AWK ]] && AWK=`look_for_prog gawk` 1968cdf0c1d5Smjnelson[[ -z $AWK ]] && AWK=`look_for_prog awk` 196902d26c39SVladimir Kotal[[ -z $SCP ]] && SCP=`look_for_prog scp` 197002d26c39SVladimir Kotal[[ -z $SFTP ]] && SFTP=`look_for_prog sftp` 197102d26c39SVladimir Kotal[[ -z $MKTEMP ]] && MKTEMP=`look_for_prog mktemp` 197202d26c39SVladimir Kotal[[ -z $GREP ]] && GREP=`look_for_prog grep` 1973*ba44d8a2SVladimir Kotal[[ -z $FIND ]] && FIND=`look_for_prog find` 1974cdf0c1d5Smjnelson 1975*ba44d8a2SVladimir Kotal# set name of trash directory for remote webrev deletion 1976*ba44d8a2SVladimir KotalTRASH_DIR=".trash" 1977*ba44d8a2SVladimir Kotal[[ -n $WEBREV_TRASH_DIR ]] && TRASH_DIR=$WEBREV_TRASH_DIR 197814983201Sdp 197914983201Sdpif [[ ! -x $PERL ]]; then 198014983201Sdp print -u2 "Error: No perl interpreter found. Exiting." 198114983201Sdp exit 1 1982daaffb31Sdpfi 198314983201Sdp 1984cdf0c1d5Smjnelsonif [[ ! -x $WHICH_SCM ]]; then 1985cdf0c1d5Smjnelson print -u2 "Error: Could not find which_scm. Exiting." 1986cdf0c1d5Smjnelson exit 1 1987cdf0c1d5Smjnelsonfi 1988cdf0c1d5Smjnelson 198914983201Sdp# 199014983201Sdp# These aren't fatal, but we want to note them to the user. 199114983201Sdp# We don't warn on the absence of 'wx' until later when we've 199214983201Sdp# determined that we actually need to try to invoke it. 199314983201Sdp# 199414983201Sdp[[ ! -x $CODEREVIEW ]] && print -u2 "WARNING: codereview(1) not found." 199514983201Sdp[[ ! -x $PS2PDF ]] && print -u2 "WARNING: ps2pdf(1) not found." 199614983201Sdp[[ ! -x $WDIFF ]] && print -u2 "WARNING: wdiff not found." 1997daaffb31Sdp 1998daaffb31Sdp# Declare global total counters. 1999daaffb31Sdpinteger TOTL TINS TDEL TMOD TUNC 2000daaffb31Sdp 2001*ba44d8a2SVladimir Kotal# default remote host for upload/delete 2002*ba44d8a2SVladimir Kotaltypeset -r DEFAULT_REMOTE_HOST="cr.opensolaris.org" 2003*ba44d8a2SVladimir Kotal 2004*ba44d8a2SVladimir KotalDflag= 200514983201Sdpflist_mode= 200614983201Sdpflist_file= 2007daaffb31Sdpiflag= 200802d26c39SVladimir Kotallflag= 200902d26c39SVladimir KotalNflag= 201002d26c39SVladimir Kotalnflag= 201102d26c39SVladimir KotalOflag= 2012daaffb31Sdpoflag= 2013daaffb31Sdppflag= 201402d26c39SVladimir Kotaltflag= 201502d26c39SVladimir Kotaluflag= 201602d26c39SVladimir KotalUflag= 2017daaffb31Sdpwflag= 201802d26c39SVladimir Kotalremote_target= 2019*ba44d8a2SVladimir Kotal 2020*ba44d8a2SVladimir Kotal# 2021*ba44d8a2SVladimir Kotal# NOTE: when adding/removing options it is necessary to sync the list 2022*ba44d8a2SVladimir Kotal# with usr/src/tools/onbld/hgext/cdm.py 2023*ba44d8a2SVladimir Kotal# 2024*ba44d8a2SVladimir Kotalwhile getopts "i:o:p:lwONnt:UD" opt 2025daaffb31Sdpdo 2026daaffb31Sdp case $opt in 2027*ba44d8a2SVladimir Kotal D) Dflag=1;; 2028*ba44d8a2SVladimir Kotal 2029daaffb31Sdp i) iflag=1 2030daaffb31Sdp INCLUDE_FILE=$OPTARG;; 2031daaffb31Sdp 2032daaffb31Sdp # 2033daaffb31Sdp # If -l has been specified, we need to abort further options 2034daaffb31Sdp # processing, because subsequent arguments are going to be 2035daaffb31Sdp # arguments to 'putback -n'. 2036daaffb31Sdp # 2037daaffb31Sdp l) lflag=1 2038daaffb31Sdp break;; 2039daaffb31Sdp 204002d26c39SVladimir Kotal N) Nflag=1;; 204102d26c39SVladimir Kotal 204202d26c39SVladimir Kotal n) nflag=1;; 2043daaffb31Sdp 2044daaffb31Sdp O) Oflag=1;; 2045daaffb31Sdp 204602d26c39SVladimir Kotal o) oflag=1 204702d26c39SVladimir Kotal WDIR=$OPTARG;; 204802d26c39SVladimir Kotal 204902d26c39SVladimir Kotal p) pflag=1 205002d26c39SVladimir Kotal codemgr_parent=$OPTARG;; 205102d26c39SVladimir Kotal 205202d26c39SVladimir Kotal t) tflag=1 205302d26c39SVladimir Kotal remote_target=$OPTARG;; 205402d26c39SVladimir Kotal 205502d26c39SVladimir Kotal U) Uflag=1;; 205602d26c39SVladimir Kotal 205702d26c39SVladimir Kotal w) wflag=1;; 20583df69ef3SDarren Moffat 2059daaffb31Sdp ?) usage;; 2060daaffb31Sdp esac 2061daaffb31Sdpdone 2062daaffb31Sdp 2063daaffb31SdpFLIST=/tmp/$$.flist 2064daaffb31Sdp 2065daaffb31Sdpif [[ -n $wflag && -n $lflag ]]; then 2066daaffb31Sdp usage 2067daaffb31Sdpfi 2068daaffb31Sdp 206902d26c39SVladimir Kotal# more sanity checking 207002d26c39SVladimir Kotalif [[ -n $nflag && -z $Uflag ]]; then 2071*ba44d8a2SVladimir Kotal print "it does not make sense to skip webrev generation" \ 2072*ba44d8a2SVladimir Kotal "without -U" 207302d26c39SVladimir Kotal exit 1 207402d26c39SVladimir Kotalfi 207502d26c39SVladimir Kotal 2076*ba44d8a2SVladimir Kotalif [[ -n $tflag && -z $Uflag && -z $Dflag ]]; then 2077*ba44d8a2SVladimir Kotal echo "remote target has to be used only for upload or delete" 207802d26c39SVladimir Kotal exit 1 207902d26c39SVladimir Kotalfi 208002d26c39SVladimir Kotal 2081daaffb31Sdp# 2082daaffb31Sdp# If this manually set as the parent, and it appears to be an earlier webrev, 2083daaffb31Sdp# then note that fact and set the parent to the raw_files/new subdirectory. 2084daaffb31Sdp# 2085daaffb31Sdpif [[ -n $pflag && -d $codemgr_parent/raw_files/new ]]; then 2086daaffb31Sdp parent_webrev="$codemgr_parent" 2087daaffb31Sdp codemgr_parent="$codemgr_parent/raw_files/new" 2088daaffb31Sdpfi 2089daaffb31Sdp 2090daaffb31Sdpif [[ -z $wflag && -z $lflag ]]; then 2091daaffb31Sdp shift $(($OPTIND - 1)) 2092daaffb31Sdp 2093daaffb31Sdp if [[ $1 == "-" ]]; then 2094daaffb31Sdp cat > $FLIST 209514983201Sdp flist_mode="stdin" 209614983201Sdp flist_done=1 209714983201Sdp shift 2098daaffb31Sdp elif [[ -n $1 ]]; then 209914983201Sdp if [[ ! -r $1 ]]; then 2100daaffb31Sdp print -u2 "$1: no such file or not readable" 2101daaffb31Sdp usage 2102daaffb31Sdp fi 2103daaffb31Sdp cat $1 > $FLIST 210414983201Sdp flist_mode="file" 210514983201Sdp flist_file=$1 210614983201Sdp flist_done=1 210714983201Sdp shift 2108daaffb31Sdp else 210914983201Sdp flist_mode="auto" 2110daaffb31Sdp fi 2111daaffb31Sdpfi 2112daaffb31Sdp 2113daaffb31Sdp# 2114daaffb31Sdp# Before we go on to further consider -l and -w, work out which SCM we think 2115daaffb31Sdp# is in use. 2116daaffb31Sdp# 2117cdf0c1d5Smjnelson$WHICH_SCM | read SCM_MODE junk || exit 1 2118cdf0c1d5Smjnelsoncase "$SCM_MODE" in 2119cdf0c1d5Smjnelsonteamware|mercurial|subversion) 2120cdf0c1d5Smjnelson ;; 2121cdf0c1d5Smjnelsonunknown) 2122cdf0c1d5Smjnelson if [[ $flist_mode == "auto" ]]; then 2123cdf0c1d5Smjnelson print -u2 "Unable to determine SCM in use and file list not specified" 2124cdf0c1d5Smjnelson print -u2 "See which_scm(1) for SCM detection information." 21257c478bd9Sstevel@tonic-gate exit 1 21267c478bd9Sstevel@tonic-gate fi 2127cdf0c1d5Smjnelson ;; 2128cdf0c1d5Smjnelson*) 2129cdf0c1d5Smjnelson if [[ $flist_mode == "auto" ]]; then 2130cdf0c1d5Smjnelson print -u2 "Unsupported SCM in use ($SCM_MODE) and file list not specified" 2131cdf0c1d5Smjnelson exit 1 2132cdf0c1d5Smjnelson fi 2133cdf0c1d5Smjnelson ;; 2134cdf0c1d5Smjnelsonesac 21357c478bd9Sstevel@tonic-gate 2136daaffb31Sdpprint -u2 " SCM detected: $SCM_MODE" 2137daaffb31Sdp 2138daaffb31Sdpif [[ -n $lflag ]]; then 2139daaffb31Sdp # 2140daaffb31Sdp # If the -l flag is given instead of the name of a file list, 2141daaffb31Sdp # then generate the file list by extracting file names from a 2142daaffb31Sdp # putback -n. 2143daaffb31Sdp # 2144daaffb31Sdp shift $(($OPTIND - 1)) 2145cdf0c1d5Smjnelson if [[ $SCM_MODE == "teamware" ]]; then 2146daaffb31Sdp flist_from_teamware "$*" 2147cdf0c1d5Smjnelson else 2148cdf0c1d5Smjnelson print -u2 -- "Error: -l option only applies to TeamWare" 2149cdf0c1d5Smjnelson exit 1 2150cdf0c1d5Smjnelson fi 2151daaffb31Sdp flist_done=1 2152daaffb31Sdp shift $# 2153daaffb31Sdpelif [[ -n $wflag ]]; then 2154daaffb31Sdp # 2155daaffb31Sdp # If the -w is given then assume the file list is in Bonwick's "wx" 2156daaffb31Sdp # command format, i.e. pathname lines alternating with SCCS comment 2157daaffb31Sdp # lines with blank lines as separators. Use the SCCS comments later 2158daaffb31Sdp # in building the index.html file. 2159daaffb31Sdp # 2160daaffb31Sdp shift $(($OPTIND - 1)) 2161daaffb31Sdp wxfile=$1 2162daaffb31Sdp if [[ -z $wxfile && -n $CODEMGR_WS ]]; then 2163daaffb31Sdp if [[ -r $CODEMGR_WS/wx/active ]]; then 2164daaffb31Sdp wxfile=$CODEMGR_WS/wx/active 2165daaffb31Sdp fi 2166daaffb31Sdp fi 2167daaffb31Sdp 2168daaffb31Sdp [[ -z $wxfile ]] && print -u2 "wx file not specified, and could not " \ 2169daaffb31Sdp "be auto-detected (check \$CODEMGR_WS)" && exit 1 2170daaffb31Sdp 2171cdf0c1d5Smjnelson if [[ ! -r $wxfile ]]; then 2172cdf0c1d5Smjnelson print -u2 "$wxfile: no such file or not readable" 2173cdf0c1d5Smjnelson usage 2174cdf0c1d5Smjnelson fi 2175cdf0c1d5Smjnelson 2176daaffb31Sdp print -u2 " File list from: wx 'active' file '$wxfile' ... \c" 2177daaffb31Sdp flist_from_wx $wxfile 2178daaffb31Sdp flist_done=1 2179daaffb31Sdp if [[ -n "$*" ]]; then 2180daaffb31Sdp shift 2181daaffb31Sdp fi 218214983201Sdpelif [[ $flist_mode == "stdin" ]]; then 218314983201Sdp print -u2 " File list from: standard input" 218414983201Sdpelif [[ $flist_mode == "file" ]]; then 218514983201Sdp print -u2 " File list from: $flist_file" 2186daaffb31Sdpfi 2187daaffb31Sdp 2188daaffb31Sdpif [[ $# -gt 0 ]]; then 218914983201Sdp print -u2 "WARNING: unused arguments: $*" 2190daaffb31Sdpfi 2191daaffb31Sdp 2192daaffb31Sdpif [[ $SCM_MODE == "teamware" ]]; then 2193daaffb31Sdp # 2194daaffb31Sdp # Parent (internally $codemgr_parent) and workspace ($codemgr_ws) can 2195daaffb31Sdp # be set in a number of ways, in decreasing precedence: 2196daaffb31Sdp # 2197daaffb31Sdp # 1) on the command line (only for the parent) 2198daaffb31Sdp # 2) in the user environment 2199daaffb31Sdp # 3) in the flist 2200daaffb31Sdp # 4) automatically based on the workspace (only for the parent) 2201daaffb31Sdp # 2202daaffb31Sdp 2203daaffb31Sdp # 2204daaffb31Sdp # Here is case (2): the user environment 2205daaffb31Sdp # 2206daaffb31Sdp [[ -z $codemgr_ws && -n $CODEMGR_WS ]] && codemgr_ws=$CODEMGR_WS 2207daaffb31Sdp if [[ -n $codemgr_ws && ! -d $codemgr_ws ]]; then 2208daaffb31Sdp print -u2 "$codemgr_ws: no such workspace" 22097c478bd9Sstevel@tonic-gate exit 1 22107c478bd9Sstevel@tonic-gate fi 22117c478bd9Sstevel@tonic-gate 2212daaffb31Sdp [[ -z $codemgr_parent && -n $CODEMGR_PARENT ]] && \ 2213daaffb31Sdp codemgr_parent=$CODEMGR_PARENT 2214daaffb31Sdp if [[ -n $codemgr_parent && ! -d $codemgr_parent ]]; then 2215daaffb31Sdp print -u2 "$codemgr_parent: no such directory" 22167c478bd9Sstevel@tonic-gate exit 1 22177c478bd9Sstevel@tonic-gate fi 22187c478bd9Sstevel@tonic-gate 2219daaffb31Sdp # 2220daaffb31Sdp # If we're in auto-detect mode and we haven't already gotten the file 2221daaffb31Sdp # list, then see if we can get it by probing for wx. 2222daaffb31Sdp # 222314983201Sdp if [[ -z $flist_done && $flist_mode == "auto" && -n $codemgr_ws ]]; then 222414983201Sdp if [[ ! -x $WX ]]; then 222514983201Sdp print -u2 "WARNING: wx not found!" 2226daaffb31Sdp fi 22277c478bd9Sstevel@tonic-gate 2228daaffb31Sdp # 2229daaffb31Sdp # We need to use wx list -w so that we get renamed files, etc. 2230daaffb31Sdp # but only if a wx active file exists-- otherwise wx will 2231daaffb31Sdp # hang asking us to initialize our wx information. 2232daaffb31Sdp # 223314983201Sdp if [[ -x $WX && -f $codemgr_ws/wx/active ]]; then 2234daaffb31Sdp print -u2 " File list from: 'wx list -w' ... \c" 2235daaffb31Sdp $WX list -w > $FLIST 2236daaffb31Sdp $WX comments > /tmp/$$.wx_comments 2237daaffb31Sdp wxfile=/tmp/$$.wx_comments 2238daaffb31Sdp print -u2 "done" 2239daaffb31Sdp flist_done=1 2240daaffb31Sdp fi 2241daaffb31Sdp fi 2242daaffb31Sdp 2243daaffb31Sdp # 2244daaffb31Sdp # If by hook or by crook we've gotten a file list by now (perhaps 2245daaffb31Sdp # from the command line), eval it to extract environment variables from 2246daaffb31Sdp # it: This is step (3). 2247daaffb31Sdp # 2248daaffb31Sdp env_from_flist 2249daaffb31Sdp 2250daaffb31Sdp # 2251daaffb31Sdp # Continuing step (3): If we still have no file list, we'll try to get 2252daaffb31Sdp # it from teamware. 2253daaffb31Sdp # 2254daaffb31Sdp if [[ -z $flist_done ]]; then 2255daaffb31Sdp flist_from_teamware 2256daaffb31Sdp env_from_flist 2257daaffb31Sdp fi 2258daaffb31Sdp 2259daaffb31Sdp # 2260daaffb31Sdp # (4) If we still don't have a value for codemgr_parent, get it 2261daaffb31Sdp # from workspace. 2262daaffb31Sdp # 2263cdf0c1d5Smjnelson [[ -z $codemgr_ws ]] && codemgr_ws=`workspace name` 2264daaffb31Sdp [[ -z $codemgr_parent ]] && codemgr_parent=`workspace parent` 2265daaffb31Sdp if [[ ! -d $codemgr_parent ]]; then 2266daaffb31Sdp print -u2 "$CODEMGR_PARENT: no such parent workspace" 2267daaffb31Sdp exit 1 2268daaffb31Sdp fi 2269daaffb31Sdp 2270daaffb31Sdp # 2271cdf0c1d5Smjnelson # Observe true directory name of CODEMGR_WS, as used later in 2272cdf0c1d5Smjnelson # webrev title. 2273cdf0c1d5Smjnelson # 2274cdf0c1d5Smjnelson codemgr_ws=$(cd $codemgr_ws;print $PWD) 2275cdf0c1d5Smjnelson 2276cdf0c1d5Smjnelson # 2277daaffb31Sdp # Reset CODEMGR_WS to make sure teamware commands are happy. 2278daaffb31Sdp # 2279daaffb31Sdp CODEMGR_WS=$codemgr_ws 2280daaffb31Sdp CWS=$codemgr_ws 2281daaffb31Sdp PWS=$codemgr_parent 2282cdf0c1d5Smjnelson 2283cdf0c1d5Smjnelson [[ -n $parent_webrev ]] && RWS=$(workspace parent $CWS) 2284cdf0c1d5Smjnelson 2285cdf0c1d5Smjnelsonelif [[ $SCM_MODE == "mercurial" ]]; then 2286cdf0c1d5Smjnelson [[ -z $codemgr_ws && -n $CODEMGR_WS ]] && \ 2287cdf0c1d5Smjnelson codemgr_ws=`hg root -R $CODEMGR_WS 2>/dev/null` 2288cdf0c1d5Smjnelson 2289cdf0c1d5Smjnelson [[ -z $codemgr_ws ]] && codemgr_ws=`hg root 2>/dev/null` 2290cdf0c1d5Smjnelson 2291cdf0c1d5Smjnelson # 2292cdf0c1d5Smjnelson # Parent can either be specified with -p 2293cdf0c1d5Smjnelson # Specified with CODEMGR_PARENT in the environment 2294cdf0c1d5Smjnelson # or taken from hg's default path. 2295cdf0c1d5Smjnelson # 2296cdf0c1d5Smjnelson 2297cdf0c1d5Smjnelson if [[ -z $codemgr_parent && -n $CODEMGR_PARENT ]]; then 2298cdf0c1d5Smjnelson codemgr_parent=$CODEMGR_PARENT 2299cdf0c1d5Smjnelson fi 2300cdf0c1d5Smjnelson 2301cdf0c1d5Smjnelson if [[ -z $codemgr_parent ]]; then 2302cdf0c1d5Smjnelson codemgr_parent=`hg path -R $codemgr_ws default 2>/dev/null` 2303cdf0c1d5Smjnelson fi 2304cdf0c1d5Smjnelson 2305cdf0c1d5Smjnelson CWS_REV=`hg parent -R $codemgr_ws --template '{node|short}' 2>/dev/null` 2306cdf0c1d5Smjnelson CWS=$codemgr_ws 2307cdf0c1d5Smjnelson PWS=$codemgr_parent 2308cdf0c1d5Smjnelson 2309cdf0c1d5Smjnelson # 2310cdf0c1d5Smjnelson # If the parent is a webrev, we want to do some things against 2311cdf0c1d5Smjnelson # the natural workspace parent (file list, comments, etc) 2312cdf0c1d5Smjnelson # 2313cdf0c1d5Smjnelson if [[ -n $parent_webrev ]]; then 2314cdf0c1d5Smjnelson real_parent=$(hg path -R $codemgr_ws default 2>/dev/null) 2315cdf0c1d5Smjnelson else 2316cdf0c1d5Smjnelson real_parent=$PWS 2317cdf0c1d5Smjnelson fi 2318cdf0c1d5Smjnelson 2319cdf0c1d5Smjnelson # 2320cdf0c1d5Smjnelson # If hg-active exists, then we run it. In the case of no explicit 2321cdf0c1d5Smjnelson # flist given, we'll use it for our comments. In the case of an 2322cdf0c1d5Smjnelson # explicit flist given we'll try to use it for comments for any 2323cdf0c1d5Smjnelson # files mentioned in the flist. 2324cdf0c1d5Smjnelson # 2325cdf0c1d5Smjnelson if [[ -z $flist_done ]]; then 2326cdf0c1d5Smjnelson flist_from_mercurial $CWS $real_parent 2327cdf0c1d5Smjnelson flist_done=1 2328cdf0c1d5Smjnelson fi 2329cdf0c1d5Smjnelson 2330cdf0c1d5Smjnelson # 2331cdf0c1d5Smjnelson # If we have a file list now, pull out any variables set 2332cdf0c1d5Smjnelson # therein. We do this now (rather than when we possibly use 2333cdf0c1d5Smjnelson # hg-active to find comments) to avoid stomping specifications 2334cdf0c1d5Smjnelson # in the user-specified flist. 2335cdf0c1d5Smjnelson # 2336cdf0c1d5Smjnelson if [[ -n $flist_done ]]; then 2337cdf0c1d5Smjnelson env_from_flist 2338cdf0c1d5Smjnelson fi 2339cdf0c1d5Smjnelson 2340cdf0c1d5Smjnelson # 2341cdf0c1d5Smjnelson # Only call hg-active if we don't have a wx formatted file already 2342cdf0c1d5Smjnelson # 2343cdf0c1d5Smjnelson if [[ -x $HG_ACTIVE && -z $wxfile ]]; then 2344cdf0c1d5Smjnelson print " Comments from: hg-active -p $real_parent ...\c" 2345cdf0c1d5Smjnelson hg_active_wxfile $CWS $real_parent 2346cdf0c1d5Smjnelson print " Done." 2347cdf0c1d5Smjnelson fi 2348cdf0c1d5Smjnelson 2349cdf0c1d5Smjnelson # 2350cdf0c1d5Smjnelson # At this point we must have a wx flist either from hg-active, 2351cdf0c1d5Smjnelson # or in general. Use it to try and find our parent revision, 2352cdf0c1d5Smjnelson # if we don't have one. 2353cdf0c1d5Smjnelson # 2354cdf0c1d5Smjnelson if [[ -z $HG_PARENT ]]; then 235502d26c39SVladimir Kotal eval `sed -e "s/#.*$//" $wxfile | $GREP HG_PARENT=` 2356cdf0c1d5Smjnelson fi 2357cdf0c1d5Smjnelson 2358cdf0c1d5Smjnelson # 2359cdf0c1d5Smjnelson # If we still don't have a parent, we must have been given a 2360cdf0c1d5Smjnelson # wx-style active list with no HG_PARENT specification, run 2361cdf0c1d5Smjnelson # hg-active and pull an HG_PARENT out of it, ignore the rest. 2362cdf0c1d5Smjnelson # 2363cdf0c1d5Smjnelson if [[ -z $HG_PARENT && -x $HG_ACTIVE ]]; then 2364cdf0c1d5Smjnelson $HG_ACTIVE -w $codemgr_ws -p $real_parent | \ 236502d26c39SVladimir Kotal eval `sed -e "s/#.*$//" | $GREP HG_PARENT=` 2366cdf0c1d5Smjnelson elif [[ -z $HG_PARENT ]]; then 2367cdf0c1d5Smjnelson print -u2 "Error: Cannot discover parent revision" 2368cdf0c1d5Smjnelson exit 1 2369cdf0c1d5Smjnelson fi 2370cdf0c1d5Smjnelsonelif [[ $SCM_MODE == "subversion" ]]; then 2371cdf0c1d5Smjnelson if [[ -n $CODEMGR_WS && -d $CODEMGR_WS/.svn ]]; then 2372cdf0c1d5Smjnelson CWS=$CODEMGR_WS 2373cdf0c1d5Smjnelson else 2374cdf0c1d5Smjnelson svn info | while read line; do 2375cdf0c1d5Smjnelson if [[ $line == "URL: "* ]]; then 2376cdf0c1d5Smjnelson url=${line#URL: } 2377cdf0c1d5Smjnelson elif [[ $line == "Repository Root: "* ]]; then 2378cdf0c1d5Smjnelson repo=${line#Repository Root: } 2379cdf0c1d5Smjnelson fi 2380cdf0c1d5Smjnelson done 2381cdf0c1d5Smjnelson 2382cdf0c1d5Smjnelson rel=${url#$repo} 2383cdf0c1d5Smjnelson CWS=${PWD%$rel} 2384cdf0c1d5Smjnelson fi 2385cdf0c1d5Smjnelson 2386cdf0c1d5Smjnelson # 2387cdf0c1d5Smjnelson # We only will have a real parent workspace in the case one 2388cdf0c1d5Smjnelson # was specified (be it an older webrev, or another checkout). 2389cdf0c1d5Smjnelson # 2390cdf0c1d5Smjnelson [[ -n $codemgr_parent ]] && PWS=$codemgr_parent 2391cdf0c1d5Smjnelson 2392cdf0c1d5Smjnelson if [[ -z $flist_done && $flist_mode == "auto" ]]; then 2393cdf0c1d5Smjnelson flist_from_subversion $CWS $OLDPWD 2394cdf0c1d5Smjnelson fi 2395cdf0c1d5Smjnelsonelse 2396cdf0c1d5Smjnelson if [[ $SCM_MODE == "unknown" ]]; then 2397cdf0c1d5Smjnelson print -u2 " Unknown type of SCM in use" 2398cdf0c1d5Smjnelson else 2399cdf0c1d5Smjnelson print -u2 " Unsupported SCM in use: $SCM_MODE" 2400cdf0c1d5Smjnelson fi 2401cdf0c1d5Smjnelson 2402cdf0c1d5Smjnelson env_from_flist 2403cdf0c1d5Smjnelson 2404cdf0c1d5Smjnelson if [[ -z $CODEMGR_WS ]]; then 2405cdf0c1d5Smjnelson print -u2 "SCM not detected/supported and CODEMGR_WS not specified" 2406cdf0c1d5Smjnelson exit 1 2407cdf0c1d5Smjnelson fi 2408cdf0c1d5Smjnelson 2409cdf0c1d5Smjnelson if [[ -z $CODEMGR_PARENT ]]; then 2410cdf0c1d5Smjnelson print -u2 "SCM not detected/supported and CODEMGR_PARENT not specified" 2411cdf0c1d5Smjnelson exit 1 2412cdf0c1d5Smjnelson fi 2413cdf0c1d5Smjnelson 2414cdf0c1d5Smjnelson CWS=$CODEMGR_WS 2415cdf0c1d5Smjnelson PWS=$CODEMGR_PARENT 2416daaffb31Sdpfi 2417daaffb31Sdp 2418daaffb31Sdp# 2419daaffb31Sdp# If the user didn't specify a -i option, check to see if there is a 2420daaffb31Sdp# webrev-info file in the workspace directory. 2421daaffb31Sdp# 2422daaffb31Sdpif [[ -z $iflag && -r "$CWS/webrev-info" ]]; then 2423daaffb31Sdp iflag=1 2424daaffb31Sdp INCLUDE_FILE="$CWS/webrev-info" 2425daaffb31Sdpfi 2426daaffb31Sdp 2427daaffb31Sdpif [[ -n $iflag ]]; then 2428daaffb31Sdp if [[ ! -r $INCLUDE_FILE ]]; then 2429daaffb31Sdp print -u2 "include file '$INCLUDE_FILE' does not exist or is" \ 2430daaffb31Sdp "not readable." 2431daaffb31Sdp exit 1 2432daaffb31Sdp else 2433daaffb31Sdp # 2434daaffb31Sdp # $INCLUDE_FILE may be a relative path, and the script alters 2435daaffb31Sdp # PWD, so we just stash a copy in /tmp. 2436daaffb31Sdp # 2437daaffb31Sdp cp $INCLUDE_FILE /tmp/$$.include 2438daaffb31Sdp fi 2439daaffb31Sdpfi 2440daaffb31Sdp 2441daaffb31Sdp# 2442daaffb31Sdp# Output directory. 2443daaffb31Sdp# 2444daaffb31SdpWDIR=${WDIR:-$CWS/webrev} 2445daaffb31Sdp 2446daaffb31Sdp# 244702d26c39SVladimir Kotal# Name of the webrev, derived from the workspace name or output directory; 244802d26c39SVladimir Kotal# in the future this could potentially be an option. 2449daaffb31Sdp# 245002d26c39SVladimir Kotalif [[ -n $oflag ]]; then 245102d26c39SVladimir Kotal WNAME=${WDIR##*/} 245202d26c39SVladimir Kotalelse 2453daaffb31Sdp WNAME=${CWS##*/} 245402d26c39SVladimir Kotalfi 245502d26c39SVladimir Kotal 2456*ba44d8a2SVladimir Kotal# Make sure remote target is well formed for remote upload/delete. 2457*ba44d8a2SVladimir Kotalif [[ -n $Dflag || -n $Uflag ]]; then 2458*ba44d8a2SVladimir Kotal # If remote target is not specified, build it from scratch using 2459*ba44d8a2SVladimir Kotal # the default values. 2460*ba44d8a2SVladimir Kotal if [[ -z $tflag ]]; then 2461*ba44d8a2SVladimir Kotal remote_target=${DEFAULT_REMOTE_HOST}:${WNAME} 2462*ba44d8a2SVladimir Kotal else 2463*ba44d8a2SVladimir Kotal # If destination specification is not in the form of 2464*ba44d8a2SVladimir Kotal # host_spec:remote_dir then assume it is just remote hostname 2465*ba44d8a2SVladimir Kotal # and append a colon and destination directory formed from 2466*ba44d8a2SVladimir Kotal # local webrev directory name. 2467*ba44d8a2SVladimir Kotal if [[ -z ${remote_target##*:} ]]; then 2468*ba44d8a2SVladimir Kotal if [[ "${remote_target}" == *: ]]; then 2469*ba44d8a2SVladimir Kotal dst=${remote_target}${WNAME} 2470*ba44d8a2SVladimir Kotal else 2471*ba44d8a2SVladimir Kotal dst=${remote_target}:${WNAME} 2472*ba44d8a2SVladimir Kotal fi 2473*ba44d8a2SVladimir Kotal fi 2474*ba44d8a2SVladimir Kotal fi 2475*ba44d8a2SVladimir Kotalfi 2476*ba44d8a2SVladimir Kotal 2477*ba44d8a2SVladimir Kotal# Option -D by itself (option -U not present) implies no webrev generation. 2478*ba44d8a2SVladimir Kotalif [[ -z $Uflag && -n $Dflag ]]; then 2479*ba44d8a2SVladimir Kotal delete_webrev 1 2480*ba44d8a2SVladimir Kotal exit $? 2481*ba44d8a2SVladimir Kotalfi 2482*ba44d8a2SVladimir Kotal 2483*ba44d8a2SVladimir Kotal# Do not generate the webrev, just upload it or delete it. 2484*ba44d8a2SVladimir Kotalif [[ -n $nflag ]]; then 2485*ba44d8a2SVladimir Kotal if [[ -n $Dflag ]]; then 2486*ba44d8a2SVladimir Kotal delete_webrev 1 2487*ba44d8a2SVladimir Kotal (( $? == 0 )) || exit $? 2488*ba44d8a2SVladimir Kotal fi 2489*ba44d8a2SVladimir Kotal if [[ -n $Uflag ]]; then 249002d26c39SVladimir Kotal upload_webrev 249102d26c39SVladimir Kotal exit $? 249202d26c39SVladimir Kotal fi 2493*ba44d8a2SVladimir Kotalfi 2494daaffb31Sdp 2495e0e0293aSjmcpif [ "${WDIR%%/*}" ]; then 24967c478bd9Sstevel@tonic-gate WDIR=$PWD/$WDIR 24977c478bd9Sstevel@tonic-gatefi 2498daaffb31Sdp 2499daaffb31Sdpif [[ ! -d $WDIR ]]; then 2500daaffb31Sdp mkdir -p $WDIR 2501*ba44d8a2SVladimir Kotal (( $? != 0 )) && exit 1 25027c478bd9Sstevel@tonic-gatefi 25037c478bd9Sstevel@tonic-gate 2504daaffb31Sdp# 2505daaffb31Sdp# Summarize what we're going to do. 2506daaffb31Sdp# 2507cdf0c1d5Smjnelsonif [[ -n $CWS_REV ]]; then 2508cdf0c1d5Smjnelson print " Workspace: $CWS (at $CWS_REV)" 2509cdf0c1d5Smjnelsonelse 2510daaffb31Sdp print " Workspace: $CWS" 2511cdf0c1d5Smjnelsonfi 2512daaffb31Sdpif [[ -n $parent_webrev ]]; then 2513daaffb31Sdp print "Compare against: webrev at $parent_webrev" 2514daaffb31Sdpelse 2515cdf0c1d5Smjnelson if [[ -n $HG_PARENT ]]; then 2516cdf0c1d5Smjnelson hg_parent_short=`echo $HG_PARENT \ 2517cdf0c1d5Smjnelson | sed -e 's/\([0-9a-f]\{12\}\).*/\1/'` 2518cdf0c1d5Smjnelson print "Compare against: $PWS (at $hg_parent_short)" 2519cdf0c1d5Smjnelson else 2520daaffb31Sdp print "Compare against: $PWS" 2521daaffb31Sdp fi 2522cdf0c1d5Smjnelsonfi 2523daaffb31Sdp 2524daaffb31Sdp[[ -n $INCLUDE_FILE ]] && print " Including: $INCLUDE_FILE" 2525daaffb31Sdpprint " Output to: $WDIR" 2526daaffb31Sdp 2527daaffb31Sdp# 25287c478bd9Sstevel@tonic-gate# Save the file list in the webrev dir 2529daaffb31Sdp# 2530daaffb31Sdp[[ ! $FLIST -ef $WDIR/file.list ]] && cp $FLIST $WDIR/file.list 25317c478bd9Sstevel@tonic-gate 2532daaffb31Sdp# 2533daaffb31Sdp# Bug IDs will be replaced by a URL. Order of precedence 2534daaffb31Sdp# is: default location, $WEBREV_BUGURL, the -O flag. 2535daaffb31Sdp# 2536daaffb31SdpBUGURL='http://monaco.sfbay.sun.com/detail.jsp?cr=' 2537daaffb31Sdp[[ -n $WEBREV_BUGURL ]] && BUGURL="$WEBREV_BUGURL" 2538daaffb31Sdp[[ -n "$Oflag" ]] && \ 2539daaffb31Sdp BUGURL='http://bugs.opensolaris.org/bugdatabase/view_bug.do?bug_id=' 25407c478bd9Sstevel@tonic-gate 2541daaffb31Sdp# 2542daaffb31Sdp# Likewise, ARC cases will be replaced by a URL. Order of precedence 2543daaffb31Sdp# is: default, $WEBREV_SACURL, the -O flag. 2544daaffb31Sdp# 2545daaffb31Sdp# Note that -O also triggers different substitution behavior for 2546daaffb31Sdp# SACURL. See sac2url(). 2547daaffb31Sdp# 2548daaffb31SdpSACURL='http://sac.eng.sun.com' 2549daaffb31Sdp[[ -n $WEBREV_SACURL ]] && SACURL="$WEBREV_SACURL" 2550e0e0293aSjmcp[[ -n "$Oflag" ]] && \ 2551daaffb31Sdp SACURL='http://www.opensolaris.org/os/community/arc/caselog' 25527c478bd9Sstevel@tonic-gate 2553daaffb31Sdprm -f $WDIR/$WNAME.patch 2554daaffb31Sdprm -f $WDIR/$WNAME.ps 2555daaffb31Sdprm -f $WDIR/$WNAME.pdf 25567c478bd9Sstevel@tonic-gate 2557daaffb31Sdptouch $WDIR/$WNAME.patch 25587c478bd9Sstevel@tonic-gate 2559daaffb31Sdpprint " Output Files:" 2560daaffb31Sdp 2561daaffb31Sdp# 2562daaffb31Sdp# Clean up the file list: Remove comments, blank lines and env variables. 2563daaffb31Sdp# 2564daaffb31Sdpsed -e "s/#.*$//" -e "/=/d" -e "/^[ ]*$/d" $FLIST > /tmp/$$.flist.clean 2565daaffb31SdpFLIST=/tmp/$$.flist.clean 2566daaffb31Sdp 2567daaffb31Sdp# 2568cdf0c1d5Smjnelson# For Mercurial, create a cache of manifest entries. 2569cdf0c1d5Smjnelson# 2570cdf0c1d5Smjnelsonif [[ $SCM_MODE == "mercurial" ]]; then 2571cdf0c1d5Smjnelson # 2572cdf0c1d5Smjnelson # Transform the FLIST into a temporary sed script that matches 2573cdf0c1d5Smjnelson # relevant entries in the Mercurial manifest as follows: 2574cdf0c1d5Smjnelson # 1) The script will be used against the parent revision manifest, 2575cdf0c1d5Smjnelson # so for FLIST lines that have two filenames (a renamed file) 2576cdf0c1d5Smjnelson # keep only the old name. 2577cdf0c1d5Smjnelson # 2) Escape all forward slashes the filename. 2578cdf0c1d5Smjnelson # 3) Change the filename into another sed command that matches 2579cdf0c1d5Smjnelson # that file in "hg manifest -v" output: start of line, three 2580cdf0c1d5Smjnelson # octal digits for file permissions, space, a file type flag 2581cdf0c1d5Smjnelson # character, space, the filename, end of line. 2582cdf0c1d5Smjnelson # 2583cdf0c1d5Smjnelson SEDFILE=/tmp/$$.manifest.sed 2584cdf0c1d5Smjnelson sed ' 2585cdf0c1d5Smjnelson s#^[^ ]* ## 2586cdf0c1d5Smjnelson s#/#\\\/#g 2587cdf0c1d5Smjnelson s#^.*$#/^... . &$/p# 2588cdf0c1d5Smjnelson ' < $FLIST > $SEDFILE 2589cdf0c1d5Smjnelson 2590cdf0c1d5Smjnelson # 2591cdf0c1d5Smjnelson # Apply the generated script to the output of "hg manifest -v" 2592cdf0c1d5Smjnelson # to get the relevant subset for this webrev. 2593cdf0c1d5Smjnelson # 2594cdf0c1d5Smjnelson HG_PARENT_MANIFEST=/tmp/$$.manifest 2595cdf0c1d5Smjnelson hg -R $CWS manifest -v -r $HG_PARENT | 2596cdf0c1d5Smjnelson sed -n -f $SEDFILE > $HG_PARENT_MANIFEST 2597cdf0c1d5Smjnelsonfi 2598cdf0c1d5Smjnelson 2599cdf0c1d5Smjnelson# 2600daaffb31Sdp# First pass through the files: generate the per-file webrev HTML-files. 2601daaffb31Sdp# 2602daaffb31Sdpcat $FLIST | while read LINE 26037c478bd9Sstevel@tonic-gatedo 26047c478bd9Sstevel@tonic-gate set - $LINE 26057c478bd9Sstevel@tonic-gate P=$1 26067c478bd9Sstevel@tonic-gate 2607daaffb31Sdp # 2608daaffb31Sdp # Normally, each line in the file list is just a pathname of a 2609daaffb31Sdp # file that has been modified or created in the child. A file 2610daaffb31Sdp # that is renamed in the child workspace has two names on the 2611daaffb31Sdp # line: new name followed by the old name. 2612daaffb31Sdp # 2613daaffb31Sdp oldname="" 2614daaffb31Sdp oldpath="" 2615daaffb31Sdp rename= 2616daaffb31Sdp if [[ $# -eq 2 ]]; then 26177c478bd9Sstevel@tonic-gate PP=$2 # old filename 2618daaffb31Sdp oldname=" (was $PP)" 2619daaffb31Sdp oldpath="$PP" 2620daaffb31Sdp rename=1 26217c478bd9Sstevel@tonic-gate PDIR=${PP%/*} 2622daaffb31Sdp if [[ $PDIR == $PP ]]; then 26237c478bd9Sstevel@tonic-gate PDIR="." # File at root of workspace 26247c478bd9Sstevel@tonic-gate fi 26257c478bd9Sstevel@tonic-gate 26267c478bd9Sstevel@tonic-gate PF=${PP##*/} 26277c478bd9Sstevel@tonic-gate 26287c478bd9Sstevel@tonic-gate DIR=${P%/*} 2629daaffb31Sdp if [[ $DIR == $P ]]; then 26307c478bd9Sstevel@tonic-gate DIR="." # File at root of workspace 26317c478bd9Sstevel@tonic-gate fi 26327c478bd9Sstevel@tonic-gate 26337c478bd9Sstevel@tonic-gate F=${P##*/} 2634daaffb31Sdp 26357c478bd9Sstevel@tonic-gate else 26367c478bd9Sstevel@tonic-gate DIR=${P%/*} 2637daaffb31Sdp if [[ "$DIR" == "$P" ]]; then 26387c478bd9Sstevel@tonic-gate DIR="." # File at root of workspace 26397c478bd9Sstevel@tonic-gate fi 26407c478bd9Sstevel@tonic-gate 26417c478bd9Sstevel@tonic-gate F=${P##*/} 26427c478bd9Sstevel@tonic-gate 26437c478bd9Sstevel@tonic-gate PP=$P 26447c478bd9Sstevel@tonic-gate PDIR=$DIR 26457c478bd9Sstevel@tonic-gate PF=$F 26467c478bd9Sstevel@tonic-gate fi 26477c478bd9Sstevel@tonic-gate 2648daaffb31Sdp COMM=`getcomments html $P $PP` 26497c478bd9Sstevel@tonic-gate 2650daaffb31Sdp print "\t$P$oldname\n\t\t\c" 26517c478bd9Sstevel@tonic-gate 26527c478bd9Sstevel@tonic-gate # Make the webrev mirror directory if necessary 26537c478bd9Sstevel@tonic-gate mkdir -p $WDIR/$DIR 26547c478bd9Sstevel@tonic-gate 2655daaffb31Sdp # 2656daaffb31Sdp # If we're in OpenSolaris mode, we enforce a minor policy: 2657daaffb31Sdp # help to make sure the reviewer doesn't accidentally publish 2658e0e0293aSjmcp # source which is in usr/closed/* or deleted_files/usr/closed/* 2659daaffb31Sdp # 2660e0e0293aSjmcp if [[ -n "$Oflag" ]]; then 2661daaffb31Sdp pclosed=${P##usr/closed/} 2662e0e0293aSjmcp pdeleted=${P##deleted_files/usr/closed/} 2663e0e0293aSjmcp if [[ "$pclosed" != "$P" || "$pdeleted" != "$P" ]]; then 2664daaffb31Sdp print "*** Omitting closed source for OpenSolaris" \ 2665daaffb31Sdp "mode review" 2666daaffb31Sdp continue 2667daaffb31Sdp fi 2668daaffb31Sdp fi 2669daaffb31Sdp 2670daaffb31Sdp # 2671cdf0c1d5Smjnelson # We stash old and new files into parallel directories in $WDIR 2672daaffb31Sdp # and do our diffs there. This makes it possible to generate 2673daaffb31Sdp # clean looking diffs which don't have absolute paths present. 2674daaffb31Sdp # 2675daaffb31Sdp 2676cdf0c1d5Smjnelson build_old_new "$WDIR" "$PWS" "$PDIR" "$PF" "$CWS" "$DIR" "$F" || \ 26777c478bd9Sstevel@tonic-gate continue 26787c478bd9Sstevel@tonic-gate 2679cdf0c1d5Smjnelson # 2680cdf0c1d5Smjnelson # Keep the old PWD around, so we can safely switch back after 2681cdf0c1d5Smjnelson # diff generation, such that build_old_new runs in a 2682cdf0c1d5Smjnelson # consistent environment. 2683cdf0c1d5Smjnelson # 2684cdf0c1d5Smjnelson OWD=$PWD 2685daaffb31Sdp cd $WDIR/raw_files 2686daaffb31Sdp ofile=old/$PDIR/$PF 2687daaffb31Sdp nfile=new/$DIR/$F 26887c478bd9Sstevel@tonic-gate 2689daaffb31Sdp mv_but_nodiff= 2690daaffb31Sdp cmp $ofile $nfile > /dev/null 2>&1 2691daaffb31Sdp if [[ $? == 0 && $rename == 1 ]]; then 2692daaffb31Sdp mv_but_nodiff=1 2693daaffb31Sdp fi 2694daaffb31Sdp 2695daaffb31Sdp # 2696daaffb31Sdp # If we have old and new versions of the file then run the appropriate 2697daaffb31Sdp # diffs. This is complicated by a couple of factors: 2698daaffb31Sdp # 2699daaffb31Sdp # - renames must be handled specially: we emit a 'remove' 2700daaffb31Sdp # diff and an 'add' diff 2701daaffb31Sdp # - new files and deleted files must be handled specially 2702daaffb31Sdp # - Solaris patch(1m) can't cope with file creation 2703daaffb31Sdp # (and hence renames) as of this writing. 2704daaffb31Sdp # - To make matters worse, gnu patch doesn't interpret the 2705daaffb31Sdp # output of Solaris diff properly when it comes to 2706daaffb31Sdp # adds and deletes. We need to do some "cleansing" 2707daaffb31Sdp # transformations: 2708daaffb31Sdp # [to add a file] @@ -1,0 +X,Y @@ --> @@ -0,0 +X,Y @@ 2709daaffb31Sdp # [to del a file] @@ -X,Y +1,0 @@ --> @@ -X,Y +0,0 @@ 2710daaffb31Sdp # 2711daaffb31Sdp cleanse_rmfile="sed 's/^\(@@ [0-9+,-]*\) [0-9+,-]* @@$/\1 +0,0 @@/'" 2712daaffb31Sdp cleanse_newfile="sed 's/^@@ [0-9+,-]* \([0-9+,-]* @@\)$/@@ -0,0 \1/'" 2713daaffb31Sdp 2714daaffb31Sdp rm -f $WDIR/$DIR/$F.patch 2715daaffb31Sdp if [[ -z $rename ]]; then 2716e0e0293aSjmcp if [ ! -f "$ofile" ]; then 2717daaffb31Sdp diff -u /dev/null $nfile | sh -c "$cleanse_newfile" \ 2718daaffb31Sdp > $WDIR/$DIR/$F.patch 2719e0e0293aSjmcp elif [ ! -f "$nfile" ]; then 2720daaffb31Sdp diff -u $ofile /dev/null | sh -c "$cleanse_rmfile" \ 2721daaffb31Sdp > $WDIR/$DIR/$F.patch 2722daaffb31Sdp else 2723daaffb31Sdp diff -u $ofile $nfile > $WDIR/$DIR/$F.patch 2724daaffb31Sdp fi 2725daaffb31Sdp else 2726daaffb31Sdp diff -u $ofile /dev/null | sh -c "$cleanse_rmfile" \ 2727daaffb31Sdp > $WDIR/$DIR/$F.patch 2728daaffb31Sdp 2729daaffb31Sdp diff -u /dev/null $nfile | sh -c "$cleanse_newfile" \ 2730daaffb31Sdp >> $WDIR/$DIR/$F.patch 2731daaffb31Sdp 2732daaffb31Sdp fi 2733daaffb31Sdp 2734daaffb31Sdp # 2735daaffb31Sdp # Tack the patch we just made onto the accumulated patch for the 2736daaffb31Sdp # whole wad. 2737daaffb31Sdp # 2738daaffb31Sdp cat $WDIR/$DIR/$F.patch >> $WDIR/$WNAME.patch 2739daaffb31Sdp 2740daaffb31Sdp print " patch\c" 2741daaffb31Sdp 2742daaffb31Sdp if [[ -f $ofile && -f $nfile && -z $mv_but_nodiff ]]; then 2743daaffb31Sdp 2744daaffb31Sdp ${CDIFFCMD:-diff -bt -C 5} $ofile $nfile > $WDIR/$DIR/$F.cdiff 2745daaffb31Sdp diff_to_html $F $DIR/$F "C" "$COMM" < $WDIR/$DIR/$F.cdiff \ 2746daaffb31Sdp > $WDIR/$DIR/$F.cdiff.html 27477c478bd9Sstevel@tonic-gate print " cdiffs\c" 27487c478bd9Sstevel@tonic-gate 2749daaffb31Sdp ${UDIFFCMD:-diff -bt -U 5} $ofile $nfile > $WDIR/$DIR/$F.udiff 2750daaffb31Sdp diff_to_html $F $DIR/$F "U" "$COMM" < $WDIR/$DIR/$F.udiff \ 2751daaffb31Sdp > $WDIR/$DIR/$F.udiff.html 2752daaffb31Sdp 27537c478bd9Sstevel@tonic-gate print " udiffs\c" 27547c478bd9Sstevel@tonic-gate 27557c478bd9Sstevel@tonic-gate if [[ -x $WDIFF ]]; then 2756daaffb31Sdp $WDIFF -c "$COMM" \ 2757daaffb31Sdp -t "$WNAME Wdiff $DIR/$F" $ofile $nfile > \ 2758daaffb31Sdp $WDIR/$DIR/$F.wdiff.html 2>/dev/null 2759daaffb31Sdp if [[ $? -eq 0 ]]; then 27607c478bd9Sstevel@tonic-gate print " wdiffs\c" 2761daaffb31Sdp else 2762daaffb31Sdp print " wdiffs[fail]\c" 2763daaffb31Sdp fi 27647c478bd9Sstevel@tonic-gate fi 27657c478bd9Sstevel@tonic-gate 2766daaffb31Sdp sdiff_to_html $ofile $nfile $F $DIR "$COMM" \ 2767daaffb31Sdp > $WDIR/$DIR/$F.sdiff.html 27687c478bd9Sstevel@tonic-gate print " sdiffs\c" 27697c478bd9Sstevel@tonic-gate 27707c478bd9Sstevel@tonic-gate print " frames\c" 27717c478bd9Sstevel@tonic-gate 27727c478bd9Sstevel@tonic-gate rm -f $WDIR/$DIR/$F.cdiff $WDIR/$DIR/$F.udiff 27737c478bd9Sstevel@tonic-gate 2774daaffb31Sdp difflines $ofile $nfile > $WDIR/$DIR/$F.count 2775daaffb31Sdp 2776daaffb31Sdp elif [[ -f $ofile && -f $nfile && -n $mv_but_nodiff ]]; then 2777daaffb31Sdp # renamed file: may also have differences 2778daaffb31Sdp difflines $ofile $nfile > $WDIR/$DIR/$F.count 2779daaffb31Sdp elif [[ -f $nfile ]]; then 27807c478bd9Sstevel@tonic-gate # new file: count added lines 2781daaffb31Sdp difflines /dev/null $nfile > $WDIR/$DIR/$F.count 2782daaffb31Sdp elif [[ -f $ofile ]]; then 27837c478bd9Sstevel@tonic-gate # old file: count deleted lines 2784daaffb31Sdp difflines $ofile /dev/null > $WDIR/$DIR/$F.count 27857c478bd9Sstevel@tonic-gate fi 27867c478bd9Sstevel@tonic-gate 2787daaffb31Sdp # 2788daaffb31Sdp # Now we generate the postscript for this file. We generate diffs 2789daaffb31Sdp # only in the event that there is delta, or the file is new (it seems 2790daaffb31Sdp # tree-killing to print out the contents of deleted files). 2791daaffb31Sdp # 2792daaffb31Sdp if [[ -f $nfile ]]; then 2793daaffb31Sdp ocr=$ofile 2794daaffb31Sdp [[ ! -f $ofile ]] && ocr=/dev/null 2795daaffb31Sdp 2796daaffb31Sdp if [[ -z $mv_but_nodiff ]]; then 2797daaffb31Sdp textcomm=`getcomments text $P $PP` 279814983201Sdp if [[ -x $CODEREVIEW ]]; then 279914983201Sdp $CODEREVIEW -y "$textcomm" \ 280014983201Sdp -e $ocr $nfile \ 280114983201Sdp > /tmp/$$.psfile 2>/dev/null && 280214983201Sdp cat /tmp/$$.psfile >> $WDIR/$WNAME.ps 2803daaffb31Sdp if [[ $? -eq 0 ]]; then 2804daaffb31Sdp print " ps\c" 2805daaffb31Sdp else 2806daaffb31Sdp print " ps[fail]\c" 2807daaffb31Sdp fi 2808daaffb31Sdp fi 2809daaffb31Sdp fi 281014983201Sdp fi 2811daaffb31Sdp 2812cdf0c1d5Smjnelson if [[ -f $ofile ]]; then 2813cdf0c1d5Smjnelson source_to_html Old $PP < $ofile > $WDIR/$DIR/$F-.html 28147c478bd9Sstevel@tonic-gate print " old\c" 28157c478bd9Sstevel@tonic-gate fi 28167c478bd9Sstevel@tonic-gate 2817daaffb31Sdp if [[ -f $nfile ]]; then 2818daaffb31Sdp source_to_html New $P < $nfile > $WDIR/$DIR/$F.html 28197c478bd9Sstevel@tonic-gate print " new\c" 28207c478bd9Sstevel@tonic-gate fi 28217c478bd9Sstevel@tonic-gate 2822cdf0c1d5Smjnelson cd $OWD 2823cdf0c1d5Smjnelson 2824daaffb31Sdp print 28257c478bd9Sstevel@tonic-gatedone 28267c478bd9Sstevel@tonic-gate 2827daaffb31Sdpframe_nav_js > $WDIR/ancnav.js 28287c478bd9Sstevel@tonic-gateframe_navigation > $WDIR/ancnav.html 2829daaffb31Sdp 283014983201Sdpif [[ ! -f $WDIR/$WNAME.ps ]]; then 283114983201Sdp print " Generating PDF: Skipped: no output available" 283214983201Sdpelif [[ -x $CODEREVIEW && -x $PS2PDF ]]; then 283314983201Sdp print " Generating PDF: \c" 283414983201Sdp fix_postscript $WDIR/$WNAME.ps | $PS2PDF - > $WDIR/$WNAME.pdf 2835daaffb31Sdp print "Done." 283614983201Sdpelse 283714983201Sdp print " Generating PDF: Skipped: missing 'ps2pdf' or 'codereview'" 283814983201Sdpfi 28397c478bd9Sstevel@tonic-gate 2840e0e0293aSjmcp# If we're in OpenSolaris mode and there's a closed dir under $WDIR, 2841e0e0293aSjmcp# delete it - prevent accidental publishing of closed source 2842e0e0293aSjmcp 2843e0e0293aSjmcpif [[ -n "$Oflag" ]]; then 2844*ba44d8a2SVladimir Kotal $FIND $WDIR -type d -name closed -exec /bin/rm -rf {} \; 2845e0e0293aSjmcpfi 2846e0e0293aSjmcp 28477c478bd9Sstevel@tonic-gate# Now build the index.html file that contains 28487c478bd9Sstevel@tonic-gate# links to the source files and their diffs. 28497c478bd9Sstevel@tonic-gate 28507c478bd9Sstevel@tonic-gatecd $CWS 28517c478bd9Sstevel@tonic-gate 28527c478bd9Sstevel@tonic-gate# Save total changed lines for Code Inspection. 2853daaffb31Sdpprint "$TOTL" > $WDIR/TotalChangedLines 28547c478bd9Sstevel@tonic-gate 2855daaffb31Sdpprint " index.html: \c" 28567c478bd9Sstevel@tonic-gateINDEXFILE=$WDIR/index.html 28577c478bd9Sstevel@tonic-gateexec 3<&1 # duplicate stdout to FD3. 28587c478bd9Sstevel@tonic-gateexec 1<&- # Close stdout. 28597c478bd9Sstevel@tonic-gateexec > $INDEXFILE # Open stdout to index file. 28607c478bd9Sstevel@tonic-gate 2861daaffb31Sdpprint "$HTML<head>$STDHEAD" 2862daaffb31Sdpprint "<title>$WNAME</title>" 2863daaffb31Sdpprint "</head>" 2864daaffb31Sdpprint "<body id=\"SUNWwebrev\">" 2865daaffb31Sdpprint "<div class=\"summary\">" 2866daaffb31Sdpprint "<h2>Code Review for $WNAME</h2>" 28677c478bd9Sstevel@tonic-gate 2868daaffb31Sdpprint "<table>" 28697c478bd9Sstevel@tonic-gate 2870daaffb31Sdp# 2871cdf0c1d5Smjnelson# Get the preparer's name: 2872daaffb31Sdp# 2873cdf0c1d5Smjnelson# If the SCM detected is Mercurial, and the configuration property 2874cdf0c1d5Smjnelson# ui.username is available, use that, but be careful to properly escape 2875cdf0c1d5Smjnelson# angle brackets (HTML syntax characters) in the email address. 2876cdf0c1d5Smjnelson# 2877cdf0c1d5Smjnelson# Otherwise, use the current userid in the form "John Doe (jdoe)", but 2878cdf0c1d5Smjnelson# to maintain compatibility with passwd(4), we must support '&' substitutions. 2879cdf0c1d5Smjnelson# 2880cdf0c1d5Smjnelsonpreparer= 2881cdf0c1d5Smjnelsonif [[ "$SCM_MODE" == mercurial ]]; then 2882cdf0c1d5Smjnelson preparer=`hg showconfig ui.username 2>/dev/null` 2883cdf0c1d5Smjnelson if [[ -n "$preparer" ]]; then 2884cdf0c1d5Smjnelson preparer="$(echo "$preparer" | html_quote)" 2885cdf0c1d5Smjnelson fi 2886cdf0c1d5Smjnelsonfi 2887cdf0c1d5Smjnelsonif [[ -z "$preparer" ]]; then 2888cdf0c1d5Smjnelson preparer=$( 2889cdf0c1d5Smjnelson $PERL -e ' 2890cdf0c1d5Smjnelson ($login, $pw, $uid, $gid, $quota, $cmt, $gcos) = getpwuid($<); 2891cdf0c1d5Smjnelson if ($login) { 2892cdf0c1d5Smjnelson $gcos =~ s/\&/ucfirst($login)/e; 2893cdf0c1d5Smjnelson printf "%s (%s)\n", $gcos, $login; 2894cdf0c1d5Smjnelson } else { 2895cdf0c1d5Smjnelson printf "(unknown)\n"; 2896cdf0c1d5Smjnelson } 2897cdf0c1d5Smjnelson ') 2898daaffb31Sdpfi 2899daaffb31Sdp 2900cdf0c1d5Smjnelsonprint "<tr><th>Prepared by:</th><td>$preparer on `date`</td></tr>" 2901cdf0c1d5Smjnelsonprint "<tr><th>Workspace:</th><td>$CWS" 2902cdf0c1d5Smjnelsonif [[ -n $CWS_REV ]]; then 2903cdf0c1d5Smjnelson print "(at $CWS_REV)" 2904cdf0c1d5Smjnelsonfi 2905cdf0c1d5Smjnelsonprint "</td></tr>" 2906daaffb31Sdpprint "<tr><th>Compare against:</th><td>" 2907daaffb31Sdpif [[ -n $parent_webrev ]]; then 2908daaffb31Sdp print "webrev at $parent_webrev" 2909daaffb31Sdpelse 2910daaffb31Sdp print "$PWS" 2911cdf0c1d5Smjnelson if [[ -n $hg_parent_short ]]; then 2912cdf0c1d5Smjnelson print "(at $hg_parent_short)" 2913cdf0c1d5Smjnelson fi 2914daaffb31Sdpfi 2915daaffb31Sdpprint "</td></tr>" 2916daaffb31Sdpprint "<tr><th>Summary of changes:</th><td>" 2917daaffb31SdpprintCI $TOTL $TINS $TDEL $TMOD $TUNC 2918daaffb31Sdpprint "</td></tr>" 2919daaffb31Sdp 2920daaffb31Sdpif [[ -f $WDIR/$WNAME.patch ]]; then 2921daaffb31Sdp print "<tr><th>Patch of changes:</th><td>" 2922daaffb31Sdp print "<a href=\"$WNAME.patch\">$WNAME.patch</a></td></tr>" 2923daaffb31Sdpfi 2924daaffb31Sdpif [[ -f $WDIR/$WNAME.pdf ]]; then 2925daaffb31Sdp print "<tr><th>Printable review:</th><td>" 2926daaffb31Sdp print "<a href=\"$WNAME.pdf\">$WNAME.pdf</a></td></tr>" 2927daaffb31Sdpfi 2928daaffb31Sdp 2929daaffb31Sdpif [[ -n "$iflag" ]]; then 2930daaffb31Sdp print "<tr><th>Author comments:</th><td><div>" 2931daaffb31Sdp cat /tmp/$$.include 2932daaffb31Sdp print "</div></td></tr>" 2933daaffb31Sdpfi 2934daaffb31Sdpprint "</table>" 2935daaffb31Sdpprint "</div>" 2936daaffb31Sdp 2937daaffb31Sdp# 2938daaffb31Sdp# Second pass through the files: generate the rest of the index file 2939daaffb31Sdp# 2940daaffb31Sdpcat $FLIST | while read LINE 29417c478bd9Sstevel@tonic-gatedo 29427c478bd9Sstevel@tonic-gate set - $LINE 29437c478bd9Sstevel@tonic-gate P=$1 29447c478bd9Sstevel@tonic-gate 2945daaffb31Sdp if [[ $# == 2 ]]; then 29467c478bd9Sstevel@tonic-gate PP=$2 2947cdf0c1d5Smjnelson oldname="$PP" 29487c478bd9Sstevel@tonic-gate else 29497c478bd9Sstevel@tonic-gate PP=$P 2950daaffb31Sdp oldname="" 2951daaffb31Sdp fi 2952daaffb31Sdp 2953cdf0c1d5Smjnelson mv_but_nodiff= 2954cdf0c1d5Smjnelson cmp $WDIR/raw_files/old/$PP $WDIR/raw_files/new/$P > /dev/null 2>&1 2955cdf0c1d5Smjnelson if [[ $? == 0 && -n "$oldname" ]]; then 2956cdf0c1d5Smjnelson mv_but_nodiff=1 2957cdf0c1d5Smjnelson fi 2958cdf0c1d5Smjnelson 2959daaffb31Sdp DIR=${P%/*} 2960daaffb31Sdp if [[ $DIR == $P ]]; then 2961daaffb31Sdp DIR="." # File at root of workspace 29627c478bd9Sstevel@tonic-gate fi 29637c478bd9Sstevel@tonic-gate 29647c478bd9Sstevel@tonic-gate # Avoid processing the same file twice. 29657c478bd9Sstevel@tonic-gate # It's possible for renamed files to 29667c478bd9Sstevel@tonic-gate # appear twice in the file list 29677c478bd9Sstevel@tonic-gate 29687c478bd9Sstevel@tonic-gate F=$WDIR/$P 29697c478bd9Sstevel@tonic-gate 2970daaffb31Sdp print "<p>" 29717c478bd9Sstevel@tonic-gate 29727c478bd9Sstevel@tonic-gate # If there's a diffs file, make diffs links 29737c478bd9Sstevel@tonic-gate 2974daaffb31Sdp if [[ -f $F.cdiff.html ]]; then 2975daaffb31Sdp print "<a href=\"$P.cdiff.html\">Cdiffs</a>" 2976daaffb31Sdp print "<a href=\"$P.udiff.html\">Udiffs</a>" 29777c478bd9Sstevel@tonic-gate 2978daaffb31Sdp if [[ -f $F.wdiff.html && -x $WDIFF ]]; then 2979daaffb31Sdp print "<a href=\"$P.wdiff.html\">Wdiffs</a>" 29807c478bd9Sstevel@tonic-gate fi 29817c478bd9Sstevel@tonic-gate 2982daaffb31Sdp print "<a href=\"$P.sdiff.html\">Sdiffs</a>" 29837c478bd9Sstevel@tonic-gate 29847c478bd9Sstevel@tonic-gate print "<a href=\"$P.frames.html\">Frames</a>" 29857c478bd9Sstevel@tonic-gate else 2986daaffb31Sdp print " ------ ------ ------" 29877c478bd9Sstevel@tonic-gate 2988daaffb31Sdp if [[ -x $WDIFF ]]; then 29897c478bd9Sstevel@tonic-gate print " ------" 29907c478bd9Sstevel@tonic-gate fi 2991daaffb31Sdp 2992daaffb31Sdp print " ------" 29937c478bd9Sstevel@tonic-gate fi 29947c478bd9Sstevel@tonic-gate 29957c478bd9Sstevel@tonic-gate # If there's an old file, make the link 29967c478bd9Sstevel@tonic-gate 2997daaffb31Sdp if [[ -f $F-.html ]]; then 2998daaffb31Sdp print "<a href=\"$P-.html\">Old</a>" 29997c478bd9Sstevel@tonic-gate else 3000daaffb31Sdp print " ---" 30017c478bd9Sstevel@tonic-gate fi 30027c478bd9Sstevel@tonic-gate 30037c478bd9Sstevel@tonic-gate # If there's an new file, make the link 30047c478bd9Sstevel@tonic-gate 3005daaffb31Sdp if [[ -f $F.html ]]; then 3006daaffb31Sdp print "<a href=\"$P.html\">New</a>" 30077c478bd9Sstevel@tonic-gate else 3008daaffb31Sdp print " ---" 30097c478bd9Sstevel@tonic-gate fi 30107c478bd9Sstevel@tonic-gate 3011daaffb31Sdp if [[ -f $F.patch ]]; then 3012daaffb31Sdp print "<a href=\"$P.patch\">Patch</a>" 3013daaffb31Sdp else 3014daaffb31Sdp print " -----" 3015daaffb31Sdp fi 3016daaffb31Sdp 3017daaffb31Sdp if [[ -f $WDIR/raw_files/new/$P ]]; then 3018daaffb31Sdp print "<a href=\"raw_files/new/$P\">Raw</a>" 3019daaffb31Sdp else 3020daaffb31Sdp print " ---" 3021daaffb31Sdp fi 3022daaffb31Sdp 3023cdf0c1d5Smjnelson print "<b>$P</b>" 3024cdf0c1d5Smjnelson 3025cdf0c1d5Smjnelson # For renamed files, clearly state whether or not they are modified 3026cdf0c1d5Smjnelson if [[ -n "$oldname" ]]; then 3027cdf0c1d5Smjnelson if [[ -n "$mv_but_nodiff" ]]; then 3028cdf0c1d5Smjnelson print "<i>(renamed only, was $oldname)</i>" 3029cdf0c1d5Smjnelson else 3030cdf0c1d5Smjnelson print "<i>(modified and renamed, was $oldname)</i>" 3031cdf0c1d5Smjnelson fi 3032cdf0c1d5Smjnelson fi 3033cdf0c1d5Smjnelson 3034cdf0c1d5Smjnelson # If there's an old file, but no new file, the file was deleted 3035cdf0c1d5Smjnelson if [[ -f $F-.html && ! -f $F.html ]]; then 3036cdf0c1d5Smjnelson print " <i>(deleted)</i>" 3037cdf0c1d5Smjnelson fi 3038daaffb31Sdp 3039daaffb31Sdp # 3040e0e0293aSjmcp # Check for usr/closed and deleted_files/usr/closed 3041daaffb31Sdp # 3042daaffb31Sdp if [ ! -z "$Oflag" ]; then 3043e0e0293aSjmcp if [[ $P == usr/closed/* || \ 3044e0e0293aSjmcp $P == deleted_files/usr/closed/* ]]; then 3045daaffb31Sdp print " <i>Closed source: omitted from" \ 3046daaffb31Sdp "this review</i>" 3047daaffb31Sdp fi 3048daaffb31Sdp fi 3049daaffb31Sdp 3050daaffb31Sdp print "</p>" 30517c478bd9Sstevel@tonic-gate # Insert delta comments 30527c478bd9Sstevel@tonic-gate 3053daaffb31Sdp print "<blockquote><pre>" 3054daaffb31Sdp getcomments html $P $PP 3055daaffb31Sdp print "</pre>" 30567c478bd9Sstevel@tonic-gate 30577c478bd9Sstevel@tonic-gate # Add additional comments comment 30587c478bd9Sstevel@tonic-gate 3059daaffb31Sdp print "<!-- Add comments to explain changes in $P here -->" 30607c478bd9Sstevel@tonic-gate 30617c478bd9Sstevel@tonic-gate # Add count of changes. 30627c478bd9Sstevel@tonic-gate 3063daaffb31Sdp if [[ -f $F.count ]]; then 30647c478bd9Sstevel@tonic-gate cat $F.count 30657c478bd9Sstevel@tonic-gate rm $F.count 30667c478bd9Sstevel@tonic-gate fi 3067cdf0c1d5Smjnelson 3068cdf0c1d5Smjnelson if [[ $SCM_MODE == "teamware" || 3069cdf0c1d5Smjnelson $SCM_MODE == "mercurial" || 3070cdf0c1d5Smjnelson $SCM_MODE == "unknown" ]]; then 3071cdf0c1d5Smjnelson 3072cdf0c1d5Smjnelson # Include warnings for important file mode situations: 3073cdf0c1d5Smjnelson # 1) New executable files 3074cdf0c1d5Smjnelson # 2) Permission changes of any kind 3075cdf0c1d5Smjnelson # 3) Existing executable files 3076cdf0c1d5Smjnelson 3077cdf0c1d5Smjnelson old_mode= 3078cdf0c1d5Smjnelson if [[ -f $WDIR/raw_files/old/$PP ]]; then 3079cdf0c1d5Smjnelson old_mode=`get_file_mode $WDIR/raw_files/old/$PP` 3080cdf0c1d5Smjnelson fi 3081cdf0c1d5Smjnelson 3082cdf0c1d5Smjnelson new_mode= 3083cdf0c1d5Smjnelson if [[ -f $WDIR/raw_files/new/$P ]]; then 3084cdf0c1d5Smjnelson new_mode=`get_file_mode $WDIR/raw_files/new/$P` 3085cdf0c1d5Smjnelson fi 3086cdf0c1d5Smjnelson 3087cdf0c1d5Smjnelson if [[ -z "$old_mode" && "$new_mode" = *[1357]* ]]; then 3088cdf0c1d5Smjnelson print "<span class=\"chmod\">" 3089cdf0c1d5Smjnelson print "<p>new executable file: mode $new_mode</p>" 3090cdf0c1d5Smjnelson print "</span>" 3091cdf0c1d5Smjnelson elif [[ -n "$old_mode" && -n "$new_mode" && 3092cdf0c1d5Smjnelson "$old_mode" != "$new_mode" ]]; then 3093cdf0c1d5Smjnelson print "<span class=\"chmod\">" 3094cdf0c1d5Smjnelson print "<p>mode change: $old_mode to $new_mode</p>" 3095cdf0c1d5Smjnelson print "</span>" 3096cdf0c1d5Smjnelson elif [[ "$new_mode" = *[1357]* ]]; then 3097cdf0c1d5Smjnelson print "<span class=\"chmod\">" 3098cdf0c1d5Smjnelson print "<p>executable file: mode $new_mode</p>" 3099cdf0c1d5Smjnelson print "</span>" 3100cdf0c1d5Smjnelson fi 3101cdf0c1d5Smjnelson fi 3102cdf0c1d5Smjnelson 3103daaffb31Sdp print "</blockquote>" 31047c478bd9Sstevel@tonic-gatedone 31057c478bd9Sstevel@tonic-gate 3106daaffb31Sdpprint 3107daaffb31Sdpprint 3108cac38512Smjnelsonprint "<hr></hr>" 3109daaffb31Sdpprint "<p style=\"font-size: small\">" 31109a70fc3bSMark J. Nelsonprint "This code review page was prepared using <b>$0</b>." 3111daaffb31Sdpprint "Webrev is maintained by the <a href=\"http://www.opensolaris.org\">" 3112daaffb31Sdpprint "OpenSolaris</a> project. The latest version may be obtained" 3113e9e2cfb2Sfr80241print "<a href=\"http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/tools/scripts/webrev.sh\">here</a>.</p>" 3114daaffb31Sdpprint "</body>" 3115daaffb31Sdpprint "</html>" 31167c478bd9Sstevel@tonic-gate 31177c478bd9Sstevel@tonic-gateexec 1<&- # Close FD 1. 31187c478bd9Sstevel@tonic-gateexec 1<&3 # dup FD 3 to restore stdout. 31197c478bd9Sstevel@tonic-gateexec 3<&- # close FD 3. 31207c478bd9Sstevel@tonic-gate 3121daaffb31Sdpprint "Done." 312202d26c39SVladimir Kotal 3123*ba44d8a2SVladimir Kotal# If remote deletion was specified and fails do not continue. 3124*ba44d8a2SVladimir Kotalif [[ -n $Dflag ]]; then 3125*ba44d8a2SVladimir Kotal delete_webrev 1 3126*ba44d8a2SVladimir Kotal (( $? == 0 )) || exit $? 3127*ba44d8a2SVladimir Kotalfi 3128*ba44d8a2SVladimir Kotal 312902d26c39SVladimir Kotalif [[ -n $Uflag ]]; then 313002d26c39SVladimir Kotal upload_webrev 313102d26c39SVladimir Kotal exit $? 313202d26c39SVladimir Kotalfi 3133