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 144*02d26c39SVladimir Kotal# Upload the webrev via rsync. Return 0 on success, 1 on error. 145*02d26c39SVladimir Kotalrsync_upload() 146*02d26c39SVladimir Kotal{ 147*02d26c39SVladimir Kotal if (( $# != 1 )); then 148*02d26c39SVladimir Kotal return 1 149*02d26c39SVladimir Kotal fi 150*02d26c39SVladimir Kotal 151*02d26c39SVladimir Kotal typeset dst=$1 152*02d26c39SVladimir Kotal 153*02d26c39SVladimir Kotal # if destination specification is not in the form of host:remote_dir 154*02d26c39SVladimir Kotal # then assume it is just remote hostname and append a colon and 155*02d26c39SVladimir Kotal # destination directory formed from local webrev directory name 156*02d26c39SVladimir Kotal if [[ -z ${dst##*:} ]]; then 157*02d26c39SVladimir Kotal if [[ "${dst}" == *: ]]; then 158*02d26c39SVladimir Kotal dst=${dst}${WNAME} 159*02d26c39SVladimir Kotal else 160*02d26c39SVladimir Kotal dst=${dst}:${WNAME} 161*02d26c39SVladimir Kotal fi 162*02d26c39SVladimir Kotal fi 163*02d26c39SVladimir Kotal 164*02d26c39SVladimir Kotal print " Syncing webrev: \c" 165*02d26c39SVladimir Kotal # end source directory with a slash in order to copy just 166*02d26c39SVladimir Kotal # directory contents, not the whole directory 167*02d26c39SVladimir Kotal $RSYNC -r -q $WDIR/ $dst 168*02d26c39SVladimir Kotal if (( $? != 0 )); then 169*02d26c39SVladimir Kotal print "failed to sync webrev directory " \ 170*02d26c39SVladimir Kotal "'$WDIR' to '$dst'" 171*02d26c39SVladimir Kotal return 1 172*02d26c39SVladimir Kotal fi 173*02d26c39SVladimir Kotal 174*02d26c39SVladimir Kotal print "Done." 175*02d26c39SVladimir Kotal return 0 176*02d26c39SVladimir Kotal} 177*02d26c39SVladimir Kotal 178*02d26c39SVladimir Kotal# Upload the webrev via SSH. Return 0 on success, 1 on error. 179*02d26c39SVladimir Kotalssh_upload() 180*02d26c39SVladimir Kotal{ 181*02d26c39SVladimir Kotal if (( $# != 1 )); then 182*02d26c39SVladimir Kotal return 1 183*02d26c39SVladimir Kotal fi 184*02d26c39SVladimir Kotal 185*02d26c39SVladimir Kotal typeset dst=$1 186*02d26c39SVladimir Kotal typeset -r host_spec=${dst%%:*} 187*02d26c39SVladimir Kotal typeset -r dir_spec=${dst##*:} 188*02d26c39SVladimir Kotal 189*02d26c39SVladimir Kotal # if destination specification is not in the form of host:remote_dir 190*02d26c39SVladimir Kotal # then assume it is just remote hostname and append a colon 191*02d26c39SVladimir Kotal if [[ "${dst}" != *:* ]]; then 192*02d26c39SVladimir Kotal dst=${dst}: 193*02d26c39SVladimir Kotal fi 194*02d26c39SVladimir Kotal 195*02d26c39SVladimir Kotal if [[ -z $tflag || -z $dir_spec ]]; then 196*02d26c39SVladimir Kotal dir_rm=$WNAME 197*02d26c39SVladimir Kotal else 198*02d26c39SVladimir Kotal if [[ "${dir_spec}" == */* ]]; then 199*02d26c39SVladimir Kotal dir_rm=${dir_spec%%/*} 200*02d26c39SVladimir Kotal else 201*02d26c39SVladimir Kotal dir_rm=${dir_spec##*/} 202*02d26c39SVladimir Kotal fi 203*02d26c39SVladimir Kotal fi 204*02d26c39SVladimir Kotal 205*02d26c39SVladimir Kotal if [[ "${dir_spec}" != /* ]]; then 206*02d26c39SVladimir Kotal print "Removing old remote webrev: \c" 207*02d26c39SVladimir Kotal if [[ -z "$dir_rm" ]]; then 208*02d26c39SVladimir Kotal echo "empty directory for removal" 209*02d26c39SVladimir Kotal return 1 210*02d26c39SVladimir Kotal fi 211*02d26c39SVladimir Kotal typeset -r batch_file_rm=$( $MKTEMP /tmp/$webrev_remove.XXX ) 212*02d26c39SVladimir Kotal echo "rename $dir_rm .trash/removed.$$" > $batch_file_rm 213*02d26c39SVladimir Kotal # we do not care about return value because this might be 214*02d26c39SVladimir Kotal # the first time this directory is uploaded 215*02d26c39SVladimir Kotal $SFTP -b $batch_file_rm $host_spec 2>/dev/null 1>&2 216*02d26c39SVladimir Kotal rm -f $batch_file_rm 217*02d26c39SVladimir Kotal print "Done." 218*02d26c39SVladimir Kotal fi 219*02d26c39SVladimir Kotal 220*02d26c39SVladimir Kotal # if the supplied path is absolute we assume all directories are 221*02d26c39SVladimir Kotal # created, otherwise try to create all directories in the path 222*02d26c39SVladimir Kotal # except the last one which will be created by scp 223*02d26c39SVladimir Kotal if [[ "${dir_spec}" == */* && "${dir_spec}" != /* ]]; then 224*02d26c39SVladimir Kotal print "Creating directories: \c" 225*02d26c39SVladimir Kotal typeset -r dirs_mk=${dir_spec%/*} 226*02d26c39SVladimir Kotal typeset -r batch_file_mkdir=$( $MKTEMP /tmp/$webrev_mkdir.XXX ) 227*02d26c39SVladimir Kotal OLDIFS=$IFS 228*02d26c39SVladimir Kotal IFS=/ 229*02d26c39SVladimir Kotal mk= 230*02d26c39SVladimir Kotal for dir in $dirs_mk; do 231*02d26c39SVladimir Kotal if [[ -z $mk ]]; then 232*02d26c39SVladimir Kotal mk=$dir 233*02d26c39SVladimir Kotal else 234*02d26c39SVladimir Kotal mk=$mk/$dir 235*02d26c39SVladimir Kotal fi 236*02d26c39SVladimir Kotal echo "mkdir $mk" >> $batch_file_mkdir 237*02d26c39SVladimir Kotal done 238*02d26c39SVladimir Kotal IFS=$OLDIFS 239*02d26c39SVladimir Kotal $SFTP -b $batch_file_mkdir $host_spec 2>/dev/null 1>&2 240*02d26c39SVladimir Kotal if (( $? != 0 )); then 241*02d26c39SVladimir Kotal echo "Failed to create remote directories" 242*02d26c39SVladimir Kotal rm -f $batch_file_mkdir 243*02d26c39SVladimir Kotal return 1 244*02d26c39SVladimir Kotal fi 245*02d26c39SVladimir Kotal rm -f $batch_file_mkdir 246*02d26c39SVladimir Kotal print "Done." 247*02d26c39SVladimir Kotal fi 248*02d26c39SVladimir Kotal 249*02d26c39SVladimir Kotal print "Uploading webrev: \c" 250*02d26c39SVladimir Kotal $SCP -q -C -B -o PreferredAuthentications=publickey -r \ 251*02d26c39SVladimir Kotal $WDIR $dst 252*02d26c39SVladimir Kotal if (( $? != 0 )); then 253*02d26c39SVladimir Kotal print "failed to upload webrev directory" \ 254*02d26c39SVladimir Kotal "'$WDIR' to '$dst'" 255*02d26c39SVladimir Kotal return 1 256*02d26c39SVladimir Kotal fi 257*02d26c39SVladimir Kotal 258*02d26c39SVladimir Kotal print "Done." 259*02d26c39SVladimir Kotal return 0 260*02d26c39SVladimir Kotal} 261*02d26c39SVladimir Kotal 262*02d26c39SVladimir Kotal# 263*02d26c39SVladimir Kotal# Upload webrev to remote site 264*02d26c39SVladimir Kotal# 265*02d26c39SVladimir Kotalupload_webrev() 266*02d26c39SVladimir Kotal{ 267*02d26c39SVladimir Kotal # default host 268*02d26c39SVladimir Kotal host_spec="cr.opensolaris.org" 269*02d26c39SVladimir Kotal typeset -r rsync_prefix="rsync://" 270*02d26c39SVladimir Kotal typeset -r ssh_prefix="ssh://" 271*02d26c39SVladimir Kotal 272*02d26c39SVladimir Kotal # if remote target is not specified, build the target from scratch 273*02d26c39SVladimir Kotal # using the default values 274*02d26c39SVladimir Kotal if [[ -z $tflag ]]; then 275*02d26c39SVladimir Kotal dst_rsync="$host_spec:$WNAME" 276*02d26c39SVladimir Kotal dst_ssh="$host_spec:$WNAME" 277*02d26c39SVladimir Kotal fi 278*02d26c39SVladimir Kotal 279*02d26c39SVladimir Kotal if [[ ! -d "$WDIR" ]]; then 280*02d26c39SVladimir Kotal echo "webrev directory '$WDIR' does not exist" 281*02d26c39SVladimir Kotal return 1 282*02d26c39SVladimir Kotal fi 283*02d26c39SVladimir Kotal 284*02d26c39SVladimir Kotal # Perform a late check to make sure we do not upload closed source 285*02d26c39SVladimir Kotal # to remote target when -n is used. If the user used custom remote 286*02d26c39SVladimir Kotal # target he probably knows what he is doing. 287*02d26c39SVladimir Kotal if [[ -n $nflag && -z $tflag ]]; then 288*02d26c39SVladimir Kotal /usr/bin/find $WDIR -type d -name closed \ 289*02d26c39SVladimir Kotal | $GREP closed >/dev/null 290*02d26c39SVladimir Kotal if (( $? == 0 )); then 291*02d26c39SVladimir Kotal echo "directory '$WDIR' contains \"closed\" directory" 292*02d26c39SVladimir Kotal return 1 293*02d26c39SVladimir Kotal fi 294*02d26c39SVladimir Kotal fi 295*02d26c39SVladimir Kotal 296*02d26c39SVladimir Kotal # we have the URI for remote destination now so let's start the upload 297*02d26c39SVladimir Kotal if [[ -n $tflag ]]; then 298*02d26c39SVladimir Kotal if [[ "${remote_target}" == ${rsync_prefix}?* ]]; then 299*02d26c39SVladimir Kotal rsync_upload ${remote_target##$rsync_prefix} 300*02d26c39SVladimir Kotal return $? 301*02d26c39SVladimir Kotal elif [[ "${remote_target}" == ${ssh_prefix}?* ]]; then 302*02d26c39SVladimir Kotal ssh_upload ${remote_target##$ssh_prefix} 303*02d26c39SVladimir Kotal return $? 304*02d26c39SVladimir Kotal else 305*02d26c39SVladimir Kotal echo "invalid upload URI ($remote_target)" 306*02d26c39SVladimir Kotal return 1 307*02d26c39SVladimir Kotal fi 308*02d26c39SVladimir Kotal else 309*02d26c39SVladimir Kotal # try rsync first and fallback to SSH in case it fails 310*02d26c39SVladimir Kotal rsync_upload $dst_rsync 311*02d26c39SVladimir Kotal if (( $? != 0 )); then 312*02d26c39SVladimir Kotal echo "rsync upload failed, falling back to SSH" 313*02d26c39SVladimir Kotal ssh_upload $dst_ssh 314*02d26c39SVladimir Kotal fi 315*02d26c39SVladimir Kotal return $? 316*02d26c39SVladimir Kotal fi 317*02d26c39SVladimir Kotal 318*02d26c39SVladimir Kotal return 0 319*02d26c39SVladimir Kotal} 320*02d26c39SVladimir Kotal 321daaffb31Sdp# 322daaffb31Sdp# input_cmd | html_quote | output_cmd 323daaffb31Sdp# or 324daaffb31Sdp# html_quote filename | output_cmd 3257c478bd9Sstevel@tonic-gate# 3267c478bd9Sstevel@tonic-gate# Make a piece of source code safe for display in an HTML <pre> block. 3277c478bd9Sstevel@tonic-gate# 3287c478bd9Sstevel@tonic-gatehtml_quote() 3297c478bd9Sstevel@tonic-gate{ 3307c478bd9Sstevel@tonic-gate sed -e "s/&/\&/g" -e "s/</\</g" -e "s/>/\>/g" "$@" | expand 3317c478bd9Sstevel@tonic-gate} 3327c478bd9Sstevel@tonic-gate 333daaffb31Sdp# 334daaffb31Sdp# input_cmd | bug2url | output_cmd 335daaffb31Sdp# 336daaffb31Sdp# Scan for bugids and insert <a> links to the relevent bug database. 337daaffb31Sdp# 338daaffb31Sdpbug2url() 3397c478bd9Sstevel@tonic-gate{ 340daaffb31Sdp sed -e 's|[0-9]\{5,\}|<a href=\"'$BUGURL'&\">&</a>|g' 341daaffb31Sdp} 342daaffb31Sdp 3437c478bd9Sstevel@tonic-gate# 344daaffb31Sdp# input_cmd | sac2url | output_cmd 3457c478bd9Sstevel@tonic-gate# 346daaffb31Sdp# Scan for ARC cases and insert <a> links to the relevent SAC database. 347daaffb31Sdp# This is slightly complicated because inside the SWAN, SAC cases are 348daaffb31Sdp# grouped by ARC: PSARC/2006/123. But on OpenSolaris.org, they are 349daaffb31Sdp# referenced as 2006/123 (without labelling the ARC). 3507c478bd9Sstevel@tonic-gate# 351daaffb31Sdpsac2url() 352daaffb31Sdp{ 353e0e0293aSjmcp if [[ -z "$Oflag" ]]; then 3540a30ef2cSstevel 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' 355daaffb31Sdp else 356daaffb31Sdp sed -e 's|\([A-Z]\{1,2\}ARC\)[ /]\([0-9]\{4\}\)/\([0-9]\{3\}\)|<a href=\"'$SACURL'/\2/\3\">\1 \2/\3</a>|g' 357daaffb31Sdp fi 358daaffb31Sdp} 359daaffb31Sdp 3607c478bd9Sstevel@tonic-gate# 361daaffb31Sdp# strip_unchanged <infile> | output_cmd 3627c478bd9Sstevel@tonic-gate# 363daaffb31Sdp# Removes chunks of sdiff documents that have not changed. This makes it 364daaffb31Sdp# easier for a code reviewer to find the bits that have changed. 3657c478bd9Sstevel@tonic-gate# 366daaffb31Sdp# Deleted lines of text are replaced by a horizontal rule. Some 367daaffb31Sdp# identical lines are retained before and after the changed lines to 368daaffb31Sdp# provide some context. The number of these lines is controlled by the 369cdf0c1d5Smjnelson# variable C in the $AWK script below. 370daaffb31Sdp# 371daaffb31Sdp# The script detects changed lines as any line that has a "<span class=" 372daaffb31Sdp# string embedded (unchanged lines have no particular class and are not 373daaffb31Sdp# part of a <span>). Blank lines (without a sequence number) are also 374daaffb31Sdp# detected since they flag lines that have been inserted or deleted. 375daaffb31Sdp# 376daaffb31Sdpstrip_unchanged() 377daaffb31Sdp{ 378cdf0c1d5Smjnelson $AWK ' 379daaffb31Sdp BEGIN { C = c = 20 } 380cdf0c1d5Smjnelson NF == 0 || /<span class="/ { 381daaffb31Sdp if (c > C) { 382daaffb31Sdp c -= C 383daaffb31Sdp inx = 0 384daaffb31Sdp if (c > C) { 385cac38512Smjnelson print "\n</pre><hr></hr><pre>" 386daaffb31Sdp inx = c % C 387daaffb31Sdp c = C 388daaffb31Sdp } 389daaffb31Sdp 390daaffb31Sdp for (i = 0; i < c; i++) 391daaffb31Sdp print ln[(inx + i) % C] 392daaffb31Sdp } 393daaffb31Sdp c = 0; 394daaffb31Sdp print 395daaffb31Sdp next 396daaffb31Sdp } 397daaffb31Sdp { if (c >= C) { 398daaffb31Sdp ln[c % C] = $0 399daaffb31Sdp c++; 400daaffb31Sdp next; 401daaffb31Sdp } 402daaffb31Sdp c++; 403daaffb31Sdp print 404daaffb31Sdp } 405cac38512Smjnelson END { if (c > (C * 2)) print "\n</pre><hr></hr>" } 406daaffb31Sdp 407daaffb31Sdp ' $1 408daaffb31Sdp} 409daaffb31Sdp 410daaffb31Sdp# 411daaffb31Sdp# sdiff_to_html 412daaffb31Sdp# 413daaffb31Sdp# This function takes two files as arguments, obtains their diff, and 414daaffb31Sdp# processes the diff output to present the files as an HTML document with 415daaffb31Sdp# the files displayed side-by-side, differences shown in color. It also 416daaffb31Sdp# takes a delta comment, rendered as an HTML snippet, as the third 417daaffb31Sdp# argument. The function takes two files as arguments, then the name of 418daaffb31Sdp# file, the path, and the comment. The HTML will be delivered on stdout, 419daaffb31Sdp# e.g. 420daaffb31Sdp# 421daaffb31Sdp# $ sdiff_to_html old/usr/src/tools/scripts/webrev.sh \ 422daaffb31Sdp# new/usr/src/tools/scripts/webrev.sh \ 423daaffb31Sdp# webrev.sh usr/src/tools/scripts \ 424daaffb31Sdp# '<a href="http://monaco.sfbay.sun.com/detail.jsp?cr=1234567"> 425daaffb31Sdp# 1234567</a> my bugid' > <file>.html 426daaffb31Sdp# 427daaffb31Sdp# framed_sdiff() is then called which creates $2.frames.html 428daaffb31Sdp# in the webrev tree. 429daaffb31Sdp# 430daaffb31Sdp# FYI: This function is rather unusual in its use of awk. The initial 431daaffb31Sdp# diff run produces conventional diff output showing changed lines mixed 432daaffb31Sdp# with editing codes. The changed lines are ignored - we're interested in 433daaffb31Sdp# the editing codes, e.g. 4347c478bd9Sstevel@tonic-gate# 4357c478bd9Sstevel@tonic-gate# 8c8 4367c478bd9Sstevel@tonic-gate# 57a61 4377c478bd9Sstevel@tonic-gate# 63c66,76 4387c478bd9Sstevel@tonic-gate# 68,93d80 4397c478bd9Sstevel@tonic-gate# 106d90 4407c478bd9Sstevel@tonic-gate# 108,110d91 4417c478bd9Sstevel@tonic-gate# 442daaffb31Sdp# These editing codes are parsed by the awk script and used to generate 443daaffb31Sdp# another awk script that generates HTML, e.g the above lines would turn 444daaffb31Sdp# into something like this: 4457c478bd9Sstevel@tonic-gate# 4467c478bd9Sstevel@tonic-gate# BEGIN { printf "<pre>\n" } 4477c478bd9Sstevel@tonic-gate# function sp(n) {for (i=0;i<n;i++)printf "\n"} 448daaffb31Sdp# function wl(n) {printf "<font color=%s>%4d %s </font>\n", n, NR, $0} 4497c478bd9Sstevel@tonic-gate# NR==8 {wl("#7A7ADD");next} 4507c478bd9Sstevel@tonic-gate# NR==54 {wl("#7A7ADD");sp(3);next} 4517c478bd9Sstevel@tonic-gate# NR==56 {wl("#7A7ADD");next} 4527c478bd9Sstevel@tonic-gate# NR==57 {wl("black");printf "\n"; next} 4537c478bd9Sstevel@tonic-gate# : : 4547c478bd9Sstevel@tonic-gate# 455daaffb31Sdp# This script is then run on the original source file to generate the 456daaffb31Sdp# HTML that corresponds to the source file. 4577c478bd9Sstevel@tonic-gate# 458daaffb31Sdp# The two HTML files are then combined into a single piece of HTML that 459daaffb31Sdp# uses an HTML table construct to present the files side by side. You'll 460daaffb31Sdp# notice that the changes are color-coded: 4617c478bd9Sstevel@tonic-gate# 4627c478bd9Sstevel@tonic-gate# black - unchanged lines 4637c478bd9Sstevel@tonic-gate# blue - changed lines 4647c478bd9Sstevel@tonic-gate# bold blue - new lines 4657c478bd9Sstevel@tonic-gate# brown - deleted lines 4667c478bd9Sstevel@tonic-gate# 467daaffb31Sdp# Blank lines are inserted in each file to keep unchanged lines in sync 468daaffb31Sdp# (side-by-side). This format is familiar to users of sdiff(1) or 469daaffb31Sdp# Teamware's filemerge tool. 470daaffb31Sdp# 471daaffb31Sdpsdiff_to_html() 472daaffb31Sdp{ 4737c478bd9Sstevel@tonic-gate diff -b $1 $2 > /tmp/$$.diffs 4747c478bd9Sstevel@tonic-gate 475daaffb31Sdp TNAME=$3 476daaffb31Sdp TPATH=$4 477daaffb31Sdp COMMENT=$5 478daaffb31Sdp 4797c478bd9Sstevel@tonic-gate # 4807c478bd9Sstevel@tonic-gate # Now we have the diffs, generate the HTML for the old file. 4817c478bd9Sstevel@tonic-gate # 482cdf0c1d5Smjnelson $AWK ' 4837c478bd9Sstevel@tonic-gate BEGIN { 4847c478bd9Sstevel@tonic-gate printf "function sp(n) {for (i=0;i<n;i++)printf \"\\n\"}\n" 485daaffb31Sdp printf "function removed() " 486daaffb31Sdp printf "{printf \"<span class=\\\"removed\\\">%%4d %%s</span>\\n\", NR, $0}\n" 487daaffb31Sdp printf "function changed() " 488daaffb31Sdp printf "{printf \"<span class=\\\"changed\\\">%%4d %%s</span>\\n\", NR, $0}\n" 489daaffb31Sdp printf "function bl() {printf \"%%4d %%s\\n\", NR, $0}\n" 4907c478bd9Sstevel@tonic-gate} 4917c478bd9Sstevel@tonic-gate /^</ {next} 4927c478bd9Sstevel@tonic-gate /^>/ {next} 4937c478bd9Sstevel@tonic-gate /^---/ {next} 494daaffb31Sdp 4957c478bd9Sstevel@tonic-gate { 4967c478bd9Sstevel@tonic-gate split($1, a, /[cad]/) ; 4977c478bd9Sstevel@tonic-gate if (index($1, "a")) { 4987c478bd9Sstevel@tonic-gate if (a[1] == 0) { 4997c478bd9Sstevel@tonic-gate n = split(a[2], r, /,/); 5007c478bd9Sstevel@tonic-gate if (n == 1) 5017c478bd9Sstevel@tonic-gate printf "BEGIN\t\t{sp(1)}\n" 5027c478bd9Sstevel@tonic-gate else 5037c478bd9Sstevel@tonic-gate printf "BEGIN\t\t{sp(%d)}\n",\ 5047c478bd9Sstevel@tonic-gate (r[2] - r[1]) + 1 5057c478bd9Sstevel@tonic-gate next 5067c478bd9Sstevel@tonic-gate } 5077c478bd9Sstevel@tonic-gate 5087c478bd9Sstevel@tonic-gate printf "NR==%s\t\t{", a[1] 5097c478bd9Sstevel@tonic-gate n = split(a[2], r, /,/); 5107c478bd9Sstevel@tonic-gate s = r[1]; 5117c478bd9Sstevel@tonic-gate if (n == 1) 5127c478bd9Sstevel@tonic-gate printf "bl();printf \"\\n\"; next}\n" 5137c478bd9Sstevel@tonic-gate else { 5147c478bd9Sstevel@tonic-gate n = r[2] - r[1] 5157c478bd9Sstevel@tonic-gate printf "bl();sp(%d);next}\n",\ 5167c478bd9Sstevel@tonic-gate (r[2] - r[1]) + 1 5177c478bd9Sstevel@tonic-gate } 5187c478bd9Sstevel@tonic-gate next 5197c478bd9Sstevel@tonic-gate } 5207c478bd9Sstevel@tonic-gate if (index($1, "d")) { 5217c478bd9Sstevel@tonic-gate n = split(a[1], r, /,/); 5227c478bd9Sstevel@tonic-gate n1 = r[1] 5237c478bd9Sstevel@tonic-gate n2 = r[2] 5247c478bd9Sstevel@tonic-gate if (n == 1) 525daaffb31Sdp printf "NR==%s\t\t{removed(); next}\n" , n1 5267c478bd9Sstevel@tonic-gate else 527daaffb31Sdp printf "NR==%s,NR==%s\t{removed(); next}\n" , n1, n2 5287c478bd9Sstevel@tonic-gate next 5297c478bd9Sstevel@tonic-gate } 5307c478bd9Sstevel@tonic-gate if (index($1, "c")) { 5317c478bd9Sstevel@tonic-gate n = split(a[1], r, /,/); 5327c478bd9Sstevel@tonic-gate n1 = r[1] 5337c478bd9Sstevel@tonic-gate n2 = r[2] 5347c478bd9Sstevel@tonic-gate final = n2 5357c478bd9Sstevel@tonic-gate d1 = 0 5367c478bd9Sstevel@tonic-gate if (n == 1) 537daaffb31Sdp printf "NR==%s\t\t{changed();" , n1 5387c478bd9Sstevel@tonic-gate else { 5397c478bd9Sstevel@tonic-gate d1 = n2 - n1 540daaffb31Sdp printf "NR==%s,NR==%s\t{changed();" , n1, n2 5417c478bd9Sstevel@tonic-gate } 5427c478bd9Sstevel@tonic-gate m = split(a[2], r, /,/); 5437c478bd9Sstevel@tonic-gate n1 = r[1] 5447c478bd9Sstevel@tonic-gate n2 = r[2] 5457c478bd9Sstevel@tonic-gate if (m > 1) { 5467c478bd9Sstevel@tonic-gate d2 = n2 - n1 5477c478bd9Sstevel@tonic-gate if (d2 > d1) { 5487c478bd9Sstevel@tonic-gate if (n > 1) printf "if (NR==%d)", final 5497c478bd9Sstevel@tonic-gate printf "sp(%d);", d2 - d1 5507c478bd9Sstevel@tonic-gate } 5517c478bd9Sstevel@tonic-gate } 5527c478bd9Sstevel@tonic-gate printf "next}\n" ; 5537c478bd9Sstevel@tonic-gate 5547c478bd9Sstevel@tonic-gate next 5557c478bd9Sstevel@tonic-gate } 5567c478bd9Sstevel@tonic-gate } 5577c478bd9Sstevel@tonic-gate 558daaffb31Sdp END { printf "{printf \"%%4d %%s\\n\", NR, $0 }\n" } 559daaffb31Sdp ' /tmp/$$.diffs > /tmp/$$.file1 5607c478bd9Sstevel@tonic-gate 5617c478bd9Sstevel@tonic-gate # 5627c478bd9Sstevel@tonic-gate # Now generate the HTML for the new file 5637c478bd9Sstevel@tonic-gate # 564cdf0c1d5Smjnelson $AWK ' 5657c478bd9Sstevel@tonic-gate BEGIN { 5667c478bd9Sstevel@tonic-gate printf "function sp(n) {for (i=0;i<n;i++)printf \"\\n\"}\n" 567daaffb31Sdp printf "function new() " 568daaffb31Sdp printf "{printf \"<span class=\\\"new\\\">%%4d %%s</span>\\n\", NR, $0}\n" 569daaffb31Sdp printf "function changed() " 570daaffb31Sdp printf "{printf \"<span class=\\\"changed\\\">%%4d %%s</span>\\n\", NR, $0}\n" 571daaffb31Sdp printf "function bl() {printf \"%%4d %%s\\n\", NR, $0}\n" 5727c478bd9Sstevel@tonic-gate } 573daaffb31Sdp 5747c478bd9Sstevel@tonic-gate /^</ {next} 5757c478bd9Sstevel@tonic-gate /^>/ {next} 5767c478bd9Sstevel@tonic-gate /^---/ {next} 577daaffb31Sdp 5787c478bd9Sstevel@tonic-gate { 5797c478bd9Sstevel@tonic-gate split($1, a, /[cad]/) ; 5807c478bd9Sstevel@tonic-gate if (index($1, "d")) { 5817c478bd9Sstevel@tonic-gate if (a[2] == 0) { 5827c478bd9Sstevel@tonic-gate n = split(a[1], r, /,/); 5837c478bd9Sstevel@tonic-gate if (n == 1) 5847c478bd9Sstevel@tonic-gate printf "BEGIN\t\t{sp(1)}\n" 5857c478bd9Sstevel@tonic-gate else 5867c478bd9Sstevel@tonic-gate printf "BEGIN\t\t{sp(%d)}\n",\ 5877c478bd9Sstevel@tonic-gate (r[2] - r[1]) + 1 5887c478bd9Sstevel@tonic-gate next 5897c478bd9Sstevel@tonic-gate } 5907c478bd9Sstevel@tonic-gate 5917c478bd9Sstevel@tonic-gate printf "NR==%s\t\t{", a[2] 5927c478bd9Sstevel@tonic-gate n = split(a[1], r, /,/); 5937c478bd9Sstevel@tonic-gate s = r[1]; 5947c478bd9Sstevel@tonic-gate if (n == 1) 5957c478bd9Sstevel@tonic-gate printf "bl();printf \"\\n\"; next}\n" 5967c478bd9Sstevel@tonic-gate else { 5977c478bd9Sstevel@tonic-gate n = r[2] - r[1] 5987c478bd9Sstevel@tonic-gate printf "bl();sp(%d);next}\n",\ 5997c478bd9Sstevel@tonic-gate (r[2] - r[1]) + 1 6007c478bd9Sstevel@tonic-gate } 6017c478bd9Sstevel@tonic-gate next 6027c478bd9Sstevel@tonic-gate } 6037c478bd9Sstevel@tonic-gate if (index($1, "a")) { 6047c478bd9Sstevel@tonic-gate n = split(a[2], r, /,/); 6057c478bd9Sstevel@tonic-gate n1 = r[1] 6067c478bd9Sstevel@tonic-gate n2 = r[2] 6077c478bd9Sstevel@tonic-gate if (n == 1) 608daaffb31Sdp printf "NR==%s\t\t{new() ; next}\n" , n1 6097c478bd9Sstevel@tonic-gate else 610daaffb31Sdp printf "NR==%s,NR==%s\t{new() ; next}\n" , n1, n2 6117c478bd9Sstevel@tonic-gate next 6127c478bd9Sstevel@tonic-gate } 6137c478bd9Sstevel@tonic-gate if (index($1, "c")) { 6147c478bd9Sstevel@tonic-gate n = split(a[2], r, /,/); 6157c478bd9Sstevel@tonic-gate n1 = r[1] 6167c478bd9Sstevel@tonic-gate n2 = r[2] 6177c478bd9Sstevel@tonic-gate final = n2 6187c478bd9Sstevel@tonic-gate d2 = 0; 6197c478bd9Sstevel@tonic-gate if (n == 1) { 6207c478bd9Sstevel@tonic-gate final = n1 621daaffb31Sdp printf "NR==%s\t\t{changed();" , n1 6227c478bd9Sstevel@tonic-gate } else { 6237c478bd9Sstevel@tonic-gate d2 = n2 - n1 624daaffb31Sdp printf "NR==%s,NR==%s\t{changed();" , n1, n2 6257c478bd9Sstevel@tonic-gate } 6267c478bd9Sstevel@tonic-gate m = split(a[1], r, /,/); 6277c478bd9Sstevel@tonic-gate n1 = r[1] 6287c478bd9Sstevel@tonic-gate n2 = r[2] 6297c478bd9Sstevel@tonic-gate if (m > 1) { 6307c478bd9Sstevel@tonic-gate d1 = n2 - n1 6317c478bd9Sstevel@tonic-gate if (d1 > d2) { 6327c478bd9Sstevel@tonic-gate if (n > 1) printf "if (NR==%d)", final 6337c478bd9Sstevel@tonic-gate printf "sp(%d);", d1 - d2 6347c478bd9Sstevel@tonic-gate } 6357c478bd9Sstevel@tonic-gate } 6367c478bd9Sstevel@tonic-gate printf "next}\n" ; 6377c478bd9Sstevel@tonic-gate next 6387c478bd9Sstevel@tonic-gate } 6397c478bd9Sstevel@tonic-gate } 640daaffb31Sdp END { printf "{printf \"%%4d %%s\\n\", NR, $0 }\n" } 6417c478bd9Sstevel@tonic-gate ' /tmp/$$.diffs > /tmp/$$.file2 6427c478bd9Sstevel@tonic-gate 643daaffb31Sdp # 644cdf0c1d5Smjnelson # Post-process the HTML files by running them back through $AWK 645daaffb31Sdp # 646cdf0c1d5Smjnelson html_quote < $1 | $AWK -f /tmp/$$.file1 > /tmp/$$.file1.html 6477c478bd9Sstevel@tonic-gate 648cdf0c1d5Smjnelson html_quote < $2 | $AWK -f /tmp/$$.file2 > /tmp/$$.file2.html 6497c478bd9Sstevel@tonic-gate 650daaffb31Sdp # 651daaffb31Sdp # Now combine into a valid HTML file and side-by-side into a table 652daaffb31Sdp # 653daaffb31Sdp print "$HTML<head>$STDHEAD" 654cdf0c1d5Smjnelson print "<title>$WNAME Sdiff $TPATH/$TNAME</title>" 655daaffb31Sdp print "</head><body id=\"SUNWwebrev\">" 656daaffb31Sdp print "<a class=\"print\" href=\"javascript:print()\">Print this page</a>" 657daaffb31Sdp print "<pre>$COMMENT</pre>\n" 658daaffb31Sdp print "<table><tr valign=\"top\">" 659daaffb31Sdp print "<td><pre>" 6607c478bd9Sstevel@tonic-gate 6617c478bd9Sstevel@tonic-gate strip_unchanged /tmp/$$.file1.html 6627c478bd9Sstevel@tonic-gate 663daaffb31Sdp print "</pre></td><td><pre>" 6647c478bd9Sstevel@tonic-gate 6657c478bd9Sstevel@tonic-gate strip_unchanged /tmp/$$.file2.html 6667c478bd9Sstevel@tonic-gate 667daaffb31Sdp print "</pre></td>" 668daaffb31Sdp print "</tr></table>" 669daaffb31Sdp print "</body></html>" 6707c478bd9Sstevel@tonic-gate 671daaffb31Sdp framed_sdiff $TNAME $TPATH /tmp/$$.file1.html /tmp/$$.file2.html \ 672daaffb31Sdp "$COMMENT" 6737c478bd9Sstevel@tonic-gate} 6747c478bd9Sstevel@tonic-gate 6757c478bd9Sstevel@tonic-gate 676daaffb31Sdp# 677daaffb31Sdp# framed_sdiff <filename> <filepath> <lhsfile> <rhsfile> <comment> 678daaffb31Sdp# 679daaffb31Sdp# Expects lefthand and righthand side html files created by sdiff_to_html. 680daaffb31Sdp# We use insert_anchors() to augment those with HTML navigation anchors, 681daaffb31Sdp# and then emit the main frame. Content is placed into: 682daaffb31Sdp# 683daaffb31Sdp# $WDIR/DIR/$TNAME.lhs.html 684daaffb31Sdp# $WDIR/DIR/$TNAME.rhs.html 685daaffb31Sdp# $WDIR/DIR/$TNAME.frames.html 686daaffb31Sdp# 687daaffb31Sdp# NOTE: We rely on standard usage of $WDIR and $DIR. 688daaffb31Sdp# 6897c478bd9Sstevel@tonic-gatefunction framed_sdiff 6907c478bd9Sstevel@tonic-gate{ 6917c478bd9Sstevel@tonic-gate typeset TNAME=$1 692daaffb31Sdp typeset TPATH=$2 693daaffb31Sdp typeset lhsfile=$3 694daaffb31Sdp typeset rhsfile=$4 695daaffb31Sdp typeset comments=$5 6967c478bd9Sstevel@tonic-gate typeset RTOP 697daaffb31Sdp 6987c478bd9Sstevel@tonic-gate # Enable html files to access WDIR via a relative path. 699daaffb31Sdp RTOP=$(relative_dir $TPATH $WDIR) 700daaffb31Sdp 701daaffb31Sdp # Make the rhs/lhs files and output the frameset file. 702daaffb31Sdp print "$HTML<head>$STDHEAD" > $WDIR/$DIR/$TNAME.lhs.html 703daaffb31Sdp 704daaffb31Sdp cat >> $WDIR/$DIR/$TNAME.lhs.html <<-EOF 705cac38512Smjnelson <script type="text/javascript" src="$RTOP/ancnav.js"></script> 7067c478bd9Sstevel@tonic-gate </head> 707daaffb31Sdp <body id="SUNWwebrev" onkeypress="keypress(event);"> 708cac38512Smjnelson <a name="0"></a> 709cac38512Smjnelson <pre>$comments</pre><hr></hr> 710daaffb31Sdp EOF 711daaffb31Sdp 712daaffb31Sdp cp $WDIR/$DIR/$TNAME.lhs.html $WDIR/$DIR/$TNAME.rhs.html 713daaffb31Sdp 714daaffb31Sdp insert_anchors $lhsfile >> $WDIR/$DIR/$TNAME.lhs.html 715daaffb31Sdp insert_anchors $rhsfile >> $WDIR/$DIR/$TNAME.rhs.html 716daaffb31Sdp 717daaffb31Sdp close='</body></html>' 718daaffb31Sdp 719daaffb31Sdp print $close >> $WDIR/$DIR/$TNAME.lhs.html 720daaffb31Sdp print $close >> $WDIR/$DIR/$TNAME.rhs.html 721daaffb31Sdp 722daaffb31Sdp print "$FRAMEHTML<head>$STDHEAD" > $WDIR/$DIR/$TNAME.frames.html 723daaffb31Sdp print "<title>$WNAME Framed-Sdiff " \ 724daaffb31Sdp "$TPATH/$TNAME</title> </head>" >> $WDIR/$DIR/$TNAME.frames.html 725daaffb31Sdp cat >> $WDIR/$DIR/$TNAME.frames.html <<-EOF 726daaffb31Sdp <frameset rows="*,60"> 727daaffb31Sdp <frameset cols="50%,50%"> 728cac38512Smjnelson <frame src="$TNAME.lhs.html" scrolling="auto" name="lhs"></frame> 729cac38512Smjnelson <frame src="$TNAME.rhs.html" scrolling="auto" name="rhs"></frame> 730daaffb31Sdp </frameset> 731daaffb31Sdp <frame src="$RTOP/ancnav.html" scrolling="no" marginwidth="0" 732cac38512Smjnelson marginheight="0" name="nav"></frame> 733daaffb31Sdp <noframes> 734daaffb31Sdp <body id="SUNWwebrev"> 735daaffb31Sdp Alas 'frames' webrev requires that your browser supports frames 7367c478bd9Sstevel@tonic-gate and has the feature enabled. 737daaffb31Sdp </body> 738daaffb31Sdp </noframes> 739daaffb31Sdp </frameset> 7407c478bd9Sstevel@tonic-gate </html> 7417c478bd9Sstevel@tonic-gate EOF 7427c478bd9Sstevel@tonic-gate} 7437c478bd9Sstevel@tonic-gate 7447c478bd9Sstevel@tonic-gate 745daaffb31Sdp# 746daaffb31Sdp# fix_postscript 747daaffb31Sdp# 748daaffb31Sdp# Merge codereview output files to a single conforming postscript file, by: 749daaffb31Sdp# - removing all extraneous headers/trailers 750daaffb31Sdp# - making the page numbers right 751daaffb31Sdp# - removing pages devoid of contents which confuse some 752daaffb31Sdp# postscript readers. 753daaffb31Sdp# 754daaffb31Sdp# From Casper. 755daaffb31Sdp# 756daaffb31Sdpfunction fix_postscript 7577c478bd9Sstevel@tonic-gate{ 758daaffb31Sdp infile=$1 7597c478bd9Sstevel@tonic-gate 760daaffb31Sdp cat > /tmp/$$.crmerge.pl << \EOF 7617c478bd9Sstevel@tonic-gate 762daaffb31Sdp print scalar(<>); # %!PS-Adobe--- 763daaffb31Sdp print "%%Orientation: Landscape\n"; 7647c478bd9Sstevel@tonic-gate 765daaffb31Sdp $pno = 0; 766daaffb31Sdp $doprint = 1; 767daaffb31Sdp 768daaffb31Sdp $page = ""; 769daaffb31Sdp 770daaffb31Sdp while (<>) { 771daaffb31Sdp next if (/^%%Pages:\s*\d+/); 772daaffb31Sdp 773daaffb31Sdp if (/^%%Page:/) { 774daaffb31Sdp if ($pno == 0 || $page =~ /\)S/) { 775daaffb31Sdp # Header or single page containing text 776daaffb31Sdp print "%%Page: ? $pno\n" if ($pno > 0); 777daaffb31Sdp print $page; 778daaffb31Sdp $pno++; 779daaffb31Sdp } else { 780daaffb31Sdp # Empty page, skip it. 7817c478bd9Sstevel@tonic-gate } 782daaffb31Sdp $page = ""; 783daaffb31Sdp $doprint = 1; 7847c478bd9Sstevel@tonic-gate next; 7857c478bd9Sstevel@tonic-gate } 7867c478bd9Sstevel@tonic-gate 787daaffb31Sdp # Skip from %%Trailer of one document to Endprolog 788daaffb31Sdp # %%Page of the next 789daaffb31Sdp $doprint = 0 if (/^%%Trailer/); 790daaffb31Sdp $page .= $_ if ($doprint); 7917c478bd9Sstevel@tonic-gate } 7927c478bd9Sstevel@tonic-gate 793daaffb31Sdp if ($page =~ /\)S/) { 794daaffb31Sdp print "%%Page: ? $pno\n"; 795daaffb31Sdp print $page; 796daaffb31Sdp } else { 797daaffb31Sdp $pno--; 798daaffb31Sdp } 799daaffb31Sdp print "%%Trailer\n%%Pages: $pno\n"; 800daaffb31SdpEOF 801daaffb31Sdp 80214983201Sdp $PERL /tmp/$$.crmerge.pl < $infile 803daaffb31Sdp} 804daaffb31Sdp 805daaffb31Sdp 806daaffb31Sdp# 807daaffb31Sdp# input_cmd | insert_anchors | output_cmd 808daaffb31Sdp# 8097c478bd9Sstevel@tonic-gate# Flag blocks of difference with sequentially numbered invisible 810daaffb31Sdp# anchors. These are used to drive the frames version of the 8117c478bd9Sstevel@tonic-gate# sdiffs output. 8127c478bd9Sstevel@tonic-gate# 8137c478bd9Sstevel@tonic-gate# NOTE: Anchor zero flags the top of the file irrespective of changes, 8147c478bd9Sstevel@tonic-gate# an additional anchor is also appended to flag the bottom. 8157c478bd9Sstevel@tonic-gate# 816daaffb31Sdp# The script detects changed lines as any line that has a "<span 817daaffb31Sdp# class=" string embedded (unchanged lines have no class set and are 818daaffb31Sdp# not part of a <span>. Blank lines (without a sequence number) 8197c478bd9Sstevel@tonic-gate# are also detected since they flag lines that have been inserted or 8207c478bd9Sstevel@tonic-gate# deleted. 8217c478bd9Sstevel@tonic-gate# 822daaffb31Sdpfunction insert_anchors 823daaffb31Sdp{ 824cdf0c1d5Smjnelson $AWK ' 8257c478bd9Sstevel@tonic-gate function ia() { 826daaffb31Sdp printf "<a name=\"%d\" id=\"anc%d\"></a>", anc, anc++; 8277c478bd9Sstevel@tonic-gate } 828daaffb31Sdp 8297c478bd9Sstevel@tonic-gate BEGIN { 830daaffb31Sdp anc=1; 8317c478bd9Sstevel@tonic-gate inblock=1; 832daaffb31Sdp printf "<pre>\n"; 8337c478bd9Sstevel@tonic-gate } 834daaffb31Sdp NF == 0 || /^<span class=/ { 8357c478bd9Sstevel@tonic-gate if (inblock == 0) { 8367c478bd9Sstevel@tonic-gate ia(); 8377c478bd9Sstevel@tonic-gate inblock=1; 8387c478bd9Sstevel@tonic-gate } 8397c478bd9Sstevel@tonic-gate print; 8407c478bd9Sstevel@tonic-gate next; 8417c478bd9Sstevel@tonic-gate } 8427c478bd9Sstevel@tonic-gate { 8437c478bd9Sstevel@tonic-gate inblock=0; 8447c478bd9Sstevel@tonic-gate print; 8457c478bd9Sstevel@tonic-gate } 8467c478bd9Sstevel@tonic-gate END { 8477c478bd9Sstevel@tonic-gate ia(); 848daaffb31Sdp 849daaffb31Sdp printf "<b style=\"font-size: large; color: red\">"; 850daaffb31Sdp printf "--- EOF ---</b>" 8517c478bd9Sstevel@tonic-gate for(i=0;i<8;i++) printf "\n\n\n\n\n\n\n\n\n\n"; 852daaffb31Sdp printf "</pre>" 853daaffb31Sdp printf "<form name=\"eof\">"; 854cac38512Smjnelson printf "<input name=\"value\" value=\"%d\" " \ 855cac38512Smjnelson "type=\"hidden\"></input>", anc - 1; 856daaffb31Sdp printf "</form>"; 8577c478bd9Sstevel@tonic-gate } 8587c478bd9Sstevel@tonic-gate ' $1 8597c478bd9Sstevel@tonic-gate} 8607c478bd9Sstevel@tonic-gate 8617c478bd9Sstevel@tonic-gate 862daaffb31Sdp# 863daaffb31Sdp# relative_dir 864daaffb31Sdp# 865daaffb31Sdp# Print a relative return path from $1 to $2. For example if 866daaffb31Sdp# $1=/tmp/myreview/raw_files/usr/src/tools/scripts and $2=/tmp/myreview, 867daaffb31Sdp# this function would print "../../../../". 868daaffb31Sdp# 869daaffb31Sdp# In the event that $1 is not in $2 a warning is printed to stderr, 870daaffb31Sdp# and $2 is returned-- the result of this is that the resulting webrev 871daaffb31Sdp# is not relocatable. 872daaffb31Sdp# 873daaffb31Sdpfunction relative_dir 8747c478bd9Sstevel@tonic-gate{ 875daaffb31Sdp typeset cur="${1##$2?(/)}" 876daaffb31Sdp typeset ret="" 877daaffb31Sdp if [[ $2 == $cur ]]; then # Should never happen. 878daaffb31Sdp # Should never happen. 87914983201Sdp print -u2 "\nWARNING: relative_dir: \"$1\" not relative " 880daaffb31Sdp print -u2 "to \"$2\". Check input paths. Framed webrev " 881daaffb31Sdp print -u2 "will not be relocatable!" 882daaffb31Sdp print $2 883daaffb31Sdp return 884daaffb31Sdp fi 885daaffb31Sdp 886daaffb31Sdp while [[ -n ${cur} ]]; 8877c478bd9Sstevel@tonic-gate do 8887c478bd9Sstevel@tonic-gate cur=${cur%%*(/)*([!/])} 889daaffb31Sdp if [[ -z $ret ]]; then 890daaffb31Sdp ret=".." 891daaffb31Sdp else 8927c478bd9Sstevel@tonic-gate ret="../$ret" 893daaffb31Sdp fi 8947c478bd9Sstevel@tonic-gate done 8957c478bd9Sstevel@tonic-gate print $ret 8967c478bd9Sstevel@tonic-gate} 8977c478bd9Sstevel@tonic-gate 8987c478bd9Sstevel@tonic-gate 899daaffb31Sdp# 900daaffb31Sdp# frame_nav_js 901daaffb31Sdp# 902daaffb31Sdp# Emit javascript for frame navigation 903daaffb31Sdp# 904daaffb31Sdpfunction frame_nav_js 9057c478bd9Sstevel@tonic-gate{ 9067c478bd9Sstevel@tonic-gatecat << \EOF 9077c478bd9Sstevel@tonic-gatevar myInt; 9087c478bd9Sstevel@tonic-gatevar scrolling=0; 909daaffb31Sdpvar sfactor = 3; 9107c478bd9Sstevel@tonic-gatevar scount=10; 9117c478bd9Sstevel@tonic-gate 9127c478bd9Sstevel@tonic-gatefunction scrollByPix() { 9137c478bd9Sstevel@tonic-gate if (scount<=0) { 9147c478bd9Sstevel@tonic-gate sfactor*=1.2; 9157c478bd9Sstevel@tonic-gate scount=10; 9167c478bd9Sstevel@tonic-gate } 9177c478bd9Sstevel@tonic-gate parent.lhs.scrollBy(0,sfactor); 9187c478bd9Sstevel@tonic-gate parent.rhs.scrollBy(0,sfactor); 9197c478bd9Sstevel@tonic-gate scount--; 9207c478bd9Sstevel@tonic-gate} 9217c478bd9Sstevel@tonic-gate 922daaffb31Sdpfunction scrollToAnc(num) { 923daaffb31Sdp 924daaffb31Sdp // Update the value of the anchor in the form which we use as 925daaffb31Sdp // storage for this value. setAncValue() will take care of 926daaffb31Sdp // correcting for overflow and underflow of the value and return 927daaffb31Sdp // us the new value. 928daaffb31Sdp num = setAncValue(num); 929daaffb31Sdp 930daaffb31Sdp // Set location and scroll back a little to expose previous 931daaffb31Sdp // lines. 932daaffb31Sdp // 933daaffb31Sdp // Note that this could be improved: it is possible although 934daaffb31Sdp // complex to compute the x and y position of an anchor, and to 935daaffb31Sdp // scroll to that location directly. 936daaffb31Sdp // 9377c478bd9Sstevel@tonic-gate parent.lhs.location.replace(parent.lhs.location.pathname + "#" + num); 9387c478bd9Sstevel@tonic-gate parent.rhs.location.replace(parent.rhs.location.pathname + "#" + num); 939daaffb31Sdp 9407c478bd9Sstevel@tonic-gate parent.lhs.scrollBy(0,-30); 9417c478bd9Sstevel@tonic-gate parent.rhs.scrollBy(0,-30); 9427c478bd9Sstevel@tonic-gate} 9437c478bd9Sstevel@tonic-gate 944daaffb31Sdpfunction getAncValue() 945daaffb31Sdp{ 946daaffb31Sdp return (parseInt(parent.nav.document.diff.real.value)); 947daaffb31Sdp} 948daaffb31Sdp 949daaffb31Sdpfunction setAncValue(val) 950daaffb31Sdp{ 951daaffb31Sdp if (val <= 0) { 952daaffb31Sdp val = 0; 953daaffb31Sdp parent.nav.document.diff.real.value = val; 954daaffb31Sdp parent.nav.document.diff.display.value = "BOF"; 955daaffb31Sdp return (val); 956daaffb31Sdp } 957daaffb31Sdp 958daaffb31Sdp // 959daaffb31Sdp // The way we compute the max anchor value is to stash it 960daaffb31Sdp // inline in the left and right hand side pages-- it's the same 961daaffb31Sdp // on each side, so we pluck from the left. 962daaffb31Sdp // 963daaffb31Sdp maxval = parent.lhs.document.eof.value.value; 964daaffb31Sdp if (val < maxval) { 965daaffb31Sdp parent.nav.document.diff.real.value = val; 966daaffb31Sdp parent.nav.document.diff.display.value = val.toString(); 967daaffb31Sdp return (val); 968daaffb31Sdp } 969daaffb31Sdp 970daaffb31Sdp // this must be: val >= maxval 971daaffb31Sdp val = maxval; 972daaffb31Sdp parent.nav.document.diff.real.value = val; 973daaffb31Sdp parent.nav.document.diff.display.value = "EOF"; 974daaffb31Sdp return (val); 975daaffb31Sdp} 976daaffb31Sdp 9777c478bd9Sstevel@tonic-gatefunction stopScroll() { 9787c478bd9Sstevel@tonic-gate if (scrolling==1) { 9797c478bd9Sstevel@tonic-gate clearInterval(myInt); 9807c478bd9Sstevel@tonic-gate scrolling=0; 9817c478bd9Sstevel@tonic-gate } 9827c478bd9Sstevel@tonic-gate} 9837c478bd9Sstevel@tonic-gate 9847c478bd9Sstevel@tonic-gatefunction startScroll() { 9857c478bd9Sstevel@tonic-gate stopScroll(); 9867c478bd9Sstevel@tonic-gate scrolling=1; 9877c478bd9Sstevel@tonic-gate myInt=setInterval("scrollByPix()",10); 9887c478bd9Sstevel@tonic-gate} 9897c478bd9Sstevel@tonic-gate 9907c478bd9Sstevel@tonic-gatefunction handlePress(b) { 991daaffb31Sdp 9927c478bd9Sstevel@tonic-gate switch (b) { 9937c478bd9Sstevel@tonic-gate case 1 : 994daaffb31Sdp scrollToAnc(-1); 9957c478bd9Sstevel@tonic-gate break; 9967c478bd9Sstevel@tonic-gate case 2 : 997daaffb31Sdp scrollToAnc(getAncValue() - 1); 9987c478bd9Sstevel@tonic-gate break; 9997c478bd9Sstevel@tonic-gate case 3 : 10007c478bd9Sstevel@tonic-gate sfactor=-3; 10017c478bd9Sstevel@tonic-gate startScroll(); 10027c478bd9Sstevel@tonic-gate break; 10037c478bd9Sstevel@tonic-gate case 4 : 10047c478bd9Sstevel@tonic-gate sfactor=3; 10057c478bd9Sstevel@tonic-gate startScroll(); 10067c478bd9Sstevel@tonic-gate break; 10077c478bd9Sstevel@tonic-gate case 5 : 1008daaffb31Sdp scrollToAnc(getAncValue() + 1); 10097c478bd9Sstevel@tonic-gate break; 10107c478bd9Sstevel@tonic-gate case 6 : 1011daaffb31Sdp scrollToAnc(999999); 10127c478bd9Sstevel@tonic-gate break; 10137c478bd9Sstevel@tonic-gate } 10147c478bd9Sstevel@tonic-gate} 10157c478bd9Sstevel@tonic-gate 10167c478bd9Sstevel@tonic-gatefunction handleRelease(b) { 10177c478bd9Sstevel@tonic-gate stopScroll(); 10187c478bd9Sstevel@tonic-gate} 10197c478bd9Sstevel@tonic-gate 1020daaffb31Sdpfunction keypress(ev) { 1021daaffb31Sdp var keynum; 1022daaffb31Sdp var keychar; 1023daaffb31Sdp 1024daaffb31Sdp if (window.event) { // IE 1025daaffb31Sdp keynum = ev.keyCode; 1026daaffb31Sdp } else if (ev.which) { // non-IE 1027daaffb31Sdp keynum = ev.which; 1028daaffb31Sdp } 1029daaffb31Sdp 1030daaffb31Sdp keychar = String.fromCharCode(keynum); 1031daaffb31Sdp 1032daaffb31Sdp if (keychar == "k") { 1033daaffb31Sdp handlePress(2); 1034daaffb31Sdp return (0); 1035daaffb31Sdp } else if (keychar == "j" || keychar == " ") { 1036daaffb31Sdp handlePress(5); 1037daaffb31Sdp return (0); 1038daaffb31Sdp } 1039daaffb31Sdp return (1); 1040daaffb31Sdp} 1041daaffb31Sdp 10427c478bd9Sstevel@tonic-gatefunction ValidateDiffNum(){ 1043daaffb31Sdp val = parent.nav.document.diff.display.value; 1044daaffb31Sdp if (val == "EOF") { 1045daaffb31Sdp scrollToAnc(999999); 1046daaffb31Sdp return; 1047daaffb31Sdp } 1048daaffb31Sdp 1049daaffb31Sdp if (val == "BOF") { 1050daaffb31Sdp scrollToAnc(0); 1051daaffb31Sdp return; 1052daaffb31Sdp } 1053daaffb31Sdp 1054daaffb31Sdp i=parseInt(val); 10557c478bd9Sstevel@tonic-gate if (isNaN(i)) { 1056daaffb31Sdp parent.nav.document.diff.display.value = getAncValue(); 10577c478bd9Sstevel@tonic-gate } else { 1058daaffb31Sdp scrollToAnc(i); 10597c478bd9Sstevel@tonic-gate } 10607c478bd9Sstevel@tonic-gate return false; 10617c478bd9Sstevel@tonic-gate} 10627c478bd9Sstevel@tonic-gate 1063daaffb31SdpEOF 1064daaffb31Sdp} 1065daaffb31Sdp 1066daaffb31Sdp# 1067daaffb31Sdp# frame_navigation 1068daaffb31Sdp# 1069daaffb31Sdp# Output anchor navigation file for framed sdiffs. 1070daaffb31Sdp# 1071daaffb31Sdpfunction frame_navigation 1072daaffb31Sdp{ 1073daaffb31Sdp print "$HTML<head>$STDHEAD" 1074daaffb31Sdp 1075daaffb31Sdp cat << \EOF 1076daaffb31Sdp<title>Anchor Navigation</title> 1077daaffb31Sdp<meta http-equiv="Content-Script-Type" content="text/javascript"> 1078daaffb31Sdp<meta http-equiv="Content-Type" content="text/html"> 1079daaffb31Sdp 1080daaffb31Sdp<style type="text/css"> 1081daaffb31Sdp div.button td { padding-left: 5px; padding-right: 5px; 1082daaffb31Sdp background-color: #eee; text-align: center; 1083daaffb31Sdp border: 1px #444 outset; cursor: pointer; } 1084daaffb31Sdp div.button a { font-weight: bold; color: black } 1085daaffb31Sdp div.button td:hover { background: #ffcc99; } 1086daaffb31Sdp</style> 1087daaffb31SdpEOF 1088daaffb31Sdp 1089cac38512Smjnelson print "<script type=\"text/javascript\" src=\"ancnav.js\"></script>" 1090daaffb31Sdp 1091daaffb31Sdp cat << \EOF 10927c478bd9Sstevel@tonic-gate</head> 1093daaffb31Sdp<body id="SUNWwebrev" bgcolor="#eeeeee" onload="document.diff.real.focus();" 1094daaffb31Sdp onkeypress="keypress(event);"> 10957c478bd9Sstevel@tonic-gate <noscript lang="javascript"> 10967c478bd9Sstevel@tonic-gate <center> 1097cac38512Smjnelson <p><big>Framed Navigation controls require Javascript</big><br></br> 10987c478bd9Sstevel@tonic-gate Either this browser is incompatable or javascript is not enabled</p> 10997c478bd9Sstevel@tonic-gate </center> 11007c478bd9Sstevel@tonic-gate </noscript> 11017c478bd9Sstevel@tonic-gate <table width="100%" border="0" align="center"> 1102daaffb31Sdp <tr> 1103daaffb31Sdp <td valign="middle" width="25%">Diff navigation: 1104daaffb31Sdp Use 'j' and 'k' for next and previous diffs; or use buttons 1105daaffb31Sdp at right</td> 1106daaffb31Sdp <td align="center" valign="top" width="50%"> 11077c478bd9Sstevel@tonic-gate <div class="button"> 1108daaffb31Sdp <table border="0" align="center"> 1109daaffb31Sdp <tr> 1110daaffb31Sdp <td> 11117c478bd9Sstevel@tonic-gate <a onMouseDown="handlePress(1);return true;" 11127c478bd9Sstevel@tonic-gate onMouseUp="handleRelease(1);return true;" 11137c478bd9Sstevel@tonic-gate onMouseOut="handleRelease(1);return true;" 11147c478bd9Sstevel@tonic-gate onClick="return false;" 11157c478bd9Sstevel@tonic-gate title="Go to Beginning Of file">BOF</a></td> 1116daaffb31Sdp <td> 11177c478bd9Sstevel@tonic-gate <a onMouseDown="handlePress(3);return true;" 11187c478bd9Sstevel@tonic-gate onMouseUp="handleRelease(3);return true;" 11197c478bd9Sstevel@tonic-gate onMouseOut="handleRelease(3);return true;" 11207c478bd9Sstevel@tonic-gate title="Scroll Up: Press and Hold to accelerate" 1121daaffb31Sdp onClick="return false;">Scroll Up</a></td> 1122daaffb31Sdp <td> 11237c478bd9Sstevel@tonic-gate <a onMouseDown="handlePress(2);return true;" 11247c478bd9Sstevel@tonic-gate onMouseUp="handleRelease(2);return true;" 11257c478bd9Sstevel@tonic-gate onMouseOut="handleRelease(2);return true;" 11267c478bd9Sstevel@tonic-gate title="Go to previous Diff" 11277c478bd9Sstevel@tonic-gate onClick="return false;">Prev Diff</a> 11287c478bd9Sstevel@tonic-gate </td></tr> 1129daaffb31Sdp 11307c478bd9Sstevel@tonic-gate <tr> 1131daaffb31Sdp <td> 11327c478bd9Sstevel@tonic-gate <a onMouseDown="handlePress(6);return true;" 11337c478bd9Sstevel@tonic-gate onMouseUp="handleRelease(6);return true;" 11347c478bd9Sstevel@tonic-gate onMouseOut="handleRelease(6);return true;" 11357c478bd9Sstevel@tonic-gate onClick="return false;" 11367c478bd9Sstevel@tonic-gate title="Go to End Of File">EOF</a></td> 1137daaffb31Sdp <td> 11387c478bd9Sstevel@tonic-gate <a onMouseDown="handlePress(4);return true;" 11397c478bd9Sstevel@tonic-gate onMouseUp="handleRelease(4);return true;" 11407c478bd9Sstevel@tonic-gate onMouseOut="handleRelease(4);return true;" 11417c478bd9Sstevel@tonic-gate title="Scroll Down: Press and Hold to accelerate" 1142daaffb31Sdp onClick="return false;">Scroll Down</a></td> 1143daaffb31Sdp <td> 11447c478bd9Sstevel@tonic-gate <a onMouseDown="handlePress(5);return true;" 11457c478bd9Sstevel@tonic-gate onMouseUp="handleRelease(5);return true;" 11467c478bd9Sstevel@tonic-gate onMouseOut="handleRelease(5);return true;" 11477c478bd9Sstevel@tonic-gate title="Go to next Diff" 11487c478bd9Sstevel@tonic-gate onClick="return false;">Next Diff</a></td> 1149daaffb31Sdp </tr> 1150daaffb31Sdp </table> 1151daaffb31Sdp </div> 1152daaffb31Sdp </td> 11537c478bd9Sstevel@tonic-gate <th valign="middle" width="25%"> 1154daaffb31Sdp <form action="" name="diff" onsubmit="return ValidateDiffNum();"> 1155cac38512Smjnelson <input name="display" value="BOF" size="8" type="text"></input> 1156cac38512Smjnelson <input name="real" value="0" size="8" type="hidden"></input> 11577c478bd9Sstevel@tonic-gate </form> 11587c478bd9Sstevel@tonic-gate </th> 1159daaffb31Sdp </tr> 11607c478bd9Sstevel@tonic-gate </table> 11617c478bd9Sstevel@tonic-gate </body> 11627c478bd9Sstevel@tonic-gate</html> 11637c478bd9Sstevel@tonic-gateEOF 11647c478bd9Sstevel@tonic-gate} 11657c478bd9Sstevel@tonic-gate 11667c478bd9Sstevel@tonic-gate 1167daaffb31Sdp 1168daaffb31Sdp# 1169daaffb31Sdp# diff_to_html <filename> <filepath> { U | C } <comment> 1170daaffb31Sdp# 1171daaffb31Sdp# Processes the output of diff to produce an HTML file representing either 1172daaffb31Sdp# context or unified diffs. 1173daaffb31Sdp# 11747c478bd9Sstevel@tonic-gatediff_to_html() 11757c478bd9Sstevel@tonic-gate{ 11767c478bd9Sstevel@tonic-gate TNAME=$1 1177daaffb31Sdp TPATH=$2 1178daaffb31Sdp DIFFTYPE=$3 1179daaffb31Sdp COMMENT=$4 1180daaffb31Sdp 1181daaffb31Sdp print "$HTML<head>$STDHEAD" 1182daaffb31Sdp print "<title>$WNAME ${DIFFTYPE}diff $TPATH</title>" 1183daaffb31Sdp 1184daaffb31Sdp if [[ $DIFFTYPE == "U" ]]; then 1185daaffb31Sdp print "$UDIFFCSS" 1186daaffb31Sdp fi 1187daaffb31Sdp 1188daaffb31Sdp cat <<-EOF 1189daaffb31Sdp </head> 1190daaffb31Sdp <body id="SUNWwebrev"> 1191daaffb31Sdp <a class="print" href="javascript:print()">Print this page</a> 1192daaffb31Sdp <pre>$COMMENT</pre> 1193daaffb31Sdp <pre> 1194daaffb31Sdp EOF 11957c478bd9Sstevel@tonic-gate 1196cdf0c1d5Smjnelson html_quote | $AWK ' 1197daaffb31Sdp /^--- new/ { next } 1198daaffb31Sdp /^\+\+\+ new/ { next } 1199daaffb31Sdp /^--- old/ { next } 1200daaffb31Sdp /^\*\*\* old/ { next } 1201daaffb31Sdp /^\*\*\*\*/ { next } 12027c478bd9Sstevel@tonic-gate /^-------/ { printf "<center><h1>%s</h1></center>\n", $0; next } 1203cac38512Smjnelson /^\@\@.*\@\@$/ { printf "</pre><hr></hr><pre>\n"; 1204daaffb31Sdp printf "<span class=\"newmarker\">%s</span>\n", $0; 1205daaffb31Sdp next} 1206daaffb31Sdp 1207cac38512Smjnelson /^\*\*\*/ { printf "<hr></hr><span class=\"oldmarker\">%s</span>\n", $0; 1208daaffb31Sdp next} 1209daaffb31Sdp /^---/ { printf "<span class=\"newmarker\">%s</span>\n", $0; 1210daaffb31Sdp next} 1211daaffb31Sdp /^\+/ {printf "<span class=\"new\">%s</span>\n", $0; next} 1212daaffb31Sdp /^!/ {printf "<span class=\"changed\">%s</span>\n", $0; next} 1213daaffb31Sdp /^-/ {printf "<span class=\"removed\">%s</span>\n", $0; next} 1214daaffb31Sdp {printf "%s\n", $0; next} 12157c478bd9Sstevel@tonic-gate ' 1216daaffb31Sdp 1217daaffb31Sdp print "</pre></body></html>\n" 12187c478bd9Sstevel@tonic-gate} 12197c478bd9Sstevel@tonic-gate 12207c478bd9Sstevel@tonic-gate 1221daaffb31Sdp# 1222daaffb31Sdp# source_to_html { new | old } <filename> 1223daaffb31Sdp# 1224daaffb31Sdp# Process a plain vanilla source file to transform it into an HTML file. 1225daaffb31Sdp# 12267c478bd9Sstevel@tonic-gatesource_to_html() 12277c478bd9Sstevel@tonic-gate{ 12287c478bd9Sstevel@tonic-gate WHICH=$1 12297c478bd9Sstevel@tonic-gate TNAME=$2 12307c478bd9Sstevel@tonic-gate 1231daaffb31Sdp print "$HTML<head>$STDHEAD" 1232cdf0c1d5Smjnelson print "<title>$WNAME $WHICH $TNAME</title>" 1233daaffb31Sdp print "<body id=\"SUNWwebrev\">" 1234daaffb31Sdp print "<pre>" 1235cdf0c1d5Smjnelson html_quote | $AWK '{line += 1 ; printf "%4d %s\n", line, $0 }' 1236daaffb31Sdp print "</pre></body></html>" 12377c478bd9Sstevel@tonic-gate} 12387c478bd9Sstevel@tonic-gate 1239daaffb31Sdp# 1240cdf0c1d5Smjnelson# comments_from_teamware {text|html} parent-file child-file 1241daaffb31Sdp# 1242daaffb31Sdp# Find the first delta in the child that's not in the parent. Get the 1243daaffb31Sdp# newest delta from the parent, get all deltas from the child starting 1244daaffb31Sdp# with that delta, and then get all info starting with the second oldest 1245daaffb31Sdp# delta in that list (the first delta unique to the child). 12467c478bd9Sstevel@tonic-gate# 12477c478bd9Sstevel@tonic-gate# This code adapted from Bill Shannon's "spc" script 1248daaffb31Sdp# 1249daaffb31Sdpcomments_from_teamware() 12507c478bd9Sstevel@tonic-gate{ 1251daaffb31Sdp fmt=$1 1252daaffb31Sdp pfile=$PWS/$2 1253daaffb31Sdp cfile=$CWS/$3 12547c478bd9Sstevel@tonic-gate 1255cdf0c1d5Smjnelson if [[ ! -f $PWS/${2%/*}/SCCS/s.${2##*/} && -n $RWS ]]; then 1256cdf0c1d5Smjnelson pfile=$RWS/$2 1257cdf0c1d5Smjnelson fi 1258cdf0c1d5Smjnelson 1259daaffb31Sdp if [[ -f $pfile ]]; then 1260cdf0c1d5Smjnelson psid=$($SCCS prs -d:I: $pfile 2>/dev/null) 12617c478bd9Sstevel@tonic-gate else 12627c478bd9Sstevel@tonic-gate psid=1.1 12637c478bd9Sstevel@tonic-gate fi 12647c478bd9Sstevel@tonic-gate 1265cdf0c1d5Smjnelson set -A sids $($SCCS prs -l -r$psid -d:I: $cfile 2>/dev/null) 12667c478bd9Sstevel@tonic-gate N=${#sids[@]} 12677c478bd9Sstevel@tonic-gate 1268daaffb31Sdp nawkprg=' 1269daaffb31Sdp /^COMMENTS:/ {p=1; continue} 1270daaffb31Sdp /^D [0-9]+\.[0-9]+/ {printf "--- %s ---\n", $2; p=0; } 1271daaffb31Sdp NF == 0u { continue } 1272daaffb31Sdp {if (p==0) continue; print $0 }' 1273daaffb31Sdp 12747c478bd9Sstevel@tonic-gate if [[ $N -ge 2 ]]; then 12757c478bd9Sstevel@tonic-gate sid1=${sids[$((N-2))]} # Gets 2nd to last sid 12767c478bd9Sstevel@tonic-gate 1277daaffb31Sdp if [[ $fmt == "text" ]]; then 1278cdf0c1d5Smjnelson $SCCS prs -l -r$sid1 $cfile 2>/dev/null | \ 1279cdf0c1d5Smjnelson $AWK "$nawkprg" 1280daaffb31Sdp return 1281daaffb31Sdp fi 1282daaffb31Sdp 1283cdf0c1d5Smjnelson $SCCS prs -l -r$sid1 $cfile 2>/dev/null | \ 1284cdf0c1d5Smjnelson html_quote | bug2url | sac2url | $AWK "$nawkprg" 12857c478bd9Sstevel@tonic-gate fi 12867c478bd9Sstevel@tonic-gate} 12877c478bd9Sstevel@tonic-gate 1288daaffb31Sdp# 1289cdf0c1d5Smjnelson# comments_from_wx {text|html} filepath 1290daaffb31Sdp# 1291cdf0c1d5Smjnelson# Given the pathname of a file, find its location in a "wx" active 1292cdf0c1d5Smjnelson# file list and print the following comment. Output is either text or 1293cdf0c1d5Smjnelson# HTML; if the latter, embedded bugids (sequence of 5 or more digits) 1294cdf0c1d5Smjnelson# are turned into URLs. 1295cdf0c1d5Smjnelson# 1296cdf0c1d5Smjnelson# This is also used with Mercurial and the file list provided by hg-active. 1297daaffb31Sdp# 1298daaffb31Sdpcomments_from_wx() 12997c478bd9Sstevel@tonic-gate{ 1300daaffb31Sdp typeset fmt=$1 1301daaffb31Sdp typeset p=$2 13027c478bd9Sstevel@tonic-gate 1303cdf0c1d5Smjnelson comm=`$AWK ' 1304daaffb31Sdp $1 == "'$p'" { 13057c478bd9Sstevel@tonic-gate do getline ; while (NF > 0) 13067c478bd9Sstevel@tonic-gate getline 13077c478bd9Sstevel@tonic-gate while (NF > 0) { print ; getline } 13087c478bd9Sstevel@tonic-gate exit 1309daaffb31Sdp }' < $wxfile` 1310daaffb31Sdp 1311cdf0c1d5Smjnelson if [[ -z $comm ]]; then 1312cdf0c1d5Smjnelson comm="*** NO COMMENTS ***" 1313cdf0c1d5Smjnelson fi 1314cdf0c1d5Smjnelson 1315daaffb31Sdp if [[ $fmt == "text" ]]; then 1316cdf0c1d5Smjnelson print -- "$comm" 1317daaffb31Sdp return 1318daaffb31Sdp fi 1319daaffb31Sdp 1320cdf0c1d5Smjnelson print -- "$comm" | html_quote | bug2url | sac2url 1321cdf0c1d5Smjnelson 13227c478bd9Sstevel@tonic-gate} 13237c478bd9Sstevel@tonic-gate 13247c478bd9Sstevel@tonic-gate# 1325daaffb31Sdp# getcomments {text|html} filepath parentpath 1326daaffb31Sdp# 1327daaffb31Sdp# Fetch the comments depending on what SCM mode we're in. 1328daaffb31Sdp# 1329daaffb31Sdpgetcomments() 1330daaffb31Sdp{ 1331daaffb31Sdp typeset fmt=$1 1332daaffb31Sdp typeset p=$2 1333daaffb31Sdp typeset pp=$3 13347c478bd9Sstevel@tonic-gate 13353df69ef3SDarren Moffat if [[ -n $Nflag ]]; then 13363df69ef3SDarren Moffat return 13373df69ef3SDarren Moffat fi 1338cdf0c1d5Smjnelson # 1339cdf0c1d5Smjnelson # Mercurial support uses a file list in wx format, so this 1340cdf0c1d5Smjnelson # will be used there, too 1341cdf0c1d5Smjnelson # 1342daaffb31Sdp if [[ -n $wxfile ]]; then 1343daaffb31Sdp comments_from_wx $fmt $p 1344daaffb31Sdp else 1345daaffb31Sdp if [[ $SCM_MODE == "teamware" ]]; then 1346daaffb31Sdp comments_from_teamware $fmt $pp $p 1347daaffb31Sdp fi 1348daaffb31Sdp fi 1349daaffb31Sdp} 1350daaffb31Sdp 1351daaffb31Sdp# 1352daaffb31Sdp# printCI <total-changed> <inserted> <deleted> <modified> <unchanged> 1353daaffb31Sdp# 1354daaffb31Sdp# Print out Code Inspection figures similar to sccs-prt(1) format. 1355daaffb31Sdp# 1356daaffb31Sdpfunction printCI 1357daaffb31Sdp{ 1358daaffb31Sdp integer tot=$1 ins=$2 del=$3 mod=$4 unc=$5 1359daaffb31Sdp typeset str 1360daaffb31Sdp if (( tot == 1 )); then 1361daaffb31Sdp str="line" 1362daaffb31Sdp else 1363daaffb31Sdp str="lines" 1364daaffb31Sdp fi 1365daaffb31Sdp printf '%d %s changed: %d ins; %d del; %d mod; %d unchg\n' \ 1366daaffb31Sdp $tot $str $ins $del $mod $unc 1367daaffb31Sdp} 1368daaffb31Sdp 1369daaffb31Sdp 1370daaffb31Sdp# 1371daaffb31Sdp# difflines <oldfile> <newfile> 1372daaffb31Sdp# 1373daaffb31Sdp# Calculate and emit number of added, removed, modified and unchanged lines, 1374daaffb31Sdp# and total lines changed, the sum of added + removed + modified. 1375daaffb31Sdp# 13767c478bd9Sstevel@tonic-gatefunction difflines 13777c478bd9Sstevel@tonic-gate{ 1378daaffb31Sdp integer tot mod del ins unc err 13797c478bd9Sstevel@tonic-gate typeset filename 13807c478bd9Sstevel@tonic-gate 1381cdf0c1d5Smjnelson eval $( diff -e $1 $2 | $AWK ' 1382daaffb31Sdp # Change range of lines: N,Nc 13837c478bd9Sstevel@tonic-gate /^[0-9]*,[0-9]*c$/ { 13847c478bd9Sstevel@tonic-gate n=split(substr($1,1,length($1)-1), counts, ","); 13857c478bd9Sstevel@tonic-gate if (n != 2) { 13867c478bd9Sstevel@tonic-gate error=2 13877c478bd9Sstevel@tonic-gate exit; 13887c478bd9Sstevel@tonic-gate } 1389daaffb31Sdp # 1390daaffb31Sdp # 3,5c means lines 3 , 4 and 5 are changed, a total of 3 lines. 1391daaffb31Sdp # following would be 5 - 3 = 2! Hence +1 for correction. 1392daaffb31Sdp # 13937c478bd9Sstevel@tonic-gate r=(counts[2]-counts[1])+1; 1394daaffb31Sdp 1395daaffb31Sdp # 1396daaffb31Sdp # Now count replacement lines: each represents a change instead 1397daaffb31Sdp # of a delete, so increment c and decrement r. 1398daaffb31Sdp # 13997c478bd9Sstevel@tonic-gate while (getline != /^\.$/) { 14007c478bd9Sstevel@tonic-gate c++; 14017c478bd9Sstevel@tonic-gate r--; 14027c478bd9Sstevel@tonic-gate } 1403daaffb31Sdp # 1404daaffb31Sdp # If there were more replacement lines than original lines, 1405daaffb31Sdp # then r will be negative; in this case there are no deletions, 1406daaffb31Sdp # but there are r changes that should be counted as adds, and 1407daaffb31Sdp # since r is negative, subtract it from a and add it to c. 1408daaffb31Sdp # 14097c478bd9Sstevel@tonic-gate if (r < 0) { 14107c478bd9Sstevel@tonic-gate a-=r; 14117c478bd9Sstevel@tonic-gate c+=r; 14127c478bd9Sstevel@tonic-gate } 1413daaffb31Sdp 1414daaffb31Sdp # 1415daaffb31Sdp # If there were more original lines than replacement lines, then 1416daaffb31Sdp # r will be positive; in this case, increment d by that much. 1417daaffb31Sdp # 14187c478bd9Sstevel@tonic-gate if (r > 0) { 14197c478bd9Sstevel@tonic-gate d+=r; 14207c478bd9Sstevel@tonic-gate } 14217c478bd9Sstevel@tonic-gate next; 14227c478bd9Sstevel@tonic-gate } 14237c478bd9Sstevel@tonic-gate 1424daaffb31Sdp # Change lines: Nc 14257c478bd9Sstevel@tonic-gate /^[0-9].*c$/ { 1426daaffb31Sdp # The first line is a replacement; any more are additions. 14277c478bd9Sstevel@tonic-gate if (getline != /^\.$/) { 14287c478bd9Sstevel@tonic-gate c++; 14297c478bd9Sstevel@tonic-gate while (getline != /^\.$/) a++; 14307c478bd9Sstevel@tonic-gate } 14317c478bd9Sstevel@tonic-gate next; 14327c478bd9Sstevel@tonic-gate } 14337c478bd9Sstevel@tonic-gate 1434daaffb31Sdp # Add lines: both Na and N,Na 14357c478bd9Sstevel@tonic-gate /^[0-9].*a$/ { 14367c478bd9Sstevel@tonic-gate while (getline != /^\.$/) a++; 14377c478bd9Sstevel@tonic-gate next; 14387c478bd9Sstevel@tonic-gate } 14397c478bd9Sstevel@tonic-gate 1440daaffb31Sdp # Delete range of lines: N,Nd 14417c478bd9Sstevel@tonic-gate /^[0-9]*,[0-9]*d$/ { 14427c478bd9Sstevel@tonic-gate n=split(substr($1,1,length($1)-1), counts, ","); 14437c478bd9Sstevel@tonic-gate if (n != 2) { 14447c478bd9Sstevel@tonic-gate error=2 14457c478bd9Sstevel@tonic-gate exit; 14467c478bd9Sstevel@tonic-gate } 1447daaffb31Sdp # 1448daaffb31Sdp # 3,5d means lines 3 , 4 and 5 are deleted, a total of 3 lines. 1449daaffb31Sdp # following would be 5 - 3 = 2! Hence +1 for correction. 1450daaffb31Sdp # 14517c478bd9Sstevel@tonic-gate r=(counts[2]-counts[1])+1; 14527c478bd9Sstevel@tonic-gate d+=r; 14537c478bd9Sstevel@tonic-gate next; 14547c478bd9Sstevel@tonic-gate } 14557c478bd9Sstevel@tonic-gate 1456daaffb31Sdp # Delete line: Nd. For example 10d says line 10 is deleted. 14577c478bd9Sstevel@tonic-gate /^[0-9]*d$/ {d++; next} 14587c478bd9Sstevel@tonic-gate 1459daaffb31Sdp # Should not get here! 14607c478bd9Sstevel@tonic-gate { 14617c478bd9Sstevel@tonic-gate error=1; 14627c478bd9Sstevel@tonic-gate exit; 14637c478bd9Sstevel@tonic-gate } 14647c478bd9Sstevel@tonic-gate 1465daaffb31Sdp # Finish off - print results 14667c478bd9Sstevel@tonic-gate END { 1467daaffb31Sdp printf("tot=%d;mod=%d;del=%d;ins=%d;err=%d\n", 14687c478bd9Sstevel@tonic-gate (c+d+a), c, d, a, error); 14697c478bd9Sstevel@tonic-gate }' ) 14707c478bd9Sstevel@tonic-gate 1471cdf0c1d5Smjnelson # End of $AWK, Check to see if any trouble occurred. 14727c478bd9Sstevel@tonic-gate if (( $? > 0 || err > 0 )); then 1473daaffb31Sdp print "Unexpected Error occurred reading" \ 1474daaffb31Sdp "\`diff -e $1 $2\`: \$?=$?, err=" $err 1475daaffb31Sdp return 1476daaffb31Sdp fi 1477daaffb31Sdp 14787c478bd9Sstevel@tonic-gate # Accumulate totals 14797c478bd9Sstevel@tonic-gate (( TOTL += tot )) 1480daaffb31Sdp (( TMOD += mod )) 14817c478bd9Sstevel@tonic-gate (( TDEL += del )) 14827c478bd9Sstevel@tonic-gate (( TINS += ins )) 14837c478bd9Sstevel@tonic-gate # Calculate unchanged lines 1484cdf0c1d5Smjnelson unc=`wc -l < $1` 14857c478bd9Sstevel@tonic-gate if (( unc > 0 )); then 1486daaffb31Sdp (( unc -= del + mod )) 14877c478bd9Sstevel@tonic-gate (( TUNC += unc )) 14887c478bd9Sstevel@tonic-gate fi 14897c478bd9Sstevel@tonic-gate # print summary 1490daaffb31Sdp print "<span class=\"lineschanged\">" 1491daaffb31Sdp printCI $tot $ins $del $mod $unc 1492daaffb31Sdp print "</span>" 14937c478bd9Sstevel@tonic-gate} 14947c478bd9Sstevel@tonic-gate 1495daaffb31Sdp 14967c478bd9Sstevel@tonic-gate# 1497daaffb31Sdp# flist_from_wx 1498daaffb31Sdp# 1499daaffb31Sdp# Sets up webrev to source its information from a wx-formatted file. 1500daaffb31Sdp# Sets the global 'wxfile' variable. 1501daaffb31Sdp# 1502daaffb31Sdpfunction flist_from_wx 15037c478bd9Sstevel@tonic-gate{ 1504daaffb31Sdp typeset argfile=$1 1505daaffb31Sdp if [[ -n ${argfile%%/*} ]]; then 1506daaffb31Sdp # 1507daaffb31Sdp # If the wx file pathname is relative then make it absolute 1508daaffb31Sdp # because the webrev does a "cd" later on. 1509daaffb31Sdp # 1510daaffb31Sdp wxfile=$PWD/$argfile 15117c478bd9Sstevel@tonic-gate else 1512daaffb31Sdp wxfile=$argfile 15137c478bd9Sstevel@tonic-gate fi 15147c478bd9Sstevel@tonic-gate 1515cdf0c1d5Smjnelson $AWK '{ c = 1; print; 15167c478bd9Sstevel@tonic-gate while (getline) { 15177c478bd9Sstevel@tonic-gate if (NF == 0) { c = -c; continue } 15187c478bd9Sstevel@tonic-gate if (c > 0) print 15197c478bd9Sstevel@tonic-gate } 1520daaffb31Sdp }' $wxfile > $FLIST 15217c478bd9Sstevel@tonic-gate 1522daaffb31Sdp print " Done." 1523daaffb31Sdp} 15247c478bd9Sstevel@tonic-gate 1525daaffb31Sdp# 1526daaffb31Sdp# flist_from_teamware [ <args-to-putback-n> ] 1527daaffb31Sdp# 1528daaffb31Sdp# Generate the file list by extracting file names from a putback -n. Some 1529daaffb31Sdp# names may come from the "update/create" messages and others from the 1530daaffb31Sdp# "currently checked out" warning. Renames are detected here too. Extract 1531daaffb31Sdp# values for CODEMGR_WS and CODEMGR_PARENT from the output of the putback 1532daaffb31Sdp# -n as well, but remove them if they are already defined. 1533daaffb31Sdp# 1534daaffb31Sdpfunction flist_from_teamware 1535daaffb31Sdp{ 1536cdf0c1d5Smjnelson if [[ -n $codemgr_parent && -z $parent_webrev ]]; then 1537daaffb31Sdp if [[ ! -d $codemgr_parent/Codemgr_wsdata ]]; then 1538daaffb31Sdp print -u2 "parent $codemgr_parent doesn't look like a" \ 1539daaffb31Sdp "valid teamware workspace" 15407c478bd9Sstevel@tonic-gate exit 1 15417c478bd9Sstevel@tonic-gate fi 1542daaffb31Sdp parent_args="-p $codemgr_parent" 15437c478bd9Sstevel@tonic-gate fi 15447c478bd9Sstevel@tonic-gate 1545daaffb31Sdp print " File list from: 'putback -n $parent_args $*' ... \c" 15467c478bd9Sstevel@tonic-gate 1547daaffb31Sdp putback -n $parent_args $* 2>&1 | 1548cdf0c1d5Smjnelson $AWK ' 1549daaffb31Sdp /^update:|^create:/ {print $2} 1550daaffb31Sdp /^Parent workspace:/ {printf("CODEMGR_PARENT=%s\n",$3)} 1551daaffb31Sdp /^Child workspace:/ {printf("CODEMGR_WS=%s\n",$3)} 1552daaffb31Sdp /^The following files are currently checked out/ {p = 1; continue} 1553daaffb31Sdp NF == 0 {p=0 ; continue} 1554daaffb31Sdp /^rename/ {old=$3} 1555daaffb31Sdp $1 == "to:" {print $2, old} 1556daaffb31Sdp /^"/ {continue} 1557daaffb31Sdp p == 1 {print $1}' | 1558daaffb31Sdp sort -r -k 1,1 -u | sort > $FLIST 15597c478bd9Sstevel@tonic-gate 1560daaffb31Sdp print " Done." 1561daaffb31Sdp} 1562daaffb31Sdp 1563cdf0c1d5Smjnelson# 1564cdf0c1d5Smjnelson# Call hg-active to get the active list output in the wx active list format 1565cdf0c1d5Smjnelson# 1566cdf0c1d5Smjnelsonfunction hg_active_wxfile 1567cdf0c1d5Smjnelson{ 1568cdf0c1d5Smjnelson typeset child=$1 1569cdf0c1d5Smjnelson typeset parent=$2 1570cdf0c1d5Smjnelson 1571cdf0c1d5Smjnelson TMPFLIST=/tmp/$$.active 15729a70fc3bSMark J. Nelson $HG_ACTIVE -w $child -p $parent -o $TMPFLIST 1573cdf0c1d5Smjnelson wxfile=$TMPFLIST 1574cdf0c1d5Smjnelson} 1575cdf0c1d5Smjnelson 1576cdf0c1d5Smjnelson# 1577cdf0c1d5Smjnelson# flist_from_mercurial 1578cdf0c1d5Smjnelson# Call hg-active to get a wx-style active list, and hand it off to 1579cdf0c1d5Smjnelson# flist_from_wx 1580cdf0c1d5Smjnelson# 1581cdf0c1d5Smjnelsonfunction flist_from_mercurial 1582cdf0c1d5Smjnelson{ 1583cdf0c1d5Smjnelson typeset child=$1 1584cdf0c1d5Smjnelson typeset parent=$2 1585cdf0c1d5Smjnelson 1586cdf0c1d5Smjnelson print " File list from: hg-active -p $parent ...\c" 1587cdf0c1d5Smjnelson 1588cdf0c1d5Smjnelson if [[ ! -x $HG_ACTIVE ]]; then 1589cdf0c1d5Smjnelson print # Blank line for the \c above 1590cdf0c1d5Smjnelson print -u2 "Error: hg-active tool not found. Exiting" 1591cdf0c1d5Smjnelson exit 1 1592cdf0c1d5Smjnelson fi 1593cdf0c1d5Smjnelson hg_active_wxfile $child $parent 1594cdf0c1d5Smjnelson 1595cdf0c1d5Smjnelson # flist_from_wx prints the Done, so we don't have to. 1596cdf0c1d5Smjnelson flist_from_wx $TMPFLIST 1597cdf0c1d5Smjnelson} 1598cdf0c1d5Smjnelson 1599cdf0c1d5Smjnelson# 1600cdf0c1d5Smjnelson# flist_from_subversion 1601cdf0c1d5Smjnelson# 1602cdf0c1d5Smjnelson# Generate the file list by extracting file names from svn status. 1603cdf0c1d5Smjnelson# 1604cdf0c1d5Smjnelsonfunction flist_from_subversion 1605cdf0c1d5Smjnelson{ 1606cdf0c1d5Smjnelson CWS=$1 1607cdf0c1d5Smjnelson OLDPWD=$2 1608cdf0c1d5Smjnelson 1609cdf0c1d5Smjnelson cd $CWS 1610cdf0c1d5Smjnelson print -u2 " File list from: svn status ... \c" 1611cdf0c1d5Smjnelson svn status | $AWK '/^[ACDMR]/ { print $NF }' > $FLIST 1612cdf0c1d5Smjnelson print -u2 " Done." 1613cdf0c1d5Smjnelson cd $OLDPWD 1614cdf0c1d5Smjnelson} 1615cdf0c1d5Smjnelson 1616daaffb31Sdpfunction env_from_flist 1617daaffb31Sdp{ 1618daaffb31Sdp [[ -r $FLIST ]] || return 1619daaffb31Sdp 1620daaffb31Sdp # 1621daaffb31Sdp # Use "eval" to set env variables that are listed in the file 1622daaffb31Sdp # list. Then copy those into our local versions of those 1623daaffb31Sdp # variables if they have not been set already. 1624daaffb31Sdp # 1625*02d26c39SVladimir Kotal eval `sed -e "s/#.*$//" $FLIST | $GREP = ` 16267c478bd9Sstevel@tonic-gate 1627cdf0c1d5Smjnelson if [[ -z $codemgr_ws && -n $CODEMGR_WS ]]; then 1628cdf0c1d5Smjnelson codemgr_ws=$CODEMGR_WS 1629cdf0c1d5Smjnelson export CODEMGR_WS 1630cdf0c1d5Smjnelson fi 16317c478bd9Sstevel@tonic-gate 1632daaffb31Sdp # 1633daaffb31Sdp # Check to see if CODEMGR_PARENT is set in the flist file. 1634daaffb31Sdp # 1635cdf0c1d5Smjnelson if [[ -z $codemgr_parent && -n $CODEMGR_PARENT ]]; then 1636daaffb31Sdp codemgr_parent=$CODEMGR_PARENT 1637cdf0c1d5Smjnelson export CODEMGR_PARENT 1638daaffb31Sdp fi 1639daaffb31Sdp} 1640daaffb31Sdp 164114983201Sdpfunction look_for_prog 164214983201Sdp{ 164314983201Sdp typeset path 164414983201Sdp typeset ppath 164514983201Sdp typeset progname=$1 164614983201Sdp 164714983201Sdp ppath=$PATH 164814983201Sdp ppath=$ppath:/usr/sfw/bin:/usr/bin:/usr/sbin 164914983201Sdp ppath=$ppath:/opt/teamware/bin:/opt/onbld/bin 1650cdf0c1d5Smjnelson ppath=$ppath:/opt/onbld/bin/`uname -p` 165114983201Sdp 165214983201Sdp PATH=$ppath prog=`whence $progname` 165314983201Sdp if [[ -n $prog ]]; then 165414983201Sdp print $prog 165514983201Sdp fi 165614983201Sdp} 165714983201Sdp 1658cdf0c1d5Smjnelsonfunction get_file_mode 1659cdf0c1d5Smjnelson{ 1660cdf0c1d5Smjnelson $PERL -e ' 1661cdf0c1d5Smjnelson if (@stat = stat($ARGV[0])) { 1662cdf0c1d5Smjnelson $mode = $stat[2] & 0777; 1663cdf0c1d5Smjnelson printf "%03o\n", $mode; 1664cdf0c1d5Smjnelson exit 0; 1665cdf0c1d5Smjnelson } else { 1666cdf0c1d5Smjnelson exit 1; 1667cdf0c1d5Smjnelson } 1668cdf0c1d5Smjnelson ' $1 1669cdf0c1d5Smjnelson} 1670cdf0c1d5Smjnelson 1671cdf0c1d5Smjnelsonfunction build_old_new_teamware 1672cdf0c1d5Smjnelson{ 1673cdf0c1d5Smjnelson typeset olddir="$1" 1674cdf0c1d5Smjnelson typeset newdir="$2" 1675cdf0c1d5Smjnelson 1676cdf0c1d5Smjnelson # If the child's version doesn't exist then 1677cdf0c1d5Smjnelson # get a readonly copy. 1678cdf0c1d5Smjnelson 1679cdf0c1d5Smjnelson if [[ ! -f $CWS/$DIR/$F && -f $CWS/$DIR/SCCS/s.$F ]]; then 1680cdf0c1d5Smjnelson $SCCS get -s -p $CWS/$DIR/$F > $CWS/$DIR/$F 1681cdf0c1d5Smjnelson fi 1682cdf0c1d5Smjnelson 1683cdf0c1d5Smjnelson # The following two sections propagate file permissions the 1684cdf0c1d5Smjnelson # same way SCCS does. If the file is already under version 1685cdf0c1d5Smjnelson # control, always use permissions from the SCCS/s.file. If 1686cdf0c1d5Smjnelson # the file is not under SCCS control, use permissions from the 1687cdf0c1d5Smjnelson # working copy. In all cases, the file copied to the webrev 1688cdf0c1d5Smjnelson # is set to read only, and group/other permissions are set to 1689cdf0c1d5Smjnelson # match those of the file owner. This way, even if the file 1690cdf0c1d5Smjnelson # is currently checked out, the webrev will display the final 1691cdf0c1d5Smjnelson # permissions that would result after check in. 1692cdf0c1d5Smjnelson 1693cdf0c1d5Smjnelson # 1694cdf0c1d5Smjnelson # Snag new version of file. 1695cdf0c1d5Smjnelson # 1696cdf0c1d5Smjnelson rm -f $newdir/$DIR/$F 1697cdf0c1d5Smjnelson cp $CWS/$DIR/$F $newdir/$DIR/$F 1698cdf0c1d5Smjnelson if [[ -f $CWS/$DIR/SCCS/s.$F ]]; then 1699cdf0c1d5Smjnelson chmod `get_file_mode $CWS/$DIR/SCCS/s.$F` \ 1700cdf0c1d5Smjnelson $newdir/$DIR/$F 1701cdf0c1d5Smjnelson fi 1702cdf0c1d5Smjnelson chmod u-w,go=u $newdir/$DIR/$F 1703cdf0c1d5Smjnelson 1704cdf0c1d5Smjnelson # 1705cdf0c1d5Smjnelson # Get the parent's version of the file. First see whether the 1706cdf0c1d5Smjnelson # child's version is checked out and get the parent's version 1707cdf0c1d5Smjnelson # with keywords expanded or unexpanded as appropriate. 1708cdf0c1d5Smjnelson # 1709cdf0c1d5Smjnelson if [[ -f $PWS/$PDIR/$PF && ! -f $PWS/$PDIR/SCCS/s.$PF && \ 1710cdf0c1d5Smjnelson ! -f $PWS/$PDIR/SCCS/p.$PF ]]; then 1711cdf0c1d5Smjnelson # Parent is not a real workspace, but just a raw 1712cdf0c1d5Smjnelson # directory tree - use the file that's there as 1713cdf0c1d5Smjnelson # the old file. 1714cdf0c1d5Smjnelson 1715cdf0c1d5Smjnelson rm -f $olddir/$PDIR/$PF 1716cdf0c1d5Smjnelson cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF 1717cdf0c1d5Smjnelson else 1718cdf0c1d5Smjnelson if [[ -f $PWS/$PDIR/SCCS/s.$PF ]]; then 1719cdf0c1d5Smjnelson real_parent=$PWS 1720cdf0c1d5Smjnelson else 1721cdf0c1d5Smjnelson real_parent=$RWS 1722cdf0c1d5Smjnelson fi 1723cdf0c1d5Smjnelson 1724cdf0c1d5Smjnelson rm -f $olddir/$PDIR/$PF 1725cdf0c1d5Smjnelson 1726cdf0c1d5Smjnelson if [[ -f $real_parent/$PDIR/$PF ]]; then 1727cdf0c1d5Smjnelson if [ -f $CWS/$DIR/SCCS/p.$F ]; then 1728cdf0c1d5Smjnelson $SCCS get -s -p -k $real_parent/$PDIR/$PF > \ 1729cdf0c1d5Smjnelson $olddir/$PDIR/$PF 1730cdf0c1d5Smjnelson else 1731cdf0c1d5Smjnelson $SCCS get -s -p $real_parent/$PDIR/$PF > \ 1732cdf0c1d5Smjnelson $olddir/$PDIR/$PF 1733cdf0c1d5Smjnelson fi 1734cdf0c1d5Smjnelson chmod `get_file_mode $real_parent/$PDIR/SCCS/s.$PF` \ 1735cdf0c1d5Smjnelson $olddir/$PDIR/$PF 1736cdf0c1d5Smjnelson fi 1737cdf0c1d5Smjnelson fi 1738cdf0c1d5Smjnelson if [[ -f $olddir/$PDIR/$PF ]]; then 1739cdf0c1d5Smjnelson chmod u-w,go=u $olddir/$PDIR/$PF 1740cdf0c1d5Smjnelson fi 1741cdf0c1d5Smjnelson} 1742cdf0c1d5Smjnelson 1743cdf0c1d5Smjnelsonfunction build_old_new_mercurial 1744cdf0c1d5Smjnelson{ 1745cdf0c1d5Smjnelson typeset olddir="$1" 1746cdf0c1d5Smjnelson typeset newdir="$2" 1747cdf0c1d5Smjnelson typeset old_mode= 1748cdf0c1d5Smjnelson typeset new_mode= 1749cdf0c1d5Smjnelson typeset file 1750cdf0c1d5Smjnelson 1751cdf0c1d5Smjnelson # 1752cdf0c1d5Smjnelson # Get old file mode, from the parent revision manifest entry. 1753cdf0c1d5Smjnelson # Mercurial only stores a "file is executable" flag, but the 1754cdf0c1d5Smjnelson # manifest will display an octal mode "644" or "755". 1755cdf0c1d5Smjnelson # 1756cdf0c1d5Smjnelson if [[ "$PDIR" == "." ]]; then 1757cdf0c1d5Smjnelson file="$PF" 1758cdf0c1d5Smjnelson else 1759cdf0c1d5Smjnelson file="$PDIR/$PF" 1760cdf0c1d5Smjnelson fi 1761cdf0c1d5Smjnelson file=`echo $file | sed 's#/#\\\/#g'` 1762cdf0c1d5Smjnelson # match the exact filename, and return only the permission digits 1763cdf0c1d5Smjnelson old_mode=`sed -n -e "/^\\(...\\) . ${file}$/s//\\1/p" \ 1764cdf0c1d5Smjnelson < $HG_PARENT_MANIFEST` 1765cdf0c1d5Smjnelson 1766cdf0c1d5Smjnelson # 1767cdf0c1d5Smjnelson # Get new file mode, directly from the filesystem. 1768cdf0c1d5Smjnelson # Normalize the mode to match Mercurial's behavior. 1769cdf0c1d5Smjnelson # 1770cdf0c1d5Smjnelson new_mode=`get_file_mode $CWS/$DIR/$F` 1771cdf0c1d5Smjnelson if [[ -n "$new_mode" ]]; then 1772cdf0c1d5Smjnelson if [[ "$new_mode" = *[1357]* ]]; then 1773cdf0c1d5Smjnelson new_mode=755 1774cdf0c1d5Smjnelson else 1775cdf0c1d5Smjnelson new_mode=644 1776cdf0c1d5Smjnelson fi 1777cdf0c1d5Smjnelson fi 1778cdf0c1d5Smjnelson 1779cdf0c1d5Smjnelson # 1780cdf0c1d5Smjnelson # new version of the file. 1781cdf0c1d5Smjnelson # 1782cdf0c1d5Smjnelson rm -rf $newdir/$DIR/$F 1783cdf0c1d5Smjnelson if [[ -e $CWS/$DIR/$F ]]; then 1784cdf0c1d5Smjnelson cp $CWS/$DIR/$F $newdir/$DIR/$F 1785cdf0c1d5Smjnelson if [[ -n $new_mode ]]; then 1786cdf0c1d5Smjnelson chmod $new_mode $newdir/$DIR/$F 1787cdf0c1d5Smjnelson else 1788cdf0c1d5Smjnelson # should never happen 1789cdf0c1d5Smjnelson print -u2 "ERROR: set mode of $newdir/$DIR/$F" 1790cdf0c1d5Smjnelson fi 1791cdf0c1d5Smjnelson fi 1792cdf0c1d5Smjnelson 1793cdf0c1d5Smjnelson # 1794cdf0c1d5Smjnelson # parent's version of the file 1795cdf0c1d5Smjnelson # 1796cdf0c1d5Smjnelson # Note that we get this from the last version common to both 1797cdf0c1d5Smjnelson # ourselves and the parent. References are via $CWS since we have no 1798cdf0c1d5Smjnelson # guarantee that the parent workspace is reachable via the filesystem. 1799cdf0c1d5Smjnelson # 1800cdf0c1d5Smjnelson if [[ -n $parent_webrev && -e $PWS/$PDIR/$PF ]]; then 1801cdf0c1d5Smjnelson cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF 1802cdf0c1d5Smjnelson elif [[ -n $HG_PARENT ]]; then 1803cdf0c1d5Smjnelson hg cat -R $CWS -r $HG_PARENT $CWS/$PDIR/$PF > \ 1804cdf0c1d5Smjnelson $olddir/$PDIR/$PF 2>/dev/null 1805cdf0c1d5Smjnelson 1806*02d26c39SVladimir Kotal if (( $? != 0 )); then 1807cdf0c1d5Smjnelson rm -f $olddir/$PDIR/$PF 1808cdf0c1d5Smjnelson else 1809cdf0c1d5Smjnelson if [[ -n $old_mode ]]; then 1810cdf0c1d5Smjnelson chmod $old_mode $olddir/$PDIR/$PF 1811cdf0c1d5Smjnelson else 1812cdf0c1d5Smjnelson # should never happen 1813cdf0c1d5Smjnelson print -u2 "ERROR: set mode of $olddir/$PDIR/$PF" 1814cdf0c1d5Smjnelson fi 1815cdf0c1d5Smjnelson fi 1816cdf0c1d5Smjnelson fi 1817cdf0c1d5Smjnelson} 1818cdf0c1d5Smjnelson 1819cdf0c1d5Smjnelsonfunction build_old_new_subversion 1820cdf0c1d5Smjnelson{ 1821cdf0c1d5Smjnelson typeset olddir="$1" 1822cdf0c1d5Smjnelson typeset newdir="$2" 1823cdf0c1d5Smjnelson 1824cdf0c1d5Smjnelson # Snag new version of file. 1825cdf0c1d5Smjnelson rm -f $newdir/$DIR/$F 1826cdf0c1d5Smjnelson [[ -e $CWS/$DIR/$F ]] && cp $CWS/$DIR/$F $newdir/$DIR/$F 1827cdf0c1d5Smjnelson 1828cdf0c1d5Smjnelson if [[ -n $PWS && -e $PWS/$PDIR/$PF ]]; then 1829cdf0c1d5Smjnelson cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF 1830cdf0c1d5Smjnelson else 1831cdf0c1d5Smjnelson # Get the parent's version of the file. 1832cdf0c1d5Smjnelson svn status $CWS/$DIR/$F | read stat file 1833cdf0c1d5Smjnelson if [[ $stat != "A" ]]; then 1834cdf0c1d5Smjnelson svn cat -r BASE $CWS/$DIR/$F > $olddir/$PDIR/$PF 1835cdf0c1d5Smjnelson fi 1836cdf0c1d5Smjnelson fi 1837cdf0c1d5Smjnelson} 1838cdf0c1d5Smjnelson 1839cdf0c1d5Smjnelsonfunction build_old_new_unknown 1840cdf0c1d5Smjnelson{ 1841cdf0c1d5Smjnelson typeset olddir="$1" 1842cdf0c1d5Smjnelson typeset newdir="$2" 1843cdf0c1d5Smjnelson 1844cdf0c1d5Smjnelson # 1845cdf0c1d5Smjnelson # Snag new version of file. 1846cdf0c1d5Smjnelson # 1847cdf0c1d5Smjnelson rm -f $newdir/$DIR/$F 1848cdf0c1d5Smjnelson [[ -e $CWS/$DIR/$F ]] && cp $CWS/$DIR/$F $newdir/$DIR/$F 1849cdf0c1d5Smjnelson 1850cdf0c1d5Smjnelson # 1851cdf0c1d5Smjnelson # Snag the parent's version of the file. 1852cdf0c1d5Smjnelson # 1853cdf0c1d5Smjnelson if [[ -f $PWS/$PDIR/$PF ]]; then 1854cdf0c1d5Smjnelson rm -f $olddir/$PDIR/$PF 1855cdf0c1d5Smjnelson cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF 1856cdf0c1d5Smjnelson fi 1857cdf0c1d5Smjnelson} 1858cdf0c1d5Smjnelson 1859cdf0c1d5Smjnelsonfunction build_old_new 1860cdf0c1d5Smjnelson{ 1861cdf0c1d5Smjnelson typeset WDIR=$1 1862cdf0c1d5Smjnelson typeset PWS=$2 1863cdf0c1d5Smjnelson typeset PDIR=$3 1864cdf0c1d5Smjnelson typeset PF=$4 1865cdf0c1d5Smjnelson typeset CWS=$5 1866cdf0c1d5Smjnelson typeset DIR=$6 1867cdf0c1d5Smjnelson typeset F=$7 1868cdf0c1d5Smjnelson 1869cdf0c1d5Smjnelson typeset olddir="$WDIR/raw_files/old" 1870cdf0c1d5Smjnelson typeset newdir="$WDIR/raw_files/new" 1871cdf0c1d5Smjnelson 1872cdf0c1d5Smjnelson mkdir -p $olddir/$PDIR 1873cdf0c1d5Smjnelson mkdir -p $newdir/$DIR 1874cdf0c1d5Smjnelson 1875cdf0c1d5Smjnelson if [[ $SCM_MODE == "teamware" ]]; then 1876cdf0c1d5Smjnelson build_old_new_teamware "$olddir" "$newdir" 1877cdf0c1d5Smjnelson elif [[ $SCM_MODE == "mercurial" ]]; then 1878cdf0c1d5Smjnelson build_old_new_mercurial "$olddir" "$newdir" 1879cdf0c1d5Smjnelson elif [[ $SCM_MODE == "subversion" ]]; then 1880cdf0c1d5Smjnelson build_old_new_subversion "$olddir" "$newdir" 1881cdf0c1d5Smjnelson elif [[ $SCM_MODE == "unknown" ]]; then 1882cdf0c1d5Smjnelson build_old_new_unknown "$olddir" "$newdir" 1883cdf0c1d5Smjnelson fi 1884cdf0c1d5Smjnelson 1885cdf0c1d5Smjnelson if [[ ! -f $olddir/$PDIR/$PF && ! -f $newdir/$DIR/$F ]]; then 1886cdf0c1d5Smjnelson print "*** Error: file not in parent or child" 1887cdf0c1d5Smjnelson return 1 1888cdf0c1d5Smjnelson fi 1889cdf0c1d5Smjnelson return 0 1890cdf0c1d5Smjnelson} 1891cdf0c1d5Smjnelson 1892cdf0c1d5Smjnelson 1893daaffb31Sdp# 1894daaffb31Sdp# Usage message. 1895daaffb31Sdp# 1896daaffb31Sdpfunction usage 1897daaffb31Sdp{ 1898daaffb31Sdp print 'Usage:\twebrev [common-options] 1899daaffb31Sdp webrev [common-options] ( <file> | - ) 1900daaffb31Sdp webrev [common-options] -w <wx file> 1901daaffb31Sdp 1902daaffb31SdpOptions: 1903daaffb31Sdp -O: Print bugids/arc cases suitable for OpenSolaris. 1904daaffb31Sdp -i <filename>: Include <filename> in the index.html file. 1905daaffb31Sdp -o <outdir>: Output webrev to specified directory. 1906daaffb31Sdp -p <compare-against>: Use specified parent wkspc or basis for comparison 1907*02d26c39SVladimir Kotal -t <remote_target>: Specify remote destination for webrev upload 1908*02d26c39SVladimir Kotal -U: upload the webrev to remote destination 1909*02d26c39SVladimir Kotal -n: do not generate the webrev (useful with -U) 1910daaffb31Sdp -w <wxfile>: Use specified wx active file. 1911daaffb31Sdp 1912daaffb31SdpEnvironment: 1913daaffb31Sdp WDIR: Control the output directory. 1914daaffb31Sdp WEBREV_BUGURL: Control the URL prefix for bugids. 1915daaffb31Sdp WEBREV_SACURL: Control the URL prefix for ARC cases. 1916daaffb31Sdp 1917cdf0c1d5SmjnelsonSCM Specific Options: 1918cdf0c1d5Smjnelson TeamWare: webrev [common-options] -l [arguments to 'putback'] 1919cdf0c1d5Smjnelson 1920daaffb31SdpSCM Environment: 1921cdf0c1d5Smjnelson CODEMGR_WS: Workspace location. 1922cdf0c1d5Smjnelson CODEMGR_PARENT: Parent workspace location. 1923daaffb31Sdp' 1924daaffb31Sdp 1925daaffb31Sdp exit 2 1926daaffb31Sdp} 1927daaffb31Sdp 1928daaffb31Sdp# 1929daaffb31Sdp# 1930daaffb31Sdp# Main program starts here 1931daaffb31Sdp# 1932daaffb31Sdp# 1933daaffb31Sdp 1934daaffb31Sdptrap "rm -f /tmp/$$.* ; exit" 0 1 2 3 15 1935daaffb31Sdp 1936daaffb31Sdpset +o noclobber 1937daaffb31Sdp 1938cdf0c1d5SmjnelsonPATH=$(dirname $(whence $0)):$PATH 1939cdf0c1d5Smjnelson 194014983201Sdp[[ -z $WDIFF ]] && WDIFF=`look_for_prog wdiff` 194114983201Sdp[[ -z $WX ]] && WX=`look_for_prog wx` 1942cdf0c1d5Smjnelson[[ -z $HG_ACTIVE ]] && HG_ACTIVE=`look_for_prog hg-active` 1943cdf0c1d5Smjnelson[[ -z $WHICH_SCM ]] && WHICH_SCM=`look_for_prog which_scm` 194414983201Sdp[[ -z $CODEREVIEW ]] && CODEREVIEW=`look_for_prog codereview` 194514983201Sdp[[ -z $PS2PDF ]] && PS2PDF=`look_for_prog ps2pdf` 194614983201Sdp[[ -z $PERL ]] && PERL=`look_for_prog perl` 1947*02d26c39SVladimir Kotal[[ -z $RSYNC ]] && RSYNC=`look_for_prog rsync` 1948cdf0c1d5Smjnelson[[ -z $SCCS ]] && SCCS=`look_for_prog sccs` 1949cdf0c1d5Smjnelson[[ -z $AWK ]] && AWK=`look_for_prog nawk` 1950cdf0c1d5Smjnelson[[ -z $AWK ]] && AWK=`look_for_prog gawk` 1951cdf0c1d5Smjnelson[[ -z $AWK ]] && AWK=`look_for_prog awk` 1952*02d26c39SVladimir Kotal[[ -z $SCP ]] && SCP=`look_for_prog scp` 1953*02d26c39SVladimir Kotal[[ -z $SFTP ]] && SFTP=`look_for_prog sftp` 1954*02d26c39SVladimir Kotal[[ -z $MKTEMP ]] && MKTEMP=`look_for_prog mktemp` 1955*02d26c39SVladimir Kotal[[ -z $GREP ]] && GREP=`look_for_prog grep` 1956cdf0c1d5Smjnelson 195714983201Sdp 195814983201Sdpif [[ ! -x $PERL ]]; then 195914983201Sdp print -u2 "Error: No perl interpreter found. Exiting." 196014983201Sdp exit 1 1961daaffb31Sdpfi 196214983201Sdp 1963cdf0c1d5Smjnelsonif [[ ! -x $WHICH_SCM ]]; then 1964cdf0c1d5Smjnelson print -u2 "Error: Could not find which_scm. Exiting." 1965cdf0c1d5Smjnelson exit 1 1966cdf0c1d5Smjnelsonfi 1967cdf0c1d5Smjnelson 196814983201Sdp# 196914983201Sdp# These aren't fatal, but we want to note them to the user. 197014983201Sdp# We don't warn on the absence of 'wx' until later when we've 197114983201Sdp# determined that we actually need to try to invoke it. 197214983201Sdp# 197314983201Sdp[[ ! -x $CODEREVIEW ]] && print -u2 "WARNING: codereview(1) not found." 197414983201Sdp[[ ! -x $PS2PDF ]] && print -u2 "WARNING: ps2pdf(1) not found." 197514983201Sdp[[ ! -x $WDIFF ]] && print -u2 "WARNING: wdiff not found." 1976daaffb31Sdp 1977daaffb31Sdp# Declare global total counters. 1978daaffb31Sdpinteger TOTL TINS TDEL TMOD TUNC 1979daaffb31Sdp 198014983201Sdpflist_mode= 198114983201Sdpflist_file= 1982daaffb31Sdpiflag= 1983*02d26c39SVladimir Kotallflag= 1984*02d26c39SVladimir KotalNflag= 1985*02d26c39SVladimir Kotalnflag= 1986*02d26c39SVladimir KotalOflag= 1987daaffb31Sdpoflag= 1988daaffb31Sdppflag= 1989*02d26c39SVladimir Kotaltflag= 1990*02d26c39SVladimir Kotaluflag= 1991*02d26c39SVladimir KotalUflag= 1992daaffb31Sdpwflag= 1993*02d26c39SVladimir Kotalremote_target= 1994*02d26c39SVladimir Kotalwhile getopts "i:o:p:lwONnt:U" opt 1995daaffb31Sdpdo 1996daaffb31Sdp case $opt in 1997daaffb31Sdp i) iflag=1 1998daaffb31Sdp INCLUDE_FILE=$OPTARG;; 1999daaffb31Sdp 2000daaffb31Sdp # 2001daaffb31Sdp # If -l has been specified, we need to abort further options 2002daaffb31Sdp # processing, because subsequent arguments are going to be 2003daaffb31Sdp # arguments to 'putback -n'. 2004daaffb31Sdp # 2005daaffb31Sdp l) lflag=1 2006daaffb31Sdp break;; 2007daaffb31Sdp 2008*02d26c39SVladimir Kotal N) Nflag=1;; 2009*02d26c39SVladimir Kotal 2010*02d26c39SVladimir Kotal n) nflag=1;; 2011daaffb31Sdp 2012daaffb31Sdp O) Oflag=1;; 2013daaffb31Sdp 2014*02d26c39SVladimir Kotal o) oflag=1 2015*02d26c39SVladimir Kotal WDIR=$OPTARG;; 2016*02d26c39SVladimir Kotal 2017*02d26c39SVladimir Kotal p) pflag=1 2018*02d26c39SVladimir Kotal codemgr_parent=$OPTARG;; 2019*02d26c39SVladimir Kotal 2020*02d26c39SVladimir Kotal t) tflag=1 2021*02d26c39SVladimir Kotal remote_target=$OPTARG;; 2022*02d26c39SVladimir Kotal 2023*02d26c39SVladimir Kotal U) Uflag=1;; 2024*02d26c39SVladimir Kotal 2025*02d26c39SVladimir Kotal w) wflag=1;; 20263df69ef3SDarren Moffat 2027daaffb31Sdp ?) usage;; 2028daaffb31Sdp esac 2029daaffb31Sdpdone 2030daaffb31Sdp 2031daaffb31SdpFLIST=/tmp/$$.flist 2032daaffb31Sdp 2033daaffb31Sdpif [[ -n $wflag && -n $lflag ]]; then 2034daaffb31Sdp usage 2035daaffb31Sdpfi 2036daaffb31Sdp 2037*02d26c39SVladimir Kotal# more sanity checking 2038*02d26c39SVladimir Kotalif [[ -n $nflag && -z $Uflag ]]; then 2039*02d26c39SVladimir Kotal print "it does not make sense to skip webrev generation without -U" 2040*02d26c39SVladimir Kotal exit 1 2041*02d26c39SVladimir Kotalfi 2042*02d26c39SVladimir Kotal 2043*02d26c39SVladimir Kotalif [[ -n $tflag && -z $Uflag ]]; then 2044*02d26c39SVladimir Kotal echo "remote target has to be used only for upload" 2045*02d26c39SVladimir Kotal exit 1 2046*02d26c39SVladimir Kotalfi 2047*02d26c39SVladimir Kotal 2048daaffb31Sdp# 2049daaffb31Sdp# If this manually set as the parent, and it appears to be an earlier webrev, 2050daaffb31Sdp# then note that fact and set the parent to the raw_files/new subdirectory. 2051daaffb31Sdp# 2052daaffb31Sdpif [[ -n $pflag && -d $codemgr_parent/raw_files/new ]]; then 2053daaffb31Sdp parent_webrev="$codemgr_parent" 2054daaffb31Sdp codemgr_parent="$codemgr_parent/raw_files/new" 2055daaffb31Sdpfi 2056daaffb31Sdp 2057daaffb31Sdpif [[ -z $wflag && -z $lflag ]]; then 2058daaffb31Sdp shift $(($OPTIND - 1)) 2059daaffb31Sdp 2060daaffb31Sdp if [[ $1 == "-" ]]; then 2061daaffb31Sdp cat > $FLIST 206214983201Sdp flist_mode="stdin" 206314983201Sdp flist_done=1 206414983201Sdp shift 2065daaffb31Sdp elif [[ -n $1 ]]; then 206614983201Sdp if [[ ! -r $1 ]]; then 2067daaffb31Sdp print -u2 "$1: no such file or not readable" 2068daaffb31Sdp usage 2069daaffb31Sdp fi 2070daaffb31Sdp cat $1 > $FLIST 207114983201Sdp flist_mode="file" 207214983201Sdp flist_file=$1 207314983201Sdp flist_done=1 207414983201Sdp shift 2075daaffb31Sdp else 207614983201Sdp flist_mode="auto" 2077daaffb31Sdp fi 2078daaffb31Sdpfi 2079daaffb31Sdp 2080daaffb31Sdp# 2081daaffb31Sdp# Before we go on to further consider -l and -w, work out which SCM we think 2082daaffb31Sdp# is in use. 2083daaffb31Sdp# 2084cdf0c1d5Smjnelson$WHICH_SCM | read SCM_MODE junk || exit 1 2085cdf0c1d5Smjnelsoncase "$SCM_MODE" in 2086cdf0c1d5Smjnelsonteamware|mercurial|subversion) 2087cdf0c1d5Smjnelson ;; 2088cdf0c1d5Smjnelsonunknown) 2089cdf0c1d5Smjnelson if [[ $flist_mode == "auto" ]]; then 2090cdf0c1d5Smjnelson print -u2 "Unable to determine SCM in use and file list not specified" 2091cdf0c1d5Smjnelson print -u2 "See which_scm(1) for SCM detection information." 20927c478bd9Sstevel@tonic-gate exit 1 20937c478bd9Sstevel@tonic-gate fi 2094cdf0c1d5Smjnelson ;; 2095cdf0c1d5Smjnelson*) 2096cdf0c1d5Smjnelson if [[ $flist_mode == "auto" ]]; then 2097cdf0c1d5Smjnelson print -u2 "Unsupported SCM in use ($SCM_MODE) and file list not specified" 2098cdf0c1d5Smjnelson exit 1 2099cdf0c1d5Smjnelson fi 2100cdf0c1d5Smjnelson ;; 2101cdf0c1d5Smjnelsonesac 21027c478bd9Sstevel@tonic-gate 2103daaffb31Sdpprint -u2 " SCM detected: $SCM_MODE" 2104daaffb31Sdp 2105daaffb31Sdpif [[ -n $lflag ]]; then 2106daaffb31Sdp # 2107daaffb31Sdp # If the -l flag is given instead of the name of a file list, 2108daaffb31Sdp # then generate the file list by extracting file names from a 2109daaffb31Sdp # putback -n. 2110daaffb31Sdp # 2111daaffb31Sdp shift $(($OPTIND - 1)) 2112cdf0c1d5Smjnelson if [[ $SCM_MODE == "teamware" ]]; then 2113daaffb31Sdp flist_from_teamware "$*" 2114cdf0c1d5Smjnelson else 2115cdf0c1d5Smjnelson print -u2 -- "Error: -l option only applies to TeamWare" 2116cdf0c1d5Smjnelson exit 1 2117cdf0c1d5Smjnelson fi 2118daaffb31Sdp flist_done=1 2119daaffb31Sdp shift $# 2120daaffb31Sdpelif [[ -n $wflag ]]; then 2121daaffb31Sdp # 2122daaffb31Sdp # If the -w is given then assume the file list is in Bonwick's "wx" 2123daaffb31Sdp # command format, i.e. pathname lines alternating with SCCS comment 2124daaffb31Sdp # lines with blank lines as separators. Use the SCCS comments later 2125daaffb31Sdp # in building the index.html file. 2126daaffb31Sdp # 2127daaffb31Sdp shift $(($OPTIND - 1)) 2128daaffb31Sdp wxfile=$1 2129daaffb31Sdp if [[ -z $wxfile && -n $CODEMGR_WS ]]; then 2130daaffb31Sdp if [[ -r $CODEMGR_WS/wx/active ]]; then 2131daaffb31Sdp wxfile=$CODEMGR_WS/wx/active 2132daaffb31Sdp fi 2133daaffb31Sdp fi 2134daaffb31Sdp 2135daaffb31Sdp [[ -z $wxfile ]] && print -u2 "wx file not specified, and could not " \ 2136daaffb31Sdp "be auto-detected (check \$CODEMGR_WS)" && exit 1 2137daaffb31Sdp 2138cdf0c1d5Smjnelson if [[ ! -r $wxfile ]]; then 2139cdf0c1d5Smjnelson print -u2 "$wxfile: no such file or not readable" 2140cdf0c1d5Smjnelson usage 2141cdf0c1d5Smjnelson fi 2142cdf0c1d5Smjnelson 2143daaffb31Sdp print -u2 " File list from: wx 'active' file '$wxfile' ... \c" 2144daaffb31Sdp flist_from_wx $wxfile 2145daaffb31Sdp flist_done=1 2146daaffb31Sdp if [[ -n "$*" ]]; then 2147daaffb31Sdp shift 2148daaffb31Sdp fi 214914983201Sdpelif [[ $flist_mode == "stdin" ]]; then 215014983201Sdp print -u2 " File list from: standard input" 215114983201Sdpelif [[ $flist_mode == "file" ]]; then 215214983201Sdp print -u2 " File list from: $flist_file" 2153daaffb31Sdpfi 2154daaffb31Sdp 2155daaffb31Sdpif [[ $# -gt 0 ]]; then 215614983201Sdp print -u2 "WARNING: unused arguments: $*" 2157daaffb31Sdpfi 2158daaffb31Sdp 2159daaffb31Sdpif [[ $SCM_MODE == "teamware" ]]; then 2160daaffb31Sdp # 2161daaffb31Sdp # Parent (internally $codemgr_parent) and workspace ($codemgr_ws) can 2162daaffb31Sdp # be set in a number of ways, in decreasing precedence: 2163daaffb31Sdp # 2164daaffb31Sdp # 1) on the command line (only for the parent) 2165daaffb31Sdp # 2) in the user environment 2166daaffb31Sdp # 3) in the flist 2167daaffb31Sdp # 4) automatically based on the workspace (only for the parent) 2168daaffb31Sdp # 2169daaffb31Sdp 2170daaffb31Sdp # 2171daaffb31Sdp # Here is case (2): the user environment 2172daaffb31Sdp # 2173daaffb31Sdp [[ -z $codemgr_ws && -n $CODEMGR_WS ]] && codemgr_ws=$CODEMGR_WS 2174daaffb31Sdp if [[ -n $codemgr_ws && ! -d $codemgr_ws ]]; then 2175daaffb31Sdp print -u2 "$codemgr_ws: no such workspace" 21767c478bd9Sstevel@tonic-gate exit 1 21777c478bd9Sstevel@tonic-gate fi 21787c478bd9Sstevel@tonic-gate 2179daaffb31Sdp [[ -z $codemgr_parent && -n $CODEMGR_PARENT ]] && \ 2180daaffb31Sdp codemgr_parent=$CODEMGR_PARENT 2181daaffb31Sdp if [[ -n $codemgr_parent && ! -d $codemgr_parent ]]; then 2182daaffb31Sdp print -u2 "$codemgr_parent: no such directory" 21837c478bd9Sstevel@tonic-gate exit 1 21847c478bd9Sstevel@tonic-gate fi 21857c478bd9Sstevel@tonic-gate 2186daaffb31Sdp # 2187daaffb31Sdp # If we're in auto-detect mode and we haven't already gotten the file 2188daaffb31Sdp # list, then see if we can get it by probing for wx. 2189daaffb31Sdp # 219014983201Sdp if [[ -z $flist_done && $flist_mode == "auto" && -n $codemgr_ws ]]; then 219114983201Sdp if [[ ! -x $WX ]]; then 219214983201Sdp print -u2 "WARNING: wx not found!" 2193daaffb31Sdp fi 21947c478bd9Sstevel@tonic-gate 2195daaffb31Sdp # 2196daaffb31Sdp # We need to use wx list -w so that we get renamed files, etc. 2197daaffb31Sdp # but only if a wx active file exists-- otherwise wx will 2198daaffb31Sdp # hang asking us to initialize our wx information. 2199daaffb31Sdp # 220014983201Sdp if [[ -x $WX && -f $codemgr_ws/wx/active ]]; then 2201daaffb31Sdp print -u2 " File list from: 'wx list -w' ... \c" 2202daaffb31Sdp $WX list -w > $FLIST 2203daaffb31Sdp $WX comments > /tmp/$$.wx_comments 2204daaffb31Sdp wxfile=/tmp/$$.wx_comments 2205daaffb31Sdp print -u2 "done" 2206daaffb31Sdp flist_done=1 2207daaffb31Sdp fi 2208daaffb31Sdp fi 2209daaffb31Sdp 2210daaffb31Sdp # 2211daaffb31Sdp # If by hook or by crook we've gotten a file list by now (perhaps 2212daaffb31Sdp # from the command line), eval it to extract environment variables from 2213daaffb31Sdp # it: This is step (3). 2214daaffb31Sdp # 2215daaffb31Sdp env_from_flist 2216daaffb31Sdp 2217daaffb31Sdp # 2218daaffb31Sdp # Continuing step (3): If we still have no file list, we'll try to get 2219daaffb31Sdp # it from teamware. 2220daaffb31Sdp # 2221daaffb31Sdp if [[ -z $flist_done ]]; then 2222daaffb31Sdp flist_from_teamware 2223daaffb31Sdp env_from_flist 2224daaffb31Sdp fi 2225daaffb31Sdp 2226daaffb31Sdp # 2227daaffb31Sdp # (4) If we still don't have a value for codemgr_parent, get it 2228daaffb31Sdp # from workspace. 2229daaffb31Sdp # 2230cdf0c1d5Smjnelson [[ -z $codemgr_ws ]] && codemgr_ws=`workspace name` 2231daaffb31Sdp [[ -z $codemgr_parent ]] && codemgr_parent=`workspace parent` 2232daaffb31Sdp if [[ ! -d $codemgr_parent ]]; then 2233daaffb31Sdp print -u2 "$CODEMGR_PARENT: no such parent workspace" 2234daaffb31Sdp exit 1 2235daaffb31Sdp fi 2236daaffb31Sdp 2237daaffb31Sdp # 2238cdf0c1d5Smjnelson # Observe true directory name of CODEMGR_WS, as used later in 2239cdf0c1d5Smjnelson # webrev title. 2240cdf0c1d5Smjnelson # 2241cdf0c1d5Smjnelson codemgr_ws=$(cd $codemgr_ws;print $PWD) 2242cdf0c1d5Smjnelson 2243cdf0c1d5Smjnelson # 2244daaffb31Sdp # Reset CODEMGR_WS to make sure teamware commands are happy. 2245daaffb31Sdp # 2246daaffb31Sdp CODEMGR_WS=$codemgr_ws 2247daaffb31Sdp CWS=$codemgr_ws 2248daaffb31Sdp PWS=$codemgr_parent 2249cdf0c1d5Smjnelson 2250cdf0c1d5Smjnelson [[ -n $parent_webrev ]] && RWS=$(workspace parent $CWS) 2251cdf0c1d5Smjnelson 2252cdf0c1d5Smjnelsonelif [[ $SCM_MODE == "mercurial" ]]; then 2253cdf0c1d5Smjnelson [[ -z $codemgr_ws && -n $CODEMGR_WS ]] && \ 2254cdf0c1d5Smjnelson codemgr_ws=`hg root -R $CODEMGR_WS 2>/dev/null` 2255cdf0c1d5Smjnelson 2256cdf0c1d5Smjnelson [[ -z $codemgr_ws ]] && codemgr_ws=`hg root 2>/dev/null` 2257cdf0c1d5Smjnelson 2258cdf0c1d5Smjnelson # 2259cdf0c1d5Smjnelson # Parent can either be specified with -p 2260cdf0c1d5Smjnelson # Specified with CODEMGR_PARENT in the environment 2261cdf0c1d5Smjnelson # or taken from hg's default path. 2262cdf0c1d5Smjnelson # 2263cdf0c1d5Smjnelson 2264cdf0c1d5Smjnelson if [[ -z $codemgr_parent && -n $CODEMGR_PARENT ]]; then 2265cdf0c1d5Smjnelson codemgr_parent=$CODEMGR_PARENT 2266cdf0c1d5Smjnelson fi 2267cdf0c1d5Smjnelson 2268cdf0c1d5Smjnelson if [[ -z $codemgr_parent ]]; then 2269cdf0c1d5Smjnelson codemgr_parent=`hg path -R $codemgr_ws default 2>/dev/null` 2270cdf0c1d5Smjnelson fi 2271cdf0c1d5Smjnelson 2272cdf0c1d5Smjnelson CWS_REV=`hg parent -R $codemgr_ws --template '{node|short}' 2>/dev/null` 2273cdf0c1d5Smjnelson CWS=$codemgr_ws 2274cdf0c1d5Smjnelson PWS=$codemgr_parent 2275cdf0c1d5Smjnelson 2276cdf0c1d5Smjnelson # 2277cdf0c1d5Smjnelson # If the parent is a webrev, we want to do some things against 2278cdf0c1d5Smjnelson # the natural workspace parent (file list, comments, etc) 2279cdf0c1d5Smjnelson # 2280cdf0c1d5Smjnelson if [[ -n $parent_webrev ]]; then 2281cdf0c1d5Smjnelson real_parent=$(hg path -R $codemgr_ws default 2>/dev/null) 2282cdf0c1d5Smjnelson else 2283cdf0c1d5Smjnelson real_parent=$PWS 2284cdf0c1d5Smjnelson fi 2285cdf0c1d5Smjnelson 2286cdf0c1d5Smjnelson # 2287cdf0c1d5Smjnelson # If hg-active exists, then we run it. In the case of no explicit 2288cdf0c1d5Smjnelson # flist given, we'll use it for our comments. In the case of an 2289cdf0c1d5Smjnelson # explicit flist given we'll try to use it for comments for any 2290cdf0c1d5Smjnelson # files mentioned in the flist. 2291cdf0c1d5Smjnelson # 2292cdf0c1d5Smjnelson if [[ -z $flist_done ]]; then 2293cdf0c1d5Smjnelson flist_from_mercurial $CWS $real_parent 2294cdf0c1d5Smjnelson flist_done=1 2295cdf0c1d5Smjnelson fi 2296cdf0c1d5Smjnelson 2297cdf0c1d5Smjnelson # 2298cdf0c1d5Smjnelson # If we have a file list now, pull out any variables set 2299cdf0c1d5Smjnelson # therein. We do this now (rather than when we possibly use 2300cdf0c1d5Smjnelson # hg-active to find comments) to avoid stomping specifications 2301cdf0c1d5Smjnelson # in the user-specified flist. 2302cdf0c1d5Smjnelson # 2303cdf0c1d5Smjnelson if [[ -n $flist_done ]]; then 2304cdf0c1d5Smjnelson env_from_flist 2305cdf0c1d5Smjnelson fi 2306cdf0c1d5Smjnelson 2307cdf0c1d5Smjnelson # 2308cdf0c1d5Smjnelson # Only call hg-active if we don't have a wx formatted file already 2309cdf0c1d5Smjnelson # 2310cdf0c1d5Smjnelson if [[ -x $HG_ACTIVE && -z $wxfile ]]; then 2311cdf0c1d5Smjnelson print " Comments from: hg-active -p $real_parent ...\c" 2312cdf0c1d5Smjnelson hg_active_wxfile $CWS $real_parent 2313cdf0c1d5Smjnelson print " Done." 2314cdf0c1d5Smjnelson fi 2315cdf0c1d5Smjnelson 2316cdf0c1d5Smjnelson # 2317cdf0c1d5Smjnelson # At this point we must have a wx flist either from hg-active, 2318cdf0c1d5Smjnelson # or in general. Use it to try and find our parent revision, 2319cdf0c1d5Smjnelson # if we don't have one. 2320cdf0c1d5Smjnelson # 2321cdf0c1d5Smjnelson if [[ -z $HG_PARENT ]]; then 2322*02d26c39SVladimir Kotal eval `sed -e "s/#.*$//" $wxfile | $GREP HG_PARENT=` 2323cdf0c1d5Smjnelson fi 2324cdf0c1d5Smjnelson 2325cdf0c1d5Smjnelson # 2326cdf0c1d5Smjnelson # If we still don't have a parent, we must have been given a 2327cdf0c1d5Smjnelson # wx-style active list with no HG_PARENT specification, run 2328cdf0c1d5Smjnelson # hg-active and pull an HG_PARENT out of it, ignore the rest. 2329cdf0c1d5Smjnelson # 2330cdf0c1d5Smjnelson if [[ -z $HG_PARENT && -x $HG_ACTIVE ]]; then 2331cdf0c1d5Smjnelson $HG_ACTIVE -w $codemgr_ws -p $real_parent | \ 2332*02d26c39SVladimir Kotal eval `sed -e "s/#.*$//" | $GREP HG_PARENT=` 2333cdf0c1d5Smjnelson elif [[ -z $HG_PARENT ]]; then 2334cdf0c1d5Smjnelson print -u2 "Error: Cannot discover parent revision" 2335cdf0c1d5Smjnelson exit 1 2336cdf0c1d5Smjnelson fi 2337cdf0c1d5Smjnelsonelif [[ $SCM_MODE == "subversion" ]]; then 2338cdf0c1d5Smjnelson if [[ -n $CODEMGR_WS && -d $CODEMGR_WS/.svn ]]; then 2339cdf0c1d5Smjnelson CWS=$CODEMGR_WS 2340cdf0c1d5Smjnelson else 2341cdf0c1d5Smjnelson svn info | while read line; do 2342cdf0c1d5Smjnelson if [[ $line == "URL: "* ]]; then 2343cdf0c1d5Smjnelson url=${line#URL: } 2344cdf0c1d5Smjnelson elif [[ $line == "Repository Root: "* ]]; then 2345cdf0c1d5Smjnelson repo=${line#Repository Root: } 2346cdf0c1d5Smjnelson fi 2347cdf0c1d5Smjnelson done 2348cdf0c1d5Smjnelson 2349cdf0c1d5Smjnelson rel=${url#$repo} 2350cdf0c1d5Smjnelson CWS=${PWD%$rel} 2351cdf0c1d5Smjnelson fi 2352cdf0c1d5Smjnelson 2353cdf0c1d5Smjnelson # 2354cdf0c1d5Smjnelson # We only will have a real parent workspace in the case one 2355cdf0c1d5Smjnelson # was specified (be it an older webrev, or another checkout). 2356cdf0c1d5Smjnelson # 2357cdf0c1d5Smjnelson [[ -n $codemgr_parent ]] && PWS=$codemgr_parent 2358cdf0c1d5Smjnelson 2359cdf0c1d5Smjnelson if [[ -z $flist_done && $flist_mode == "auto" ]]; then 2360cdf0c1d5Smjnelson flist_from_subversion $CWS $OLDPWD 2361cdf0c1d5Smjnelson fi 2362cdf0c1d5Smjnelsonelse 2363cdf0c1d5Smjnelson if [[ $SCM_MODE == "unknown" ]]; then 2364cdf0c1d5Smjnelson print -u2 " Unknown type of SCM in use" 2365cdf0c1d5Smjnelson else 2366cdf0c1d5Smjnelson print -u2 " Unsupported SCM in use: $SCM_MODE" 2367cdf0c1d5Smjnelson fi 2368cdf0c1d5Smjnelson 2369cdf0c1d5Smjnelson env_from_flist 2370cdf0c1d5Smjnelson 2371cdf0c1d5Smjnelson if [[ -z $CODEMGR_WS ]]; then 2372cdf0c1d5Smjnelson print -u2 "SCM not detected/supported and CODEMGR_WS not specified" 2373cdf0c1d5Smjnelson exit 1 2374cdf0c1d5Smjnelson fi 2375cdf0c1d5Smjnelson 2376cdf0c1d5Smjnelson if [[ -z $CODEMGR_PARENT ]]; then 2377cdf0c1d5Smjnelson print -u2 "SCM not detected/supported and CODEMGR_PARENT not specified" 2378cdf0c1d5Smjnelson exit 1 2379cdf0c1d5Smjnelson fi 2380cdf0c1d5Smjnelson 2381cdf0c1d5Smjnelson CWS=$CODEMGR_WS 2382cdf0c1d5Smjnelson PWS=$CODEMGR_PARENT 2383daaffb31Sdpfi 2384daaffb31Sdp 2385daaffb31Sdp# 2386daaffb31Sdp# If the user didn't specify a -i option, check to see if there is a 2387daaffb31Sdp# webrev-info file in the workspace directory. 2388daaffb31Sdp# 2389daaffb31Sdpif [[ -z $iflag && -r "$CWS/webrev-info" ]]; then 2390daaffb31Sdp iflag=1 2391daaffb31Sdp INCLUDE_FILE="$CWS/webrev-info" 2392daaffb31Sdpfi 2393daaffb31Sdp 2394daaffb31Sdpif [[ -n $iflag ]]; then 2395daaffb31Sdp if [[ ! -r $INCLUDE_FILE ]]; then 2396daaffb31Sdp print -u2 "include file '$INCLUDE_FILE' does not exist or is" \ 2397daaffb31Sdp "not readable." 2398daaffb31Sdp exit 1 2399daaffb31Sdp else 2400daaffb31Sdp # 2401daaffb31Sdp # $INCLUDE_FILE may be a relative path, and the script alters 2402daaffb31Sdp # PWD, so we just stash a copy in /tmp. 2403daaffb31Sdp # 2404daaffb31Sdp cp $INCLUDE_FILE /tmp/$$.include 2405daaffb31Sdp fi 2406daaffb31Sdpfi 2407daaffb31Sdp 2408daaffb31Sdp# 2409daaffb31Sdp# Output directory. 2410daaffb31Sdp# 2411daaffb31SdpWDIR=${WDIR:-$CWS/webrev} 2412daaffb31Sdp 2413daaffb31Sdp# 2414*02d26c39SVladimir Kotal# Name of the webrev, derived from the workspace name or output directory; 2415*02d26c39SVladimir Kotal# in the future this could potentially be an option. 2416daaffb31Sdp# 2417*02d26c39SVladimir Kotalif [[ -n $oflag ]]; then 2418*02d26c39SVladimir Kotal WNAME=${WDIR##*/} 2419*02d26c39SVladimir Kotalelse 2420daaffb31Sdp WNAME=${CWS##*/} 2421*02d26c39SVladimir Kotalfi 2422*02d26c39SVladimir Kotal 2423*02d26c39SVladimir Kotal# Do not generate the webrev, just upload it. We trust the user that the 2424*02d26c39SVladimir Kotal# webrev is OpenSolaris one. 2425*02d26c39SVladimir Kotalif [[ -n $Uflag && -n $nflag ]]; then 2426*02d26c39SVladimir Kotal upload_webrev 2427*02d26c39SVladimir Kotal exit $? 2428*02d26c39SVladimir Kotalfi 2429daaffb31Sdp 2430e0e0293aSjmcpif [ "${WDIR%%/*}" ]; then 24317c478bd9Sstevel@tonic-gate WDIR=$PWD/$WDIR 24327c478bd9Sstevel@tonic-gatefi 2433daaffb31Sdp 2434daaffb31Sdpif [[ ! -d $WDIR ]]; then 2435daaffb31Sdp mkdir -p $WDIR 2436daaffb31Sdp [[ $? != 0 ]] && exit 1 24377c478bd9Sstevel@tonic-gatefi 24387c478bd9Sstevel@tonic-gate 2439daaffb31Sdp# 2440daaffb31Sdp# Summarize what we're going to do. 2441daaffb31Sdp# 2442cdf0c1d5Smjnelsonif [[ -n $CWS_REV ]]; then 2443cdf0c1d5Smjnelson print " Workspace: $CWS (at $CWS_REV)" 2444cdf0c1d5Smjnelsonelse 2445daaffb31Sdp print " Workspace: $CWS" 2446cdf0c1d5Smjnelsonfi 2447daaffb31Sdpif [[ -n $parent_webrev ]]; then 2448daaffb31Sdp print "Compare against: webrev at $parent_webrev" 2449daaffb31Sdpelse 2450cdf0c1d5Smjnelson if [[ -n $HG_PARENT ]]; then 2451cdf0c1d5Smjnelson hg_parent_short=`echo $HG_PARENT \ 2452cdf0c1d5Smjnelson | sed -e 's/\([0-9a-f]\{12\}\).*/\1/'` 2453cdf0c1d5Smjnelson print "Compare against: $PWS (at $hg_parent_short)" 2454cdf0c1d5Smjnelson else 2455daaffb31Sdp print "Compare against: $PWS" 2456daaffb31Sdp fi 2457cdf0c1d5Smjnelsonfi 2458daaffb31Sdp 2459daaffb31Sdp[[ -n $INCLUDE_FILE ]] && print " Including: $INCLUDE_FILE" 2460daaffb31Sdpprint " Output to: $WDIR" 2461daaffb31Sdp 2462daaffb31Sdp# 24637c478bd9Sstevel@tonic-gate# Save the file list in the webrev dir 2464daaffb31Sdp# 2465daaffb31Sdp[[ ! $FLIST -ef $WDIR/file.list ]] && cp $FLIST $WDIR/file.list 24667c478bd9Sstevel@tonic-gate 2467daaffb31Sdp# 2468daaffb31Sdp# Bug IDs will be replaced by a URL. Order of precedence 2469daaffb31Sdp# is: default location, $WEBREV_BUGURL, the -O flag. 2470daaffb31Sdp# 2471daaffb31SdpBUGURL='http://monaco.sfbay.sun.com/detail.jsp?cr=' 2472daaffb31Sdp[[ -n $WEBREV_BUGURL ]] && BUGURL="$WEBREV_BUGURL" 2473daaffb31Sdp[[ -n "$Oflag" ]] && \ 2474daaffb31Sdp BUGURL='http://bugs.opensolaris.org/bugdatabase/view_bug.do?bug_id=' 24757c478bd9Sstevel@tonic-gate 2476daaffb31Sdp# 2477daaffb31Sdp# Likewise, ARC cases will be replaced by a URL. Order of precedence 2478daaffb31Sdp# is: default, $WEBREV_SACURL, the -O flag. 2479daaffb31Sdp# 2480daaffb31Sdp# Note that -O also triggers different substitution behavior for 2481daaffb31Sdp# SACURL. See sac2url(). 2482daaffb31Sdp# 2483daaffb31SdpSACURL='http://sac.eng.sun.com' 2484daaffb31Sdp[[ -n $WEBREV_SACURL ]] && SACURL="$WEBREV_SACURL" 2485e0e0293aSjmcp[[ -n "$Oflag" ]] && \ 2486daaffb31Sdp SACURL='http://www.opensolaris.org/os/community/arc/caselog' 24877c478bd9Sstevel@tonic-gate 2488daaffb31Sdprm -f $WDIR/$WNAME.patch 2489daaffb31Sdprm -f $WDIR/$WNAME.ps 2490daaffb31Sdprm -f $WDIR/$WNAME.pdf 24917c478bd9Sstevel@tonic-gate 2492daaffb31Sdptouch $WDIR/$WNAME.patch 24937c478bd9Sstevel@tonic-gate 2494daaffb31Sdpprint " Output Files:" 2495daaffb31Sdp 2496daaffb31Sdp# 2497daaffb31Sdp# Clean up the file list: Remove comments, blank lines and env variables. 2498daaffb31Sdp# 2499daaffb31Sdpsed -e "s/#.*$//" -e "/=/d" -e "/^[ ]*$/d" $FLIST > /tmp/$$.flist.clean 2500daaffb31SdpFLIST=/tmp/$$.flist.clean 2501daaffb31Sdp 2502daaffb31Sdp# 2503cdf0c1d5Smjnelson# For Mercurial, create a cache of manifest entries. 2504cdf0c1d5Smjnelson# 2505cdf0c1d5Smjnelsonif [[ $SCM_MODE == "mercurial" ]]; then 2506cdf0c1d5Smjnelson # 2507cdf0c1d5Smjnelson # Transform the FLIST into a temporary sed script that matches 2508cdf0c1d5Smjnelson # relevant entries in the Mercurial manifest as follows: 2509cdf0c1d5Smjnelson # 1) The script will be used against the parent revision manifest, 2510cdf0c1d5Smjnelson # so for FLIST lines that have two filenames (a renamed file) 2511cdf0c1d5Smjnelson # keep only the old name. 2512cdf0c1d5Smjnelson # 2) Escape all forward slashes the filename. 2513cdf0c1d5Smjnelson # 3) Change the filename into another sed command that matches 2514cdf0c1d5Smjnelson # that file in "hg manifest -v" output: start of line, three 2515cdf0c1d5Smjnelson # octal digits for file permissions, space, a file type flag 2516cdf0c1d5Smjnelson # character, space, the filename, end of line. 2517cdf0c1d5Smjnelson # 2518cdf0c1d5Smjnelson SEDFILE=/tmp/$$.manifest.sed 2519cdf0c1d5Smjnelson sed ' 2520cdf0c1d5Smjnelson s#^[^ ]* ## 2521cdf0c1d5Smjnelson s#/#\\\/#g 2522cdf0c1d5Smjnelson s#^.*$#/^... . &$/p# 2523cdf0c1d5Smjnelson ' < $FLIST > $SEDFILE 2524cdf0c1d5Smjnelson 2525cdf0c1d5Smjnelson # 2526cdf0c1d5Smjnelson # Apply the generated script to the output of "hg manifest -v" 2527cdf0c1d5Smjnelson # to get the relevant subset for this webrev. 2528cdf0c1d5Smjnelson # 2529cdf0c1d5Smjnelson HG_PARENT_MANIFEST=/tmp/$$.manifest 2530cdf0c1d5Smjnelson hg -R $CWS manifest -v -r $HG_PARENT | 2531cdf0c1d5Smjnelson sed -n -f $SEDFILE > $HG_PARENT_MANIFEST 2532cdf0c1d5Smjnelsonfi 2533cdf0c1d5Smjnelson 2534cdf0c1d5Smjnelson# 2535daaffb31Sdp# First pass through the files: generate the per-file webrev HTML-files. 2536daaffb31Sdp# 2537daaffb31Sdpcat $FLIST | while read LINE 25387c478bd9Sstevel@tonic-gatedo 25397c478bd9Sstevel@tonic-gate set - $LINE 25407c478bd9Sstevel@tonic-gate P=$1 25417c478bd9Sstevel@tonic-gate 2542daaffb31Sdp # 2543daaffb31Sdp # Normally, each line in the file list is just a pathname of a 2544daaffb31Sdp # file that has been modified or created in the child. A file 2545daaffb31Sdp # that is renamed in the child workspace has two names on the 2546daaffb31Sdp # line: new name followed by the old name. 2547daaffb31Sdp # 2548daaffb31Sdp oldname="" 2549daaffb31Sdp oldpath="" 2550daaffb31Sdp rename= 2551daaffb31Sdp if [[ $# -eq 2 ]]; then 25527c478bd9Sstevel@tonic-gate PP=$2 # old filename 2553daaffb31Sdp oldname=" (was $PP)" 2554daaffb31Sdp oldpath="$PP" 2555daaffb31Sdp rename=1 25567c478bd9Sstevel@tonic-gate PDIR=${PP%/*} 2557daaffb31Sdp if [[ $PDIR == $PP ]]; then 25587c478bd9Sstevel@tonic-gate PDIR="." # File at root of workspace 25597c478bd9Sstevel@tonic-gate fi 25607c478bd9Sstevel@tonic-gate 25617c478bd9Sstevel@tonic-gate PF=${PP##*/} 25627c478bd9Sstevel@tonic-gate 25637c478bd9Sstevel@tonic-gate DIR=${P%/*} 2564daaffb31Sdp if [[ $DIR == $P ]]; then 25657c478bd9Sstevel@tonic-gate DIR="." # File at root of workspace 25667c478bd9Sstevel@tonic-gate fi 25677c478bd9Sstevel@tonic-gate 25687c478bd9Sstevel@tonic-gate F=${P##*/} 2569daaffb31Sdp 25707c478bd9Sstevel@tonic-gate else 25717c478bd9Sstevel@tonic-gate DIR=${P%/*} 2572daaffb31Sdp if [[ "$DIR" == "$P" ]]; then 25737c478bd9Sstevel@tonic-gate DIR="." # File at root of workspace 25747c478bd9Sstevel@tonic-gate fi 25757c478bd9Sstevel@tonic-gate 25767c478bd9Sstevel@tonic-gate F=${P##*/} 25777c478bd9Sstevel@tonic-gate 25787c478bd9Sstevel@tonic-gate PP=$P 25797c478bd9Sstevel@tonic-gate PDIR=$DIR 25807c478bd9Sstevel@tonic-gate PF=$F 25817c478bd9Sstevel@tonic-gate fi 25827c478bd9Sstevel@tonic-gate 2583daaffb31Sdp COMM=`getcomments html $P $PP` 25847c478bd9Sstevel@tonic-gate 2585daaffb31Sdp print "\t$P$oldname\n\t\t\c" 25867c478bd9Sstevel@tonic-gate 25877c478bd9Sstevel@tonic-gate # Make the webrev mirror directory if necessary 25887c478bd9Sstevel@tonic-gate mkdir -p $WDIR/$DIR 25897c478bd9Sstevel@tonic-gate 2590daaffb31Sdp # 2591daaffb31Sdp # If we're in OpenSolaris mode, we enforce a minor policy: 2592daaffb31Sdp # help to make sure the reviewer doesn't accidentally publish 2593e0e0293aSjmcp # source which is in usr/closed/* or deleted_files/usr/closed/* 2594daaffb31Sdp # 2595e0e0293aSjmcp if [[ -n "$Oflag" ]]; then 2596daaffb31Sdp pclosed=${P##usr/closed/} 2597e0e0293aSjmcp pdeleted=${P##deleted_files/usr/closed/} 2598e0e0293aSjmcp if [[ "$pclosed" != "$P" || "$pdeleted" != "$P" ]]; then 2599daaffb31Sdp print "*** Omitting closed source for OpenSolaris" \ 2600daaffb31Sdp "mode review" 2601daaffb31Sdp continue 2602daaffb31Sdp fi 2603daaffb31Sdp fi 2604daaffb31Sdp 2605daaffb31Sdp # 2606cdf0c1d5Smjnelson # We stash old and new files into parallel directories in $WDIR 2607daaffb31Sdp # and do our diffs there. This makes it possible to generate 2608daaffb31Sdp # clean looking diffs which don't have absolute paths present. 2609daaffb31Sdp # 2610daaffb31Sdp 2611cdf0c1d5Smjnelson build_old_new "$WDIR" "$PWS" "$PDIR" "$PF" "$CWS" "$DIR" "$F" || \ 26127c478bd9Sstevel@tonic-gate continue 26137c478bd9Sstevel@tonic-gate 2614cdf0c1d5Smjnelson # 2615cdf0c1d5Smjnelson # Keep the old PWD around, so we can safely switch back after 2616cdf0c1d5Smjnelson # diff generation, such that build_old_new runs in a 2617cdf0c1d5Smjnelson # consistent environment. 2618cdf0c1d5Smjnelson # 2619cdf0c1d5Smjnelson OWD=$PWD 2620daaffb31Sdp cd $WDIR/raw_files 2621daaffb31Sdp ofile=old/$PDIR/$PF 2622daaffb31Sdp nfile=new/$DIR/$F 26237c478bd9Sstevel@tonic-gate 2624daaffb31Sdp mv_but_nodiff= 2625daaffb31Sdp cmp $ofile $nfile > /dev/null 2>&1 2626daaffb31Sdp if [[ $? == 0 && $rename == 1 ]]; then 2627daaffb31Sdp mv_but_nodiff=1 2628daaffb31Sdp fi 2629daaffb31Sdp 2630daaffb31Sdp # 2631daaffb31Sdp # If we have old and new versions of the file then run the appropriate 2632daaffb31Sdp # diffs. This is complicated by a couple of factors: 2633daaffb31Sdp # 2634daaffb31Sdp # - renames must be handled specially: we emit a 'remove' 2635daaffb31Sdp # diff and an 'add' diff 2636daaffb31Sdp # - new files and deleted files must be handled specially 2637daaffb31Sdp # - Solaris patch(1m) can't cope with file creation 2638daaffb31Sdp # (and hence renames) as of this writing. 2639daaffb31Sdp # - To make matters worse, gnu patch doesn't interpret the 2640daaffb31Sdp # output of Solaris diff properly when it comes to 2641daaffb31Sdp # adds and deletes. We need to do some "cleansing" 2642daaffb31Sdp # transformations: 2643daaffb31Sdp # [to add a file] @@ -1,0 +X,Y @@ --> @@ -0,0 +X,Y @@ 2644daaffb31Sdp # [to del a file] @@ -X,Y +1,0 @@ --> @@ -X,Y +0,0 @@ 2645daaffb31Sdp # 2646daaffb31Sdp cleanse_rmfile="sed 's/^\(@@ [0-9+,-]*\) [0-9+,-]* @@$/\1 +0,0 @@/'" 2647daaffb31Sdp cleanse_newfile="sed 's/^@@ [0-9+,-]* \([0-9+,-]* @@\)$/@@ -0,0 \1/'" 2648daaffb31Sdp 2649daaffb31Sdp rm -f $WDIR/$DIR/$F.patch 2650daaffb31Sdp if [[ -z $rename ]]; then 2651e0e0293aSjmcp if [ ! -f "$ofile" ]; then 2652daaffb31Sdp diff -u /dev/null $nfile | sh -c "$cleanse_newfile" \ 2653daaffb31Sdp > $WDIR/$DIR/$F.patch 2654e0e0293aSjmcp elif [ ! -f "$nfile" ]; then 2655daaffb31Sdp diff -u $ofile /dev/null | sh -c "$cleanse_rmfile" \ 2656daaffb31Sdp > $WDIR/$DIR/$F.patch 2657daaffb31Sdp else 2658daaffb31Sdp diff -u $ofile $nfile > $WDIR/$DIR/$F.patch 2659daaffb31Sdp fi 2660daaffb31Sdp else 2661daaffb31Sdp diff -u $ofile /dev/null | sh -c "$cleanse_rmfile" \ 2662daaffb31Sdp > $WDIR/$DIR/$F.patch 2663daaffb31Sdp 2664daaffb31Sdp diff -u /dev/null $nfile | sh -c "$cleanse_newfile" \ 2665daaffb31Sdp >> $WDIR/$DIR/$F.patch 2666daaffb31Sdp 2667daaffb31Sdp fi 2668daaffb31Sdp 2669daaffb31Sdp # 2670daaffb31Sdp # Tack the patch we just made onto the accumulated patch for the 2671daaffb31Sdp # whole wad. 2672daaffb31Sdp # 2673daaffb31Sdp cat $WDIR/$DIR/$F.patch >> $WDIR/$WNAME.patch 2674daaffb31Sdp 2675daaffb31Sdp print " patch\c" 2676daaffb31Sdp 2677daaffb31Sdp if [[ -f $ofile && -f $nfile && -z $mv_but_nodiff ]]; then 2678daaffb31Sdp 2679daaffb31Sdp ${CDIFFCMD:-diff -bt -C 5} $ofile $nfile > $WDIR/$DIR/$F.cdiff 2680daaffb31Sdp diff_to_html $F $DIR/$F "C" "$COMM" < $WDIR/$DIR/$F.cdiff \ 2681daaffb31Sdp > $WDIR/$DIR/$F.cdiff.html 26827c478bd9Sstevel@tonic-gate print " cdiffs\c" 26837c478bd9Sstevel@tonic-gate 2684daaffb31Sdp ${UDIFFCMD:-diff -bt -U 5} $ofile $nfile > $WDIR/$DIR/$F.udiff 2685daaffb31Sdp diff_to_html $F $DIR/$F "U" "$COMM" < $WDIR/$DIR/$F.udiff \ 2686daaffb31Sdp > $WDIR/$DIR/$F.udiff.html 2687daaffb31Sdp 26887c478bd9Sstevel@tonic-gate print " udiffs\c" 26897c478bd9Sstevel@tonic-gate 26907c478bd9Sstevel@tonic-gate if [[ -x $WDIFF ]]; then 2691daaffb31Sdp $WDIFF -c "$COMM" \ 2692daaffb31Sdp -t "$WNAME Wdiff $DIR/$F" $ofile $nfile > \ 2693daaffb31Sdp $WDIR/$DIR/$F.wdiff.html 2>/dev/null 2694daaffb31Sdp if [[ $? -eq 0 ]]; then 26957c478bd9Sstevel@tonic-gate print " wdiffs\c" 2696daaffb31Sdp else 2697daaffb31Sdp print " wdiffs[fail]\c" 2698daaffb31Sdp fi 26997c478bd9Sstevel@tonic-gate fi 27007c478bd9Sstevel@tonic-gate 2701daaffb31Sdp sdiff_to_html $ofile $nfile $F $DIR "$COMM" \ 2702daaffb31Sdp > $WDIR/$DIR/$F.sdiff.html 27037c478bd9Sstevel@tonic-gate print " sdiffs\c" 27047c478bd9Sstevel@tonic-gate 27057c478bd9Sstevel@tonic-gate print " frames\c" 27067c478bd9Sstevel@tonic-gate 27077c478bd9Sstevel@tonic-gate rm -f $WDIR/$DIR/$F.cdiff $WDIR/$DIR/$F.udiff 27087c478bd9Sstevel@tonic-gate 2709daaffb31Sdp difflines $ofile $nfile > $WDIR/$DIR/$F.count 2710daaffb31Sdp 2711daaffb31Sdp elif [[ -f $ofile && -f $nfile && -n $mv_but_nodiff ]]; then 2712daaffb31Sdp # renamed file: may also have differences 2713daaffb31Sdp difflines $ofile $nfile > $WDIR/$DIR/$F.count 2714daaffb31Sdp elif [[ -f $nfile ]]; then 27157c478bd9Sstevel@tonic-gate # new file: count added lines 2716daaffb31Sdp difflines /dev/null $nfile > $WDIR/$DIR/$F.count 2717daaffb31Sdp elif [[ -f $ofile ]]; then 27187c478bd9Sstevel@tonic-gate # old file: count deleted lines 2719daaffb31Sdp difflines $ofile /dev/null > $WDIR/$DIR/$F.count 27207c478bd9Sstevel@tonic-gate fi 27217c478bd9Sstevel@tonic-gate 2722daaffb31Sdp # 2723daaffb31Sdp # Now we generate the postscript for this file. We generate diffs 2724daaffb31Sdp # only in the event that there is delta, or the file is new (it seems 2725daaffb31Sdp # tree-killing to print out the contents of deleted files). 2726daaffb31Sdp # 2727daaffb31Sdp if [[ -f $nfile ]]; then 2728daaffb31Sdp ocr=$ofile 2729daaffb31Sdp [[ ! -f $ofile ]] && ocr=/dev/null 2730daaffb31Sdp 2731daaffb31Sdp if [[ -z $mv_but_nodiff ]]; then 2732daaffb31Sdp textcomm=`getcomments text $P $PP` 273314983201Sdp if [[ -x $CODEREVIEW ]]; then 273414983201Sdp $CODEREVIEW -y "$textcomm" \ 273514983201Sdp -e $ocr $nfile \ 273614983201Sdp > /tmp/$$.psfile 2>/dev/null && 273714983201Sdp cat /tmp/$$.psfile >> $WDIR/$WNAME.ps 2738daaffb31Sdp if [[ $? -eq 0 ]]; then 2739daaffb31Sdp print " ps\c" 2740daaffb31Sdp else 2741daaffb31Sdp print " ps[fail]\c" 2742daaffb31Sdp fi 2743daaffb31Sdp fi 2744daaffb31Sdp fi 274514983201Sdp fi 2746daaffb31Sdp 2747cdf0c1d5Smjnelson if [[ -f $ofile ]]; then 2748cdf0c1d5Smjnelson source_to_html Old $PP < $ofile > $WDIR/$DIR/$F-.html 27497c478bd9Sstevel@tonic-gate print " old\c" 27507c478bd9Sstevel@tonic-gate fi 27517c478bd9Sstevel@tonic-gate 2752daaffb31Sdp if [[ -f $nfile ]]; then 2753daaffb31Sdp source_to_html New $P < $nfile > $WDIR/$DIR/$F.html 27547c478bd9Sstevel@tonic-gate print " new\c" 27557c478bd9Sstevel@tonic-gate fi 27567c478bd9Sstevel@tonic-gate 2757cdf0c1d5Smjnelson cd $OWD 2758cdf0c1d5Smjnelson 2759daaffb31Sdp print 27607c478bd9Sstevel@tonic-gatedone 27617c478bd9Sstevel@tonic-gate 2762daaffb31Sdpframe_nav_js > $WDIR/ancnav.js 27637c478bd9Sstevel@tonic-gateframe_navigation > $WDIR/ancnav.html 2764daaffb31Sdp 276514983201Sdpif [[ ! -f $WDIR/$WNAME.ps ]]; then 276614983201Sdp print " Generating PDF: Skipped: no output available" 276714983201Sdpelif [[ -x $CODEREVIEW && -x $PS2PDF ]]; then 276814983201Sdp print " Generating PDF: \c" 276914983201Sdp fix_postscript $WDIR/$WNAME.ps | $PS2PDF - > $WDIR/$WNAME.pdf 2770daaffb31Sdp print "Done." 277114983201Sdpelse 277214983201Sdp print " Generating PDF: Skipped: missing 'ps2pdf' or 'codereview'" 277314983201Sdpfi 27747c478bd9Sstevel@tonic-gate 2775e0e0293aSjmcp# If we're in OpenSolaris mode and there's a closed dir under $WDIR, 2776e0e0293aSjmcp# delete it - prevent accidental publishing of closed source 2777e0e0293aSjmcp 2778e0e0293aSjmcpif [[ -n "$Oflag" ]]; then 2779e0e0293aSjmcp /usr/bin/find $WDIR -type d -name closed -exec /bin/rm -rf {} \; 2780e0e0293aSjmcpfi 2781e0e0293aSjmcp 27827c478bd9Sstevel@tonic-gate# Now build the index.html file that contains 27837c478bd9Sstevel@tonic-gate# links to the source files and their diffs. 27847c478bd9Sstevel@tonic-gate 27857c478bd9Sstevel@tonic-gatecd $CWS 27867c478bd9Sstevel@tonic-gate 27877c478bd9Sstevel@tonic-gate# Save total changed lines for Code Inspection. 2788daaffb31Sdpprint "$TOTL" > $WDIR/TotalChangedLines 27897c478bd9Sstevel@tonic-gate 2790daaffb31Sdpprint " index.html: \c" 27917c478bd9Sstevel@tonic-gateINDEXFILE=$WDIR/index.html 27927c478bd9Sstevel@tonic-gateexec 3<&1 # duplicate stdout to FD3. 27937c478bd9Sstevel@tonic-gateexec 1<&- # Close stdout. 27947c478bd9Sstevel@tonic-gateexec > $INDEXFILE # Open stdout to index file. 27957c478bd9Sstevel@tonic-gate 2796daaffb31Sdpprint "$HTML<head>$STDHEAD" 2797daaffb31Sdpprint "<title>$WNAME</title>" 2798daaffb31Sdpprint "</head>" 2799daaffb31Sdpprint "<body id=\"SUNWwebrev\">" 2800daaffb31Sdpprint "<div class=\"summary\">" 2801daaffb31Sdpprint "<h2>Code Review for $WNAME</h2>" 28027c478bd9Sstevel@tonic-gate 2803daaffb31Sdpprint "<table>" 28047c478bd9Sstevel@tonic-gate 2805daaffb31Sdp# 2806cdf0c1d5Smjnelson# Get the preparer's name: 2807daaffb31Sdp# 2808cdf0c1d5Smjnelson# If the SCM detected is Mercurial, and the configuration property 2809cdf0c1d5Smjnelson# ui.username is available, use that, but be careful to properly escape 2810cdf0c1d5Smjnelson# angle brackets (HTML syntax characters) in the email address. 2811cdf0c1d5Smjnelson# 2812cdf0c1d5Smjnelson# Otherwise, use the current userid in the form "John Doe (jdoe)", but 2813cdf0c1d5Smjnelson# to maintain compatibility with passwd(4), we must support '&' substitutions. 2814cdf0c1d5Smjnelson# 2815cdf0c1d5Smjnelsonpreparer= 2816cdf0c1d5Smjnelsonif [[ "$SCM_MODE" == mercurial ]]; then 2817cdf0c1d5Smjnelson preparer=`hg showconfig ui.username 2>/dev/null` 2818cdf0c1d5Smjnelson if [[ -n "$preparer" ]]; then 2819cdf0c1d5Smjnelson preparer="$(echo "$preparer" | html_quote)" 2820cdf0c1d5Smjnelson fi 2821cdf0c1d5Smjnelsonfi 2822cdf0c1d5Smjnelsonif [[ -z "$preparer" ]]; then 2823cdf0c1d5Smjnelson preparer=$( 2824cdf0c1d5Smjnelson $PERL -e ' 2825cdf0c1d5Smjnelson ($login, $pw, $uid, $gid, $quota, $cmt, $gcos) = getpwuid($<); 2826cdf0c1d5Smjnelson if ($login) { 2827cdf0c1d5Smjnelson $gcos =~ s/\&/ucfirst($login)/e; 2828cdf0c1d5Smjnelson printf "%s (%s)\n", $gcos, $login; 2829cdf0c1d5Smjnelson } else { 2830cdf0c1d5Smjnelson printf "(unknown)\n"; 2831cdf0c1d5Smjnelson } 2832cdf0c1d5Smjnelson ') 2833daaffb31Sdpfi 2834daaffb31Sdp 2835cdf0c1d5Smjnelsonprint "<tr><th>Prepared by:</th><td>$preparer on `date`</td></tr>" 2836cdf0c1d5Smjnelsonprint "<tr><th>Workspace:</th><td>$CWS" 2837cdf0c1d5Smjnelsonif [[ -n $CWS_REV ]]; then 2838cdf0c1d5Smjnelson print "(at $CWS_REV)" 2839cdf0c1d5Smjnelsonfi 2840cdf0c1d5Smjnelsonprint "</td></tr>" 2841daaffb31Sdpprint "<tr><th>Compare against:</th><td>" 2842daaffb31Sdpif [[ -n $parent_webrev ]]; then 2843daaffb31Sdp print "webrev at $parent_webrev" 2844daaffb31Sdpelse 2845daaffb31Sdp print "$PWS" 2846cdf0c1d5Smjnelson if [[ -n $hg_parent_short ]]; then 2847cdf0c1d5Smjnelson print "(at $hg_parent_short)" 2848cdf0c1d5Smjnelson fi 2849daaffb31Sdpfi 2850daaffb31Sdpprint "</td></tr>" 2851daaffb31Sdpprint "<tr><th>Summary of changes:</th><td>" 2852daaffb31SdpprintCI $TOTL $TINS $TDEL $TMOD $TUNC 2853daaffb31Sdpprint "</td></tr>" 2854daaffb31Sdp 2855daaffb31Sdpif [[ -f $WDIR/$WNAME.patch ]]; then 2856daaffb31Sdp print "<tr><th>Patch of changes:</th><td>" 2857daaffb31Sdp print "<a href=\"$WNAME.patch\">$WNAME.patch</a></td></tr>" 2858daaffb31Sdpfi 2859daaffb31Sdpif [[ -f $WDIR/$WNAME.pdf ]]; then 2860daaffb31Sdp print "<tr><th>Printable review:</th><td>" 2861daaffb31Sdp print "<a href=\"$WNAME.pdf\">$WNAME.pdf</a></td></tr>" 2862daaffb31Sdpfi 2863daaffb31Sdp 2864daaffb31Sdpif [[ -n "$iflag" ]]; then 2865daaffb31Sdp print "<tr><th>Author comments:</th><td><div>" 2866daaffb31Sdp cat /tmp/$$.include 2867daaffb31Sdp print "</div></td></tr>" 2868daaffb31Sdpfi 2869daaffb31Sdpprint "</table>" 2870daaffb31Sdpprint "</div>" 2871daaffb31Sdp 2872daaffb31Sdp# 2873daaffb31Sdp# Second pass through the files: generate the rest of the index file 2874daaffb31Sdp# 2875daaffb31Sdpcat $FLIST | while read LINE 28767c478bd9Sstevel@tonic-gatedo 28777c478bd9Sstevel@tonic-gate set - $LINE 28787c478bd9Sstevel@tonic-gate P=$1 28797c478bd9Sstevel@tonic-gate 2880daaffb31Sdp if [[ $# == 2 ]]; then 28817c478bd9Sstevel@tonic-gate PP=$2 2882cdf0c1d5Smjnelson oldname="$PP" 28837c478bd9Sstevel@tonic-gate else 28847c478bd9Sstevel@tonic-gate PP=$P 2885daaffb31Sdp oldname="" 2886daaffb31Sdp fi 2887daaffb31Sdp 2888cdf0c1d5Smjnelson mv_but_nodiff= 2889cdf0c1d5Smjnelson cmp $WDIR/raw_files/old/$PP $WDIR/raw_files/new/$P > /dev/null 2>&1 2890cdf0c1d5Smjnelson if [[ $? == 0 && -n "$oldname" ]]; then 2891cdf0c1d5Smjnelson mv_but_nodiff=1 2892cdf0c1d5Smjnelson fi 2893cdf0c1d5Smjnelson 2894daaffb31Sdp DIR=${P%/*} 2895daaffb31Sdp if [[ $DIR == $P ]]; then 2896daaffb31Sdp DIR="." # File at root of workspace 28977c478bd9Sstevel@tonic-gate fi 28987c478bd9Sstevel@tonic-gate 28997c478bd9Sstevel@tonic-gate # Avoid processing the same file twice. 29007c478bd9Sstevel@tonic-gate # It's possible for renamed files to 29017c478bd9Sstevel@tonic-gate # appear twice in the file list 29027c478bd9Sstevel@tonic-gate 29037c478bd9Sstevel@tonic-gate F=$WDIR/$P 29047c478bd9Sstevel@tonic-gate 2905daaffb31Sdp print "<p>" 29067c478bd9Sstevel@tonic-gate 29077c478bd9Sstevel@tonic-gate # If there's a diffs file, make diffs links 29087c478bd9Sstevel@tonic-gate 2909daaffb31Sdp if [[ -f $F.cdiff.html ]]; then 2910daaffb31Sdp print "<a href=\"$P.cdiff.html\">Cdiffs</a>" 2911daaffb31Sdp print "<a href=\"$P.udiff.html\">Udiffs</a>" 29127c478bd9Sstevel@tonic-gate 2913daaffb31Sdp if [[ -f $F.wdiff.html && -x $WDIFF ]]; then 2914daaffb31Sdp print "<a href=\"$P.wdiff.html\">Wdiffs</a>" 29157c478bd9Sstevel@tonic-gate fi 29167c478bd9Sstevel@tonic-gate 2917daaffb31Sdp print "<a href=\"$P.sdiff.html\">Sdiffs</a>" 29187c478bd9Sstevel@tonic-gate 29197c478bd9Sstevel@tonic-gate print "<a href=\"$P.frames.html\">Frames</a>" 29207c478bd9Sstevel@tonic-gate else 2921daaffb31Sdp print " ------ ------ ------" 29227c478bd9Sstevel@tonic-gate 2923daaffb31Sdp if [[ -x $WDIFF ]]; then 29247c478bd9Sstevel@tonic-gate print " ------" 29257c478bd9Sstevel@tonic-gate fi 2926daaffb31Sdp 2927daaffb31Sdp print " ------" 29287c478bd9Sstevel@tonic-gate fi 29297c478bd9Sstevel@tonic-gate 29307c478bd9Sstevel@tonic-gate # If there's an old file, make the link 29317c478bd9Sstevel@tonic-gate 2932daaffb31Sdp if [[ -f $F-.html ]]; then 2933daaffb31Sdp print "<a href=\"$P-.html\">Old</a>" 29347c478bd9Sstevel@tonic-gate else 2935daaffb31Sdp print " ---" 29367c478bd9Sstevel@tonic-gate fi 29377c478bd9Sstevel@tonic-gate 29387c478bd9Sstevel@tonic-gate # If there's an new file, make the link 29397c478bd9Sstevel@tonic-gate 2940daaffb31Sdp if [[ -f $F.html ]]; then 2941daaffb31Sdp print "<a href=\"$P.html\">New</a>" 29427c478bd9Sstevel@tonic-gate else 2943daaffb31Sdp print " ---" 29447c478bd9Sstevel@tonic-gate fi 29457c478bd9Sstevel@tonic-gate 2946daaffb31Sdp if [[ -f $F.patch ]]; then 2947daaffb31Sdp print "<a href=\"$P.patch\">Patch</a>" 2948daaffb31Sdp else 2949daaffb31Sdp print " -----" 2950daaffb31Sdp fi 2951daaffb31Sdp 2952daaffb31Sdp if [[ -f $WDIR/raw_files/new/$P ]]; then 2953daaffb31Sdp print "<a href=\"raw_files/new/$P\">Raw</a>" 2954daaffb31Sdp else 2955daaffb31Sdp print " ---" 2956daaffb31Sdp fi 2957daaffb31Sdp 2958cdf0c1d5Smjnelson print "<b>$P</b>" 2959cdf0c1d5Smjnelson 2960cdf0c1d5Smjnelson # For renamed files, clearly state whether or not they are modified 2961cdf0c1d5Smjnelson if [[ -n "$oldname" ]]; then 2962cdf0c1d5Smjnelson if [[ -n "$mv_but_nodiff" ]]; then 2963cdf0c1d5Smjnelson print "<i>(renamed only, was $oldname)</i>" 2964cdf0c1d5Smjnelson else 2965cdf0c1d5Smjnelson print "<i>(modified and renamed, was $oldname)</i>" 2966cdf0c1d5Smjnelson fi 2967cdf0c1d5Smjnelson fi 2968cdf0c1d5Smjnelson 2969cdf0c1d5Smjnelson # If there's an old file, but no new file, the file was deleted 2970cdf0c1d5Smjnelson if [[ -f $F-.html && ! -f $F.html ]]; then 2971cdf0c1d5Smjnelson print " <i>(deleted)</i>" 2972cdf0c1d5Smjnelson fi 2973daaffb31Sdp 2974daaffb31Sdp # 2975e0e0293aSjmcp # Check for usr/closed and deleted_files/usr/closed 2976daaffb31Sdp # 2977daaffb31Sdp if [ ! -z "$Oflag" ]; then 2978e0e0293aSjmcp if [[ $P == usr/closed/* || \ 2979e0e0293aSjmcp $P == deleted_files/usr/closed/* ]]; then 2980daaffb31Sdp print " <i>Closed source: omitted from" \ 2981daaffb31Sdp "this review</i>" 2982daaffb31Sdp fi 2983daaffb31Sdp fi 2984daaffb31Sdp 2985daaffb31Sdp print "</p>" 29867c478bd9Sstevel@tonic-gate # Insert delta comments 29877c478bd9Sstevel@tonic-gate 2988daaffb31Sdp print "<blockquote><pre>" 2989daaffb31Sdp getcomments html $P $PP 2990daaffb31Sdp print "</pre>" 29917c478bd9Sstevel@tonic-gate 29927c478bd9Sstevel@tonic-gate # Add additional comments comment 29937c478bd9Sstevel@tonic-gate 2994daaffb31Sdp print "<!-- Add comments to explain changes in $P here -->" 29957c478bd9Sstevel@tonic-gate 29967c478bd9Sstevel@tonic-gate # Add count of changes. 29977c478bd9Sstevel@tonic-gate 2998daaffb31Sdp if [[ -f $F.count ]]; then 29997c478bd9Sstevel@tonic-gate cat $F.count 30007c478bd9Sstevel@tonic-gate rm $F.count 30017c478bd9Sstevel@tonic-gate fi 3002cdf0c1d5Smjnelson 3003cdf0c1d5Smjnelson if [[ $SCM_MODE == "teamware" || 3004cdf0c1d5Smjnelson $SCM_MODE == "mercurial" || 3005cdf0c1d5Smjnelson $SCM_MODE == "unknown" ]]; then 3006cdf0c1d5Smjnelson 3007cdf0c1d5Smjnelson # Include warnings for important file mode situations: 3008cdf0c1d5Smjnelson # 1) New executable files 3009cdf0c1d5Smjnelson # 2) Permission changes of any kind 3010cdf0c1d5Smjnelson # 3) Existing executable files 3011cdf0c1d5Smjnelson 3012cdf0c1d5Smjnelson old_mode= 3013cdf0c1d5Smjnelson if [[ -f $WDIR/raw_files/old/$PP ]]; then 3014cdf0c1d5Smjnelson old_mode=`get_file_mode $WDIR/raw_files/old/$PP` 3015cdf0c1d5Smjnelson fi 3016cdf0c1d5Smjnelson 3017cdf0c1d5Smjnelson new_mode= 3018cdf0c1d5Smjnelson if [[ -f $WDIR/raw_files/new/$P ]]; then 3019cdf0c1d5Smjnelson new_mode=`get_file_mode $WDIR/raw_files/new/$P` 3020cdf0c1d5Smjnelson fi 3021cdf0c1d5Smjnelson 3022cdf0c1d5Smjnelson if [[ -z "$old_mode" && "$new_mode" = *[1357]* ]]; then 3023cdf0c1d5Smjnelson print "<span class=\"chmod\">" 3024cdf0c1d5Smjnelson print "<p>new executable file: mode $new_mode</p>" 3025cdf0c1d5Smjnelson print "</span>" 3026cdf0c1d5Smjnelson elif [[ -n "$old_mode" && -n "$new_mode" && 3027cdf0c1d5Smjnelson "$old_mode" != "$new_mode" ]]; then 3028cdf0c1d5Smjnelson print "<span class=\"chmod\">" 3029cdf0c1d5Smjnelson print "<p>mode change: $old_mode to $new_mode</p>" 3030cdf0c1d5Smjnelson print "</span>" 3031cdf0c1d5Smjnelson elif [[ "$new_mode" = *[1357]* ]]; then 3032cdf0c1d5Smjnelson print "<span class=\"chmod\">" 3033cdf0c1d5Smjnelson print "<p>executable file: mode $new_mode</p>" 3034cdf0c1d5Smjnelson print "</span>" 3035cdf0c1d5Smjnelson fi 3036cdf0c1d5Smjnelson fi 3037cdf0c1d5Smjnelson 3038daaffb31Sdp print "</blockquote>" 30397c478bd9Sstevel@tonic-gatedone 30407c478bd9Sstevel@tonic-gate 3041daaffb31Sdpprint 3042daaffb31Sdpprint 3043cac38512Smjnelsonprint "<hr></hr>" 3044daaffb31Sdpprint "<p style=\"font-size: small\">" 30459a70fc3bSMark J. Nelsonprint "This code review page was prepared using <b>$0</b>." 3046daaffb31Sdpprint "Webrev is maintained by the <a href=\"http://www.opensolaris.org\">" 3047daaffb31Sdpprint "OpenSolaris</a> project. The latest version may be obtained" 3048e9e2cfb2Sfr80241print "<a href=\"http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/tools/scripts/webrev.sh\">here</a>.</p>" 3049daaffb31Sdpprint "</body>" 3050daaffb31Sdpprint "</html>" 30517c478bd9Sstevel@tonic-gate 30527c478bd9Sstevel@tonic-gateexec 1<&- # Close FD 1. 30537c478bd9Sstevel@tonic-gateexec 1<&3 # dup FD 3 to restore stdout. 30547c478bd9Sstevel@tonic-gateexec 3<&- # close FD 3. 30557c478bd9Sstevel@tonic-gate 3056daaffb31Sdpprint "Done." 3057*02d26c39SVladimir Kotal 3058*02d26c39SVladimir Kotalif [[ -n $Uflag ]]; then 3059*02d26c39SVladimir Kotal upload_webrev 3060*02d26c39SVladimir Kotal exit $? 3061*02d26c39SVladimir Kotalfi 3062