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# 24371d72daSLubomir Sedlacik# Copyright 2009 Sun Microsystems, Inc. All rights reserved. 257c478bd9Sstevel@tonic-gate# Use is subject to license terms. 267c478bd9Sstevel@tonic-gate# 27cdf0c1d5Smjnelson 28cdf0c1d5Smjnelson# 29daaffb31Sdp# This script takes a file list and a workspace and builds a set of html files 30daaffb31Sdp# suitable for doing a code review of source changes via a web page. 31daaffb31Sdp# Documentation is available via the manual page, webrev.1, or just 32daaffb31Sdp# type 'webrev -h'. 337c478bd9Sstevel@tonic-gate# 34daaffb31Sdp# Acknowledgements to contributors to webrev are listed in the webrev(1) 35daaffb31Sdp# man page. 367c478bd9Sstevel@tonic-gate# 37daaffb31Sdp 387c478bd9Sstevel@tonic-gateREMOVED_COLOR=brown 397c478bd9Sstevel@tonic-gateCHANGED_COLOR=blue 407c478bd9Sstevel@tonic-gateNEW_COLOR=blue 417c478bd9Sstevel@tonic-gate 42daaffb31SdpHTML='<?xml version="1.0"?> 43daaffb31Sdp<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 44daaffb31Sdp "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 45daaffb31Sdp<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">\n' 46daaffb31Sdp 47daaffb31SdpFRAMEHTML='<?xml version="1.0"?> 48daaffb31Sdp<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" 49daaffb31Sdp "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd"> 50daaffb31Sdp<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">\n' 51daaffb31Sdp 52cac38512SmjnelsonSTDHEAD='<meta http-equiv="cache-control" content="no-cache"></meta> 53cac38512Smjnelson<meta http-equiv="Pragma" content="no-cache"></meta> 54cac38512Smjnelson<meta http-equiv="Expires" content="-1"></meta> 55daaffb31Sdp<!-- 56daaffb31Sdp Note to customizers: the body of the webrev is IDed as SUNWwebrev 57daaffb31Sdp to allow easy overriding by users of webrev via the userContent.css 58daaffb31Sdp mechanism available in some browsers. 59daaffb31Sdp 60daaffb31Sdp For example, to have all "removed" information be red instead of 61daaffb31Sdp brown, set a rule in your userContent.css file like: 62daaffb31Sdp 63daaffb31Sdp body#SUNWwebrev span.removed { color: red ! important; } 64daaffb31Sdp--> 65daaffb31Sdp<style type="text/css" media="screen"> 66daaffb31Sdpbody { 67daaffb31Sdp background-color: #eeeeee; 68daaffb31Sdp} 69daaffb31Sdphr { 70daaffb31Sdp border: none 0; 71daaffb31Sdp border-top: 1px solid #aaa; 72daaffb31Sdp height: 1px; 73daaffb31Sdp} 74daaffb31Sdpdiv.summary { 75daaffb31Sdp font-size: .8em; 76daaffb31Sdp border-bottom: 1px solid #aaa; 77daaffb31Sdp padding-left: 1em; 78daaffb31Sdp padding-right: 1em; 79daaffb31Sdp} 80daaffb31Sdpdiv.summary h2 { 81daaffb31Sdp margin-bottom: 0.3em; 82daaffb31Sdp} 83daaffb31Sdpdiv.summary table th { 84daaffb31Sdp text-align: right; 85daaffb31Sdp vertical-align: top; 86daaffb31Sdp white-space: nowrap; 87daaffb31Sdp} 88daaffb31Sdpspan.lineschanged { 89daaffb31Sdp font-size: 0.7em; 90daaffb31Sdp} 91daaffb31Sdpspan.oldmarker { 92daaffb31Sdp color: red; 93daaffb31Sdp font-size: large; 94daaffb31Sdp font-weight: bold; 95daaffb31Sdp} 96daaffb31Sdpspan.newmarker { 97daaffb31Sdp color: green; 98daaffb31Sdp font-size: large; 99daaffb31Sdp font-weight: bold; 100daaffb31Sdp} 101daaffb31Sdpspan.removed { 102daaffb31Sdp color: brown; 103daaffb31Sdp} 104daaffb31Sdpspan.changed { 105daaffb31Sdp color: blue; 106daaffb31Sdp} 107daaffb31Sdpspan.new { 108daaffb31Sdp color: blue; 109daaffb31Sdp font-weight: bold; 110daaffb31Sdp} 111cdf0c1d5Smjnelsonspan.chmod { 112cdf0c1d5Smjnelson font-size: 0.7em; 113cdf0c1d5Smjnelson color: #db7800; 114cdf0c1d5Smjnelson} 115daaffb31Sdpa.print { font-size: x-small; } 116daaffb31Sdpa:hover { background-color: #ffcc99; } 117daaffb31Sdp</style> 118daaffb31Sdp 119daaffb31Sdp<style type="text/css" media="print"> 120daaffb31Sdppre { font-size: 0.8em; font-family: courier, monospace; } 121daaffb31Sdpspan.removed { color: #444; font-style: italic } 122daaffb31Sdpspan.changed { font-weight: bold; } 123daaffb31Sdpspan.new { font-weight: bold; } 124daaffb31Sdpspan.newmarker { font-size: 1.2em; font-weight: bold; } 125daaffb31Sdpspan.oldmarker { font-size: 1.2em; font-weight: bold; } 126daaffb31Sdpa.print {display: none} 127daaffb31Sdphr { border: none 0; border-top: 1px solid #aaa; height: 1px; } 128daaffb31Sdp</style> 129daaffb31Sdp' 130daaffb31Sdp 131daaffb31Sdp# 132daaffb31Sdp# UDiffs need a slightly different CSS rule for 'new' items (we don't 133daaffb31Sdp# want them to be bolded as we do in cdiffs or sdiffs). 134daaffb31Sdp# 135daaffb31SdpUDIFFCSS=' 136daaffb31Sdp<style type="text/css" media="screen"> 137daaffb31Sdpspan.new { 138daaffb31Sdp color: blue; 139daaffb31Sdp font-weight: normal; 140daaffb31Sdp} 141daaffb31Sdp</style> 142daaffb31Sdp' 143daaffb31Sdp 144*b0088928SVladimir Kotal# 145*b0088928SVladimir Kotal# Display remote target with prefix and trailing slash. 146*b0088928SVladimir Kotal# 147*b0088928SVladimir Kotalfunction print_upload_header 148*b0088928SVladimir Kotal{ 149*b0088928SVladimir Kotal typeset -r prefix=$1 150*b0088928SVladimir Kotal typeset display_target 151*b0088928SVladimir Kotal 152*b0088928SVladimir Kotal if [[ -z $tflag ]]; then 153*b0088928SVladimir Kotal display_target=${prefix}${remote_target} 154*b0088928SVladimir Kotal else 155*b0088928SVladimir Kotal display_target=${remote_target} 156*b0088928SVladimir Kotal fi 157*b0088928SVladimir Kotal 158*b0088928SVladimir Kotal if [[ ${display_target} != */ ]]; then 159*b0088928SVladimir Kotal display_target=${display_target}/ 160*b0088928SVladimir Kotal fi 161*b0088928SVladimir Kotal 162*b0088928SVladimir Kotal print " Upload to: ${display_target}\n" \ 163*b0088928SVladimir Kotal " Uploading: \c" 164*b0088928SVladimir Kotal} 165*b0088928SVladimir Kotal 166*b0088928SVladimir Kotal# 16702d26c39SVladimir Kotal# Upload the webrev via rsync. Return 0 on success, 1 on error. 168*b0088928SVladimir Kotal# 169ba44d8a2SVladimir Kotalfunction rsync_upload 17002d26c39SVladimir Kotal{ 171*b0088928SVladimir Kotal if (( $# != 2 )); then 172*b0088928SVladimir Kotal print "\nERROR: rsync_upload: wrong usage ($#)" 173*b0088928SVladimir Kotal exit 1 17402d26c39SVladimir Kotal fi 17502d26c39SVladimir Kotal 176*b0088928SVladimir Kotal typeset -r dst=$1 177*b0088928SVladimir Kotal integer -r print_err_msg=$2 17802d26c39SVladimir Kotal 179*b0088928SVladimir Kotal print_upload_header ${rsync_prefix} 180*b0088928SVladimir Kotal print "rsync ... \c" 181*b0088928SVladimir Kotal typeset -r err_msg=$( $MKTEMP /tmp/rsync_err.XXX ) 182*b0088928SVladimir Kotal if [[ -z $err_msg ]]; then 183*b0088928SVladimir Kotal print "\nERROR: rsync_upload: cannot create temporary file" 184*b0088928SVladimir Kotal return 1 185*b0088928SVladimir Kotal fi 186*b0088928SVladimir Kotal # 187*b0088928SVladimir Kotal # The source directory must end with a slash in order to copy just 188*b0088928SVladimir Kotal # directory contents, not the whole directory. 189*b0088928SVladimir Kotal # 190*b0088928SVladimir Kotal typeset src_dir=$WDIR 191*b0088928SVladimir Kotal if [[ ${src_dir} != */ ]]; then 192*b0088928SVladimir Kotal src_dir=${src_dir}/ 193*b0088928SVladimir Kotal fi 194*b0088928SVladimir Kotal $RSYNC -r -q ${src_dir} $dst 2>$err_msg 19502d26c39SVladimir Kotal if (( $? != 0 )); then 196*b0088928SVladimir Kotal if (( ${print_err_msg} > 0 )); then 197*b0088928SVladimir Kotal print "Failed.\nERROR: rsync failed" 198*b0088928SVladimir Kotal print "src dir: '${src_dir}'\ndst dir: '$dst'" 199*b0088928SVladimir Kotal print "error messages:" 200*b0088928SVladimir Kotal $SED 's/^/> /' $err_msg 201*b0088928SVladimir Kotal rm -f $err_msg 202*b0088928SVladimir Kotal fi 20302d26c39SVladimir Kotal return 1 20402d26c39SVladimir Kotal fi 20502d26c39SVladimir Kotal 206*b0088928SVladimir Kotal rm -f $err_msg 20702d26c39SVladimir Kotal print "Done." 20802d26c39SVladimir Kotal return 0 20902d26c39SVladimir Kotal} 21002d26c39SVladimir Kotal 211*b0088928SVladimir Kotal# 212*b0088928SVladimir Kotal# Create directories on remote host using SFTP. Return 0 on success, 213*b0088928SVladimir Kotal# 1 on failure. 214*b0088928SVladimir Kotal# 215*b0088928SVladimir Kotalfunction remote_mkdirs 216*b0088928SVladimir Kotal{ 217*b0088928SVladimir Kotal typeset -r dir_spec=$1 218*b0088928SVladimir Kotal 219*b0088928SVladimir Kotal # 220*b0088928SVladimir Kotal # If the supplied path is absolute we assume all directories are 221*b0088928SVladimir Kotal # created, otherwise try to create all directories in the path 222*b0088928SVladimir Kotal # except the last one which will be created by scp. 223*b0088928SVladimir Kotal # 224*b0088928SVladimir Kotal if [[ "${dir_spec}" == */* && "${dir_spec}" != /* ]]; then 225*b0088928SVladimir Kotal print "mkdirs \c" 226*b0088928SVladimir Kotal # 227*b0088928SVladimir Kotal # Remove the last directory from directory specification. 228*b0088928SVladimir Kotal # 229*b0088928SVladimir Kotal typeset -r dirs_mk=${dir_spec%/*} 230*b0088928SVladimir Kotal typeset -r batch_file_mkdir=$( $MKTEMP /tmp/webrev_mkdir.XXX ) 231*b0088928SVladimir Kotal if [[ -z $batch_file_mkdir ]]; then 232*b0088928SVladimir Kotal print "\nERROR: remote_mkdirs:" \ 233*b0088928SVladimir Kotal "cannot create temporary file for batch file" 234*b0088928SVladimir Kotal return 1 235*b0088928SVladimir Kotal fi 236*b0088928SVladimir Kotal OLDIFS=$IFS 237*b0088928SVladimir Kotal IFS=/ 238*b0088928SVladimir Kotal typeset dir 239*b0088928SVladimir Kotal for dir in ${dirs_mk}; do 240*b0088928SVladimir Kotal # 241*b0088928SVladimir Kotal # Use the '-' prefix to ignore mkdir errors in order 242*b0088928SVladimir Kotal # to avoid an error in case the directory already 243*b0088928SVladimir Kotal # exists. We check the directory with chdir to be sure 244*b0088928SVladimir Kotal # there is one. 245*b0088928SVladimir Kotal # 246*b0088928SVladimir Kotal print -- "-mkdir ${dir}" >> ${batch_file_mkdir} 247*b0088928SVladimir Kotal print "chdir ${dir}" >> ${batch_file_mkdir} 248*b0088928SVladimir Kotal done 249*b0088928SVladimir Kotal IFS=$OLDIFS 250*b0088928SVladimir Kotal typeset -r sftp_err_msg=$( $MKTEMP /tmp/webrev_scp_err.XXX ) 251*b0088928SVladimir Kotal if [[ -z ${sftp_err_msg} ]]; then 252*b0088928SVladimir Kotal print "\nERROR: remote_mkdirs:" \ 253*b0088928SVladimir Kotal "cannot create temporary file for error messages" 254*b0088928SVladimir Kotal return 1 255*b0088928SVladimir Kotal fi 256*b0088928SVladimir Kotal $SFTP -b ${batch_file_mkdir} ${host_spec} 2>${sftp_err_msg} 1>&2 257*b0088928SVladimir Kotal if (( $? != 0 )); then 258*b0088928SVladimir Kotal print "\nERROR: failed to create remote directories" 259*b0088928SVladimir Kotal print "error messages:" 260*b0088928SVladimir Kotal $SED 's/^/> /' ${sftp_err_msg} 261*b0088928SVladimir Kotal rm -f ${sftp_err_msg} ${batch_file_mkdir} 262*b0088928SVladimir Kotal return 1 263*b0088928SVladimir Kotal fi 264*b0088928SVladimir Kotal rm -f ${sftp_err_msg} ${batch_file_mkdir} 265*b0088928SVladimir Kotal fi 266*b0088928SVladimir Kotal 267*b0088928SVladimir Kotal return 0 268*b0088928SVladimir Kotal} 269*b0088928SVladimir Kotal 270*b0088928SVladimir Kotal# 27102d26c39SVladimir Kotal# Upload the webrev via SSH. Return 0 on success, 1 on error. 272*b0088928SVladimir Kotal# 273ba44d8a2SVladimir Kotalfunction ssh_upload 27402d26c39SVladimir Kotal{ 27502d26c39SVladimir Kotal if (( $# != 1 )); then 276*b0088928SVladimir Kotal print "\nERROR: ssh_upload: wrong number of arguments" 277*b0088928SVladimir Kotal exit 1 27802d26c39SVladimir Kotal fi 27902d26c39SVladimir Kotal 28002d26c39SVladimir Kotal typeset dst=$1 28102d26c39SVladimir Kotal typeset -r host_spec=${dst%%:*} 282ba44d8a2SVladimir Kotal typeset -r dir_spec=${dst#*:} 28302d26c39SVladimir Kotal 284*b0088928SVladimir Kotal # 285*b0088928SVladimir Kotal # Display the upload information before calling delete_webrev 286*b0088928SVladimir Kotal # because it will also print its progress. 287*b0088928SVladimir Kotal # 288*b0088928SVladimir Kotal print_upload_header ${ssh_prefix} 289*b0088928SVladimir Kotal 290*b0088928SVladimir Kotal # 291*b0088928SVladimir Kotal # If the deletion was explicitly requested there is no need 292*b0088928SVladimir Kotal # to perform it again. 293*b0088928SVladimir Kotal # 294ba44d8a2SVladimir Kotal if [[ -z $Dflag ]]; then 295*b0088928SVladimir Kotal # 296*b0088928SVladimir Kotal # We do not care about return value because this might be 297*b0088928SVladimir Kotal # the first time this directory is uploaded. 298*b0088928SVladimir Kotal # 299ba44d8a2SVladimir Kotal delete_webrev 0 30002d26c39SVladimir Kotal fi 30102d26c39SVladimir Kotal 302*b0088928SVladimir Kotal # 303*b0088928SVladimir Kotal # Create remote directories. Any error reporting will be done 304*b0088928SVladimir Kotal # in remote_mkdirs function. 305*b0088928SVladimir Kotal # 306*b0088928SVladimir Kotal remote_mkdirs ${dir_spec} 30702d26c39SVladimir Kotal if (( $? != 0 )); then 30802d26c39SVladimir Kotal return 1 30902d26c39SVladimir Kotal fi 31002d26c39SVladimir Kotal 311*b0088928SVladimir Kotal print "upload ... \c" 312*b0088928SVladimir Kotal typeset -r scp_err_msg=$( $MKTEMP /tmp/scp_err.XXX ) 313*b0088928SVladimir Kotal if [[ -z ${scp_err_msg} ]]; then 314*b0088928SVladimir Kotal print "\nERROR: ssh_upload:" \ 315*b0088928SVladimir Kotal "cannot create temporary file for error messages" 316*b0088928SVladimir Kotal return 1 317*b0088928SVladimir Kotal fi 31802d26c39SVladimir Kotal $SCP -q -C -B -o PreferredAuthentications=publickey -r \ 319*b0088928SVladimir Kotal $WDIR $dst 2>${scp_err_msg} 32002d26c39SVladimir Kotal if (( $? != 0 )); then 321*b0088928SVladimir Kotal print "Failed.\nERROR: scp failed" 322*b0088928SVladimir Kotal print "src dir: '$WDIR'\ndst dir: '$dst'" 323*b0088928SVladimir Kotal print "error messages:" 324*b0088928SVladimir Kotal $SED 's/^/> /' ${scp_err_msg} 325*b0088928SVladimir Kotal rm -f ${scp_err_msg} 32602d26c39SVladimir Kotal return 1 32702d26c39SVladimir Kotal fi 32802d26c39SVladimir Kotal 329*b0088928SVladimir Kotal rm -f ${scp_err_msg} 33002d26c39SVladimir Kotal print "Done." 33102d26c39SVladimir Kotal return 0 33202d26c39SVladimir Kotal} 33302d26c39SVladimir Kotal 33402d26c39SVladimir Kotal# 335ba44d8a2SVladimir Kotal# Delete webrev at remote site. Return 0 on success, 1 or exit code from sftp 336*b0088928SVladimir Kotal# on failure. If first argument is 1 then perform the check of sftp return 337*b0088928SVladimir Kotal# value otherwise ignore it. If second argument is present it means this run 338*b0088928SVladimir Kotal# only performs deletion. 339ba44d8a2SVladimir Kotal# 340ba44d8a2SVladimir Kotalfunction delete_webrev 341ba44d8a2SVladimir Kotal{ 342*b0088928SVladimir Kotal if (( $# < 1 )); then 343*b0088928SVladimir Kotal print "delete_webrev: wrong number of arguments" 344*b0088928SVladimir Kotal exit 1 345ba44d8a2SVladimir Kotal fi 346ba44d8a2SVladimir Kotal 347*b0088928SVladimir Kotal integer -r check=$1 348*b0088928SVladimir Kotal integer delete_only=0 349*b0088928SVladimir Kotal if (( $# == 2 )); then 350*b0088928SVladimir Kotal delete_only=1 351*b0088928SVladimir Kotal fi 352*b0088928SVladimir Kotal 353*b0088928SVladimir Kotal # 354ba44d8a2SVladimir Kotal # Strip the transport specification part of remote target first. 355*b0088928SVladimir Kotal # 356ba44d8a2SVladimir Kotal typeset -r stripped_target=${remote_target##*://} 357ba44d8a2SVladimir Kotal typeset -r host_spec=${stripped_target%%:*} 358ba44d8a2SVladimir Kotal typeset -r dir_spec=${stripped_target#*:} 359ba44d8a2SVladimir Kotal typeset dir_rm 360ba44d8a2SVladimir Kotal 361*b0088928SVladimir Kotal # 362ba44d8a2SVladimir Kotal # Do not accept an absolute path. 363*b0088928SVladimir Kotal # 364ba44d8a2SVladimir Kotal if [[ ${dir_spec} == /* ]]; then 365ba44d8a2SVladimir Kotal return 1 366ba44d8a2SVladimir Kotal fi 367ba44d8a2SVladimir Kotal 368*b0088928SVladimir Kotal # 369ba44d8a2SVladimir Kotal # Strip the ending slash. 370*b0088928SVladimir Kotal # 371ba44d8a2SVladimir Kotal if [[ ${dir_spec} == */ ]]; then 372ba44d8a2SVladimir Kotal dir_rm=${dir_spec%%/} 373ba44d8a2SVladimir Kotal else 374ba44d8a2SVladimir Kotal dir_rm=${dir_spec} 375ba44d8a2SVladimir Kotal fi 376ba44d8a2SVladimir Kotal 377*b0088928SVladimir Kotal if (( ${delete_only} > 0 )); then 378*b0088928SVladimir Kotal print " Removing: \c" 379*b0088928SVladimir Kotal else 380*b0088928SVladimir Kotal print "rmdir \c" 381*b0088928SVladimir Kotal fi 382ba44d8a2SVladimir Kotal if [[ -z "$dir_rm" ]]; then 383*b0088928SVladimir Kotal print "\nERROR: empty directory for removal" 384ba44d8a2SVladimir Kotal return 1 385ba44d8a2SVladimir Kotal fi 386ba44d8a2SVladimir Kotal 387*b0088928SVladimir Kotal # 388ba44d8a2SVladimir Kotal # Prepare batch file. 389*b0088928SVladimir Kotal # 390ba44d8a2SVladimir Kotal typeset -r batch_file_rm=$( $MKTEMP /tmp/webrev_remove.XXX ) 391ba44d8a2SVladimir Kotal if [[ -z $batch_file_rm ]]; then 392*b0088928SVladimir Kotal print "\nERROR: delete_webrev: cannot create temporary file" 393ba44d8a2SVladimir Kotal return 1 394ba44d8a2SVladimir Kotal fi 395ba44d8a2SVladimir Kotal print "rename $dir_rm $TRASH_DIR/removed.$$" > $batch_file_rm 396ba44d8a2SVladimir Kotal 397*b0088928SVladimir Kotal # 398ba44d8a2SVladimir Kotal # Perform remote deletion and remove the batch file. 399*b0088928SVladimir Kotal # 400*b0088928SVladimir Kotal typeset -r sftp_err_msg=$( $MKTEMP /tmp/webrev_scp_err.XXX ) 401*b0088928SVladimir Kotal if [[ -z ${sftp_err_msg} ]]; then 402*b0088928SVladimir Kotal print "\nERROR: delete_webrev:" \ 403*b0088928SVladimir Kotal "cannot create temporary file for error messages" 404*b0088928SVladimir Kotal return 1 405*b0088928SVladimir Kotal fi 406*b0088928SVladimir Kotal $SFTP -b $batch_file_rm $host_spec 2>${sftp_err_msg} 1>&2 407ba44d8a2SVladimir Kotal integer -r ret=$? 408ba44d8a2SVladimir Kotal rm -f $batch_file_rm 409ba44d8a2SVladimir Kotal if (( $ret != 0 && $check > 0 )); then 410*b0088928SVladimir Kotal print "Failed.\nERROR: failed to remove remote directories" 411*b0088928SVladimir Kotal print "error messages:" 412*b0088928SVladimir Kotal $SED 's/^/> /' ${sftp_err_msg} 413*b0088928SVladimir Kotal rm -f ${sftp_err_msg} 414ba44d8a2SVladimir Kotal return $ret 415ba44d8a2SVladimir Kotal fi 416*b0088928SVladimir Kotal rm -f ${sftp_err_msg} 417*b0088928SVladimir Kotal if (( ${delete_only} > 0 )); then 418ba44d8a2SVladimir Kotal print "Done." 419*b0088928SVladimir Kotal fi 420ba44d8a2SVladimir Kotal 421ba44d8a2SVladimir Kotal return 0 422ba44d8a2SVladimir Kotal} 423ba44d8a2SVladimir Kotal 424ba44d8a2SVladimir Kotal# 42502d26c39SVladimir Kotal# Upload webrev to remote site 42602d26c39SVladimir Kotal# 427ba44d8a2SVladimir Kotalfunction upload_webrev 42802d26c39SVladimir Kotal{ 429*b0088928SVladimir Kotal integer ret 43002d26c39SVladimir Kotal 43102d26c39SVladimir Kotal if [[ ! -d "$WDIR" ]]; then 432*b0088928SVladimir Kotal print "\nERROR: webrev directory '$WDIR' does not exist" 43302d26c39SVladimir Kotal return 1 43402d26c39SVladimir Kotal fi 43502d26c39SVladimir Kotal 436*b0088928SVladimir Kotal # 43702d26c39SVladimir Kotal # Perform a late check to make sure we do not upload closed source 43802d26c39SVladimir Kotal # to remote target when -n is used. If the user used custom remote 43902d26c39SVladimir Kotal # target he probably knows what he is doing. 440*b0088928SVladimir Kotal # 44102d26c39SVladimir Kotal if [[ -n $nflag && -z $tflag ]]; then 442ba44d8a2SVladimir Kotal $FIND $WDIR -type d -name closed \ 44302d26c39SVladimir Kotal | $GREP closed >/dev/null 44402d26c39SVladimir Kotal if (( $? == 0 )); then 445*b0088928SVladimir Kotal print "\nERROR: directory '$WDIR' contains" \ 446*b0088928SVladimir Kotal "\"closed\" directory" 44702d26c39SVladimir Kotal return 1 44802d26c39SVladimir Kotal fi 44902d26c39SVladimir Kotal fi 45002d26c39SVladimir Kotal 451*b0088928SVladimir Kotal 452*b0088928SVladimir Kotal # 453*b0088928SVladimir Kotal # We have the URI for remote destination now so let's start the upload. 454*b0088928SVladimir Kotal # 45502d26c39SVladimir Kotal if [[ -n $tflag ]]; then 45602d26c39SVladimir Kotal if [[ "${remote_target}" == ${rsync_prefix}?* ]]; then 457*b0088928SVladimir Kotal rsync_upload ${remote_target##$rsync_prefix} 1 458*b0088928SVladimir Kotal ret=$? 459*b0088928SVladimir Kotal return $ret 46002d26c39SVladimir Kotal elif [[ "${remote_target}" == ${ssh_prefix}?* ]]; then 46102d26c39SVladimir Kotal ssh_upload ${remote_target##$ssh_prefix} 462*b0088928SVladimir Kotal ret=$? 463*b0088928SVladimir Kotal return $ret 46402d26c39SVladimir Kotal fi 46502d26c39SVladimir Kotal else 466*b0088928SVladimir Kotal # 467*b0088928SVladimir Kotal # Try rsync first and fallback to SSH in case it fails. 468*b0088928SVladimir Kotal # 469*b0088928SVladimir Kotal rsync_upload ${remote_target} 0 470*b0088928SVladimir Kotal ret=$? 471*b0088928SVladimir Kotal if (( $ret != 0 )); then 472*b0088928SVladimir Kotal print "Failed. (falling back to SSH)" 473ba44d8a2SVladimir Kotal ssh_upload ${remote_target} 474*b0088928SVladimir Kotal ret=$? 47502d26c39SVladimir Kotal fi 476*b0088928SVladimir Kotal return $ret 47702d26c39SVladimir Kotal fi 47802d26c39SVladimir Kotal} 47902d26c39SVladimir Kotal 480daaffb31Sdp# 481371d72daSLubomir Sedlacik# input_cmd | url_encode | output_cmd 482371d72daSLubomir Sedlacik# 483371d72daSLubomir Sedlacik# URL-encode (percent-encode) reserved characters as defined in RFC 3986. 484371d72daSLubomir Sedlacik# 485371d72daSLubomir Sedlacik# Reserved characters are: :/?#[]@!$&'()*+,;= 486371d72daSLubomir Sedlacik# 487371d72daSLubomir Sedlacik# While not a reserved character itself, percent '%' is reserved by definition 488371d72daSLubomir Sedlacik# so encode it first to avoid recursive transformation, and skip '/' which is 489371d72daSLubomir Sedlacik# a path delimiter. 490371d72daSLubomir Sedlacik# 491371d72daSLubomir Sedlacikfunction url_encode 492371d72daSLubomir Sedlacik{ 493*b0088928SVladimir Kotal $SED -e "s|%|%25|g" -e "s|:|%3A|g" -e "s|\&|%26|g" \ 494371d72daSLubomir Sedlacik -e "s|?|%3F|g" -e "s|#|%23|g" -e "s|\[|%5B|g" \ 495371d72daSLubomir Sedlacik -e "s|*|%2A|g" -e "s|@|%40|g" -e "s|\!|%21|g" \ 496371d72daSLubomir Sedlacik -e "s|=|%3D|g" -e "s|;|%3B|g" -e "s|\]|%5D|g" \ 497371d72daSLubomir Sedlacik -e "s|(|%28|g" -e "s|)|%29|g" -e "s|\'|%27|g" \ 498371d72daSLubomir Sedlacik -e "s|+|%2B|g" -e "s|\,|%2C|g" -e "s|\\\$|%24|g" 499371d72daSLubomir Sedlacik} 500371d72daSLubomir Sedlacik 501371d72daSLubomir Sedlacik# 502daaffb31Sdp# input_cmd | html_quote | output_cmd 503daaffb31Sdp# or 504daaffb31Sdp# html_quote filename | output_cmd 5057c478bd9Sstevel@tonic-gate# 5067c478bd9Sstevel@tonic-gate# Make a piece of source code safe for display in an HTML <pre> block. 5077c478bd9Sstevel@tonic-gate# 5087c478bd9Sstevel@tonic-gatehtml_quote() 5097c478bd9Sstevel@tonic-gate{ 510*b0088928SVladimir Kotal $SED -e "s/&/\&/g" -e "s/</\</g" -e "s/>/\>/g" "$@" | expand 5117c478bd9Sstevel@tonic-gate} 5127c478bd9Sstevel@tonic-gate 513daaffb31Sdp# 514daaffb31Sdp# input_cmd | bug2url | output_cmd 515daaffb31Sdp# 516daaffb31Sdp# Scan for bugids and insert <a> links to the relevent bug database. 517daaffb31Sdp# 518daaffb31Sdpbug2url() 5197c478bd9Sstevel@tonic-gate{ 520*b0088928SVladimir Kotal $SED -e 's|[0-9]\{5,\}|<a href=\"'$BUGURL'&\">&</a>|g' 521daaffb31Sdp} 522daaffb31Sdp 5237c478bd9Sstevel@tonic-gate# 524daaffb31Sdp# input_cmd | sac2url | output_cmd 5257c478bd9Sstevel@tonic-gate# 526daaffb31Sdp# Scan for ARC cases and insert <a> links to the relevent SAC database. 527daaffb31Sdp# This is slightly complicated because inside the SWAN, SAC cases are 528daaffb31Sdp# grouped by ARC: PSARC/2006/123. But on OpenSolaris.org, they are 529daaffb31Sdp# referenced as 2006/123 (without labelling the ARC). 5307c478bd9Sstevel@tonic-gate# 531daaffb31Sdpsac2url() 532daaffb31Sdp{ 533e0e0293aSjmcp if [[ -z "$Oflag" ]]; then 534*b0088928SVladimir Kotal $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' 535daaffb31Sdp else 536*b0088928SVladimir Kotal $SED -e 's|\([A-Z]\{1,2\}ARC\)[ /]\([0-9]\{4\}\)/\([0-9]\{3\}\)|<a href=\"'$SACURL'/\2/\3\">\1 \2/\3</a>|g' 537daaffb31Sdp fi 538daaffb31Sdp} 539daaffb31Sdp 5407c478bd9Sstevel@tonic-gate# 541daaffb31Sdp# strip_unchanged <infile> | output_cmd 5427c478bd9Sstevel@tonic-gate# 543daaffb31Sdp# Removes chunks of sdiff documents that have not changed. This makes it 544daaffb31Sdp# easier for a code reviewer to find the bits that have changed. 5457c478bd9Sstevel@tonic-gate# 546daaffb31Sdp# Deleted lines of text are replaced by a horizontal rule. Some 547daaffb31Sdp# identical lines are retained before and after the changed lines to 548daaffb31Sdp# provide some context. The number of these lines is controlled by the 549cdf0c1d5Smjnelson# variable C in the $AWK script below. 550daaffb31Sdp# 551daaffb31Sdp# The script detects changed lines as any line that has a "<span class=" 552daaffb31Sdp# string embedded (unchanged lines have no particular class and are not 553daaffb31Sdp# part of a <span>). Blank lines (without a sequence number) are also 554daaffb31Sdp# detected since they flag lines that have been inserted or deleted. 555daaffb31Sdp# 556daaffb31Sdpstrip_unchanged() 557daaffb31Sdp{ 558cdf0c1d5Smjnelson $AWK ' 559daaffb31Sdp BEGIN { C = c = 20 } 560cdf0c1d5Smjnelson NF == 0 || /<span class="/ { 561daaffb31Sdp if (c > C) { 562daaffb31Sdp c -= C 563daaffb31Sdp inx = 0 564daaffb31Sdp if (c > C) { 565cac38512Smjnelson print "\n</pre><hr></hr><pre>" 566daaffb31Sdp inx = c % C 567daaffb31Sdp c = C 568daaffb31Sdp } 569daaffb31Sdp 570daaffb31Sdp for (i = 0; i < c; i++) 571daaffb31Sdp print ln[(inx + i) % C] 572daaffb31Sdp } 573daaffb31Sdp c = 0; 574daaffb31Sdp print 575daaffb31Sdp next 576daaffb31Sdp } 577daaffb31Sdp { if (c >= C) { 578daaffb31Sdp ln[c % C] = $0 579daaffb31Sdp c++; 580daaffb31Sdp next; 581daaffb31Sdp } 582daaffb31Sdp c++; 583daaffb31Sdp print 584daaffb31Sdp } 585cac38512Smjnelson END { if (c > (C * 2)) print "\n</pre><hr></hr>" } 586daaffb31Sdp 587daaffb31Sdp ' $1 588daaffb31Sdp} 589daaffb31Sdp 590daaffb31Sdp# 591daaffb31Sdp# sdiff_to_html 592daaffb31Sdp# 593daaffb31Sdp# This function takes two files as arguments, obtains their diff, and 594daaffb31Sdp# processes the diff output to present the files as an HTML document with 595daaffb31Sdp# the files displayed side-by-side, differences shown in color. It also 596daaffb31Sdp# takes a delta comment, rendered as an HTML snippet, as the third 597daaffb31Sdp# argument. The function takes two files as arguments, then the name of 598daaffb31Sdp# file, the path, and the comment. The HTML will be delivered on stdout, 599daaffb31Sdp# e.g. 600daaffb31Sdp# 601daaffb31Sdp# $ sdiff_to_html old/usr/src/tools/scripts/webrev.sh \ 602daaffb31Sdp# new/usr/src/tools/scripts/webrev.sh \ 603daaffb31Sdp# webrev.sh usr/src/tools/scripts \ 604daaffb31Sdp# '<a href="http://monaco.sfbay.sun.com/detail.jsp?cr=1234567"> 605daaffb31Sdp# 1234567</a> my bugid' > <file>.html 606daaffb31Sdp# 607daaffb31Sdp# framed_sdiff() is then called which creates $2.frames.html 608daaffb31Sdp# in the webrev tree. 609daaffb31Sdp# 610daaffb31Sdp# FYI: This function is rather unusual in its use of awk. The initial 611daaffb31Sdp# diff run produces conventional diff output showing changed lines mixed 612daaffb31Sdp# with editing codes. The changed lines are ignored - we're interested in 613daaffb31Sdp# the editing codes, e.g. 6147c478bd9Sstevel@tonic-gate# 6157c478bd9Sstevel@tonic-gate# 8c8 6167c478bd9Sstevel@tonic-gate# 57a61 6177c478bd9Sstevel@tonic-gate# 63c66,76 6187c478bd9Sstevel@tonic-gate# 68,93d80 6197c478bd9Sstevel@tonic-gate# 106d90 6207c478bd9Sstevel@tonic-gate# 108,110d91 6217c478bd9Sstevel@tonic-gate# 622daaffb31Sdp# These editing codes are parsed by the awk script and used to generate 623daaffb31Sdp# another awk script that generates HTML, e.g the above lines would turn 624daaffb31Sdp# into something like this: 6257c478bd9Sstevel@tonic-gate# 6267c478bd9Sstevel@tonic-gate# BEGIN { printf "<pre>\n" } 6277c478bd9Sstevel@tonic-gate# function sp(n) {for (i=0;i<n;i++)printf "\n"} 628daaffb31Sdp# function wl(n) {printf "<font color=%s>%4d %s </font>\n", n, NR, $0} 6297c478bd9Sstevel@tonic-gate# NR==8 {wl("#7A7ADD");next} 6307c478bd9Sstevel@tonic-gate# NR==54 {wl("#7A7ADD");sp(3);next} 6317c478bd9Sstevel@tonic-gate# NR==56 {wl("#7A7ADD");next} 6327c478bd9Sstevel@tonic-gate# NR==57 {wl("black");printf "\n"; next} 6337c478bd9Sstevel@tonic-gate# : : 6347c478bd9Sstevel@tonic-gate# 635daaffb31Sdp# This script is then run on the original source file to generate the 636daaffb31Sdp# HTML that corresponds to the source file. 6377c478bd9Sstevel@tonic-gate# 638daaffb31Sdp# The two HTML files are then combined into a single piece of HTML that 639daaffb31Sdp# uses an HTML table construct to present the files side by side. You'll 640daaffb31Sdp# notice that the changes are color-coded: 6417c478bd9Sstevel@tonic-gate# 6427c478bd9Sstevel@tonic-gate# black - unchanged lines 6437c478bd9Sstevel@tonic-gate# blue - changed lines 6447c478bd9Sstevel@tonic-gate# bold blue - new lines 6457c478bd9Sstevel@tonic-gate# brown - deleted lines 6467c478bd9Sstevel@tonic-gate# 647daaffb31Sdp# Blank lines are inserted in each file to keep unchanged lines in sync 648daaffb31Sdp# (side-by-side). This format is familiar to users of sdiff(1) or 649daaffb31Sdp# Teamware's filemerge tool. 650daaffb31Sdp# 651daaffb31Sdpsdiff_to_html() 652daaffb31Sdp{ 6537c478bd9Sstevel@tonic-gate diff -b $1 $2 > /tmp/$$.diffs 6547c478bd9Sstevel@tonic-gate 655daaffb31Sdp TNAME=$3 656daaffb31Sdp TPATH=$4 657daaffb31Sdp COMMENT=$5 658daaffb31Sdp 6597c478bd9Sstevel@tonic-gate # 6607c478bd9Sstevel@tonic-gate # Now we have the diffs, generate the HTML for the old file. 6617c478bd9Sstevel@tonic-gate # 662cdf0c1d5Smjnelson $AWK ' 6637c478bd9Sstevel@tonic-gate BEGIN { 6647c478bd9Sstevel@tonic-gate printf "function sp(n) {for (i=0;i<n;i++)printf \"\\n\"}\n" 665daaffb31Sdp printf "function removed() " 666daaffb31Sdp printf "{printf \"<span class=\\\"removed\\\">%%4d %%s</span>\\n\", NR, $0}\n" 667daaffb31Sdp printf "function changed() " 668daaffb31Sdp printf "{printf \"<span class=\\\"changed\\\">%%4d %%s</span>\\n\", NR, $0}\n" 669daaffb31Sdp printf "function bl() {printf \"%%4d %%s\\n\", NR, $0}\n" 6707c478bd9Sstevel@tonic-gate} 6717c478bd9Sstevel@tonic-gate /^</ {next} 6727c478bd9Sstevel@tonic-gate /^>/ {next} 6737c478bd9Sstevel@tonic-gate /^---/ {next} 674daaffb31Sdp 6757c478bd9Sstevel@tonic-gate { 6767c478bd9Sstevel@tonic-gate split($1, a, /[cad]/) ; 6777c478bd9Sstevel@tonic-gate if (index($1, "a")) { 6787c478bd9Sstevel@tonic-gate if (a[1] == 0) { 6797c478bd9Sstevel@tonic-gate n = split(a[2], r, /,/); 6807c478bd9Sstevel@tonic-gate if (n == 1) 6817c478bd9Sstevel@tonic-gate printf "BEGIN\t\t{sp(1)}\n" 6827c478bd9Sstevel@tonic-gate else 6837c478bd9Sstevel@tonic-gate printf "BEGIN\t\t{sp(%d)}\n",\ 6847c478bd9Sstevel@tonic-gate (r[2] - r[1]) + 1 6857c478bd9Sstevel@tonic-gate next 6867c478bd9Sstevel@tonic-gate } 6877c478bd9Sstevel@tonic-gate 6887c478bd9Sstevel@tonic-gate printf "NR==%s\t\t{", a[1] 6897c478bd9Sstevel@tonic-gate n = split(a[2], r, /,/); 6907c478bd9Sstevel@tonic-gate s = r[1]; 6917c478bd9Sstevel@tonic-gate if (n == 1) 6927c478bd9Sstevel@tonic-gate printf "bl();printf \"\\n\"; next}\n" 6937c478bd9Sstevel@tonic-gate else { 6947c478bd9Sstevel@tonic-gate n = r[2] - r[1] 6957c478bd9Sstevel@tonic-gate printf "bl();sp(%d);next}\n",\ 6967c478bd9Sstevel@tonic-gate (r[2] - r[1]) + 1 6977c478bd9Sstevel@tonic-gate } 6987c478bd9Sstevel@tonic-gate next 6997c478bd9Sstevel@tonic-gate } 7007c478bd9Sstevel@tonic-gate if (index($1, "d")) { 7017c478bd9Sstevel@tonic-gate n = split(a[1], r, /,/); 7027c478bd9Sstevel@tonic-gate n1 = r[1] 7037c478bd9Sstevel@tonic-gate n2 = r[2] 7047c478bd9Sstevel@tonic-gate if (n == 1) 705daaffb31Sdp printf "NR==%s\t\t{removed(); next}\n" , n1 7067c478bd9Sstevel@tonic-gate else 707daaffb31Sdp printf "NR==%s,NR==%s\t{removed(); next}\n" , n1, n2 7087c478bd9Sstevel@tonic-gate next 7097c478bd9Sstevel@tonic-gate } 7107c478bd9Sstevel@tonic-gate if (index($1, "c")) { 7117c478bd9Sstevel@tonic-gate n = split(a[1], r, /,/); 7127c478bd9Sstevel@tonic-gate n1 = r[1] 7137c478bd9Sstevel@tonic-gate n2 = r[2] 7147c478bd9Sstevel@tonic-gate final = n2 7157c478bd9Sstevel@tonic-gate d1 = 0 7167c478bd9Sstevel@tonic-gate if (n == 1) 717daaffb31Sdp printf "NR==%s\t\t{changed();" , n1 7187c478bd9Sstevel@tonic-gate else { 7197c478bd9Sstevel@tonic-gate d1 = n2 - n1 720daaffb31Sdp printf "NR==%s,NR==%s\t{changed();" , n1, n2 7217c478bd9Sstevel@tonic-gate } 7227c478bd9Sstevel@tonic-gate m = split(a[2], r, /,/); 7237c478bd9Sstevel@tonic-gate n1 = r[1] 7247c478bd9Sstevel@tonic-gate n2 = r[2] 7257c478bd9Sstevel@tonic-gate if (m > 1) { 7267c478bd9Sstevel@tonic-gate d2 = n2 - n1 7277c478bd9Sstevel@tonic-gate if (d2 > d1) { 7287c478bd9Sstevel@tonic-gate if (n > 1) printf "if (NR==%d)", final 7297c478bd9Sstevel@tonic-gate printf "sp(%d);", d2 - d1 7307c478bd9Sstevel@tonic-gate } 7317c478bd9Sstevel@tonic-gate } 7327c478bd9Sstevel@tonic-gate printf "next}\n" ; 7337c478bd9Sstevel@tonic-gate 7347c478bd9Sstevel@tonic-gate next 7357c478bd9Sstevel@tonic-gate } 7367c478bd9Sstevel@tonic-gate } 7377c478bd9Sstevel@tonic-gate 738daaffb31Sdp END { printf "{printf \"%%4d %%s\\n\", NR, $0 }\n" } 739daaffb31Sdp ' /tmp/$$.diffs > /tmp/$$.file1 7407c478bd9Sstevel@tonic-gate 7417c478bd9Sstevel@tonic-gate # 7427c478bd9Sstevel@tonic-gate # Now generate the HTML for the new file 7437c478bd9Sstevel@tonic-gate # 744cdf0c1d5Smjnelson $AWK ' 7457c478bd9Sstevel@tonic-gate BEGIN { 7467c478bd9Sstevel@tonic-gate printf "function sp(n) {for (i=0;i<n;i++)printf \"\\n\"}\n" 747daaffb31Sdp printf "function new() " 748daaffb31Sdp printf "{printf \"<span class=\\\"new\\\">%%4d %%s</span>\\n\", NR, $0}\n" 749daaffb31Sdp printf "function changed() " 750daaffb31Sdp printf "{printf \"<span class=\\\"changed\\\">%%4d %%s</span>\\n\", NR, $0}\n" 751daaffb31Sdp printf "function bl() {printf \"%%4d %%s\\n\", NR, $0}\n" 7527c478bd9Sstevel@tonic-gate } 753daaffb31Sdp 7547c478bd9Sstevel@tonic-gate /^</ {next} 7557c478bd9Sstevel@tonic-gate /^>/ {next} 7567c478bd9Sstevel@tonic-gate /^---/ {next} 757daaffb31Sdp 7587c478bd9Sstevel@tonic-gate { 7597c478bd9Sstevel@tonic-gate split($1, a, /[cad]/) ; 7607c478bd9Sstevel@tonic-gate if (index($1, "d")) { 7617c478bd9Sstevel@tonic-gate if (a[2] == 0) { 7627c478bd9Sstevel@tonic-gate n = split(a[1], r, /,/); 7637c478bd9Sstevel@tonic-gate if (n == 1) 7647c478bd9Sstevel@tonic-gate printf "BEGIN\t\t{sp(1)}\n" 7657c478bd9Sstevel@tonic-gate else 7667c478bd9Sstevel@tonic-gate printf "BEGIN\t\t{sp(%d)}\n",\ 7677c478bd9Sstevel@tonic-gate (r[2] - r[1]) + 1 7687c478bd9Sstevel@tonic-gate next 7697c478bd9Sstevel@tonic-gate } 7707c478bd9Sstevel@tonic-gate 7717c478bd9Sstevel@tonic-gate printf "NR==%s\t\t{", a[2] 7727c478bd9Sstevel@tonic-gate n = split(a[1], r, /,/); 7737c478bd9Sstevel@tonic-gate s = r[1]; 7747c478bd9Sstevel@tonic-gate if (n == 1) 7757c478bd9Sstevel@tonic-gate printf "bl();printf \"\\n\"; next}\n" 7767c478bd9Sstevel@tonic-gate else { 7777c478bd9Sstevel@tonic-gate n = r[2] - r[1] 7787c478bd9Sstevel@tonic-gate printf "bl();sp(%d);next}\n",\ 7797c478bd9Sstevel@tonic-gate (r[2] - r[1]) + 1 7807c478bd9Sstevel@tonic-gate } 7817c478bd9Sstevel@tonic-gate next 7827c478bd9Sstevel@tonic-gate } 7837c478bd9Sstevel@tonic-gate if (index($1, "a")) { 7847c478bd9Sstevel@tonic-gate n = split(a[2], r, /,/); 7857c478bd9Sstevel@tonic-gate n1 = r[1] 7867c478bd9Sstevel@tonic-gate n2 = r[2] 7877c478bd9Sstevel@tonic-gate if (n == 1) 788daaffb31Sdp printf "NR==%s\t\t{new() ; next}\n" , n1 7897c478bd9Sstevel@tonic-gate else 790daaffb31Sdp printf "NR==%s,NR==%s\t{new() ; next}\n" , n1, n2 7917c478bd9Sstevel@tonic-gate next 7927c478bd9Sstevel@tonic-gate } 7937c478bd9Sstevel@tonic-gate if (index($1, "c")) { 7947c478bd9Sstevel@tonic-gate n = split(a[2], r, /,/); 7957c478bd9Sstevel@tonic-gate n1 = r[1] 7967c478bd9Sstevel@tonic-gate n2 = r[2] 7977c478bd9Sstevel@tonic-gate final = n2 7987c478bd9Sstevel@tonic-gate d2 = 0; 7997c478bd9Sstevel@tonic-gate if (n == 1) { 8007c478bd9Sstevel@tonic-gate final = n1 801daaffb31Sdp printf "NR==%s\t\t{changed();" , n1 8027c478bd9Sstevel@tonic-gate } else { 8037c478bd9Sstevel@tonic-gate d2 = n2 - n1 804daaffb31Sdp printf "NR==%s,NR==%s\t{changed();" , n1, n2 8057c478bd9Sstevel@tonic-gate } 8067c478bd9Sstevel@tonic-gate m = split(a[1], r, /,/); 8077c478bd9Sstevel@tonic-gate n1 = r[1] 8087c478bd9Sstevel@tonic-gate n2 = r[2] 8097c478bd9Sstevel@tonic-gate if (m > 1) { 8107c478bd9Sstevel@tonic-gate d1 = n2 - n1 8117c478bd9Sstevel@tonic-gate if (d1 > d2) { 8127c478bd9Sstevel@tonic-gate if (n > 1) printf "if (NR==%d)", final 8137c478bd9Sstevel@tonic-gate printf "sp(%d);", d1 - d2 8147c478bd9Sstevel@tonic-gate } 8157c478bd9Sstevel@tonic-gate } 8167c478bd9Sstevel@tonic-gate printf "next}\n" ; 8177c478bd9Sstevel@tonic-gate next 8187c478bd9Sstevel@tonic-gate } 8197c478bd9Sstevel@tonic-gate } 820daaffb31Sdp END { printf "{printf \"%%4d %%s\\n\", NR, $0 }\n" } 8217c478bd9Sstevel@tonic-gate ' /tmp/$$.diffs > /tmp/$$.file2 8227c478bd9Sstevel@tonic-gate 823daaffb31Sdp # 824cdf0c1d5Smjnelson # Post-process the HTML files by running them back through $AWK 825daaffb31Sdp # 826cdf0c1d5Smjnelson html_quote < $1 | $AWK -f /tmp/$$.file1 > /tmp/$$.file1.html 8277c478bd9Sstevel@tonic-gate 828cdf0c1d5Smjnelson html_quote < $2 | $AWK -f /tmp/$$.file2 > /tmp/$$.file2.html 8297c478bd9Sstevel@tonic-gate 830daaffb31Sdp # 831daaffb31Sdp # Now combine into a valid HTML file and side-by-side into a table 832daaffb31Sdp # 833daaffb31Sdp print "$HTML<head>$STDHEAD" 834cdf0c1d5Smjnelson print "<title>$WNAME Sdiff $TPATH/$TNAME</title>" 835daaffb31Sdp print "</head><body id=\"SUNWwebrev\">" 836daaffb31Sdp print "<a class=\"print\" href=\"javascript:print()\">Print this page</a>" 837daaffb31Sdp print "<pre>$COMMENT</pre>\n" 838daaffb31Sdp print "<table><tr valign=\"top\">" 839daaffb31Sdp print "<td><pre>" 8407c478bd9Sstevel@tonic-gate 8417c478bd9Sstevel@tonic-gate strip_unchanged /tmp/$$.file1.html 8427c478bd9Sstevel@tonic-gate 843daaffb31Sdp print "</pre></td><td><pre>" 8447c478bd9Sstevel@tonic-gate 8457c478bd9Sstevel@tonic-gate strip_unchanged /tmp/$$.file2.html 8467c478bd9Sstevel@tonic-gate 847daaffb31Sdp print "</pre></td>" 848daaffb31Sdp print "</tr></table>" 849daaffb31Sdp print "</body></html>" 8507c478bd9Sstevel@tonic-gate 851daaffb31Sdp framed_sdiff $TNAME $TPATH /tmp/$$.file1.html /tmp/$$.file2.html \ 852daaffb31Sdp "$COMMENT" 8537c478bd9Sstevel@tonic-gate} 8547c478bd9Sstevel@tonic-gate 8557c478bd9Sstevel@tonic-gate 856daaffb31Sdp# 857daaffb31Sdp# framed_sdiff <filename> <filepath> <lhsfile> <rhsfile> <comment> 858daaffb31Sdp# 859daaffb31Sdp# Expects lefthand and righthand side html files created by sdiff_to_html. 860daaffb31Sdp# We use insert_anchors() to augment those with HTML navigation anchors, 861daaffb31Sdp# and then emit the main frame. Content is placed into: 862daaffb31Sdp# 863daaffb31Sdp# $WDIR/DIR/$TNAME.lhs.html 864daaffb31Sdp# $WDIR/DIR/$TNAME.rhs.html 865daaffb31Sdp# $WDIR/DIR/$TNAME.frames.html 866daaffb31Sdp# 867daaffb31Sdp# NOTE: We rely on standard usage of $WDIR and $DIR. 868daaffb31Sdp# 8697c478bd9Sstevel@tonic-gatefunction framed_sdiff 8707c478bd9Sstevel@tonic-gate{ 8717c478bd9Sstevel@tonic-gate typeset TNAME=$1 872daaffb31Sdp typeset TPATH=$2 873daaffb31Sdp typeset lhsfile=$3 874daaffb31Sdp typeset rhsfile=$4 875daaffb31Sdp typeset comments=$5 8767c478bd9Sstevel@tonic-gate typeset RTOP 877daaffb31Sdp 8787c478bd9Sstevel@tonic-gate # Enable html files to access WDIR via a relative path. 879daaffb31Sdp RTOP=$(relative_dir $TPATH $WDIR) 880daaffb31Sdp 881daaffb31Sdp # Make the rhs/lhs files and output the frameset file. 882daaffb31Sdp print "$HTML<head>$STDHEAD" > $WDIR/$DIR/$TNAME.lhs.html 883daaffb31Sdp 884daaffb31Sdp cat >> $WDIR/$DIR/$TNAME.lhs.html <<-EOF 885cac38512Smjnelson <script type="text/javascript" src="$RTOP/ancnav.js"></script> 8867c478bd9Sstevel@tonic-gate </head> 887daaffb31Sdp <body id="SUNWwebrev" onkeypress="keypress(event);"> 888cac38512Smjnelson <a name="0"></a> 889cac38512Smjnelson <pre>$comments</pre><hr></hr> 890daaffb31Sdp EOF 891daaffb31Sdp 892daaffb31Sdp cp $WDIR/$DIR/$TNAME.lhs.html $WDIR/$DIR/$TNAME.rhs.html 893daaffb31Sdp 894daaffb31Sdp insert_anchors $lhsfile >> $WDIR/$DIR/$TNAME.lhs.html 895daaffb31Sdp insert_anchors $rhsfile >> $WDIR/$DIR/$TNAME.rhs.html 896daaffb31Sdp 897daaffb31Sdp close='</body></html>' 898daaffb31Sdp 899daaffb31Sdp print $close >> $WDIR/$DIR/$TNAME.lhs.html 900daaffb31Sdp print $close >> $WDIR/$DIR/$TNAME.rhs.html 901daaffb31Sdp 902daaffb31Sdp print "$FRAMEHTML<head>$STDHEAD" > $WDIR/$DIR/$TNAME.frames.html 903daaffb31Sdp print "<title>$WNAME Framed-Sdiff " \ 904daaffb31Sdp "$TPATH/$TNAME</title> </head>" >> $WDIR/$DIR/$TNAME.frames.html 905daaffb31Sdp cat >> $WDIR/$DIR/$TNAME.frames.html <<-EOF 906daaffb31Sdp <frameset rows="*,60"> 907daaffb31Sdp <frameset cols="50%,50%"> 908cac38512Smjnelson <frame src="$TNAME.lhs.html" scrolling="auto" name="lhs"></frame> 909cac38512Smjnelson <frame src="$TNAME.rhs.html" scrolling="auto" name="rhs"></frame> 910daaffb31Sdp </frameset> 911daaffb31Sdp <frame src="$RTOP/ancnav.html" scrolling="no" marginwidth="0" 912cac38512Smjnelson marginheight="0" name="nav"></frame> 913daaffb31Sdp <noframes> 914daaffb31Sdp <body id="SUNWwebrev"> 915daaffb31Sdp Alas 'frames' webrev requires that your browser supports frames 9167c478bd9Sstevel@tonic-gate and has the feature enabled. 917daaffb31Sdp </body> 918daaffb31Sdp </noframes> 919daaffb31Sdp </frameset> 9207c478bd9Sstevel@tonic-gate </html> 9217c478bd9Sstevel@tonic-gate EOF 9227c478bd9Sstevel@tonic-gate} 9237c478bd9Sstevel@tonic-gate 9247c478bd9Sstevel@tonic-gate 925daaffb31Sdp# 926daaffb31Sdp# fix_postscript 927daaffb31Sdp# 928daaffb31Sdp# Merge codereview output files to a single conforming postscript file, by: 929daaffb31Sdp# - removing all extraneous headers/trailers 930daaffb31Sdp# - making the page numbers right 931daaffb31Sdp# - removing pages devoid of contents which confuse some 932daaffb31Sdp# postscript readers. 933daaffb31Sdp# 934daaffb31Sdp# From Casper. 935daaffb31Sdp# 936daaffb31Sdpfunction fix_postscript 9377c478bd9Sstevel@tonic-gate{ 938daaffb31Sdp infile=$1 9397c478bd9Sstevel@tonic-gate 940daaffb31Sdp cat > /tmp/$$.crmerge.pl << \EOF 9417c478bd9Sstevel@tonic-gate 942daaffb31Sdp print scalar(<>); # %!PS-Adobe--- 943daaffb31Sdp print "%%Orientation: Landscape\n"; 9447c478bd9Sstevel@tonic-gate 945daaffb31Sdp $pno = 0; 946daaffb31Sdp $doprint = 1; 947daaffb31Sdp 948daaffb31Sdp $page = ""; 949daaffb31Sdp 950daaffb31Sdp while (<>) { 951daaffb31Sdp next if (/^%%Pages:\s*\d+/); 952daaffb31Sdp 953daaffb31Sdp if (/^%%Page:/) { 954daaffb31Sdp if ($pno == 0 || $page =~ /\)S/) { 955daaffb31Sdp # Header or single page containing text 956daaffb31Sdp print "%%Page: ? $pno\n" if ($pno > 0); 957daaffb31Sdp print $page; 958daaffb31Sdp $pno++; 959daaffb31Sdp } else { 960daaffb31Sdp # Empty page, skip it. 9617c478bd9Sstevel@tonic-gate } 962daaffb31Sdp $page = ""; 963daaffb31Sdp $doprint = 1; 9647c478bd9Sstevel@tonic-gate next; 9657c478bd9Sstevel@tonic-gate } 9667c478bd9Sstevel@tonic-gate 967daaffb31Sdp # Skip from %%Trailer of one document to Endprolog 968daaffb31Sdp # %%Page of the next 969daaffb31Sdp $doprint = 0 if (/^%%Trailer/); 970daaffb31Sdp $page .= $_ if ($doprint); 9717c478bd9Sstevel@tonic-gate } 9727c478bd9Sstevel@tonic-gate 973daaffb31Sdp if ($page =~ /\)S/) { 974daaffb31Sdp print "%%Page: ? $pno\n"; 975daaffb31Sdp print $page; 976daaffb31Sdp } else { 977daaffb31Sdp $pno--; 978daaffb31Sdp } 979daaffb31Sdp print "%%Trailer\n%%Pages: $pno\n"; 980daaffb31SdpEOF 981daaffb31Sdp 98214983201Sdp $PERL /tmp/$$.crmerge.pl < $infile 983daaffb31Sdp} 984daaffb31Sdp 985daaffb31Sdp 986daaffb31Sdp# 987daaffb31Sdp# input_cmd | insert_anchors | output_cmd 988daaffb31Sdp# 9897c478bd9Sstevel@tonic-gate# Flag blocks of difference with sequentially numbered invisible 990daaffb31Sdp# anchors. These are used to drive the frames version of the 9917c478bd9Sstevel@tonic-gate# sdiffs output. 9927c478bd9Sstevel@tonic-gate# 9937c478bd9Sstevel@tonic-gate# NOTE: Anchor zero flags the top of the file irrespective of changes, 9947c478bd9Sstevel@tonic-gate# an additional anchor is also appended to flag the bottom. 9957c478bd9Sstevel@tonic-gate# 996daaffb31Sdp# The script detects changed lines as any line that has a "<span 997daaffb31Sdp# class=" string embedded (unchanged lines have no class set and are 998daaffb31Sdp# not part of a <span>. Blank lines (without a sequence number) 9997c478bd9Sstevel@tonic-gate# are also detected since they flag lines that have been inserted or 10007c478bd9Sstevel@tonic-gate# deleted. 10017c478bd9Sstevel@tonic-gate# 1002daaffb31Sdpfunction insert_anchors 1003daaffb31Sdp{ 1004cdf0c1d5Smjnelson $AWK ' 10057c478bd9Sstevel@tonic-gate function ia() { 1006daaffb31Sdp printf "<a name=\"%d\" id=\"anc%d\"></a>", anc, anc++; 10077c478bd9Sstevel@tonic-gate } 1008daaffb31Sdp 10097c478bd9Sstevel@tonic-gate BEGIN { 1010daaffb31Sdp anc=1; 10117c478bd9Sstevel@tonic-gate inblock=1; 1012daaffb31Sdp printf "<pre>\n"; 10137c478bd9Sstevel@tonic-gate } 1014daaffb31Sdp NF == 0 || /^<span class=/ { 10157c478bd9Sstevel@tonic-gate if (inblock == 0) { 10167c478bd9Sstevel@tonic-gate ia(); 10177c478bd9Sstevel@tonic-gate inblock=1; 10187c478bd9Sstevel@tonic-gate } 10197c478bd9Sstevel@tonic-gate print; 10207c478bd9Sstevel@tonic-gate next; 10217c478bd9Sstevel@tonic-gate } 10227c478bd9Sstevel@tonic-gate { 10237c478bd9Sstevel@tonic-gate inblock=0; 10247c478bd9Sstevel@tonic-gate print; 10257c478bd9Sstevel@tonic-gate } 10267c478bd9Sstevel@tonic-gate END { 10277c478bd9Sstevel@tonic-gate ia(); 1028daaffb31Sdp 1029daaffb31Sdp printf "<b style=\"font-size: large; color: red\">"; 1030daaffb31Sdp printf "--- EOF ---</b>" 10317c478bd9Sstevel@tonic-gate for(i=0;i<8;i++) printf "\n\n\n\n\n\n\n\n\n\n"; 1032daaffb31Sdp printf "</pre>" 1033daaffb31Sdp printf "<form name=\"eof\">"; 1034cac38512Smjnelson printf "<input name=\"value\" value=\"%d\" " \ 1035cac38512Smjnelson "type=\"hidden\"></input>", anc - 1; 1036daaffb31Sdp printf "</form>"; 10377c478bd9Sstevel@tonic-gate } 10387c478bd9Sstevel@tonic-gate ' $1 10397c478bd9Sstevel@tonic-gate} 10407c478bd9Sstevel@tonic-gate 10417c478bd9Sstevel@tonic-gate 1042daaffb31Sdp# 1043daaffb31Sdp# relative_dir 1044daaffb31Sdp# 1045daaffb31Sdp# Print a relative return path from $1 to $2. For example if 1046daaffb31Sdp# $1=/tmp/myreview/raw_files/usr/src/tools/scripts and $2=/tmp/myreview, 1047daaffb31Sdp# this function would print "../../../../". 1048daaffb31Sdp# 1049daaffb31Sdp# In the event that $1 is not in $2 a warning is printed to stderr, 1050daaffb31Sdp# and $2 is returned-- the result of this is that the resulting webrev 1051daaffb31Sdp# is not relocatable. 1052daaffb31Sdp# 1053daaffb31Sdpfunction relative_dir 10547c478bd9Sstevel@tonic-gate{ 1055daaffb31Sdp typeset cur="${1##$2?(/)}" 1056daaffb31Sdp typeset ret="" 1057daaffb31Sdp if [[ $2 == $cur ]]; then # Should never happen. 1058daaffb31Sdp # Should never happen. 105914983201Sdp print -u2 "\nWARNING: relative_dir: \"$1\" not relative " 1060daaffb31Sdp print -u2 "to \"$2\". Check input paths. Framed webrev " 1061daaffb31Sdp print -u2 "will not be relocatable!" 1062daaffb31Sdp print $2 1063daaffb31Sdp return 1064daaffb31Sdp fi 1065daaffb31Sdp 1066daaffb31Sdp while [[ -n ${cur} ]]; 10677c478bd9Sstevel@tonic-gate do 10687c478bd9Sstevel@tonic-gate cur=${cur%%*(/)*([!/])} 1069daaffb31Sdp if [[ -z $ret ]]; then 1070daaffb31Sdp ret=".." 1071daaffb31Sdp else 10727c478bd9Sstevel@tonic-gate ret="../$ret" 1073daaffb31Sdp fi 10747c478bd9Sstevel@tonic-gate done 10757c478bd9Sstevel@tonic-gate print $ret 10767c478bd9Sstevel@tonic-gate} 10777c478bd9Sstevel@tonic-gate 10787c478bd9Sstevel@tonic-gate 1079daaffb31Sdp# 1080daaffb31Sdp# frame_nav_js 1081daaffb31Sdp# 1082daaffb31Sdp# Emit javascript for frame navigation 1083daaffb31Sdp# 1084daaffb31Sdpfunction frame_nav_js 10857c478bd9Sstevel@tonic-gate{ 10867c478bd9Sstevel@tonic-gatecat << \EOF 10877c478bd9Sstevel@tonic-gatevar myInt; 10887c478bd9Sstevel@tonic-gatevar scrolling=0; 1089daaffb31Sdpvar sfactor = 3; 10907c478bd9Sstevel@tonic-gatevar scount=10; 10917c478bd9Sstevel@tonic-gate 10927c478bd9Sstevel@tonic-gatefunction scrollByPix() { 10937c478bd9Sstevel@tonic-gate if (scount<=0) { 10947c478bd9Sstevel@tonic-gate sfactor*=1.2; 10957c478bd9Sstevel@tonic-gate scount=10; 10967c478bd9Sstevel@tonic-gate } 10977c478bd9Sstevel@tonic-gate parent.lhs.scrollBy(0,sfactor); 10987c478bd9Sstevel@tonic-gate parent.rhs.scrollBy(0,sfactor); 10997c478bd9Sstevel@tonic-gate scount--; 11007c478bd9Sstevel@tonic-gate} 11017c478bd9Sstevel@tonic-gate 1102daaffb31Sdpfunction scrollToAnc(num) { 1103daaffb31Sdp 1104daaffb31Sdp // Update the value of the anchor in the form which we use as 1105daaffb31Sdp // storage for this value. setAncValue() will take care of 1106daaffb31Sdp // correcting for overflow and underflow of the value and return 1107daaffb31Sdp // us the new value. 1108daaffb31Sdp num = setAncValue(num); 1109daaffb31Sdp 1110daaffb31Sdp // Set location and scroll back a little to expose previous 1111daaffb31Sdp // lines. 1112daaffb31Sdp // 1113daaffb31Sdp // Note that this could be improved: it is possible although 1114daaffb31Sdp // complex to compute the x and y position of an anchor, and to 1115daaffb31Sdp // scroll to that location directly. 1116daaffb31Sdp // 11177c478bd9Sstevel@tonic-gate parent.lhs.location.replace(parent.lhs.location.pathname + "#" + num); 11187c478bd9Sstevel@tonic-gate parent.rhs.location.replace(parent.rhs.location.pathname + "#" + num); 1119daaffb31Sdp 11207c478bd9Sstevel@tonic-gate parent.lhs.scrollBy(0,-30); 11217c478bd9Sstevel@tonic-gate parent.rhs.scrollBy(0,-30); 11227c478bd9Sstevel@tonic-gate} 11237c478bd9Sstevel@tonic-gate 1124daaffb31Sdpfunction getAncValue() 1125daaffb31Sdp{ 1126daaffb31Sdp return (parseInt(parent.nav.document.diff.real.value)); 1127daaffb31Sdp} 1128daaffb31Sdp 1129daaffb31Sdpfunction setAncValue(val) 1130daaffb31Sdp{ 1131daaffb31Sdp if (val <= 0) { 1132daaffb31Sdp val = 0; 1133daaffb31Sdp parent.nav.document.diff.real.value = val; 1134daaffb31Sdp parent.nav.document.diff.display.value = "BOF"; 1135daaffb31Sdp return (val); 1136daaffb31Sdp } 1137daaffb31Sdp 1138daaffb31Sdp // 1139daaffb31Sdp // The way we compute the max anchor value is to stash it 1140daaffb31Sdp // inline in the left and right hand side pages-- it's the same 1141daaffb31Sdp // on each side, so we pluck from the left. 1142daaffb31Sdp // 1143daaffb31Sdp maxval = parent.lhs.document.eof.value.value; 1144daaffb31Sdp if (val < maxval) { 1145daaffb31Sdp parent.nav.document.diff.real.value = val; 1146daaffb31Sdp parent.nav.document.diff.display.value = val.toString(); 1147daaffb31Sdp return (val); 1148daaffb31Sdp } 1149daaffb31Sdp 1150daaffb31Sdp // this must be: val >= maxval 1151daaffb31Sdp val = maxval; 1152daaffb31Sdp parent.nav.document.diff.real.value = val; 1153daaffb31Sdp parent.nav.document.diff.display.value = "EOF"; 1154daaffb31Sdp return (val); 1155daaffb31Sdp} 1156daaffb31Sdp 11577c478bd9Sstevel@tonic-gatefunction stopScroll() { 11587c478bd9Sstevel@tonic-gate if (scrolling==1) { 11597c478bd9Sstevel@tonic-gate clearInterval(myInt); 11607c478bd9Sstevel@tonic-gate scrolling=0; 11617c478bd9Sstevel@tonic-gate } 11627c478bd9Sstevel@tonic-gate} 11637c478bd9Sstevel@tonic-gate 11647c478bd9Sstevel@tonic-gatefunction startScroll() { 11657c478bd9Sstevel@tonic-gate stopScroll(); 11667c478bd9Sstevel@tonic-gate scrolling=1; 11677c478bd9Sstevel@tonic-gate myInt=setInterval("scrollByPix()",10); 11687c478bd9Sstevel@tonic-gate} 11697c478bd9Sstevel@tonic-gate 11707c478bd9Sstevel@tonic-gatefunction handlePress(b) { 1171daaffb31Sdp 11727c478bd9Sstevel@tonic-gate switch (b) { 11737c478bd9Sstevel@tonic-gate case 1 : 1174daaffb31Sdp scrollToAnc(-1); 11757c478bd9Sstevel@tonic-gate break; 11767c478bd9Sstevel@tonic-gate case 2 : 1177daaffb31Sdp scrollToAnc(getAncValue() - 1); 11787c478bd9Sstevel@tonic-gate break; 11797c478bd9Sstevel@tonic-gate case 3 : 11807c478bd9Sstevel@tonic-gate sfactor=-3; 11817c478bd9Sstevel@tonic-gate startScroll(); 11827c478bd9Sstevel@tonic-gate break; 11837c478bd9Sstevel@tonic-gate case 4 : 11847c478bd9Sstevel@tonic-gate sfactor=3; 11857c478bd9Sstevel@tonic-gate startScroll(); 11867c478bd9Sstevel@tonic-gate break; 11877c478bd9Sstevel@tonic-gate case 5 : 1188daaffb31Sdp scrollToAnc(getAncValue() + 1); 11897c478bd9Sstevel@tonic-gate break; 11907c478bd9Sstevel@tonic-gate case 6 : 1191daaffb31Sdp scrollToAnc(999999); 11927c478bd9Sstevel@tonic-gate break; 11937c478bd9Sstevel@tonic-gate } 11947c478bd9Sstevel@tonic-gate} 11957c478bd9Sstevel@tonic-gate 11967c478bd9Sstevel@tonic-gatefunction handleRelease(b) { 11977c478bd9Sstevel@tonic-gate stopScroll(); 11987c478bd9Sstevel@tonic-gate} 11997c478bd9Sstevel@tonic-gate 1200daaffb31Sdpfunction keypress(ev) { 1201daaffb31Sdp var keynum; 1202daaffb31Sdp var keychar; 1203daaffb31Sdp 1204daaffb31Sdp if (window.event) { // IE 1205daaffb31Sdp keynum = ev.keyCode; 1206daaffb31Sdp } else if (ev.which) { // non-IE 1207daaffb31Sdp keynum = ev.which; 1208daaffb31Sdp } 1209daaffb31Sdp 1210daaffb31Sdp keychar = String.fromCharCode(keynum); 1211daaffb31Sdp 1212daaffb31Sdp if (keychar == "k") { 1213daaffb31Sdp handlePress(2); 1214daaffb31Sdp return (0); 1215daaffb31Sdp } else if (keychar == "j" || keychar == " ") { 1216daaffb31Sdp handlePress(5); 1217daaffb31Sdp return (0); 1218daaffb31Sdp } 1219daaffb31Sdp return (1); 1220daaffb31Sdp} 1221daaffb31Sdp 12227c478bd9Sstevel@tonic-gatefunction ValidateDiffNum(){ 1223daaffb31Sdp val = parent.nav.document.diff.display.value; 1224daaffb31Sdp if (val == "EOF") { 1225daaffb31Sdp scrollToAnc(999999); 1226daaffb31Sdp return; 1227daaffb31Sdp } 1228daaffb31Sdp 1229daaffb31Sdp if (val == "BOF") { 1230daaffb31Sdp scrollToAnc(0); 1231daaffb31Sdp return; 1232daaffb31Sdp } 1233daaffb31Sdp 1234daaffb31Sdp i=parseInt(val); 12357c478bd9Sstevel@tonic-gate if (isNaN(i)) { 1236daaffb31Sdp parent.nav.document.diff.display.value = getAncValue(); 12377c478bd9Sstevel@tonic-gate } else { 1238daaffb31Sdp scrollToAnc(i); 12397c478bd9Sstevel@tonic-gate } 12407c478bd9Sstevel@tonic-gate return false; 12417c478bd9Sstevel@tonic-gate} 12427c478bd9Sstevel@tonic-gate 1243daaffb31SdpEOF 1244daaffb31Sdp} 1245daaffb31Sdp 1246daaffb31Sdp# 1247daaffb31Sdp# frame_navigation 1248daaffb31Sdp# 1249daaffb31Sdp# Output anchor navigation file for framed sdiffs. 1250daaffb31Sdp# 1251daaffb31Sdpfunction frame_navigation 1252daaffb31Sdp{ 1253daaffb31Sdp print "$HTML<head>$STDHEAD" 1254daaffb31Sdp 1255daaffb31Sdp cat << \EOF 1256daaffb31Sdp<title>Anchor Navigation</title> 1257daaffb31Sdp<meta http-equiv="Content-Script-Type" content="text/javascript"> 1258daaffb31Sdp<meta http-equiv="Content-Type" content="text/html"> 1259daaffb31Sdp 1260daaffb31Sdp<style type="text/css"> 1261daaffb31Sdp div.button td { padding-left: 5px; padding-right: 5px; 1262daaffb31Sdp background-color: #eee; text-align: center; 1263daaffb31Sdp border: 1px #444 outset; cursor: pointer; } 1264daaffb31Sdp div.button a { font-weight: bold; color: black } 1265daaffb31Sdp div.button td:hover { background: #ffcc99; } 1266daaffb31Sdp</style> 1267daaffb31SdpEOF 1268daaffb31Sdp 1269cac38512Smjnelson print "<script type=\"text/javascript\" src=\"ancnav.js\"></script>" 1270daaffb31Sdp 1271daaffb31Sdp cat << \EOF 12727c478bd9Sstevel@tonic-gate</head> 1273daaffb31Sdp<body id="SUNWwebrev" bgcolor="#eeeeee" onload="document.diff.real.focus();" 1274daaffb31Sdp onkeypress="keypress(event);"> 12757c478bd9Sstevel@tonic-gate <noscript lang="javascript"> 12767c478bd9Sstevel@tonic-gate <center> 1277cac38512Smjnelson <p><big>Framed Navigation controls require Javascript</big><br></br> 12787c478bd9Sstevel@tonic-gate Either this browser is incompatable or javascript is not enabled</p> 12797c478bd9Sstevel@tonic-gate </center> 12807c478bd9Sstevel@tonic-gate </noscript> 12817c478bd9Sstevel@tonic-gate <table width="100%" border="0" align="center"> 1282daaffb31Sdp <tr> 1283daaffb31Sdp <td valign="middle" width="25%">Diff navigation: 1284daaffb31Sdp Use 'j' and 'k' for next and previous diffs; or use buttons 1285daaffb31Sdp at right</td> 1286daaffb31Sdp <td align="center" valign="top" width="50%"> 12877c478bd9Sstevel@tonic-gate <div class="button"> 1288daaffb31Sdp <table border="0" align="center"> 1289daaffb31Sdp <tr> 1290daaffb31Sdp <td> 12917c478bd9Sstevel@tonic-gate <a onMouseDown="handlePress(1);return true;" 12927c478bd9Sstevel@tonic-gate onMouseUp="handleRelease(1);return true;" 12937c478bd9Sstevel@tonic-gate onMouseOut="handleRelease(1);return true;" 12947c478bd9Sstevel@tonic-gate onClick="return false;" 12957c478bd9Sstevel@tonic-gate title="Go to Beginning Of file">BOF</a></td> 1296daaffb31Sdp <td> 12977c478bd9Sstevel@tonic-gate <a onMouseDown="handlePress(3);return true;" 12987c478bd9Sstevel@tonic-gate onMouseUp="handleRelease(3);return true;" 12997c478bd9Sstevel@tonic-gate onMouseOut="handleRelease(3);return true;" 13007c478bd9Sstevel@tonic-gate title="Scroll Up: Press and Hold to accelerate" 1301daaffb31Sdp onClick="return false;">Scroll Up</a></td> 1302daaffb31Sdp <td> 13037c478bd9Sstevel@tonic-gate <a onMouseDown="handlePress(2);return true;" 13047c478bd9Sstevel@tonic-gate onMouseUp="handleRelease(2);return true;" 13057c478bd9Sstevel@tonic-gate onMouseOut="handleRelease(2);return true;" 13067c478bd9Sstevel@tonic-gate title="Go to previous Diff" 13077c478bd9Sstevel@tonic-gate onClick="return false;">Prev Diff</a> 13087c478bd9Sstevel@tonic-gate </td></tr> 1309daaffb31Sdp 13107c478bd9Sstevel@tonic-gate <tr> 1311daaffb31Sdp <td> 13127c478bd9Sstevel@tonic-gate <a onMouseDown="handlePress(6);return true;" 13137c478bd9Sstevel@tonic-gate onMouseUp="handleRelease(6);return true;" 13147c478bd9Sstevel@tonic-gate onMouseOut="handleRelease(6);return true;" 13157c478bd9Sstevel@tonic-gate onClick="return false;" 13167c478bd9Sstevel@tonic-gate title="Go to End Of File">EOF</a></td> 1317daaffb31Sdp <td> 13187c478bd9Sstevel@tonic-gate <a onMouseDown="handlePress(4);return true;" 13197c478bd9Sstevel@tonic-gate onMouseUp="handleRelease(4);return true;" 13207c478bd9Sstevel@tonic-gate onMouseOut="handleRelease(4);return true;" 13217c478bd9Sstevel@tonic-gate title="Scroll Down: Press and Hold to accelerate" 1322daaffb31Sdp onClick="return false;">Scroll Down</a></td> 1323daaffb31Sdp <td> 13247c478bd9Sstevel@tonic-gate <a onMouseDown="handlePress(5);return true;" 13257c478bd9Sstevel@tonic-gate onMouseUp="handleRelease(5);return true;" 13267c478bd9Sstevel@tonic-gate onMouseOut="handleRelease(5);return true;" 13277c478bd9Sstevel@tonic-gate title="Go to next Diff" 13287c478bd9Sstevel@tonic-gate onClick="return false;">Next Diff</a></td> 1329daaffb31Sdp </tr> 1330daaffb31Sdp </table> 1331daaffb31Sdp </div> 1332daaffb31Sdp </td> 13337c478bd9Sstevel@tonic-gate <th valign="middle" width="25%"> 1334daaffb31Sdp <form action="" name="diff" onsubmit="return ValidateDiffNum();"> 1335cac38512Smjnelson <input name="display" value="BOF" size="8" type="text"></input> 1336cac38512Smjnelson <input name="real" value="0" size="8" type="hidden"></input> 13377c478bd9Sstevel@tonic-gate </form> 13387c478bd9Sstevel@tonic-gate </th> 1339daaffb31Sdp </tr> 13407c478bd9Sstevel@tonic-gate </table> 13417c478bd9Sstevel@tonic-gate </body> 13427c478bd9Sstevel@tonic-gate</html> 13437c478bd9Sstevel@tonic-gateEOF 13447c478bd9Sstevel@tonic-gate} 13457c478bd9Sstevel@tonic-gate 13467c478bd9Sstevel@tonic-gate 1347daaffb31Sdp 1348daaffb31Sdp# 1349daaffb31Sdp# diff_to_html <filename> <filepath> { U | C } <comment> 1350daaffb31Sdp# 1351daaffb31Sdp# Processes the output of diff to produce an HTML file representing either 1352daaffb31Sdp# context or unified diffs. 1353daaffb31Sdp# 13547c478bd9Sstevel@tonic-gatediff_to_html() 13557c478bd9Sstevel@tonic-gate{ 13567c478bd9Sstevel@tonic-gate TNAME=$1 1357daaffb31Sdp TPATH=$2 1358daaffb31Sdp DIFFTYPE=$3 1359daaffb31Sdp COMMENT=$4 1360daaffb31Sdp 1361daaffb31Sdp print "$HTML<head>$STDHEAD" 1362daaffb31Sdp print "<title>$WNAME ${DIFFTYPE}diff $TPATH</title>" 1363daaffb31Sdp 1364daaffb31Sdp if [[ $DIFFTYPE == "U" ]]; then 1365daaffb31Sdp print "$UDIFFCSS" 1366daaffb31Sdp fi 1367daaffb31Sdp 1368daaffb31Sdp cat <<-EOF 1369daaffb31Sdp </head> 1370daaffb31Sdp <body id="SUNWwebrev"> 1371daaffb31Sdp <a class="print" href="javascript:print()">Print this page</a> 1372daaffb31Sdp <pre>$COMMENT</pre> 1373daaffb31Sdp <pre> 1374daaffb31Sdp EOF 13757c478bd9Sstevel@tonic-gate 1376cdf0c1d5Smjnelson html_quote | $AWK ' 1377daaffb31Sdp /^--- new/ { next } 1378daaffb31Sdp /^\+\+\+ new/ { next } 1379daaffb31Sdp /^--- old/ { next } 1380daaffb31Sdp /^\*\*\* old/ { next } 1381daaffb31Sdp /^\*\*\*\*/ { next } 13827c478bd9Sstevel@tonic-gate /^-------/ { printf "<center><h1>%s</h1></center>\n", $0; next } 1383cac38512Smjnelson /^\@\@.*\@\@$/ { printf "</pre><hr></hr><pre>\n"; 1384daaffb31Sdp printf "<span class=\"newmarker\">%s</span>\n", $0; 1385daaffb31Sdp next} 1386daaffb31Sdp 1387cac38512Smjnelson /^\*\*\*/ { printf "<hr></hr><span class=\"oldmarker\">%s</span>\n", $0; 1388daaffb31Sdp next} 1389daaffb31Sdp /^---/ { printf "<span class=\"newmarker\">%s</span>\n", $0; 1390daaffb31Sdp next} 1391daaffb31Sdp /^\+/ {printf "<span class=\"new\">%s</span>\n", $0; next} 1392daaffb31Sdp /^!/ {printf "<span class=\"changed\">%s</span>\n", $0; next} 1393daaffb31Sdp /^-/ {printf "<span class=\"removed\">%s</span>\n", $0; next} 1394daaffb31Sdp {printf "%s\n", $0; next} 13957c478bd9Sstevel@tonic-gate ' 1396daaffb31Sdp 1397daaffb31Sdp print "</pre></body></html>\n" 13987c478bd9Sstevel@tonic-gate} 13997c478bd9Sstevel@tonic-gate 14007c478bd9Sstevel@tonic-gate 1401daaffb31Sdp# 1402daaffb31Sdp# source_to_html { new | old } <filename> 1403daaffb31Sdp# 1404daaffb31Sdp# Process a plain vanilla source file to transform it into an HTML file. 1405daaffb31Sdp# 14067c478bd9Sstevel@tonic-gatesource_to_html() 14077c478bd9Sstevel@tonic-gate{ 14087c478bd9Sstevel@tonic-gate WHICH=$1 14097c478bd9Sstevel@tonic-gate TNAME=$2 14107c478bd9Sstevel@tonic-gate 1411daaffb31Sdp print "$HTML<head>$STDHEAD" 1412cdf0c1d5Smjnelson print "<title>$WNAME $WHICH $TNAME</title>" 1413daaffb31Sdp print "<body id=\"SUNWwebrev\">" 1414daaffb31Sdp print "<pre>" 1415cdf0c1d5Smjnelson html_quote | $AWK '{line += 1 ; printf "%4d %s\n", line, $0 }' 1416daaffb31Sdp print "</pre></body></html>" 14177c478bd9Sstevel@tonic-gate} 14187c478bd9Sstevel@tonic-gate 1419daaffb31Sdp# 1420cdf0c1d5Smjnelson# comments_from_teamware {text|html} parent-file child-file 1421daaffb31Sdp# 1422daaffb31Sdp# Find the first delta in the child that's not in the parent. Get the 1423daaffb31Sdp# newest delta from the parent, get all deltas from the child starting 1424daaffb31Sdp# with that delta, and then get all info starting with the second oldest 1425daaffb31Sdp# delta in that list (the first delta unique to the child). 14267c478bd9Sstevel@tonic-gate# 14277c478bd9Sstevel@tonic-gate# This code adapted from Bill Shannon's "spc" script 1428daaffb31Sdp# 1429daaffb31Sdpcomments_from_teamware() 14307c478bd9Sstevel@tonic-gate{ 1431daaffb31Sdp fmt=$1 1432daaffb31Sdp pfile=$PWS/$2 1433daaffb31Sdp cfile=$CWS/$3 14347c478bd9Sstevel@tonic-gate 1435cdf0c1d5Smjnelson if [[ ! -f $PWS/${2%/*}/SCCS/s.${2##*/} && -n $RWS ]]; then 1436cdf0c1d5Smjnelson pfile=$RWS/$2 1437cdf0c1d5Smjnelson fi 1438cdf0c1d5Smjnelson 1439daaffb31Sdp if [[ -f $pfile ]]; then 1440cdf0c1d5Smjnelson psid=$($SCCS prs -d:I: $pfile 2>/dev/null) 14417c478bd9Sstevel@tonic-gate else 14427c478bd9Sstevel@tonic-gate psid=1.1 14437c478bd9Sstevel@tonic-gate fi 14447c478bd9Sstevel@tonic-gate 1445cdf0c1d5Smjnelson set -A sids $($SCCS prs -l -r$psid -d:I: $cfile 2>/dev/null) 14467c478bd9Sstevel@tonic-gate N=${#sids[@]} 14477c478bd9Sstevel@tonic-gate 1448daaffb31Sdp nawkprg=' 1449daaffb31Sdp /^COMMENTS:/ {p=1; continue} 1450daaffb31Sdp /^D [0-9]+\.[0-9]+/ {printf "--- %s ---\n", $2; p=0; } 1451daaffb31Sdp NF == 0u { continue } 1452daaffb31Sdp {if (p==0) continue; print $0 }' 1453daaffb31Sdp 14547c478bd9Sstevel@tonic-gate if [[ $N -ge 2 ]]; then 14557c478bd9Sstevel@tonic-gate sid1=${sids[$((N-2))]} # Gets 2nd to last sid 14567c478bd9Sstevel@tonic-gate 1457daaffb31Sdp if [[ $fmt == "text" ]]; then 1458cdf0c1d5Smjnelson $SCCS prs -l -r$sid1 $cfile 2>/dev/null | \ 1459cdf0c1d5Smjnelson $AWK "$nawkprg" 1460daaffb31Sdp return 1461daaffb31Sdp fi 1462daaffb31Sdp 1463cdf0c1d5Smjnelson $SCCS prs -l -r$sid1 $cfile 2>/dev/null | \ 1464cdf0c1d5Smjnelson html_quote | bug2url | sac2url | $AWK "$nawkprg" 14657c478bd9Sstevel@tonic-gate fi 14667c478bd9Sstevel@tonic-gate} 14677c478bd9Sstevel@tonic-gate 1468daaffb31Sdp# 1469cdf0c1d5Smjnelson# comments_from_wx {text|html} filepath 1470daaffb31Sdp# 1471cdf0c1d5Smjnelson# Given the pathname of a file, find its location in a "wx" active 1472cdf0c1d5Smjnelson# file list and print the following comment. Output is either text or 1473cdf0c1d5Smjnelson# HTML; if the latter, embedded bugids (sequence of 5 or more digits) 1474cdf0c1d5Smjnelson# are turned into URLs. 1475cdf0c1d5Smjnelson# 1476cdf0c1d5Smjnelson# This is also used with Mercurial and the file list provided by hg-active. 1477daaffb31Sdp# 1478daaffb31Sdpcomments_from_wx() 14797c478bd9Sstevel@tonic-gate{ 1480daaffb31Sdp typeset fmt=$1 1481daaffb31Sdp typeset p=$2 14827c478bd9Sstevel@tonic-gate 1483cdf0c1d5Smjnelson comm=`$AWK ' 1484daaffb31Sdp $1 == "'$p'" { 14857c478bd9Sstevel@tonic-gate do getline ; while (NF > 0) 14867c478bd9Sstevel@tonic-gate getline 14877c478bd9Sstevel@tonic-gate while (NF > 0) { print ; getline } 14887c478bd9Sstevel@tonic-gate exit 1489daaffb31Sdp }' < $wxfile` 1490daaffb31Sdp 1491cdf0c1d5Smjnelson if [[ -z $comm ]]; then 1492cdf0c1d5Smjnelson comm="*** NO COMMENTS ***" 1493cdf0c1d5Smjnelson fi 1494cdf0c1d5Smjnelson 1495daaffb31Sdp if [[ $fmt == "text" ]]; then 1496cdf0c1d5Smjnelson print -- "$comm" 1497daaffb31Sdp return 1498daaffb31Sdp fi 1499daaffb31Sdp 1500cdf0c1d5Smjnelson print -- "$comm" | html_quote | bug2url | sac2url 1501cdf0c1d5Smjnelson 15027c478bd9Sstevel@tonic-gate} 15037c478bd9Sstevel@tonic-gate 15047c478bd9Sstevel@tonic-gate# 1505daaffb31Sdp# getcomments {text|html} filepath parentpath 1506daaffb31Sdp# 1507daaffb31Sdp# Fetch the comments depending on what SCM mode we're in. 1508daaffb31Sdp# 1509daaffb31Sdpgetcomments() 1510daaffb31Sdp{ 1511daaffb31Sdp typeset fmt=$1 1512daaffb31Sdp typeset p=$2 1513daaffb31Sdp typeset pp=$3 15147c478bd9Sstevel@tonic-gate 15153df69ef3SDarren Moffat if [[ -n $Nflag ]]; then 15163df69ef3SDarren Moffat return 15173df69ef3SDarren Moffat fi 1518cdf0c1d5Smjnelson # 1519cdf0c1d5Smjnelson # Mercurial support uses a file list in wx format, so this 1520cdf0c1d5Smjnelson # will be used there, too 1521cdf0c1d5Smjnelson # 1522daaffb31Sdp if [[ -n $wxfile ]]; then 1523daaffb31Sdp comments_from_wx $fmt $p 1524daaffb31Sdp else 1525daaffb31Sdp if [[ $SCM_MODE == "teamware" ]]; then 1526daaffb31Sdp comments_from_teamware $fmt $pp $p 1527daaffb31Sdp fi 1528daaffb31Sdp fi 1529daaffb31Sdp} 1530daaffb31Sdp 1531daaffb31Sdp# 1532daaffb31Sdp# printCI <total-changed> <inserted> <deleted> <modified> <unchanged> 1533daaffb31Sdp# 1534daaffb31Sdp# Print out Code Inspection figures similar to sccs-prt(1) format. 1535daaffb31Sdp# 1536daaffb31Sdpfunction printCI 1537daaffb31Sdp{ 1538daaffb31Sdp integer tot=$1 ins=$2 del=$3 mod=$4 unc=$5 1539daaffb31Sdp typeset str 1540daaffb31Sdp if (( tot == 1 )); then 1541daaffb31Sdp str="line" 1542daaffb31Sdp else 1543daaffb31Sdp str="lines" 1544daaffb31Sdp fi 1545daaffb31Sdp printf '%d %s changed: %d ins; %d del; %d mod; %d unchg\n' \ 1546daaffb31Sdp $tot $str $ins $del $mod $unc 1547daaffb31Sdp} 1548daaffb31Sdp 1549daaffb31Sdp 1550daaffb31Sdp# 1551daaffb31Sdp# difflines <oldfile> <newfile> 1552daaffb31Sdp# 1553daaffb31Sdp# Calculate and emit number of added, removed, modified and unchanged lines, 1554daaffb31Sdp# and total lines changed, the sum of added + removed + modified. 1555daaffb31Sdp# 15567c478bd9Sstevel@tonic-gatefunction difflines 15577c478bd9Sstevel@tonic-gate{ 1558daaffb31Sdp integer tot mod del ins unc err 15597c478bd9Sstevel@tonic-gate typeset filename 15607c478bd9Sstevel@tonic-gate 1561cdf0c1d5Smjnelson eval $( diff -e $1 $2 | $AWK ' 1562daaffb31Sdp # Change range of lines: N,Nc 15637c478bd9Sstevel@tonic-gate /^[0-9]*,[0-9]*c$/ { 15647c478bd9Sstevel@tonic-gate n=split(substr($1,1,length($1)-1), counts, ","); 15657c478bd9Sstevel@tonic-gate if (n != 2) { 15667c478bd9Sstevel@tonic-gate error=2 15677c478bd9Sstevel@tonic-gate exit; 15687c478bd9Sstevel@tonic-gate } 1569daaffb31Sdp # 1570daaffb31Sdp # 3,5c means lines 3 , 4 and 5 are changed, a total of 3 lines. 1571daaffb31Sdp # following would be 5 - 3 = 2! Hence +1 for correction. 1572daaffb31Sdp # 15737c478bd9Sstevel@tonic-gate r=(counts[2]-counts[1])+1; 1574daaffb31Sdp 1575daaffb31Sdp # 1576daaffb31Sdp # Now count replacement lines: each represents a change instead 1577daaffb31Sdp # of a delete, so increment c and decrement r. 1578daaffb31Sdp # 15797c478bd9Sstevel@tonic-gate while (getline != /^\.$/) { 15807c478bd9Sstevel@tonic-gate c++; 15817c478bd9Sstevel@tonic-gate r--; 15827c478bd9Sstevel@tonic-gate } 1583daaffb31Sdp # 1584daaffb31Sdp # If there were more replacement lines than original lines, 1585daaffb31Sdp # then r will be negative; in this case there are no deletions, 1586daaffb31Sdp # but there are r changes that should be counted as adds, and 1587daaffb31Sdp # since r is negative, subtract it from a and add it to c. 1588daaffb31Sdp # 15897c478bd9Sstevel@tonic-gate if (r < 0) { 15907c478bd9Sstevel@tonic-gate a-=r; 15917c478bd9Sstevel@tonic-gate c+=r; 15927c478bd9Sstevel@tonic-gate } 1593daaffb31Sdp 1594daaffb31Sdp # 1595daaffb31Sdp # If there were more original lines than replacement lines, then 1596daaffb31Sdp # r will be positive; in this case, increment d by that much. 1597daaffb31Sdp # 15987c478bd9Sstevel@tonic-gate if (r > 0) { 15997c478bd9Sstevel@tonic-gate d+=r; 16007c478bd9Sstevel@tonic-gate } 16017c478bd9Sstevel@tonic-gate next; 16027c478bd9Sstevel@tonic-gate } 16037c478bd9Sstevel@tonic-gate 1604daaffb31Sdp # Change lines: Nc 16057c478bd9Sstevel@tonic-gate /^[0-9].*c$/ { 1606daaffb31Sdp # The first line is a replacement; any more are additions. 16077c478bd9Sstevel@tonic-gate if (getline != /^\.$/) { 16087c478bd9Sstevel@tonic-gate c++; 16097c478bd9Sstevel@tonic-gate while (getline != /^\.$/) a++; 16107c478bd9Sstevel@tonic-gate } 16117c478bd9Sstevel@tonic-gate next; 16127c478bd9Sstevel@tonic-gate } 16137c478bd9Sstevel@tonic-gate 1614daaffb31Sdp # Add lines: both Na and N,Na 16157c478bd9Sstevel@tonic-gate /^[0-9].*a$/ { 16167c478bd9Sstevel@tonic-gate while (getline != /^\.$/) a++; 16177c478bd9Sstevel@tonic-gate next; 16187c478bd9Sstevel@tonic-gate } 16197c478bd9Sstevel@tonic-gate 1620daaffb31Sdp # Delete range of lines: N,Nd 16217c478bd9Sstevel@tonic-gate /^[0-9]*,[0-9]*d$/ { 16227c478bd9Sstevel@tonic-gate n=split(substr($1,1,length($1)-1), counts, ","); 16237c478bd9Sstevel@tonic-gate if (n != 2) { 16247c478bd9Sstevel@tonic-gate error=2 16257c478bd9Sstevel@tonic-gate exit; 16267c478bd9Sstevel@tonic-gate } 1627daaffb31Sdp # 1628daaffb31Sdp # 3,5d means lines 3 , 4 and 5 are deleted, a total of 3 lines. 1629daaffb31Sdp # following would be 5 - 3 = 2! Hence +1 for correction. 1630daaffb31Sdp # 16317c478bd9Sstevel@tonic-gate r=(counts[2]-counts[1])+1; 16327c478bd9Sstevel@tonic-gate d+=r; 16337c478bd9Sstevel@tonic-gate next; 16347c478bd9Sstevel@tonic-gate } 16357c478bd9Sstevel@tonic-gate 1636daaffb31Sdp # Delete line: Nd. For example 10d says line 10 is deleted. 16377c478bd9Sstevel@tonic-gate /^[0-9]*d$/ {d++; next} 16387c478bd9Sstevel@tonic-gate 1639daaffb31Sdp # Should not get here! 16407c478bd9Sstevel@tonic-gate { 16417c478bd9Sstevel@tonic-gate error=1; 16427c478bd9Sstevel@tonic-gate exit; 16437c478bd9Sstevel@tonic-gate } 16447c478bd9Sstevel@tonic-gate 1645daaffb31Sdp # Finish off - print results 16467c478bd9Sstevel@tonic-gate END { 1647daaffb31Sdp printf("tot=%d;mod=%d;del=%d;ins=%d;err=%d\n", 16487c478bd9Sstevel@tonic-gate (c+d+a), c, d, a, error); 16497c478bd9Sstevel@tonic-gate }' ) 16507c478bd9Sstevel@tonic-gate 1651cdf0c1d5Smjnelson # End of $AWK, Check to see if any trouble occurred. 16527c478bd9Sstevel@tonic-gate if (( $? > 0 || err > 0 )); then 1653daaffb31Sdp print "Unexpected Error occurred reading" \ 1654daaffb31Sdp "\`diff -e $1 $2\`: \$?=$?, err=" $err 1655daaffb31Sdp return 1656daaffb31Sdp fi 1657daaffb31Sdp 16587c478bd9Sstevel@tonic-gate # Accumulate totals 16597c478bd9Sstevel@tonic-gate (( TOTL += tot )) 1660daaffb31Sdp (( TMOD += mod )) 16617c478bd9Sstevel@tonic-gate (( TDEL += del )) 16627c478bd9Sstevel@tonic-gate (( TINS += ins )) 16637c478bd9Sstevel@tonic-gate # Calculate unchanged lines 1664cdf0c1d5Smjnelson unc=`wc -l < $1` 16657c478bd9Sstevel@tonic-gate if (( unc > 0 )); then 1666daaffb31Sdp (( unc -= del + mod )) 16677c478bd9Sstevel@tonic-gate (( TUNC += unc )) 16687c478bd9Sstevel@tonic-gate fi 16697c478bd9Sstevel@tonic-gate # print summary 1670daaffb31Sdp print "<span class=\"lineschanged\">" 1671daaffb31Sdp printCI $tot $ins $del $mod $unc 1672daaffb31Sdp print "</span>" 16737c478bd9Sstevel@tonic-gate} 16747c478bd9Sstevel@tonic-gate 1675daaffb31Sdp 16767c478bd9Sstevel@tonic-gate# 1677daaffb31Sdp# flist_from_wx 1678daaffb31Sdp# 1679daaffb31Sdp# Sets up webrev to source its information from a wx-formatted file. 1680daaffb31Sdp# Sets the global 'wxfile' variable. 1681daaffb31Sdp# 1682daaffb31Sdpfunction flist_from_wx 16837c478bd9Sstevel@tonic-gate{ 1684daaffb31Sdp typeset argfile=$1 1685daaffb31Sdp if [[ -n ${argfile%%/*} ]]; then 1686daaffb31Sdp # 1687daaffb31Sdp # If the wx file pathname is relative then make it absolute 1688daaffb31Sdp # because the webrev does a "cd" later on. 1689daaffb31Sdp # 1690daaffb31Sdp wxfile=$PWD/$argfile 16917c478bd9Sstevel@tonic-gate else 1692daaffb31Sdp wxfile=$argfile 16937c478bd9Sstevel@tonic-gate fi 16947c478bd9Sstevel@tonic-gate 1695cdf0c1d5Smjnelson $AWK '{ c = 1; print; 16967c478bd9Sstevel@tonic-gate while (getline) { 16977c478bd9Sstevel@tonic-gate if (NF == 0) { c = -c; continue } 16987c478bd9Sstevel@tonic-gate if (c > 0) print 16997c478bd9Sstevel@tonic-gate } 1700daaffb31Sdp }' $wxfile > $FLIST 17017c478bd9Sstevel@tonic-gate 1702daaffb31Sdp print " Done." 1703daaffb31Sdp} 17047c478bd9Sstevel@tonic-gate 1705daaffb31Sdp# 1706daaffb31Sdp# flist_from_teamware [ <args-to-putback-n> ] 1707daaffb31Sdp# 1708daaffb31Sdp# Generate the file list by extracting file names from a putback -n. Some 1709daaffb31Sdp# names may come from the "update/create" messages and others from the 1710daaffb31Sdp# "currently checked out" warning. Renames are detected here too. Extract 1711daaffb31Sdp# values for CODEMGR_WS and CODEMGR_PARENT from the output of the putback 1712daaffb31Sdp# -n as well, but remove them if they are already defined. 1713daaffb31Sdp# 1714daaffb31Sdpfunction flist_from_teamware 1715daaffb31Sdp{ 1716cdf0c1d5Smjnelson if [[ -n $codemgr_parent && -z $parent_webrev ]]; then 1717daaffb31Sdp if [[ ! -d $codemgr_parent/Codemgr_wsdata ]]; then 1718daaffb31Sdp print -u2 "parent $codemgr_parent doesn't look like a" \ 1719daaffb31Sdp "valid teamware workspace" 17207c478bd9Sstevel@tonic-gate exit 1 17217c478bd9Sstevel@tonic-gate fi 1722daaffb31Sdp parent_args="-p $codemgr_parent" 17237c478bd9Sstevel@tonic-gate fi 17247c478bd9Sstevel@tonic-gate 1725daaffb31Sdp print " File list from: 'putback -n $parent_args $*' ... \c" 17267c478bd9Sstevel@tonic-gate 1727daaffb31Sdp putback -n $parent_args $* 2>&1 | 1728cdf0c1d5Smjnelson $AWK ' 1729daaffb31Sdp /^update:|^create:/ {print $2} 1730daaffb31Sdp /^Parent workspace:/ {printf("CODEMGR_PARENT=%s\n",$3)} 1731daaffb31Sdp /^Child workspace:/ {printf("CODEMGR_WS=%s\n",$3)} 1732daaffb31Sdp /^The following files are currently checked out/ {p = 1; continue} 1733daaffb31Sdp NF == 0 {p=0 ; continue} 1734daaffb31Sdp /^rename/ {old=$3} 1735daaffb31Sdp $1 == "to:" {print $2, old} 1736daaffb31Sdp /^"/ {continue} 1737daaffb31Sdp p == 1 {print $1}' | 1738daaffb31Sdp sort -r -k 1,1 -u | sort > $FLIST 17397c478bd9Sstevel@tonic-gate 1740daaffb31Sdp print " Done." 1741daaffb31Sdp} 1742daaffb31Sdp 1743cdf0c1d5Smjnelson# 1744cdf0c1d5Smjnelson# Call hg-active to get the active list output in the wx active list format 1745cdf0c1d5Smjnelson# 1746cdf0c1d5Smjnelsonfunction hg_active_wxfile 1747cdf0c1d5Smjnelson{ 1748cdf0c1d5Smjnelson typeset child=$1 1749cdf0c1d5Smjnelson typeset parent=$2 1750cdf0c1d5Smjnelson 1751cdf0c1d5Smjnelson TMPFLIST=/tmp/$$.active 17529a70fc3bSMark J. Nelson $HG_ACTIVE -w $child -p $parent -o $TMPFLIST 1753cdf0c1d5Smjnelson wxfile=$TMPFLIST 1754cdf0c1d5Smjnelson} 1755cdf0c1d5Smjnelson 1756cdf0c1d5Smjnelson# 1757cdf0c1d5Smjnelson# flist_from_mercurial 1758cdf0c1d5Smjnelson# Call hg-active to get a wx-style active list, and hand it off to 1759cdf0c1d5Smjnelson# flist_from_wx 1760cdf0c1d5Smjnelson# 1761cdf0c1d5Smjnelsonfunction flist_from_mercurial 1762cdf0c1d5Smjnelson{ 1763cdf0c1d5Smjnelson typeset child=$1 1764cdf0c1d5Smjnelson typeset parent=$2 1765cdf0c1d5Smjnelson 1766cdf0c1d5Smjnelson print " File list from: hg-active -p $parent ...\c" 1767cdf0c1d5Smjnelson 1768cdf0c1d5Smjnelson if [[ ! -x $HG_ACTIVE ]]; then 1769cdf0c1d5Smjnelson print # Blank line for the \c above 1770cdf0c1d5Smjnelson print -u2 "Error: hg-active tool not found. Exiting" 1771cdf0c1d5Smjnelson exit 1 1772cdf0c1d5Smjnelson fi 1773cdf0c1d5Smjnelson hg_active_wxfile $child $parent 1774cdf0c1d5Smjnelson 1775cdf0c1d5Smjnelson # flist_from_wx prints the Done, so we don't have to. 1776cdf0c1d5Smjnelson flist_from_wx $TMPFLIST 1777cdf0c1d5Smjnelson} 1778cdf0c1d5Smjnelson 1779cdf0c1d5Smjnelson# 1780cdf0c1d5Smjnelson# flist_from_subversion 1781cdf0c1d5Smjnelson# 1782cdf0c1d5Smjnelson# Generate the file list by extracting file names from svn status. 1783cdf0c1d5Smjnelson# 1784cdf0c1d5Smjnelsonfunction flist_from_subversion 1785cdf0c1d5Smjnelson{ 1786cdf0c1d5Smjnelson CWS=$1 1787cdf0c1d5Smjnelson OLDPWD=$2 1788cdf0c1d5Smjnelson 1789cdf0c1d5Smjnelson cd $CWS 1790cdf0c1d5Smjnelson print -u2 " File list from: svn status ... \c" 1791cdf0c1d5Smjnelson svn status | $AWK '/^[ACDMR]/ { print $NF }' > $FLIST 1792cdf0c1d5Smjnelson print -u2 " Done." 1793cdf0c1d5Smjnelson cd $OLDPWD 1794cdf0c1d5Smjnelson} 1795cdf0c1d5Smjnelson 1796daaffb31Sdpfunction env_from_flist 1797daaffb31Sdp{ 1798daaffb31Sdp [[ -r $FLIST ]] || return 1799daaffb31Sdp 1800daaffb31Sdp # 1801daaffb31Sdp # Use "eval" to set env variables that are listed in the file 1802daaffb31Sdp # list. Then copy those into our local versions of those 1803daaffb31Sdp # variables if they have not been set already. 1804daaffb31Sdp # 1805*b0088928SVladimir Kotal eval `$SED -e "s/#.*$//" $FLIST | $GREP = ` 18067c478bd9Sstevel@tonic-gate 1807cdf0c1d5Smjnelson if [[ -z $codemgr_ws && -n $CODEMGR_WS ]]; then 1808cdf0c1d5Smjnelson codemgr_ws=$CODEMGR_WS 1809cdf0c1d5Smjnelson export CODEMGR_WS 1810cdf0c1d5Smjnelson fi 18117c478bd9Sstevel@tonic-gate 1812daaffb31Sdp # 1813daaffb31Sdp # Check to see if CODEMGR_PARENT is set in the flist file. 1814daaffb31Sdp # 1815cdf0c1d5Smjnelson if [[ -z $codemgr_parent && -n $CODEMGR_PARENT ]]; then 1816daaffb31Sdp codemgr_parent=$CODEMGR_PARENT 1817cdf0c1d5Smjnelson export CODEMGR_PARENT 1818daaffb31Sdp fi 1819daaffb31Sdp} 1820daaffb31Sdp 182114983201Sdpfunction look_for_prog 182214983201Sdp{ 182314983201Sdp typeset path 182414983201Sdp typeset ppath 182514983201Sdp typeset progname=$1 182614983201Sdp 182714983201Sdp ppath=$PATH 182814983201Sdp ppath=$ppath:/usr/sfw/bin:/usr/bin:/usr/sbin 182914983201Sdp ppath=$ppath:/opt/teamware/bin:/opt/onbld/bin 1830cdf0c1d5Smjnelson ppath=$ppath:/opt/onbld/bin/`uname -p` 183114983201Sdp 183214983201Sdp PATH=$ppath prog=`whence $progname` 183314983201Sdp if [[ -n $prog ]]; then 183414983201Sdp print $prog 183514983201Sdp fi 183614983201Sdp} 183714983201Sdp 1838cdf0c1d5Smjnelsonfunction get_file_mode 1839cdf0c1d5Smjnelson{ 1840cdf0c1d5Smjnelson $PERL -e ' 1841cdf0c1d5Smjnelson if (@stat = stat($ARGV[0])) { 1842cdf0c1d5Smjnelson $mode = $stat[2] & 0777; 1843cdf0c1d5Smjnelson printf "%03o\n", $mode; 1844cdf0c1d5Smjnelson exit 0; 1845cdf0c1d5Smjnelson } else { 1846cdf0c1d5Smjnelson exit 1; 1847cdf0c1d5Smjnelson } 1848cdf0c1d5Smjnelson ' $1 1849cdf0c1d5Smjnelson} 1850cdf0c1d5Smjnelson 1851cdf0c1d5Smjnelsonfunction build_old_new_teamware 1852cdf0c1d5Smjnelson{ 1853cdf0c1d5Smjnelson typeset olddir="$1" 1854cdf0c1d5Smjnelson typeset newdir="$2" 1855cdf0c1d5Smjnelson 1856cdf0c1d5Smjnelson # If the child's version doesn't exist then 1857cdf0c1d5Smjnelson # get a readonly copy. 1858cdf0c1d5Smjnelson 1859cdf0c1d5Smjnelson if [[ ! -f $CWS/$DIR/$F && -f $CWS/$DIR/SCCS/s.$F ]]; then 1860cdf0c1d5Smjnelson $SCCS get -s -p $CWS/$DIR/$F > $CWS/$DIR/$F 1861cdf0c1d5Smjnelson fi 1862cdf0c1d5Smjnelson 1863cdf0c1d5Smjnelson # The following two sections propagate file permissions the 1864cdf0c1d5Smjnelson # same way SCCS does. If the file is already under version 1865cdf0c1d5Smjnelson # control, always use permissions from the SCCS/s.file. If 1866cdf0c1d5Smjnelson # the file is not under SCCS control, use permissions from the 1867cdf0c1d5Smjnelson # working copy. In all cases, the file copied to the webrev 1868cdf0c1d5Smjnelson # is set to read only, and group/other permissions are set to 1869cdf0c1d5Smjnelson # match those of the file owner. This way, even if the file 1870cdf0c1d5Smjnelson # is currently checked out, the webrev will display the final 1871cdf0c1d5Smjnelson # permissions that would result after check in. 1872cdf0c1d5Smjnelson 1873cdf0c1d5Smjnelson # 1874cdf0c1d5Smjnelson # Snag new version of file. 1875cdf0c1d5Smjnelson # 1876cdf0c1d5Smjnelson rm -f $newdir/$DIR/$F 1877cdf0c1d5Smjnelson cp $CWS/$DIR/$F $newdir/$DIR/$F 1878cdf0c1d5Smjnelson if [[ -f $CWS/$DIR/SCCS/s.$F ]]; then 1879cdf0c1d5Smjnelson chmod `get_file_mode $CWS/$DIR/SCCS/s.$F` \ 1880cdf0c1d5Smjnelson $newdir/$DIR/$F 1881cdf0c1d5Smjnelson fi 1882cdf0c1d5Smjnelson chmod u-w,go=u $newdir/$DIR/$F 1883cdf0c1d5Smjnelson 1884cdf0c1d5Smjnelson # 1885cdf0c1d5Smjnelson # Get the parent's version of the file. First see whether the 1886cdf0c1d5Smjnelson # child's version is checked out and get the parent's version 1887cdf0c1d5Smjnelson # with keywords expanded or unexpanded as appropriate. 1888cdf0c1d5Smjnelson # 1889cdf0c1d5Smjnelson if [[ -f $PWS/$PDIR/$PF && ! -f $PWS/$PDIR/SCCS/s.$PF && \ 1890cdf0c1d5Smjnelson ! -f $PWS/$PDIR/SCCS/p.$PF ]]; then 1891cdf0c1d5Smjnelson # Parent is not a real workspace, but just a raw 1892cdf0c1d5Smjnelson # directory tree - use the file that's there as 1893cdf0c1d5Smjnelson # the old file. 1894cdf0c1d5Smjnelson 1895cdf0c1d5Smjnelson rm -f $olddir/$PDIR/$PF 1896cdf0c1d5Smjnelson cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF 1897cdf0c1d5Smjnelson else 1898cdf0c1d5Smjnelson if [[ -f $PWS/$PDIR/SCCS/s.$PF ]]; then 1899cdf0c1d5Smjnelson real_parent=$PWS 1900cdf0c1d5Smjnelson else 1901cdf0c1d5Smjnelson real_parent=$RWS 1902cdf0c1d5Smjnelson fi 1903cdf0c1d5Smjnelson 1904cdf0c1d5Smjnelson rm -f $olddir/$PDIR/$PF 1905cdf0c1d5Smjnelson 1906cdf0c1d5Smjnelson if [[ -f $real_parent/$PDIR/$PF ]]; then 1907cdf0c1d5Smjnelson if [ -f $CWS/$DIR/SCCS/p.$F ]; then 1908cdf0c1d5Smjnelson $SCCS get -s -p -k $real_parent/$PDIR/$PF > \ 1909cdf0c1d5Smjnelson $olddir/$PDIR/$PF 1910cdf0c1d5Smjnelson else 1911cdf0c1d5Smjnelson $SCCS get -s -p $real_parent/$PDIR/$PF > \ 1912cdf0c1d5Smjnelson $olddir/$PDIR/$PF 1913cdf0c1d5Smjnelson fi 1914cdf0c1d5Smjnelson chmod `get_file_mode $real_parent/$PDIR/SCCS/s.$PF` \ 1915cdf0c1d5Smjnelson $olddir/$PDIR/$PF 1916cdf0c1d5Smjnelson fi 1917cdf0c1d5Smjnelson fi 1918cdf0c1d5Smjnelson if [[ -f $olddir/$PDIR/$PF ]]; then 1919cdf0c1d5Smjnelson chmod u-w,go=u $olddir/$PDIR/$PF 1920cdf0c1d5Smjnelson fi 1921cdf0c1d5Smjnelson} 1922cdf0c1d5Smjnelson 1923cdf0c1d5Smjnelsonfunction build_old_new_mercurial 1924cdf0c1d5Smjnelson{ 1925cdf0c1d5Smjnelson typeset olddir="$1" 1926cdf0c1d5Smjnelson typeset newdir="$2" 1927cdf0c1d5Smjnelson typeset old_mode= 1928cdf0c1d5Smjnelson typeset new_mode= 1929cdf0c1d5Smjnelson typeset file 1930cdf0c1d5Smjnelson 1931cdf0c1d5Smjnelson # 1932cdf0c1d5Smjnelson # Get old file mode, from the parent revision manifest entry. 1933cdf0c1d5Smjnelson # Mercurial only stores a "file is executable" flag, but the 1934cdf0c1d5Smjnelson # manifest will display an octal mode "644" or "755". 1935cdf0c1d5Smjnelson # 1936cdf0c1d5Smjnelson if [[ "$PDIR" == "." ]]; then 1937cdf0c1d5Smjnelson file="$PF" 1938cdf0c1d5Smjnelson else 1939cdf0c1d5Smjnelson file="$PDIR/$PF" 1940cdf0c1d5Smjnelson fi 1941*b0088928SVladimir Kotal file=`echo $file | $SED 's#/#\\\/#g'` 1942cdf0c1d5Smjnelson # match the exact filename, and return only the permission digits 1943*b0088928SVladimir Kotal old_mode=`$SED -n -e "/^\\(...\\) . ${file}$/s//\\1/p" \ 1944cdf0c1d5Smjnelson < $HG_PARENT_MANIFEST` 1945cdf0c1d5Smjnelson 1946cdf0c1d5Smjnelson # 1947cdf0c1d5Smjnelson # Get new file mode, directly from the filesystem. 1948cdf0c1d5Smjnelson # Normalize the mode to match Mercurial's behavior. 1949cdf0c1d5Smjnelson # 1950cdf0c1d5Smjnelson new_mode=`get_file_mode $CWS/$DIR/$F` 1951cdf0c1d5Smjnelson if [[ -n "$new_mode" ]]; then 1952cdf0c1d5Smjnelson if [[ "$new_mode" = *[1357]* ]]; then 1953cdf0c1d5Smjnelson new_mode=755 1954cdf0c1d5Smjnelson else 1955cdf0c1d5Smjnelson new_mode=644 1956cdf0c1d5Smjnelson fi 1957cdf0c1d5Smjnelson fi 1958cdf0c1d5Smjnelson 1959cdf0c1d5Smjnelson # 1960cdf0c1d5Smjnelson # new version of the file. 1961cdf0c1d5Smjnelson # 1962cdf0c1d5Smjnelson rm -rf $newdir/$DIR/$F 1963cdf0c1d5Smjnelson if [[ -e $CWS/$DIR/$F ]]; then 1964cdf0c1d5Smjnelson cp $CWS/$DIR/$F $newdir/$DIR/$F 1965cdf0c1d5Smjnelson if [[ -n $new_mode ]]; then 1966cdf0c1d5Smjnelson chmod $new_mode $newdir/$DIR/$F 1967cdf0c1d5Smjnelson else 1968cdf0c1d5Smjnelson # should never happen 1969cdf0c1d5Smjnelson print -u2 "ERROR: set mode of $newdir/$DIR/$F" 1970cdf0c1d5Smjnelson fi 1971cdf0c1d5Smjnelson fi 1972cdf0c1d5Smjnelson 1973cdf0c1d5Smjnelson # 1974cdf0c1d5Smjnelson # parent's version of the file 1975cdf0c1d5Smjnelson # 1976cdf0c1d5Smjnelson # Note that we get this from the last version common to both 1977cdf0c1d5Smjnelson # ourselves and the parent. References are via $CWS since we have no 1978cdf0c1d5Smjnelson # guarantee that the parent workspace is reachable via the filesystem. 1979cdf0c1d5Smjnelson # 1980cdf0c1d5Smjnelson if [[ -n $parent_webrev && -e $PWS/$PDIR/$PF ]]; then 1981cdf0c1d5Smjnelson cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF 1982cdf0c1d5Smjnelson elif [[ -n $HG_PARENT ]]; then 1983cdf0c1d5Smjnelson hg cat -R $CWS -r $HG_PARENT $CWS/$PDIR/$PF > \ 1984cdf0c1d5Smjnelson $olddir/$PDIR/$PF 2>/dev/null 1985cdf0c1d5Smjnelson 198602d26c39SVladimir Kotal if (( $? != 0 )); then 1987cdf0c1d5Smjnelson rm -f $olddir/$PDIR/$PF 1988cdf0c1d5Smjnelson else 1989cdf0c1d5Smjnelson if [[ -n $old_mode ]]; then 1990cdf0c1d5Smjnelson chmod $old_mode $olddir/$PDIR/$PF 1991cdf0c1d5Smjnelson else 1992cdf0c1d5Smjnelson # should never happen 1993cdf0c1d5Smjnelson print -u2 "ERROR: set mode of $olddir/$PDIR/$PF" 1994cdf0c1d5Smjnelson fi 1995cdf0c1d5Smjnelson fi 1996cdf0c1d5Smjnelson fi 1997cdf0c1d5Smjnelson} 1998cdf0c1d5Smjnelson 1999cdf0c1d5Smjnelsonfunction build_old_new_subversion 2000cdf0c1d5Smjnelson{ 2001cdf0c1d5Smjnelson typeset olddir="$1" 2002cdf0c1d5Smjnelson typeset newdir="$2" 2003cdf0c1d5Smjnelson 2004cdf0c1d5Smjnelson # Snag new version of file. 2005cdf0c1d5Smjnelson rm -f $newdir/$DIR/$F 2006cdf0c1d5Smjnelson [[ -e $CWS/$DIR/$F ]] && cp $CWS/$DIR/$F $newdir/$DIR/$F 2007cdf0c1d5Smjnelson 2008cdf0c1d5Smjnelson if [[ -n $PWS && -e $PWS/$PDIR/$PF ]]; then 2009cdf0c1d5Smjnelson cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF 2010cdf0c1d5Smjnelson else 2011cdf0c1d5Smjnelson # Get the parent's version of the file. 2012cdf0c1d5Smjnelson svn status $CWS/$DIR/$F | read stat file 2013cdf0c1d5Smjnelson if [[ $stat != "A" ]]; then 2014cdf0c1d5Smjnelson svn cat -r BASE $CWS/$DIR/$F > $olddir/$PDIR/$PF 2015cdf0c1d5Smjnelson fi 2016cdf0c1d5Smjnelson fi 2017cdf0c1d5Smjnelson} 2018cdf0c1d5Smjnelson 2019cdf0c1d5Smjnelsonfunction build_old_new_unknown 2020cdf0c1d5Smjnelson{ 2021cdf0c1d5Smjnelson typeset olddir="$1" 2022cdf0c1d5Smjnelson typeset newdir="$2" 2023cdf0c1d5Smjnelson 2024cdf0c1d5Smjnelson # 2025cdf0c1d5Smjnelson # Snag new version of file. 2026cdf0c1d5Smjnelson # 2027cdf0c1d5Smjnelson rm -f $newdir/$DIR/$F 2028cdf0c1d5Smjnelson [[ -e $CWS/$DIR/$F ]] && cp $CWS/$DIR/$F $newdir/$DIR/$F 2029cdf0c1d5Smjnelson 2030cdf0c1d5Smjnelson # 2031cdf0c1d5Smjnelson # Snag the parent's version of the file. 2032cdf0c1d5Smjnelson # 2033cdf0c1d5Smjnelson if [[ -f $PWS/$PDIR/$PF ]]; then 2034cdf0c1d5Smjnelson rm -f $olddir/$PDIR/$PF 2035cdf0c1d5Smjnelson cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF 2036cdf0c1d5Smjnelson fi 2037cdf0c1d5Smjnelson} 2038cdf0c1d5Smjnelson 2039cdf0c1d5Smjnelsonfunction build_old_new 2040cdf0c1d5Smjnelson{ 2041cdf0c1d5Smjnelson typeset WDIR=$1 2042cdf0c1d5Smjnelson typeset PWS=$2 2043cdf0c1d5Smjnelson typeset PDIR=$3 2044cdf0c1d5Smjnelson typeset PF=$4 2045cdf0c1d5Smjnelson typeset CWS=$5 2046cdf0c1d5Smjnelson typeset DIR=$6 2047cdf0c1d5Smjnelson typeset F=$7 2048cdf0c1d5Smjnelson 2049cdf0c1d5Smjnelson typeset olddir="$WDIR/raw_files/old" 2050cdf0c1d5Smjnelson typeset newdir="$WDIR/raw_files/new" 2051cdf0c1d5Smjnelson 2052cdf0c1d5Smjnelson mkdir -p $olddir/$PDIR 2053cdf0c1d5Smjnelson mkdir -p $newdir/$DIR 2054cdf0c1d5Smjnelson 2055cdf0c1d5Smjnelson if [[ $SCM_MODE == "teamware" ]]; then 2056cdf0c1d5Smjnelson build_old_new_teamware "$olddir" "$newdir" 2057cdf0c1d5Smjnelson elif [[ $SCM_MODE == "mercurial" ]]; then 2058cdf0c1d5Smjnelson build_old_new_mercurial "$olddir" "$newdir" 2059cdf0c1d5Smjnelson elif [[ $SCM_MODE == "subversion" ]]; then 2060cdf0c1d5Smjnelson build_old_new_subversion "$olddir" "$newdir" 2061cdf0c1d5Smjnelson elif [[ $SCM_MODE == "unknown" ]]; then 2062cdf0c1d5Smjnelson build_old_new_unknown "$olddir" "$newdir" 2063cdf0c1d5Smjnelson fi 2064cdf0c1d5Smjnelson 2065cdf0c1d5Smjnelson if [[ ! -f $olddir/$PDIR/$PF && ! -f $newdir/$DIR/$F ]]; then 2066cdf0c1d5Smjnelson print "*** Error: file not in parent or child" 2067cdf0c1d5Smjnelson return 1 2068cdf0c1d5Smjnelson fi 2069cdf0c1d5Smjnelson return 0 2070cdf0c1d5Smjnelson} 2071cdf0c1d5Smjnelson 2072cdf0c1d5Smjnelson 2073daaffb31Sdp# 2074daaffb31Sdp# Usage message. 2075daaffb31Sdp# 2076daaffb31Sdpfunction usage 2077daaffb31Sdp{ 2078daaffb31Sdp print 'Usage:\twebrev [common-options] 2079daaffb31Sdp webrev [common-options] ( <file> | - ) 2080daaffb31Sdp webrev [common-options] -w <wx file> 2081daaffb31Sdp 2082daaffb31SdpOptions: 2083ba44d8a2SVladimir Kotal -D: delete remote webrev 2084daaffb31Sdp -i <filename>: Include <filename> in the index.html file. 2085ba44d8a2SVladimir Kotal -n: do not generate the webrev (useful with -U) 2086ba44d8a2SVladimir Kotal -O: Print bugids/arc cases suitable for OpenSolaris. 2087daaffb31Sdp -o <outdir>: Output webrev to specified directory. 2088daaffb31Sdp -p <compare-against>: Use specified parent wkspc or basis for comparison 208902d26c39SVladimir Kotal -t <remote_target>: Specify remote destination for webrev upload 209002d26c39SVladimir Kotal -U: upload the webrev to remote destination 2091daaffb31Sdp -w <wxfile>: Use specified wx active file. 2092daaffb31Sdp 2093daaffb31SdpEnvironment: 2094daaffb31Sdp WDIR: Control the output directory. 2095daaffb31Sdp WEBREV_BUGURL: Control the URL prefix for bugids. 2096daaffb31Sdp WEBREV_SACURL: Control the URL prefix for ARC cases. 2097ba44d8a2SVladimir Kotal WEBREV_TRASH_DIR: Set directory for webrev delete. 2098daaffb31Sdp 2099cdf0c1d5SmjnelsonSCM Specific Options: 2100cdf0c1d5Smjnelson TeamWare: webrev [common-options] -l [arguments to 'putback'] 2101cdf0c1d5Smjnelson 2102daaffb31SdpSCM Environment: 2103cdf0c1d5Smjnelson CODEMGR_WS: Workspace location. 2104cdf0c1d5Smjnelson CODEMGR_PARENT: Parent workspace location. 2105daaffb31Sdp' 2106daaffb31Sdp 2107daaffb31Sdp exit 2 2108daaffb31Sdp} 2109daaffb31Sdp 2110daaffb31Sdp# 2111daaffb31Sdp# 2112daaffb31Sdp# Main program starts here 2113daaffb31Sdp# 2114daaffb31Sdp# 2115daaffb31Sdp 2116daaffb31Sdptrap "rm -f /tmp/$$.* ; exit" 0 1 2 3 15 2117daaffb31Sdp 2118daaffb31Sdpset +o noclobber 2119daaffb31Sdp 2120cdf0c1d5SmjnelsonPATH=$(dirname $(whence $0)):$PATH 2121cdf0c1d5Smjnelson 212214983201Sdp[[ -z $WDIFF ]] && WDIFF=`look_for_prog wdiff` 212314983201Sdp[[ -z $WX ]] && WX=`look_for_prog wx` 2124cdf0c1d5Smjnelson[[ -z $HG_ACTIVE ]] && HG_ACTIVE=`look_for_prog hg-active` 2125cdf0c1d5Smjnelson[[ -z $WHICH_SCM ]] && WHICH_SCM=`look_for_prog which_scm` 212614983201Sdp[[ -z $CODEREVIEW ]] && CODEREVIEW=`look_for_prog codereview` 212714983201Sdp[[ -z $PS2PDF ]] && PS2PDF=`look_for_prog ps2pdf` 212814983201Sdp[[ -z $PERL ]] && PERL=`look_for_prog perl` 212902d26c39SVladimir Kotal[[ -z $RSYNC ]] && RSYNC=`look_for_prog rsync` 2130cdf0c1d5Smjnelson[[ -z $SCCS ]] && SCCS=`look_for_prog sccs` 2131cdf0c1d5Smjnelson[[ -z $AWK ]] && AWK=`look_for_prog nawk` 2132cdf0c1d5Smjnelson[[ -z $AWK ]] && AWK=`look_for_prog gawk` 2133cdf0c1d5Smjnelson[[ -z $AWK ]] && AWK=`look_for_prog awk` 213402d26c39SVladimir Kotal[[ -z $SCP ]] && SCP=`look_for_prog scp` 2135*b0088928SVladimir Kotal[[ -z $SED ]] && SED=`look_for_prog sed` 213602d26c39SVladimir Kotal[[ -z $SFTP ]] && SFTP=`look_for_prog sftp` 213702d26c39SVladimir Kotal[[ -z $MKTEMP ]] && MKTEMP=`look_for_prog mktemp` 213802d26c39SVladimir Kotal[[ -z $GREP ]] && GREP=`look_for_prog grep` 2139ba44d8a2SVladimir Kotal[[ -z $FIND ]] && FIND=`look_for_prog find` 2140cdf0c1d5Smjnelson 2141ba44d8a2SVladimir Kotal# set name of trash directory for remote webrev deletion 2142ba44d8a2SVladimir KotalTRASH_DIR=".trash" 2143ba44d8a2SVladimir Kotal[[ -n $WEBREV_TRASH_DIR ]] && TRASH_DIR=$WEBREV_TRASH_DIR 214414983201Sdp 214514983201Sdpif [[ ! -x $PERL ]]; then 214614983201Sdp print -u2 "Error: No perl interpreter found. Exiting." 214714983201Sdp exit 1 2148daaffb31Sdpfi 214914983201Sdp 2150cdf0c1d5Smjnelsonif [[ ! -x $WHICH_SCM ]]; then 2151cdf0c1d5Smjnelson print -u2 "Error: Could not find which_scm. Exiting." 2152cdf0c1d5Smjnelson exit 1 2153cdf0c1d5Smjnelsonfi 2154cdf0c1d5Smjnelson 215514983201Sdp# 215614983201Sdp# These aren't fatal, but we want to note them to the user. 215714983201Sdp# We don't warn on the absence of 'wx' until later when we've 215814983201Sdp# determined that we actually need to try to invoke it. 215914983201Sdp# 216014983201Sdp[[ ! -x $CODEREVIEW ]] && print -u2 "WARNING: codereview(1) not found." 216114983201Sdp[[ ! -x $PS2PDF ]] && print -u2 "WARNING: ps2pdf(1) not found." 216214983201Sdp[[ ! -x $WDIFF ]] && print -u2 "WARNING: wdiff not found." 2163daaffb31Sdp 2164daaffb31Sdp# Declare global total counters. 2165daaffb31Sdpinteger TOTL TINS TDEL TMOD TUNC 2166daaffb31Sdp 2167ba44d8a2SVladimir Kotal# default remote host for upload/delete 2168ba44d8a2SVladimir Kotaltypeset -r DEFAULT_REMOTE_HOST="cr.opensolaris.org" 2169*b0088928SVladimir Kotal# prefixes for upload targets 2170*b0088928SVladimir Kotaltypeset -r rsync_prefix="rsync://" 2171*b0088928SVladimir Kotaltypeset -r ssh_prefix="ssh://" 2172ba44d8a2SVladimir Kotal 2173ba44d8a2SVladimir KotalDflag= 217414983201Sdpflist_mode= 217514983201Sdpflist_file= 2176daaffb31Sdpiflag= 217702d26c39SVladimir Kotallflag= 217802d26c39SVladimir KotalNflag= 217902d26c39SVladimir Kotalnflag= 218002d26c39SVladimir KotalOflag= 2181daaffb31Sdpoflag= 2182daaffb31Sdppflag= 218302d26c39SVladimir Kotaltflag= 218402d26c39SVladimir Kotaluflag= 218502d26c39SVladimir KotalUflag= 2186daaffb31Sdpwflag= 218702d26c39SVladimir Kotalremote_target= 2188ba44d8a2SVladimir Kotal 2189ba44d8a2SVladimir Kotal# 2190ba44d8a2SVladimir Kotal# NOTE: when adding/removing options it is necessary to sync the list 2191ba44d8a2SVladimir Kotal# with usr/src/tools/onbld/hgext/cdm.py 2192ba44d8a2SVladimir Kotal# 2193ba44d8a2SVladimir Kotalwhile getopts "i:o:p:lwONnt:UD" opt 2194daaffb31Sdpdo 2195daaffb31Sdp case $opt in 2196ba44d8a2SVladimir Kotal D) Dflag=1;; 2197ba44d8a2SVladimir Kotal 2198daaffb31Sdp i) iflag=1 2199daaffb31Sdp INCLUDE_FILE=$OPTARG;; 2200daaffb31Sdp 2201daaffb31Sdp # 2202daaffb31Sdp # If -l has been specified, we need to abort further options 2203daaffb31Sdp # processing, because subsequent arguments are going to be 2204daaffb31Sdp # arguments to 'putback -n'. 2205daaffb31Sdp # 2206daaffb31Sdp l) lflag=1 2207daaffb31Sdp break;; 2208daaffb31Sdp 220902d26c39SVladimir Kotal N) Nflag=1;; 221002d26c39SVladimir Kotal 221102d26c39SVladimir Kotal n) nflag=1;; 2212daaffb31Sdp 2213daaffb31Sdp O) Oflag=1;; 2214daaffb31Sdp 221502d26c39SVladimir Kotal o) oflag=1 221602d26c39SVladimir Kotal WDIR=$OPTARG;; 221702d26c39SVladimir Kotal 221802d26c39SVladimir Kotal p) pflag=1 221902d26c39SVladimir Kotal codemgr_parent=$OPTARG;; 222002d26c39SVladimir Kotal 222102d26c39SVladimir Kotal t) tflag=1 222202d26c39SVladimir Kotal remote_target=$OPTARG;; 222302d26c39SVladimir Kotal 222402d26c39SVladimir Kotal U) Uflag=1;; 222502d26c39SVladimir Kotal 222602d26c39SVladimir Kotal w) wflag=1;; 22273df69ef3SDarren Moffat 2228daaffb31Sdp ?) usage;; 2229daaffb31Sdp esac 2230daaffb31Sdpdone 2231daaffb31Sdp 2232daaffb31SdpFLIST=/tmp/$$.flist 2233daaffb31Sdp 2234daaffb31Sdpif [[ -n $wflag && -n $lflag ]]; then 2235daaffb31Sdp usage 2236daaffb31Sdpfi 2237daaffb31Sdp 223802d26c39SVladimir Kotal# more sanity checking 223902d26c39SVladimir Kotalif [[ -n $nflag && -z $Uflag ]]; then 2240ba44d8a2SVladimir Kotal print "it does not make sense to skip webrev generation" \ 2241ba44d8a2SVladimir Kotal "without -U" 224202d26c39SVladimir Kotal exit 1 224302d26c39SVladimir Kotalfi 224402d26c39SVladimir Kotal 2245ba44d8a2SVladimir Kotalif [[ -n $tflag && -z $Uflag && -z $Dflag ]]; then 2246ba44d8a2SVladimir Kotal echo "remote target has to be used only for upload or delete" 224702d26c39SVladimir Kotal exit 1 224802d26c39SVladimir Kotalfi 224902d26c39SVladimir Kotal 2250daaffb31Sdp# 2251daaffb31Sdp# If this manually set as the parent, and it appears to be an earlier webrev, 2252daaffb31Sdp# then note that fact and set the parent to the raw_files/new subdirectory. 2253daaffb31Sdp# 2254daaffb31Sdpif [[ -n $pflag && -d $codemgr_parent/raw_files/new ]]; then 2255daaffb31Sdp parent_webrev="$codemgr_parent" 2256daaffb31Sdp codemgr_parent="$codemgr_parent/raw_files/new" 2257daaffb31Sdpfi 2258daaffb31Sdp 2259daaffb31Sdpif [[ -z $wflag && -z $lflag ]]; then 2260daaffb31Sdp shift $(($OPTIND - 1)) 2261daaffb31Sdp 2262daaffb31Sdp if [[ $1 == "-" ]]; then 2263daaffb31Sdp cat > $FLIST 226414983201Sdp flist_mode="stdin" 226514983201Sdp flist_done=1 226614983201Sdp shift 2267daaffb31Sdp elif [[ -n $1 ]]; then 226814983201Sdp if [[ ! -r $1 ]]; then 2269daaffb31Sdp print -u2 "$1: no such file or not readable" 2270daaffb31Sdp usage 2271daaffb31Sdp fi 2272daaffb31Sdp cat $1 > $FLIST 227314983201Sdp flist_mode="file" 227414983201Sdp flist_file=$1 227514983201Sdp flist_done=1 227614983201Sdp shift 2277daaffb31Sdp else 227814983201Sdp flist_mode="auto" 2279daaffb31Sdp fi 2280daaffb31Sdpfi 2281daaffb31Sdp 2282daaffb31Sdp# 2283daaffb31Sdp# Before we go on to further consider -l and -w, work out which SCM we think 2284daaffb31Sdp# is in use. 2285daaffb31Sdp# 2286cdf0c1d5Smjnelson$WHICH_SCM | read SCM_MODE junk || exit 1 2287cdf0c1d5Smjnelsoncase "$SCM_MODE" in 2288cdf0c1d5Smjnelsonteamware|mercurial|subversion) 2289cdf0c1d5Smjnelson ;; 2290cdf0c1d5Smjnelsonunknown) 2291cdf0c1d5Smjnelson if [[ $flist_mode == "auto" ]]; then 2292cdf0c1d5Smjnelson print -u2 "Unable to determine SCM in use and file list not specified" 2293cdf0c1d5Smjnelson print -u2 "See which_scm(1) for SCM detection information." 22947c478bd9Sstevel@tonic-gate exit 1 22957c478bd9Sstevel@tonic-gate fi 2296cdf0c1d5Smjnelson ;; 2297cdf0c1d5Smjnelson*) 2298cdf0c1d5Smjnelson if [[ $flist_mode == "auto" ]]; then 2299cdf0c1d5Smjnelson print -u2 "Unsupported SCM in use ($SCM_MODE) and file list not specified" 2300cdf0c1d5Smjnelson exit 1 2301cdf0c1d5Smjnelson fi 2302cdf0c1d5Smjnelson ;; 2303cdf0c1d5Smjnelsonesac 23047c478bd9Sstevel@tonic-gate 2305daaffb31Sdpprint -u2 " SCM detected: $SCM_MODE" 2306daaffb31Sdp 2307daaffb31Sdpif [[ -n $lflag ]]; then 2308daaffb31Sdp # 2309daaffb31Sdp # If the -l flag is given instead of the name of a file list, 2310daaffb31Sdp # then generate the file list by extracting file names from a 2311daaffb31Sdp # putback -n. 2312daaffb31Sdp # 2313daaffb31Sdp shift $(($OPTIND - 1)) 2314cdf0c1d5Smjnelson if [[ $SCM_MODE == "teamware" ]]; then 2315daaffb31Sdp flist_from_teamware "$*" 2316cdf0c1d5Smjnelson else 2317cdf0c1d5Smjnelson print -u2 -- "Error: -l option only applies to TeamWare" 2318cdf0c1d5Smjnelson exit 1 2319cdf0c1d5Smjnelson fi 2320daaffb31Sdp flist_done=1 2321daaffb31Sdp shift $# 2322daaffb31Sdpelif [[ -n $wflag ]]; then 2323daaffb31Sdp # 2324daaffb31Sdp # If the -w is given then assume the file list is in Bonwick's "wx" 2325daaffb31Sdp # command format, i.e. pathname lines alternating with SCCS comment 2326daaffb31Sdp # lines with blank lines as separators. Use the SCCS comments later 2327daaffb31Sdp # in building the index.html file. 2328daaffb31Sdp # 2329daaffb31Sdp shift $(($OPTIND - 1)) 2330daaffb31Sdp wxfile=$1 2331daaffb31Sdp if [[ -z $wxfile && -n $CODEMGR_WS ]]; then 2332daaffb31Sdp if [[ -r $CODEMGR_WS/wx/active ]]; then 2333daaffb31Sdp wxfile=$CODEMGR_WS/wx/active 2334daaffb31Sdp fi 2335daaffb31Sdp fi 2336daaffb31Sdp 2337daaffb31Sdp [[ -z $wxfile ]] && print -u2 "wx file not specified, and could not " \ 2338daaffb31Sdp "be auto-detected (check \$CODEMGR_WS)" && exit 1 2339daaffb31Sdp 2340cdf0c1d5Smjnelson if [[ ! -r $wxfile ]]; then 2341cdf0c1d5Smjnelson print -u2 "$wxfile: no such file or not readable" 2342cdf0c1d5Smjnelson usage 2343cdf0c1d5Smjnelson fi 2344cdf0c1d5Smjnelson 2345daaffb31Sdp print -u2 " File list from: wx 'active' file '$wxfile' ... \c" 2346daaffb31Sdp flist_from_wx $wxfile 2347daaffb31Sdp flist_done=1 2348daaffb31Sdp if [[ -n "$*" ]]; then 2349daaffb31Sdp shift 2350daaffb31Sdp fi 235114983201Sdpelif [[ $flist_mode == "stdin" ]]; then 235214983201Sdp print -u2 " File list from: standard input" 235314983201Sdpelif [[ $flist_mode == "file" ]]; then 235414983201Sdp print -u2 " File list from: $flist_file" 2355daaffb31Sdpfi 2356daaffb31Sdp 2357daaffb31Sdpif [[ $# -gt 0 ]]; then 235814983201Sdp print -u2 "WARNING: unused arguments: $*" 2359daaffb31Sdpfi 2360daaffb31Sdp 2361daaffb31Sdpif [[ $SCM_MODE == "teamware" ]]; then 2362daaffb31Sdp # 2363daaffb31Sdp # Parent (internally $codemgr_parent) and workspace ($codemgr_ws) can 2364daaffb31Sdp # be set in a number of ways, in decreasing precedence: 2365daaffb31Sdp # 2366daaffb31Sdp # 1) on the command line (only for the parent) 2367daaffb31Sdp # 2) in the user environment 2368daaffb31Sdp # 3) in the flist 2369daaffb31Sdp # 4) automatically based on the workspace (only for the parent) 2370daaffb31Sdp # 2371daaffb31Sdp 2372daaffb31Sdp # 2373daaffb31Sdp # Here is case (2): the user environment 2374daaffb31Sdp # 2375daaffb31Sdp [[ -z $codemgr_ws && -n $CODEMGR_WS ]] && codemgr_ws=$CODEMGR_WS 2376daaffb31Sdp if [[ -n $codemgr_ws && ! -d $codemgr_ws ]]; then 2377daaffb31Sdp print -u2 "$codemgr_ws: no such workspace" 23787c478bd9Sstevel@tonic-gate exit 1 23797c478bd9Sstevel@tonic-gate fi 23807c478bd9Sstevel@tonic-gate 2381daaffb31Sdp [[ -z $codemgr_parent && -n $CODEMGR_PARENT ]] && \ 2382daaffb31Sdp codemgr_parent=$CODEMGR_PARENT 2383daaffb31Sdp if [[ -n $codemgr_parent && ! -d $codemgr_parent ]]; then 2384daaffb31Sdp print -u2 "$codemgr_parent: no such directory" 23857c478bd9Sstevel@tonic-gate exit 1 23867c478bd9Sstevel@tonic-gate fi 23877c478bd9Sstevel@tonic-gate 2388daaffb31Sdp # 2389daaffb31Sdp # If we're in auto-detect mode and we haven't already gotten the file 2390daaffb31Sdp # list, then see if we can get it by probing for wx. 2391daaffb31Sdp # 239214983201Sdp if [[ -z $flist_done && $flist_mode == "auto" && -n $codemgr_ws ]]; then 239314983201Sdp if [[ ! -x $WX ]]; then 239414983201Sdp print -u2 "WARNING: wx not found!" 2395daaffb31Sdp fi 23967c478bd9Sstevel@tonic-gate 2397daaffb31Sdp # 2398daaffb31Sdp # We need to use wx list -w so that we get renamed files, etc. 2399daaffb31Sdp # but only if a wx active file exists-- otherwise wx will 2400daaffb31Sdp # hang asking us to initialize our wx information. 2401daaffb31Sdp # 240214983201Sdp if [[ -x $WX && -f $codemgr_ws/wx/active ]]; then 2403daaffb31Sdp print -u2 " File list from: 'wx list -w' ... \c" 2404daaffb31Sdp $WX list -w > $FLIST 2405daaffb31Sdp $WX comments > /tmp/$$.wx_comments 2406daaffb31Sdp wxfile=/tmp/$$.wx_comments 2407daaffb31Sdp print -u2 "done" 2408daaffb31Sdp flist_done=1 2409daaffb31Sdp fi 2410daaffb31Sdp fi 2411daaffb31Sdp 2412daaffb31Sdp # 2413daaffb31Sdp # If by hook or by crook we've gotten a file list by now (perhaps 2414daaffb31Sdp # from the command line), eval it to extract environment variables from 2415daaffb31Sdp # it: This is step (3). 2416daaffb31Sdp # 2417daaffb31Sdp env_from_flist 2418daaffb31Sdp 2419daaffb31Sdp # 2420daaffb31Sdp # Continuing step (3): If we still have no file list, we'll try to get 2421daaffb31Sdp # it from teamware. 2422daaffb31Sdp # 2423daaffb31Sdp if [[ -z $flist_done ]]; then 2424daaffb31Sdp flist_from_teamware 2425daaffb31Sdp env_from_flist 2426daaffb31Sdp fi 2427daaffb31Sdp 2428daaffb31Sdp # 2429daaffb31Sdp # (4) If we still don't have a value for codemgr_parent, get it 2430daaffb31Sdp # from workspace. 2431daaffb31Sdp # 2432cdf0c1d5Smjnelson [[ -z $codemgr_ws ]] && codemgr_ws=`workspace name` 2433daaffb31Sdp [[ -z $codemgr_parent ]] && codemgr_parent=`workspace parent` 2434daaffb31Sdp if [[ ! -d $codemgr_parent ]]; then 2435daaffb31Sdp print -u2 "$CODEMGR_PARENT: no such parent workspace" 2436daaffb31Sdp exit 1 2437daaffb31Sdp fi 2438daaffb31Sdp 2439daaffb31Sdp # 2440cdf0c1d5Smjnelson # Observe true directory name of CODEMGR_WS, as used later in 2441cdf0c1d5Smjnelson # webrev title. 2442cdf0c1d5Smjnelson # 2443cdf0c1d5Smjnelson codemgr_ws=$(cd $codemgr_ws;print $PWD) 2444cdf0c1d5Smjnelson 2445cdf0c1d5Smjnelson # 2446daaffb31Sdp # Reset CODEMGR_WS to make sure teamware commands are happy. 2447daaffb31Sdp # 2448daaffb31Sdp CODEMGR_WS=$codemgr_ws 2449daaffb31Sdp CWS=$codemgr_ws 2450daaffb31Sdp PWS=$codemgr_parent 2451cdf0c1d5Smjnelson 2452cdf0c1d5Smjnelson [[ -n $parent_webrev ]] && RWS=$(workspace parent $CWS) 2453cdf0c1d5Smjnelson 2454cdf0c1d5Smjnelsonelif [[ $SCM_MODE == "mercurial" ]]; then 2455cdf0c1d5Smjnelson [[ -z $codemgr_ws && -n $CODEMGR_WS ]] && \ 2456cdf0c1d5Smjnelson codemgr_ws=`hg root -R $CODEMGR_WS 2>/dev/null` 2457cdf0c1d5Smjnelson 2458cdf0c1d5Smjnelson [[ -z $codemgr_ws ]] && codemgr_ws=`hg root 2>/dev/null` 2459cdf0c1d5Smjnelson 2460cdf0c1d5Smjnelson # 2461cdf0c1d5Smjnelson # Parent can either be specified with -p 2462cdf0c1d5Smjnelson # Specified with CODEMGR_PARENT in the environment 2463cdf0c1d5Smjnelson # or taken from hg's default path. 2464cdf0c1d5Smjnelson # 2465cdf0c1d5Smjnelson 2466cdf0c1d5Smjnelson if [[ -z $codemgr_parent && -n $CODEMGR_PARENT ]]; then 2467cdf0c1d5Smjnelson codemgr_parent=$CODEMGR_PARENT 2468cdf0c1d5Smjnelson fi 2469cdf0c1d5Smjnelson 2470cdf0c1d5Smjnelson if [[ -z $codemgr_parent ]]; then 2471cdf0c1d5Smjnelson codemgr_parent=`hg path -R $codemgr_ws default 2>/dev/null` 2472cdf0c1d5Smjnelson fi 2473cdf0c1d5Smjnelson 2474cdf0c1d5Smjnelson CWS_REV=`hg parent -R $codemgr_ws --template '{node|short}' 2>/dev/null` 2475cdf0c1d5Smjnelson CWS=$codemgr_ws 2476cdf0c1d5Smjnelson PWS=$codemgr_parent 2477cdf0c1d5Smjnelson 2478cdf0c1d5Smjnelson # 2479cdf0c1d5Smjnelson # If the parent is a webrev, we want to do some things against 2480cdf0c1d5Smjnelson # the natural workspace parent (file list, comments, etc) 2481cdf0c1d5Smjnelson # 2482cdf0c1d5Smjnelson if [[ -n $parent_webrev ]]; then 2483cdf0c1d5Smjnelson real_parent=$(hg path -R $codemgr_ws default 2>/dev/null) 2484cdf0c1d5Smjnelson else 2485cdf0c1d5Smjnelson real_parent=$PWS 2486cdf0c1d5Smjnelson fi 2487cdf0c1d5Smjnelson 2488cdf0c1d5Smjnelson # 2489cdf0c1d5Smjnelson # If hg-active exists, then we run it. In the case of no explicit 2490cdf0c1d5Smjnelson # flist given, we'll use it for our comments. In the case of an 2491cdf0c1d5Smjnelson # explicit flist given we'll try to use it for comments for any 2492cdf0c1d5Smjnelson # files mentioned in the flist. 2493cdf0c1d5Smjnelson # 2494cdf0c1d5Smjnelson if [[ -z $flist_done ]]; then 2495cdf0c1d5Smjnelson flist_from_mercurial $CWS $real_parent 2496cdf0c1d5Smjnelson flist_done=1 2497cdf0c1d5Smjnelson fi 2498cdf0c1d5Smjnelson 2499cdf0c1d5Smjnelson # 2500cdf0c1d5Smjnelson # If we have a file list now, pull out any variables set 2501cdf0c1d5Smjnelson # therein. We do this now (rather than when we possibly use 2502cdf0c1d5Smjnelson # hg-active to find comments) to avoid stomping specifications 2503cdf0c1d5Smjnelson # in the user-specified flist. 2504cdf0c1d5Smjnelson # 2505cdf0c1d5Smjnelson if [[ -n $flist_done ]]; then 2506cdf0c1d5Smjnelson env_from_flist 2507cdf0c1d5Smjnelson fi 2508cdf0c1d5Smjnelson 2509cdf0c1d5Smjnelson # 2510cdf0c1d5Smjnelson # Only call hg-active if we don't have a wx formatted file already 2511cdf0c1d5Smjnelson # 2512cdf0c1d5Smjnelson if [[ -x $HG_ACTIVE && -z $wxfile ]]; then 2513cdf0c1d5Smjnelson print " Comments from: hg-active -p $real_parent ...\c" 2514cdf0c1d5Smjnelson hg_active_wxfile $CWS $real_parent 2515cdf0c1d5Smjnelson print " Done." 2516cdf0c1d5Smjnelson fi 2517cdf0c1d5Smjnelson 2518cdf0c1d5Smjnelson # 2519cdf0c1d5Smjnelson # At this point we must have a wx flist either from hg-active, 2520cdf0c1d5Smjnelson # or in general. Use it to try and find our parent revision, 2521cdf0c1d5Smjnelson # if we don't have one. 2522cdf0c1d5Smjnelson # 2523cdf0c1d5Smjnelson if [[ -z $HG_PARENT ]]; then 2524*b0088928SVladimir Kotal eval `$SED -e "s/#.*$//" $wxfile | $GREP HG_PARENT=` 2525cdf0c1d5Smjnelson fi 2526cdf0c1d5Smjnelson 2527cdf0c1d5Smjnelson # 2528cdf0c1d5Smjnelson # If we still don't have a parent, we must have been given a 2529cdf0c1d5Smjnelson # wx-style active list with no HG_PARENT specification, run 2530cdf0c1d5Smjnelson # hg-active and pull an HG_PARENT out of it, ignore the rest. 2531cdf0c1d5Smjnelson # 2532cdf0c1d5Smjnelson if [[ -z $HG_PARENT && -x $HG_ACTIVE ]]; then 2533cdf0c1d5Smjnelson $HG_ACTIVE -w $codemgr_ws -p $real_parent | \ 2534*b0088928SVladimir Kotal eval `$SED -e "s/#.*$//" | $GREP HG_PARENT=` 2535cdf0c1d5Smjnelson elif [[ -z $HG_PARENT ]]; then 2536cdf0c1d5Smjnelson print -u2 "Error: Cannot discover parent revision" 2537cdf0c1d5Smjnelson exit 1 2538cdf0c1d5Smjnelson fi 2539cdf0c1d5Smjnelsonelif [[ $SCM_MODE == "subversion" ]]; then 2540cdf0c1d5Smjnelson if [[ -n $CODEMGR_WS && -d $CODEMGR_WS/.svn ]]; then 2541cdf0c1d5Smjnelson CWS=$CODEMGR_WS 2542cdf0c1d5Smjnelson else 2543cdf0c1d5Smjnelson svn info | while read line; do 2544cdf0c1d5Smjnelson if [[ $line == "URL: "* ]]; then 2545cdf0c1d5Smjnelson url=${line#URL: } 2546cdf0c1d5Smjnelson elif [[ $line == "Repository Root: "* ]]; then 2547cdf0c1d5Smjnelson repo=${line#Repository Root: } 2548cdf0c1d5Smjnelson fi 2549cdf0c1d5Smjnelson done 2550cdf0c1d5Smjnelson 2551cdf0c1d5Smjnelson rel=${url#$repo} 2552cdf0c1d5Smjnelson CWS=${PWD%$rel} 2553cdf0c1d5Smjnelson fi 2554cdf0c1d5Smjnelson 2555cdf0c1d5Smjnelson # 2556cdf0c1d5Smjnelson # We only will have a real parent workspace in the case one 2557cdf0c1d5Smjnelson # was specified (be it an older webrev, or another checkout). 2558cdf0c1d5Smjnelson # 2559cdf0c1d5Smjnelson [[ -n $codemgr_parent ]] && PWS=$codemgr_parent 2560cdf0c1d5Smjnelson 2561cdf0c1d5Smjnelson if [[ -z $flist_done && $flist_mode == "auto" ]]; then 2562cdf0c1d5Smjnelson flist_from_subversion $CWS $OLDPWD 2563cdf0c1d5Smjnelson fi 2564cdf0c1d5Smjnelsonelse 2565cdf0c1d5Smjnelson if [[ $SCM_MODE == "unknown" ]]; then 2566cdf0c1d5Smjnelson print -u2 " Unknown type of SCM in use" 2567cdf0c1d5Smjnelson else 2568cdf0c1d5Smjnelson print -u2 " Unsupported SCM in use: $SCM_MODE" 2569cdf0c1d5Smjnelson fi 2570cdf0c1d5Smjnelson 2571cdf0c1d5Smjnelson env_from_flist 2572cdf0c1d5Smjnelson 2573cdf0c1d5Smjnelson if [[ -z $CODEMGR_WS ]]; then 2574cdf0c1d5Smjnelson print -u2 "SCM not detected/supported and CODEMGR_WS not specified" 2575cdf0c1d5Smjnelson exit 1 2576cdf0c1d5Smjnelson fi 2577cdf0c1d5Smjnelson 2578cdf0c1d5Smjnelson if [[ -z $CODEMGR_PARENT ]]; then 2579cdf0c1d5Smjnelson print -u2 "SCM not detected/supported and CODEMGR_PARENT not specified" 2580cdf0c1d5Smjnelson exit 1 2581cdf0c1d5Smjnelson fi 2582cdf0c1d5Smjnelson 2583cdf0c1d5Smjnelson CWS=$CODEMGR_WS 2584cdf0c1d5Smjnelson PWS=$CODEMGR_PARENT 2585daaffb31Sdpfi 2586daaffb31Sdp 2587daaffb31Sdp# 2588daaffb31Sdp# If the user didn't specify a -i option, check to see if there is a 2589daaffb31Sdp# webrev-info file in the workspace directory. 2590daaffb31Sdp# 2591daaffb31Sdpif [[ -z $iflag && -r "$CWS/webrev-info" ]]; then 2592daaffb31Sdp iflag=1 2593daaffb31Sdp INCLUDE_FILE="$CWS/webrev-info" 2594daaffb31Sdpfi 2595daaffb31Sdp 2596daaffb31Sdpif [[ -n $iflag ]]; then 2597daaffb31Sdp if [[ ! -r $INCLUDE_FILE ]]; then 2598daaffb31Sdp print -u2 "include file '$INCLUDE_FILE' does not exist or is" \ 2599daaffb31Sdp "not readable." 2600daaffb31Sdp exit 1 2601daaffb31Sdp else 2602daaffb31Sdp # 2603daaffb31Sdp # $INCLUDE_FILE may be a relative path, and the script alters 2604daaffb31Sdp # PWD, so we just stash a copy in /tmp. 2605daaffb31Sdp # 2606daaffb31Sdp cp $INCLUDE_FILE /tmp/$$.include 2607daaffb31Sdp fi 2608daaffb31Sdpfi 2609daaffb31Sdp 2610daaffb31Sdp# 2611daaffb31Sdp# Output directory. 2612daaffb31Sdp# 2613daaffb31SdpWDIR=${WDIR:-$CWS/webrev} 2614daaffb31Sdp 2615daaffb31Sdp# 261602d26c39SVladimir Kotal# Name of the webrev, derived from the workspace name or output directory; 261702d26c39SVladimir Kotal# in the future this could potentially be an option. 2618daaffb31Sdp# 261902d26c39SVladimir Kotalif [[ -n $oflag ]]; then 262002d26c39SVladimir Kotal WNAME=${WDIR##*/} 262102d26c39SVladimir Kotalelse 2622daaffb31Sdp WNAME=${CWS##*/} 262302d26c39SVladimir Kotalfi 262402d26c39SVladimir Kotal 2625ba44d8a2SVladimir Kotal# Make sure remote target is well formed for remote upload/delete. 2626ba44d8a2SVladimir Kotalif [[ -n $Dflag || -n $Uflag ]]; then 2627*b0088928SVladimir Kotal # 2628ba44d8a2SVladimir Kotal # If remote target is not specified, build it from scratch using 2629ba44d8a2SVladimir Kotal # the default values. 2630*b0088928SVladimir Kotal # 2631ba44d8a2SVladimir Kotal if [[ -z $tflag ]]; then 2632ba44d8a2SVladimir Kotal remote_target=${DEFAULT_REMOTE_HOST}:${WNAME} 2633ba44d8a2SVladimir Kotal else 2634*b0088928SVladimir Kotal # 2635*b0088928SVladimir Kotal # Check upload target prefix first. 2636*b0088928SVladimir Kotal # 2637*b0088928SVladimir Kotal if [[ "${remote_target}" != ${rsync_prefix}* && 2638*b0088928SVladimir Kotal "${remote_target}" != ${ssh_prefix}* ]]; then 2639*b0088928SVladimir Kotal print "ERROR: invalid prefix of upload URI" \ 2640*b0088928SVladimir Kotal "($remote_target)" 2641*b0088928SVladimir Kotal exit 1 2642*b0088928SVladimir Kotal fi 2643*b0088928SVladimir Kotal # 2644ba44d8a2SVladimir Kotal # If destination specification is not in the form of 2645ba44d8a2SVladimir Kotal # host_spec:remote_dir then assume it is just remote hostname 2646ba44d8a2SVladimir Kotal # and append a colon and destination directory formed from 2647ba44d8a2SVladimir Kotal # local webrev directory name. 2648*b0088928SVladimir Kotal # 2649*b0088928SVladimir Kotal typeset target_no_prefix=${remote_target##*://} 2650*b0088928SVladimir Kotal if [[ ${target_no_prefix} == *:* ]]; then 2651ba44d8a2SVladimir Kotal if [[ "${remote_target}" == *: ]]; then 2652*b0088928SVladimir Kotal remote_target=${remote_target}${WNAME} 2653ba44d8a2SVladimir Kotal fi 2654*b0088928SVladimir Kotal else 2655*b0088928SVladimir Kotal if [[ ${target_no_prefix} == */* ]]; then 2656*b0088928SVladimir Kotal print "ERROR: badly formed upload URI" \ 2657*b0088928SVladimir Kotal "($remote_target)" 2658*b0088928SVladimir Kotal exit 1 2659*b0088928SVladimir Kotal else 2660*b0088928SVladimir Kotal remote_target=${remote_target}:${WNAME} 2661ba44d8a2SVladimir Kotal fi 2662ba44d8a2SVladimir Kotal fi 2663ba44d8a2SVladimir Kotal fi 2664ba44d8a2SVladimir Kotal 2665*b0088928SVladimir Kotal # 2666*b0088928SVladimir Kotal # Strip trailing slash. Each upload method will deal with directory 2667*b0088928SVladimir Kotal # specification separately. 2668*b0088928SVladimir Kotal # 2669*b0088928SVladimir Kotal remote_target=${remote_target%/} 2670*b0088928SVladimir Kotalfi 2671*b0088928SVladimir Kotal 2672*b0088928SVladimir Kotal# 2673ba44d8a2SVladimir Kotal# Option -D by itself (option -U not present) implies no webrev generation. 2674*b0088928SVladimir Kotal# 2675ba44d8a2SVladimir Kotalif [[ -z $Uflag && -n $Dflag ]]; then 2676*b0088928SVladimir Kotal delete_webrev 1 1 2677ba44d8a2SVladimir Kotal exit $? 2678ba44d8a2SVladimir Kotalfi 2679ba44d8a2SVladimir Kotal 2680*b0088928SVladimir Kotal# 2681ba44d8a2SVladimir Kotal# Do not generate the webrev, just upload it or delete it. 2682*b0088928SVladimir Kotal# 2683ba44d8a2SVladimir Kotalif [[ -n $nflag ]]; then 2684ba44d8a2SVladimir Kotal if [[ -n $Dflag ]]; then 2685*b0088928SVladimir Kotal delete_webrev 1 1 2686ba44d8a2SVladimir Kotal (( $? == 0 )) || exit $? 2687ba44d8a2SVladimir Kotal fi 2688ba44d8a2SVladimir Kotal if [[ -n $Uflag ]]; then 268902d26c39SVladimir Kotal upload_webrev 269002d26c39SVladimir Kotal exit $? 269102d26c39SVladimir Kotal fi 2692ba44d8a2SVladimir Kotalfi 2693daaffb31Sdp 2694e0e0293aSjmcpif [ "${WDIR%%/*}" ]; then 26957c478bd9Sstevel@tonic-gate WDIR=$PWD/$WDIR 26967c478bd9Sstevel@tonic-gatefi 2697daaffb31Sdp 2698daaffb31Sdpif [[ ! -d $WDIR ]]; then 2699daaffb31Sdp mkdir -p $WDIR 2700ba44d8a2SVladimir Kotal (( $? != 0 )) && exit 1 27017c478bd9Sstevel@tonic-gatefi 27027c478bd9Sstevel@tonic-gate 2703daaffb31Sdp# 2704daaffb31Sdp# Summarize what we're going to do. 2705daaffb31Sdp# 2706cdf0c1d5Smjnelsonif [[ -n $CWS_REV ]]; then 2707cdf0c1d5Smjnelson print " Workspace: $CWS (at $CWS_REV)" 2708cdf0c1d5Smjnelsonelse 2709daaffb31Sdp print " Workspace: $CWS" 2710cdf0c1d5Smjnelsonfi 2711daaffb31Sdpif [[ -n $parent_webrev ]]; then 2712daaffb31Sdp print "Compare against: webrev at $parent_webrev" 2713daaffb31Sdpelse 2714cdf0c1d5Smjnelson if [[ -n $HG_PARENT ]]; then 2715cdf0c1d5Smjnelson hg_parent_short=`echo $HG_PARENT \ 2716*b0088928SVladimir Kotal | $SED -e 's/\([0-9a-f]\{12\}\).*/\1/'` 2717cdf0c1d5Smjnelson print "Compare against: $PWS (at $hg_parent_short)" 2718cdf0c1d5Smjnelson else 2719daaffb31Sdp print "Compare against: $PWS" 2720daaffb31Sdp fi 2721cdf0c1d5Smjnelsonfi 2722daaffb31Sdp 2723daaffb31Sdp[[ -n $INCLUDE_FILE ]] && print " Including: $INCLUDE_FILE" 2724daaffb31Sdpprint " Output to: $WDIR" 2725daaffb31Sdp 2726daaffb31Sdp# 27277c478bd9Sstevel@tonic-gate# Save the file list in the webrev dir 2728daaffb31Sdp# 2729daaffb31Sdp[[ ! $FLIST -ef $WDIR/file.list ]] && cp $FLIST $WDIR/file.list 27307c478bd9Sstevel@tonic-gate 2731daaffb31Sdp# 2732daaffb31Sdp# Bug IDs will be replaced by a URL. Order of precedence 2733daaffb31Sdp# is: default location, $WEBREV_BUGURL, the -O flag. 2734daaffb31Sdp# 2735daaffb31SdpBUGURL='http://monaco.sfbay.sun.com/detail.jsp?cr=' 2736daaffb31Sdp[[ -n $WEBREV_BUGURL ]] && BUGURL="$WEBREV_BUGURL" 2737daaffb31Sdp[[ -n "$Oflag" ]] && \ 2738daaffb31Sdp BUGURL='http://bugs.opensolaris.org/bugdatabase/view_bug.do?bug_id=' 27397c478bd9Sstevel@tonic-gate 2740daaffb31Sdp# 2741daaffb31Sdp# Likewise, ARC cases will be replaced by a URL. Order of precedence 2742daaffb31Sdp# is: default, $WEBREV_SACURL, the -O flag. 2743daaffb31Sdp# 2744daaffb31Sdp# Note that -O also triggers different substitution behavior for 2745daaffb31Sdp# SACURL. See sac2url(). 2746daaffb31Sdp# 2747daaffb31SdpSACURL='http://sac.eng.sun.com' 2748daaffb31Sdp[[ -n $WEBREV_SACURL ]] && SACURL="$WEBREV_SACURL" 2749e0e0293aSjmcp[[ -n "$Oflag" ]] && \ 2750daaffb31Sdp SACURL='http://www.opensolaris.org/os/community/arc/caselog' 27517c478bd9Sstevel@tonic-gate 2752daaffb31Sdprm -f $WDIR/$WNAME.patch 2753daaffb31Sdprm -f $WDIR/$WNAME.ps 2754daaffb31Sdprm -f $WDIR/$WNAME.pdf 27557c478bd9Sstevel@tonic-gate 2756daaffb31Sdptouch $WDIR/$WNAME.patch 27577c478bd9Sstevel@tonic-gate 2758daaffb31Sdpprint " Output Files:" 2759daaffb31Sdp 2760daaffb31Sdp# 2761daaffb31Sdp# Clean up the file list: Remove comments, blank lines and env variables. 2762daaffb31Sdp# 2763*b0088928SVladimir Kotal$SED -e "s/#.*$//" -e "/=/d" -e "/^[ ]*$/d" $FLIST > /tmp/$$.flist.clean 2764daaffb31SdpFLIST=/tmp/$$.flist.clean 2765daaffb31Sdp 2766daaffb31Sdp# 2767cdf0c1d5Smjnelson# For Mercurial, create a cache of manifest entries. 2768cdf0c1d5Smjnelson# 2769cdf0c1d5Smjnelsonif [[ $SCM_MODE == "mercurial" ]]; then 2770cdf0c1d5Smjnelson # 2771cdf0c1d5Smjnelson # Transform the FLIST into a temporary sed script that matches 2772cdf0c1d5Smjnelson # relevant entries in the Mercurial manifest as follows: 2773cdf0c1d5Smjnelson # 1) The script will be used against the parent revision manifest, 2774cdf0c1d5Smjnelson # so for FLIST lines that have two filenames (a renamed file) 2775cdf0c1d5Smjnelson # keep only the old name. 2776cdf0c1d5Smjnelson # 2) Escape all forward slashes the filename. 2777cdf0c1d5Smjnelson # 3) Change the filename into another sed command that matches 2778cdf0c1d5Smjnelson # that file in "hg manifest -v" output: start of line, three 2779cdf0c1d5Smjnelson # octal digits for file permissions, space, a file type flag 2780cdf0c1d5Smjnelson # character, space, the filename, end of line. 2781cdf0c1d5Smjnelson # 2782cdf0c1d5Smjnelson SEDFILE=/tmp/$$.manifest.sed 2783*b0088928SVladimir Kotal $SED ' 2784cdf0c1d5Smjnelson s#^[^ ]* ## 2785cdf0c1d5Smjnelson s#/#\\\/#g 2786cdf0c1d5Smjnelson s#^.*$#/^... . &$/p# 2787cdf0c1d5Smjnelson ' < $FLIST > $SEDFILE 2788cdf0c1d5Smjnelson 2789cdf0c1d5Smjnelson # 2790cdf0c1d5Smjnelson # Apply the generated script to the output of "hg manifest -v" 2791cdf0c1d5Smjnelson # to get the relevant subset for this webrev. 2792cdf0c1d5Smjnelson # 2793cdf0c1d5Smjnelson HG_PARENT_MANIFEST=/tmp/$$.manifest 2794cdf0c1d5Smjnelson hg -R $CWS manifest -v -r $HG_PARENT | 2795*b0088928SVladimir Kotal $SED -n -f $SEDFILE > $HG_PARENT_MANIFEST 2796cdf0c1d5Smjnelsonfi 2797cdf0c1d5Smjnelson 2798cdf0c1d5Smjnelson# 2799daaffb31Sdp# First pass through the files: generate the per-file webrev HTML-files. 2800daaffb31Sdp# 2801daaffb31Sdpcat $FLIST | while read LINE 28027c478bd9Sstevel@tonic-gatedo 28037c478bd9Sstevel@tonic-gate set - $LINE 28047c478bd9Sstevel@tonic-gate P=$1 28057c478bd9Sstevel@tonic-gate 2806daaffb31Sdp # 2807daaffb31Sdp # Normally, each line in the file list is just a pathname of a 2808daaffb31Sdp # file that has been modified or created in the child. A file 2809daaffb31Sdp # that is renamed in the child workspace has two names on the 2810daaffb31Sdp # line: new name followed by the old name. 2811daaffb31Sdp # 2812daaffb31Sdp oldname="" 2813daaffb31Sdp oldpath="" 2814daaffb31Sdp rename= 2815daaffb31Sdp if [[ $# -eq 2 ]]; then 28167c478bd9Sstevel@tonic-gate PP=$2 # old filename 2817daaffb31Sdp oldname=" (was $PP)" 2818daaffb31Sdp oldpath="$PP" 2819daaffb31Sdp rename=1 28207c478bd9Sstevel@tonic-gate PDIR=${PP%/*} 2821daaffb31Sdp if [[ $PDIR == $PP ]]; then 28227c478bd9Sstevel@tonic-gate PDIR="." # File at root of workspace 28237c478bd9Sstevel@tonic-gate fi 28247c478bd9Sstevel@tonic-gate 28257c478bd9Sstevel@tonic-gate PF=${PP##*/} 28267c478bd9Sstevel@tonic-gate 28277c478bd9Sstevel@tonic-gate DIR=${P%/*} 2828daaffb31Sdp if [[ $DIR == $P ]]; then 28297c478bd9Sstevel@tonic-gate DIR="." # File at root of workspace 28307c478bd9Sstevel@tonic-gate fi 28317c478bd9Sstevel@tonic-gate 28327c478bd9Sstevel@tonic-gate F=${P##*/} 2833daaffb31Sdp 28347c478bd9Sstevel@tonic-gate else 28357c478bd9Sstevel@tonic-gate DIR=${P%/*} 2836daaffb31Sdp if [[ "$DIR" == "$P" ]]; then 28377c478bd9Sstevel@tonic-gate DIR="." # File at root of workspace 28387c478bd9Sstevel@tonic-gate fi 28397c478bd9Sstevel@tonic-gate 28407c478bd9Sstevel@tonic-gate F=${P##*/} 28417c478bd9Sstevel@tonic-gate 28427c478bd9Sstevel@tonic-gate PP=$P 28437c478bd9Sstevel@tonic-gate PDIR=$DIR 28447c478bd9Sstevel@tonic-gate PF=$F 28457c478bd9Sstevel@tonic-gate fi 28467c478bd9Sstevel@tonic-gate 2847daaffb31Sdp COMM=`getcomments html $P $PP` 28487c478bd9Sstevel@tonic-gate 2849daaffb31Sdp print "\t$P$oldname\n\t\t\c" 28507c478bd9Sstevel@tonic-gate 28517c478bd9Sstevel@tonic-gate # Make the webrev mirror directory if necessary 28527c478bd9Sstevel@tonic-gate mkdir -p $WDIR/$DIR 28537c478bd9Sstevel@tonic-gate 2854daaffb31Sdp # 2855daaffb31Sdp # If we're in OpenSolaris mode, we enforce a minor policy: 2856daaffb31Sdp # help to make sure the reviewer doesn't accidentally publish 2857e0e0293aSjmcp # source which is in usr/closed/* or deleted_files/usr/closed/* 2858daaffb31Sdp # 2859e0e0293aSjmcp if [[ -n "$Oflag" ]]; then 2860daaffb31Sdp pclosed=${P##usr/closed/} 2861e0e0293aSjmcp pdeleted=${P##deleted_files/usr/closed/} 2862e0e0293aSjmcp if [[ "$pclosed" != "$P" || "$pdeleted" != "$P" ]]; then 2863daaffb31Sdp print "*** Omitting closed source for OpenSolaris" \ 2864daaffb31Sdp "mode review" 2865daaffb31Sdp continue 2866daaffb31Sdp fi 2867daaffb31Sdp fi 2868daaffb31Sdp 2869daaffb31Sdp # 2870cdf0c1d5Smjnelson # We stash old and new files into parallel directories in $WDIR 2871daaffb31Sdp # and do our diffs there. This makes it possible to generate 2872daaffb31Sdp # clean looking diffs which don't have absolute paths present. 2873daaffb31Sdp # 2874daaffb31Sdp 2875cdf0c1d5Smjnelson build_old_new "$WDIR" "$PWS" "$PDIR" "$PF" "$CWS" "$DIR" "$F" || \ 28767c478bd9Sstevel@tonic-gate continue 28777c478bd9Sstevel@tonic-gate 2878cdf0c1d5Smjnelson # 2879cdf0c1d5Smjnelson # Keep the old PWD around, so we can safely switch back after 2880cdf0c1d5Smjnelson # diff generation, such that build_old_new runs in a 2881cdf0c1d5Smjnelson # consistent environment. 2882cdf0c1d5Smjnelson # 2883cdf0c1d5Smjnelson OWD=$PWD 2884daaffb31Sdp cd $WDIR/raw_files 2885daaffb31Sdp ofile=old/$PDIR/$PF 2886daaffb31Sdp nfile=new/$DIR/$F 28877c478bd9Sstevel@tonic-gate 2888daaffb31Sdp mv_but_nodiff= 2889daaffb31Sdp cmp $ofile $nfile > /dev/null 2>&1 2890daaffb31Sdp if [[ $? == 0 && $rename == 1 ]]; then 2891daaffb31Sdp mv_but_nodiff=1 2892daaffb31Sdp fi 2893daaffb31Sdp 2894daaffb31Sdp # 2895daaffb31Sdp # If we have old and new versions of the file then run the appropriate 2896daaffb31Sdp # diffs. This is complicated by a couple of factors: 2897daaffb31Sdp # 2898daaffb31Sdp # - renames must be handled specially: we emit a 'remove' 2899daaffb31Sdp # diff and an 'add' diff 2900daaffb31Sdp # - new files and deleted files must be handled specially 2901daaffb31Sdp # - Solaris patch(1m) can't cope with file creation 2902daaffb31Sdp # (and hence renames) as of this writing. 2903daaffb31Sdp # - To make matters worse, gnu patch doesn't interpret the 2904daaffb31Sdp # output of Solaris diff properly when it comes to 2905daaffb31Sdp # adds and deletes. We need to do some "cleansing" 2906daaffb31Sdp # transformations: 2907daaffb31Sdp # [to add a file] @@ -1,0 +X,Y @@ --> @@ -0,0 +X,Y @@ 2908daaffb31Sdp # [to del a file] @@ -X,Y +1,0 @@ --> @@ -X,Y +0,0 @@ 2909daaffb31Sdp # 2910*b0088928SVladimir Kotal cleanse_rmfile="$SED 's/^\(@@ [0-9+,-]*\) [0-9+,-]* @@$/\1 +0,0 @@/'" 2911*b0088928SVladimir Kotal cleanse_newfile="$SED 's/^@@ [0-9+,-]* \([0-9+,-]* @@\)$/@@ -0,0 \1/'" 2912daaffb31Sdp 2913daaffb31Sdp rm -f $WDIR/$DIR/$F.patch 2914daaffb31Sdp if [[ -z $rename ]]; then 2915e0e0293aSjmcp if [ ! -f "$ofile" ]; then 2916daaffb31Sdp diff -u /dev/null $nfile | sh -c "$cleanse_newfile" \ 2917daaffb31Sdp > $WDIR/$DIR/$F.patch 2918e0e0293aSjmcp elif [ ! -f "$nfile" ]; then 2919daaffb31Sdp diff -u $ofile /dev/null | sh -c "$cleanse_rmfile" \ 2920daaffb31Sdp > $WDIR/$DIR/$F.patch 2921daaffb31Sdp else 2922daaffb31Sdp diff -u $ofile $nfile > $WDIR/$DIR/$F.patch 2923daaffb31Sdp fi 2924daaffb31Sdp else 2925daaffb31Sdp diff -u $ofile /dev/null | sh -c "$cleanse_rmfile" \ 2926daaffb31Sdp > $WDIR/$DIR/$F.patch 2927daaffb31Sdp 2928daaffb31Sdp diff -u /dev/null $nfile | sh -c "$cleanse_newfile" \ 2929daaffb31Sdp >> $WDIR/$DIR/$F.patch 2930daaffb31Sdp 2931daaffb31Sdp fi 2932daaffb31Sdp 2933daaffb31Sdp # 2934daaffb31Sdp # Tack the patch we just made onto the accumulated patch for the 2935daaffb31Sdp # whole wad. 2936daaffb31Sdp # 2937daaffb31Sdp cat $WDIR/$DIR/$F.patch >> $WDIR/$WNAME.patch 2938daaffb31Sdp 2939daaffb31Sdp print " patch\c" 2940daaffb31Sdp 2941daaffb31Sdp if [[ -f $ofile && -f $nfile && -z $mv_but_nodiff ]]; then 2942daaffb31Sdp 2943daaffb31Sdp ${CDIFFCMD:-diff -bt -C 5} $ofile $nfile > $WDIR/$DIR/$F.cdiff 2944daaffb31Sdp diff_to_html $F $DIR/$F "C" "$COMM" < $WDIR/$DIR/$F.cdiff \ 2945daaffb31Sdp > $WDIR/$DIR/$F.cdiff.html 29467c478bd9Sstevel@tonic-gate print " cdiffs\c" 29477c478bd9Sstevel@tonic-gate 2948daaffb31Sdp ${UDIFFCMD:-diff -bt -U 5} $ofile $nfile > $WDIR/$DIR/$F.udiff 2949daaffb31Sdp diff_to_html $F $DIR/$F "U" "$COMM" < $WDIR/$DIR/$F.udiff \ 2950daaffb31Sdp > $WDIR/$DIR/$F.udiff.html 2951daaffb31Sdp 29527c478bd9Sstevel@tonic-gate print " udiffs\c" 29537c478bd9Sstevel@tonic-gate 29547c478bd9Sstevel@tonic-gate if [[ -x $WDIFF ]]; then 2955daaffb31Sdp $WDIFF -c "$COMM" \ 2956daaffb31Sdp -t "$WNAME Wdiff $DIR/$F" $ofile $nfile > \ 2957daaffb31Sdp $WDIR/$DIR/$F.wdiff.html 2>/dev/null 2958daaffb31Sdp if [[ $? -eq 0 ]]; then 29597c478bd9Sstevel@tonic-gate print " wdiffs\c" 2960daaffb31Sdp else 2961daaffb31Sdp print " wdiffs[fail]\c" 2962daaffb31Sdp fi 29637c478bd9Sstevel@tonic-gate fi 29647c478bd9Sstevel@tonic-gate 2965daaffb31Sdp sdiff_to_html $ofile $nfile $F $DIR "$COMM" \ 2966daaffb31Sdp > $WDIR/$DIR/$F.sdiff.html 29677c478bd9Sstevel@tonic-gate print " sdiffs\c" 29687c478bd9Sstevel@tonic-gate 29697c478bd9Sstevel@tonic-gate print " frames\c" 29707c478bd9Sstevel@tonic-gate 29717c478bd9Sstevel@tonic-gate rm -f $WDIR/$DIR/$F.cdiff $WDIR/$DIR/$F.udiff 29727c478bd9Sstevel@tonic-gate 2973daaffb31Sdp difflines $ofile $nfile > $WDIR/$DIR/$F.count 2974daaffb31Sdp 2975daaffb31Sdp elif [[ -f $ofile && -f $nfile && -n $mv_but_nodiff ]]; then 2976daaffb31Sdp # renamed file: may also have differences 2977daaffb31Sdp difflines $ofile $nfile > $WDIR/$DIR/$F.count 2978daaffb31Sdp elif [[ -f $nfile ]]; then 29797c478bd9Sstevel@tonic-gate # new file: count added lines 2980daaffb31Sdp difflines /dev/null $nfile > $WDIR/$DIR/$F.count 2981daaffb31Sdp elif [[ -f $ofile ]]; then 29827c478bd9Sstevel@tonic-gate # old file: count deleted lines 2983daaffb31Sdp difflines $ofile /dev/null > $WDIR/$DIR/$F.count 29847c478bd9Sstevel@tonic-gate fi 29857c478bd9Sstevel@tonic-gate 2986daaffb31Sdp # 2987daaffb31Sdp # Now we generate the postscript for this file. We generate diffs 2988daaffb31Sdp # only in the event that there is delta, or the file is new (it seems 2989daaffb31Sdp # tree-killing to print out the contents of deleted files). 2990daaffb31Sdp # 2991daaffb31Sdp if [[ -f $nfile ]]; then 2992daaffb31Sdp ocr=$ofile 2993daaffb31Sdp [[ ! -f $ofile ]] && ocr=/dev/null 2994daaffb31Sdp 2995daaffb31Sdp if [[ -z $mv_but_nodiff ]]; then 2996daaffb31Sdp textcomm=`getcomments text $P $PP` 299714983201Sdp if [[ -x $CODEREVIEW ]]; then 299814983201Sdp $CODEREVIEW -y "$textcomm" \ 299914983201Sdp -e $ocr $nfile \ 300014983201Sdp > /tmp/$$.psfile 2>/dev/null && 300114983201Sdp cat /tmp/$$.psfile >> $WDIR/$WNAME.ps 3002daaffb31Sdp if [[ $? -eq 0 ]]; then 3003daaffb31Sdp print " ps\c" 3004daaffb31Sdp else 3005daaffb31Sdp print " ps[fail]\c" 3006daaffb31Sdp fi 3007daaffb31Sdp fi 3008daaffb31Sdp fi 300914983201Sdp fi 3010daaffb31Sdp 3011cdf0c1d5Smjnelson if [[ -f $ofile ]]; then 3012cdf0c1d5Smjnelson source_to_html Old $PP < $ofile > $WDIR/$DIR/$F-.html 30137c478bd9Sstevel@tonic-gate print " old\c" 30147c478bd9Sstevel@tonic-gate fi 30157c478bd9Sstevel@tonic-gate 3016daaffb31Sdp if [[ -f $nfile ]]; then 3017daaffb31Sdp source_to_html New $P < $nfile > $WDIR/$DIR/$F.html 30187c478bd9Sstevel@tonic-gate print " new\c" 30197c478bd9Sstevel@tonic-gate fi 30207c478bd9Sstevel@tonic-gate 3021cdf0c1d5Smjnelson cd $OWD 3022cdf0c1d5Smjnelson 3023daaffb31Sdp print 30247c478bd9Sstevel@tonic-gatedone 30257c478bd9Sstevel@tonic-gate 3026daaffb31Sdpframe_nav_js > $WDIR/ancnav.js 30277c478bd9Sstevel@tonic-gateframe_navigation > $WDIR/ancnav.html 3028daaffb31Sdp 302914983201Sdpif [[ ! -f $WDIR/$WNAME.ps ]]; then 303014983201Sdp print " Generating PDF: Skipped: no output available" 303114983201Sdpelif [[ -x $CODEREVIEW && -x $PS2PDF ]]; then 303214983201Sdp print " Generating PDF: \c" 303314983201Sdp fix_postscript $WDIR/$WNAME.ps | $PS2PDF - > $WDIR/$WNAME.pdf 3034daaffb31Sdp print "Done." 303514983201Sdpelse 303614983201Sdp print " Generating PDF: Skipped: missing 'ps2pdf' or 'codereview'" 303714983201Sdpfi 30387c478bd9Sstevel@tonic-gate 3039e0e0293aSjmcp# If we're in OpenSolaris mode and there's a closed dir under $WDIR, 3040e0e0293aSjmcp# delete it - prevent accidental publishing of closed source 3041e0e0293aSjmcp 3042e0e0293aSjmcpif [[ -n "$Oflag" ]]; then 3043ba44d8a2SVladimir Kotal $FIND $WDIR -type d -name closed -exec /bin/rm -rf {} \; 3044e0e0293aSjmcpfi 3045e0e0293aSjmcp 30467c478bd9Sstevel@tonic-gate# Now build the index.html file that contains 30477c478bd9Sstevel@tonic-gate# links to the source files and their diffs. 30487c478bd9Sstevel@tonic-gate 30497c478bd9Sstevel@tonic-gatecd $CWS 30507c478bd9Sstevel@tonic-gate 30517c478bd9Sstevel@tonic-gate# Save total changed lines for Code Inspection. 3052daaffb31Sdpprint "$TOTL" > $WDIR/TotalChangedLines 30537c478bd9Sstevel@tonic-gate 3054daaffb31Sdpprint " index.html: \c" 30557c478bd9Sstevel@tonic-gateINDEXFILE=$WDIR/index.html 30567c478bd9Sstevel@tonic-gateexec 3<&1 # duplicate stdout to FD3. 30577c478bd9Sstevel@tonic-gateexec 1<&- # Close stdout. 30587c478bd9Sstevel@tonic-gateexec > $INDEXFILE # Open stdout to index file. 30597c478bd9Sstevel@tonic-gate 3060daaffb31Sdpprint "$HTML<head>$STDHEAD" 3061daaffb31Sdpprint "<title>$WNAME</title>" 3062daaffb31Sdpprint "</head>" 3063daaffb31Sdpprint "<body id=\"SUNWwebrev\">" 3064daaffb31Sdpprint "<div class=\"summary\">" 3065daaffb31Sdpprint "<h2>Code Review for $WNAME</h2>" 30667c478bd9Sstevel@tonic-gate 3067daaffb31Sdpprint "<table>" 30687c478bd9Sstevel@tonic-gate 3069daaffb31Sdp# 3070cdf0c1d5Smjnelson# Get the preparer's name: 3071daaffb31Sdp# 3072cdf0c1d5Smjnelson# If the SCM detected is Mercurial, and the configuration property 3073cdf0c1d5Smjnelson# ui.username is available, use that, but be careful to properly escape 3074cdf0c1d5Smjnelson# angle brackets (HTML syntax characters) in the email address. 3075cdf0c1d5Smjnelson# 3076cdf0c1d5Smjnelson# Otherwise, use the current userid in the form "John Doe (jdoe)", but 3077cdf0c1d5Smjnelson# to maintain compatibility with passwd(4), we must support '&' substitutions. 3078cdf0c1d5Smjnelson# 3079cdf0c1d5Smjnelsonpreparer= 3080cdf0c1d5Smjnelsonif [[ "$SCM_MODE" == mercurial ]]; then 3081cdf0c1d5Smjnelson preparer=`hg showconfig ui.username 2>/dev/null` 3082cdf0c1d5Smjnelson if [[ -n "$preparer" ]]; then 3083cdf0c1d5Smjnelson preparer="$(echo "$preparer" | html_quote)" 3084cdf0c1d5Smjnelson fi 3085cdf0c1d5Smjnelsonfi 3086cdf0c1d5Smjnelsonif [[ -z "$preparer" ]]; then 3087cdf0c1d5Smjnelson preparer=$( 3088cdf0c1d5Smjnelson $PERL -e ' 3089cdf0c1d5Smjnelson ($login, $pw, $uid, $gid, $quota, $cmt, $gcos) = getpwuid($<); 3090cdf0c1d5Smjnelson if ($login) { 3091cdf0c1d5Smjnelson $gcos =~ s/\&/ucfirst($login)/e; 3092cdf0c1d5Smjnelson printf "%s (%s)\n", $gcos, $login; 3093cdf0c1d5Smjnelson } else { 3094cdf0c1d5Smjnelson printf "(unknown)\n"; 3095cdf0c1d5Smjnelson } 3096cdf0c1d5Smjnelson ') 3097daaffb31Sdpfi 3098daaffb31Sdp 3099cdf0c1d5Smjnelsonprint "<tr><th>Prepared by:</th><td>$preparer on `date`</td></tr>" 3100cdf0c1d5Smjnelsonprint "<tr><th>Workspace:</th><td>$CWS" 3101cdf0c1d5Smjnelsonif [[ -n $CWS_REV ]]; then 3102cdf0c1d5Smjnelson print "(at $CWS_REV)" 3103cdf0c1d5Smjnelsonfi 3104cdf0c1d5Smjnelsonprint "</td></tr>" 3105daaffb31Sdpprint "<tr><th>Compare against:</th><td>" 3106daaffb31Sdpif [[ -n $parent_webrev ]]; then 3107daaffb31Sdp print "webrev at $parent_webrev" 3108daaffb31Sdpelse 3109daaffb31Sdp print "$PWS" 3110cdf0c1d5Smjnelson if [[ -n $hg_parent_short ]]; then 3111cdf0c1d5Smjnelson print "(at $hg_parent_short)" 3112cdf0c1d5Smjnelson fi 3113daaffb31Sdpfi 3114daaffb31Sdpprint "</td></tr>" 3115daaffb31Sdpprint "<tr><th>Summary of changes:</th><td>" 3116daaffb31SdpprintCI $TOTL $TINS $TDEL $TMOD $TUNC 3117daaffb31Sdpprint "</td></tr>" 3118daaffb31Sdp 3119daaffb31Sdpif [[ -f $WDIR/$WNAME.patch ]]; then 3120371d72daSLubomir Sedlacik wpatch_url="$(print $WNAME.patch | url_encode)" 3121daaffb31Sdp print "<tr><th>Patch of changes:</th><td>" 3122371d72daSLubomir Sedlacik print "<a href=\"$wpatch_url\">$WNAME.patch</a></td></tr>" 3123daaffb31Sdpfi 3124daaffb31Sdpif [[ -f $WDIR/$WNAME.pdf ]]; then 3125371d72daSLubomir Sedlacik wpdf_url="$(print $WNAME.pdf | url_encode)" 3126daaffb31Sdp print "<tr><th>Printable review:</th><td>" 3127371d72daSLubomir Sedlacik print "<a href=\"$wpdf_url\">$WNAME.pdf</a></td></tr>" 3128daaffb31Sdpfi 3129daaffb31Sdp 3130daaffb31Sdpif [[ -n "$iflag" ]]; then 3131daaffb31Sdp print "<tr><th>Author comments:</th><td><div>" 3132daaffb31Sdp cat /tmp/$$.include 3133daaffb31Sdp print "</div></td></tr>" 3134daaffb31Sdpfi 3135daaffb31Sdpprint "</table>" 3136daaffb31Sdpprint "</div>" 3137daaffb31Sdp 3138daaffb31Sdp# 3139daaffb31Sdp# Second pass through the files: generate the rest of the index file 3140daaffb31Sdp# 3141daaffb31Sdpcat $FLIST | while read LINE 31427c478bd9Sstevel@tonic-gatedo 31437c478bd9Sstevel@tonic-gate set - $LINE 31447c478bd9Sstevel@tonic-gate P=$1 31457c478bd9Sstevel@tonic-gate 3146daaffb31Sdp if [[ $# == 2 ]]; then 31477c478bd9Sstevel@tonic-gate PP=$2 3148cdf0c1d5Smjnelson oldname="$PP" 31497c478bd9Sstevel@tonic-gate else 31507c478bd9Sstevel@tonic-gate PP=$P 3151daaffb31Sdp oldname="" 3152daaffb31Sdp fi 3153daaffb31Sdp 3154cdf0c1d5Smjnelson mv_but_nodiff= 3155cdf0c1d5Smjnelson cmp $WDIR/raw_files/old/$PP $WDIR/raw_files/new/$P > /dev/null 2>&1 3156cdf0c1d5Smjnelson if [[ $? == 0 && -n "$oldname" ]]; then 3157cdf0c1d5Smjnelson mv_but_nodiff=1 3158cdf0c1d5Smjnelson fi 3159cdf0c1d5Smjnelson 3160daaffb31Sdp DIR=${P%/*} 3161daaffb31Sdp if [[ $DIR == $P ]]; then 3162daaffb31Sdp DIR="." # File at root of workspace 31637c478bd9Sstevel@tonic-gate fi 31647c478bd9Sstevel@tonic-gate 31657c478bd9Sstevel@tonic-gate # Avoid processing the same file twice. 31667c478bd9Sstevel@tonic-gate # It's possible for renamed files to 31677c478bd9Sstevel@tonic-gate # appear twice in the file list 31687c478bd9Sstevel@tonic-gate 31697c478bd9Sstevel@tonic-gate F=$WDIR/$P 31707c478bd9Sstevel@tonic-gate 3171daaffb31Sdp print "<p>" 31727c478bd9Sstevel@tonic-gate 31737c478bd9Sstevel@tonic-gate # If there's a diffs file, make diffs links 31747c478bd9Sstevel@tonic-gate 3175daaffb31Sdp if [[ -f $F.cdiff.html ]]; then 3176371d72daSLubomir Sedlacik cdiff_url="$(print $P.cdiff.html | url_encode)" 3177371d72daSLubomir Sedlacik udiff_url="$(print $P.udiff.html | url_encode)" 3178371d72daSLubomir Sedlacik print "<a href=\"$cdiff_url\">Cdiffs</a>" 3179371d72daSLubomir Sedlacik print "<a href=\"$udiff_url\">Udiffs</a>" 31807c478bd9Sstevel@tonic-gate 3181daaffb31Sdp if [[ -f $F.wdiff.html && -x $WDIFF ]]; then 3182371d72daSLubomir Sedlacik wdiff_url="$(print $P.wdiff.html | url_encode)" 3183371d72daSLubomir Sedlacik print "<a href=\"$wdiff_url\">Wdiffs</a>" 31847c478bd9Sstevel@tonic-gate fi 31857c478bd9Sstevel@tonic-gate 3186371d72daSLubomir Sedlacik sdiff_url="$(print $P.sdiff.html | url_encode)" 3187371d72daSLubomir Sedlacik print "<a href=\"$sdiff_url\">Sdiffs</a>" 31887c478bd9Sstevel@tonic-gate 3189371d72daSLubomir Sedlacik frames_url="$(print $P.frames.html | url_encode)" 3190371d72daSLubomir Sedlacik print "<a href=\"$frames_url\">Frames</a>" 31917c478bd9Sstevel@tonic-gate else 3192daaffb31Sdp print " ------ ------ ------" 31937c478bd9Sstevel@tonic-gate 3194daaffb31Sdp if [[ -x $WDIFF ]]; then 31957c478bd9Sstevel@tonic-gate print " ------" 31967c478bd9Sstevel@tonic-gate fi 3197daaffb31Sdp 3198daaffb31Sdp print " ------" 31997c478bd9Sstevel@tonic-gate fi 32007c478bd9Sstevel@tonic-gate 32017c478bd9Sstevel@tonic-gate # If there's an old file, make the link 32027c478bd9Sstevel@tonic-gate 3203daaffb31Sdp if [[ -f $F-.html ]]; then 3204371d72daSLubomir Sedlacik oldfile_url="$(print $P-.html | url_encode)" 3205371d72daSLubomir Sedlacik print "<a href=\"$oldfile_url\">Old</a>" 32067c478bd9Sstevel@tonic-gate else 3207daaffb31Sdp print " ---" 32087c478bd9Sstevel@tonic-gate fi 32097c478bd9Sstevel@tonic-gate 32107c478bd9Sstevel@tonic-gate # If there's an new file, make the link 32117c478bd9Sstevel@tonic-gate 3212daaffb31Sdp if [[ -f $F.html ]]; then 3213371d72daSLubomir Sedlacik newfile_url="$(print $P.html | url_encode)" 3214371d72daSLubomir Sedlacik print "<a href=\"$newfile_url\">New</a>" 32157c478bd9Sstevel@tonic-gate else 3216daaffb31Sdp print " ---" 32177c478bd9Sstevel@tonic-gate fi 32187c478bd9Sstevel@tonic-gate 3219daaffb31Sdp if [[ -f $F.patch ]]; then 3220371d72daSLubomir Sedlacik patch_url="$(print $P.patch | url_encode)" 3221371d72daSLubomir Sedlacik print "<a href=\"$patch_url\">Patch</a>" 3222daaffb31Sdp else 3223daaffb31Sdp print " -----" 3224daaffb31Sdp fi 3225daaffb31Sdp 3226daaffb31Sdp if [[ -f $WDIR/raw_files/new/$P ]]; then 3227371d72daSLubomir Sedlacik rawfiles_url="$(print raw_files/new/$P | url_encode)" 3228371d72daSLubomir Sedlacik print "<a href=\"$rawfiles_url\">Raw</a>" 3229daaffb31Sdp else 3230daaffb31Sdp print " ---" 3231daaffb31Sdp fi 3232daaffb31Sdp 3233cdf0c1d5Smjnelson print "<b>$P</b>" 3234cdf0c1d5Smjnelson 3235cdf0c1d5Smjnelson # For renamed files, clearly state whether or not they are modified 3236cdf0c1d5Smjnelson if [[ -n "$oldname" ]]; then 3237cdf0c1d5Smjnelson if [[ -n "$mv_but_nodiff" ]]; then 3238cdf0c1d5Smjnelson print "<i>(renamed only, was $oldname)</i>" 3239cdf0c1d5Smjnelson else 3240cdf0c1d5Smjnelson print "<i>(modified and renamed, was $oldname)</i>" 3241cdf0c1d5Smjnelson fi 3242cdf0c1d5Smjnelson fi 3243cdf0c1d5Smjnelson 3244cdf0c1d5Smjnelson # If there's an old file, but no new file, the file was deleted 3245cdf0c1d5Smjnelson if [[ -f $F-.html && ! -f $F.html ]]; then 3246cdf0c1d5Smjnelson print " <i>(deleted)</i>" 3247cdf0c1d5Smjnelson fi 3248daaffb31Sdp 3249daaffb31Sdp # 3250e0e0293aSjmcp # Check for usr/closed and deleted_files/usr/closed 3251daaffb31Sdp # 3252daaffb31Sdp if [ ! -z "$Oflag" ]; then 3253e0e0293aSjmcp if [[ $P == usr/closed/* || \ 3254e0e0293aSjmcp $P == deleted_files/usr/closed/* ]]; then 3255daaffb31Sdp print " <i>Closed source: omitted from" \ 3256daaffb31Sdp "this review</i>" 3257daaffb31Sdp fi 3258daaffb31Sdp fi 3259daaffb31Sdp 3260daaffb31Sdp print "</p>" 32617c478bd9Sstevel@tonic-gate # Insert delta comments 32627c478bd9Sstevel@tonic-gate 3263daaffb31Sdp print "<blockquote><pre>" 3264daaffb31Sdp getcomments html $P $PP 3265daaffb31Sdp print "</pre>" 32667c478bd9Sstevel@tonic-gate 32677c478bd9Sstevel@tonic-gate # Add additional comments comment 32687c478bd9Sstevel@tonic-gate 3269daaffb31Sdp print "<!-- Add comments to explain changes in $P here -->" 32707c478bd9Sstevel@tonic-gate 32717c478bd9Sstevel@tonic-gate # Add count of changes. 32727c478bd9Sstevel@tonic-gate 3273daaffb31Sdp if [[ -f $F.count ]]; then 32747c478bd9Sstevel@tonic-gate cat $F.count 32757c478bd9Sstevel@tonic-gate rm $F.count 32767c478bd9Sstevel@tonic-gate fi 3277cdf0c1d5Smjnelson 3278cdf0c1d5Smjnelson if [[ $SCM_MODE == "teamware" || 3279cdf0c1d5Smjnelson $SCM_MODE == "mercurial" || 3280cdf0c1d5Smjnelson $SCM_MODE == "unknown" ]]; then 3281cdf0c1d5Smjnelson 3282cdf0c1d5Smjnelson # Include warnings for important file mode situations: 3283cdf0c1d5Smjnelson # 1) New executable files 3284cdf0c1d5Smjnelson # 2) Permission changes of any kind 3285cdf0c1d5Smjnelson # 3) Existing executable files 3286cdf0c1d5Smjnelson 3287cdf0c1d5Smjnelson old_mode= 3288cdf0c1d5Smjnelson if [[ -f $WDIR/raw_files/old/$PP ]]; then 3289cdf0c1d5Smjnelson old_mode=`get_file_mode $WDIR/raw_files/old/$PP` 3290cdf0c1d5Smjnelson fi 3291cdf0c1d5Smjnelson 3292cdf0c1d5Smjnelson new_mode= 3293cdf0c1d5Smjnelson if [[ -f $WDIR/raw_files/new/$P ]]; then 3294cdf0c1d5Smjnelson new_mode=`get_file_mode $WDIR/raw_files/new/$P` 3295cdf0c1d5Smjnelson fi 3296cdf0c1d5Smjnelson 3297cdf0c1d5Smjnelson if [[ -z "$old_mode" && "$new_mode" = *[1357]* ]]; then 3298cdf0c1d5Smjnelson print "<span class=\"chmod\">" 3299cdf0c1d5Smjnelson print "<p>new executable file: mode $new_mode</p>" 3300cdf0c1d5Smjnelson print "</span>" 3301cdf0c1d5Smjnelson elif [[ -n "$old_mode" && -n "$new_mode" && 3302cdf0c1d5Smjnelson "$old_mode" != "$new_mode" ]]; then 3303cdf0c1d5Smjnelson print "<span class=\"chmod\">" 3304cdf0c1d5Smjnelson print "<p>mode change: $old_mode to $new_mode</p>" 3305cdf0c1d5Smjnelson print "</span>" 3306cdf0c1d5Smjnelson elif [[ "$new_mode" = *[1357]* ]]; then 3307cdf0c1d5Smjnelson print "<span class=\"chmod\">" 3308cdf0c1d5Smjnelson print "<p>executable file: mode $new_mode</p>" 3309cdf0c1d5Smjnelson print "</span>" 3310cdf0c1d5Smjnelson fi 3311cdf0c1d5Smjnelson fi 3312cdf0c1d5Smjnelson 3313daaffb31Sdp print "</blockquote>" 33147c478bd9Sstevel@tonic-gatedone 33157c478bd9Sstevel@tonic-gate 3316daaffb31Sdpprint 3317daaffb31Sdpprint 3318cac38512Smjnelsonprint "<hr></hr>" 3319daaffb31Sdpprint "<p style=\"font-size: small\">" 33209a70fc3bSMark J. Nelsonprint "This code review page was prepared using <b>$0</b>." 3321daaffb31Sdpprint "Webrev is maintained by the <a href=\"http://www.opensolaris.org\">" 3322daaffb31Sdpprint "OpenSolaris</a> project. The latest version may be obtained" 3323e9e2cfb2Sfr80241print "<a href=\"http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/tools/scripts/webrev.sh\">here</a>.</p>" 3324daaffb31Sdpprint "</body>" 3325daaffb31Sdpprint "</html>" 33267c478bd9Sstevel@tonic-gate 33277c478bd9Sstevel@tonic-gateexec 1<&- # Close FD 1. 33287c478bd9Sstevel@tonic-gateexec 1<&3 # dup FD 3 to restore stdout. 33297c478bd9Sstevel@tonic-gateexec 3<&- # close FD 3. 33307c478bd9Sstevel@tonic-gate 3331daaffb31Sdpprint "Done." 333202d26c39SVladimir Kotal 3333*b0088928SVladimir Kotal# 3334ba44d8a2SVladimir Kotal# If remote deletion was specified and fails do not continue. 3335*b0088928SVladimir Kotal# 3336ba44d8a2SVladimir Kotalif [[ -n $Dflag ]]; then 3337*b0088928SVladimir Kotal delete_webrev 1 1 3338ba44d8a2SVladimir Kotal (( $? == 0 )) || exit $? 3339ba44d8a2SVladimir Kotalfi 3340ba44d8a2SVladimir Kotal 334102d26c39SVladimir Kotalif [[ -n $Uflag ]]; then 334202d26c39SVladimir Kotal upload_webrev 334302d26c39SVladimir Kotal exit $? 334402d26c39SVladimir Kotalfi 3345