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 144b0088928SVladimir Kotal# 145b0088928SVladimir Kotal# Display remote target with prefix and trailing slash. 146b0088928SVladimir Kotal# 147b0088928SVladimir Kotalfunction print_upload_header 148b0088928SVladimir Kotal{ 149b0088928SVladimir Kotal typeset -r prefix=$1 150b0088928SVladimir Kotal typeset display_target 151b0088928SVladimir Kotal 152b0088928SVladimir Kotal if [[ -z $tflag ]]; then 153b0088928SVladimir Kotal display_target=${prefix}${remote_target} 154b0088928SVladimir Kotal else 155b0088928SVladimir Kotal display_target=${remote_target} 156b0088928SVladimir Kotal fi 157b0088928SVladimir Kotal 158b0088928SVladimir Kotal if [[ ${display_target} != */ ]]; then 159b0088928SVladimir Kotal display_target=${display_target}/ 160b0088928SVladimir Kotal fi 161b0088928SVladimir Kotal 162b0088928SVladimir Kotal print " Upload to: ${display_target}\n" \ 163b0088928SVladimir Kotal " Uploading: \c" 164b0088928SVladimir Kotal} 165b0088928SVladimir Kotal 166b0088928SVladimir Kotal# 16702d26c39SVladimir Kotal# Upload the webrev via rsync. Return 0 on success, 1 on error. 168b0088928SVladimir Kotal# 169ba44d8a2SVladimir Kotalfunction rsync_upload 17002d26c39SVladimir Kotal{ 171b0088928SVladimir Kotal if (( $# != 2 )); then 172b0088928SVladimir Kotal print "\nERROR: rsync_upload: wrong usage ($#)" 173b0088928SVladimir Kotal exit 1 17402d26c39SVladimir Kotal fi 17502d26c39SVladimir Kotal 176b0088928SVladimir Kotal typeset -r dst=$1 177b0088928SVladimir Kotal integer -r print_err_msg=$2 17802d26c39SVladimir Kotal 179b0088928SVladimir Kotal print_upload_header ${rsync_prefix} 180b0088928SVladimir Kotal print "rsync ... \c" 181b0088928SVladimir Kotal typeset -r err_msg=$( $MKTEMP /tmp/rsync_err.XXX ) 182b0088928SVladimir Kotal if [[ -z $err_msg ]]; then 183b0088928SVladimir Kotal print "\nERROR: rsync_upload: cannot create temporary file" 184b0088928SVladimir Kotal return 1 185b0088928SVladimir Kotal fi 186b0088928SVladimir Kotal # 187b0088928SVladimir Kotal # The source directory must end with a slash in order to copy just 188b0088928SVladimir Kotal # directory contents, not the whole directory. 189b0088928SVladimir Kotal # 190b0088928SVladimir Kotal typeset src_dir=$WDIR 191b0088928SVladimir Kotal if [[ ${src_dir} != */ ]]; then 192b0088928SVladimir Kotal src_dir=${src_dir}/ 193b0088928SVladimir Kotal fi 194b0088928SVladimir Kotal $RSYNC -r -q ${src_dir} $dst 2>$err_msg 19502d26c39SVladimir Kotal if (( $? != 0 )); then 196b0088928SVladimir Kotal if (( ${print_err_msg} > 0 )); then 197b0088928SVladimir Kotal print "Failed.\nERROR: rsync failed" 198b0088928SVladimir Kotal print "src dir: '${src_dir}'\ndst dir: '$dst'" 199b0088928SVladimir Kotal print "error messages:" 200b0088928SVladimir Kotal $SED 's/^/> /' $err_msg 201b0088928SVladimir Kotal rm -f $err_msg 202b0088928SVladimir Kotal fi 20302d26c39SVladimir Kotal return 1 20402d26c39SVladimir Kotal fi 20502d26c39SVladimir Kotal 206b0088928SVladimir Kotal rm -f $err_msg 20702d26c39SVladimir Kotal print "Done." 20802d26c39SVladimir Kotal return 0 20902d26c39SVladimir Kotal} 21002d26c39SVladimir Kotal 211b0088928SVladimir Kotal# 212b0088928SVladimir Kotal# Create directories on remote host using SFTP. Return 0 on success, 213b0088928SVladimir Kotal# 1 on failure. 214b0088928SVladimir Kotal# 215b0088928SVladimir Kotalfunction remote_mkdirs 216b0088928SVladimir Kotal{ 217b0088928SVladimir Kotal typeset -r dir_spec=$1 218b0088928SVladimir Kotal 219b0088928SVladimir Kotal # 220b0088928SVladimir Kotal # If the supplied path is absolute we assume all directories are 221b0088928SVladimir Kotal # created, otherwise try to create all directories in the path 222b0088928SVladimir Kotal # except the last one which will be created by scp. 223b0088928SVladimir Kotal # 224b0088928SVladimir Kotal if [[ "${dir_spec}" == */* && "${dir_spec}" != /* ]]; then 225b0088928SVladimir Kotal print "mkdirs \c" 226b0088928SVladimir Kotal # 227b0088928SVladimir Kotal # Remove the last directory from directory specification. 228b0088928SVladimir Kotal # 229b0088928SVladimir Kotal typeset -r dirs_mk=${dir_spec%/*} 230b0088928SVladimir Kotal typeset -r batch_file_mkdir=$( $MKTEMP /tmp/webrev_mkdir.XXX ) 231b0088928SVladimir Kotal if [[ -z $batch_file_mkdir ]]; then 232b0088928SVladimir Kotal print "\nERROR: remote_mkdirs:" \ 233b0088928SVladimir Kotal "cannot create temporary file for batch file" 234b0088928SVladimir Kotal return 1 235b0088928SVladimir Kotal fi 236b0088928SVladimir Kotal OLDIFS=$IFS 237b0088928SVladimir Kotal IFS=/ 238b0088928SVladimir Kotal typeset dir 239b0088928SVladimir Kotal for dir in ${dirs_mk}; do 240b0088928SVladimir Kotal # 241b0088928SVladimir Kotal # Use the '-' prefix to ignore mkdir errors in order 242b0088928SVladimir Kotal # to avoid an error in case the directory already 243b0088928SVladimir Kotal # exists. We check the directory with chdir to be sure 244b0088928SVladimir Kotal # there is one. 245b0088928SVladimir Kotal # 246b0088928SVladimir Kotal print -- "-mkdir ${dir}" >> ${batch_file_mkdir} 247b0088928SVladimir Kotal print "chdir ${dir}" >> ${batch_file_mkdir} 248b0088928SVladimir Kotal done 249b0088928SVladimir Kotal IFS=$OLDIFS 250b0088928SVladimir Kotal typeset -r sftp_err_msg=$( $MKTEMP /tmp/webrev_scp_err.XXX ) 251b0088928SVladimir Kotal if [[ -z ${sftp_err_msg} ]]; then 252b0088928SVladimir Kotal print "\nERROR: remote_mkdirs:" \ 253b0088928SVladimir Kotal "cannot create temporary file for error messages" 254b0088928SVladimir Kotal return 1 255b0088928SVladimir Kotal fi 256b0088928SVladimir Kotal $SFTP -b ${batch_file_mkdir} ${host_spec} 2>${sftp_err_msg} 1>&2 257b0088928SVladimir Kotal if (( $? != 0 )); then 258b0088928SVladimir Kotal print "\nERROR: failed to create remote directories" 259b0088928SVladimir Kotal print "error messages:" 260b0088928SVladimir Kotal $SED 's/^/> /' ${sftp_err_msg} 261b0088928SVladimir Kotal rm -f ${sftp_err_msg} ${batch_file_mkdir} 262b0088928SVladimir Kotal return 1 263b0088928SVladimir Kotal fi 264b0088928SVladimir Kotal rm -f ${sftp_err_msg} ${batch_file_mkdir} 265b0088928SVladimir Kotal fi 266b0088928SVladimir Kotal 267b0088928SVladimir Kotal return 0 268b0088928SVladimir Kotal} 269b0088928SVladimir Kotal 270b0088928SVladimir Kotal# 27102d26c39SVladimir Kotal# Upload the webrev via SSH. Return 0 on success, 1 on error. 272b0088928SVladimir Kotal# 273ba44d8a2SVladimir Kotalfunction ssh_upload 27402d26c39SVladimir Kotal{ 27502d26c39SVladimir Kotal if (( $# != 1 )); then 276b0088928SVladimir Kotal print "\nERROR: ssh_upload: wrong number of arguments" 277b0088928SVladimir 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 284b0088928SVladimir Kotal # 285b0088928SVladimir Kotal # Display the upload information before calling delete_webrev 286b0088928SVladimir Kotal # because it will also print its progress. 287b0088928SVladimir Kotal # 288b0088928SVladimir Kotal print_upload_header ${ssh_prefix} 289b0088928SVladimir Kotal 290b0088928SVladimir Kotal # 291b0088928SVladimir Kotal # If the deletion was explicitly requested there is no need 292b0088928SVladimir Kotal # to perform it again. 293b0088928SVladimir Kotal # 294ba44d8a2SVladimir Kotal if [[ -z $Dflag ]]; then 295b0088928SVladimir Kotal # 296b0088928SVladimir Kotal # We do not care about return value because this might be 297b0088928SVladimir Kotal # the first time this directory is uploaded. 298b0088928SVladimir Kotal # 299ba44d8a2SVladimir Kotal delete_webrev 0 30002d26c39SVladimir Kotal fi 30102d26c39SVladimir Kotal 302b0088928SVladimir Kotal # 303b0088928SVladimir Kotal # Create remote directories. Any error reporting will be done 304b0088928SVladimir Kotal # in remote_mkdirs function. 305b0088928SVladimir Kotal # 306b0088928SVladimir Kotal remote_mkdirs ${dir_spec} 30702d26c39SVladimir Kotal if (( $? != 0 )); then 30802d26c39SVladimir Kotal return 1 30902d26c39SVladimir Kotal fi 31002d26c39SVladimir Kotal 311b0088928SVladimir Kotal print "upload ... \c" 312b0088928SVladimir Kotal typeset -r scp_err_msg=$( $MKTEMP /tmp/scp_err.XXX ) 313b0088928SVladimir Kotal if [[ -z ${scp_err_msg} ]]; then 314b0088928SVladimir Kotal print "\nERROR: ssh_upload:" \ 315b0088928SVladimir Kotal "cannot create temporary file for error messages" 316b0088928SVladimir Kotal return 1 317b0088928SVladimir Kotal fi 31802d26c39SVladimir Kotal $SCP -q -C -B -o PreferredAuthentications=publickey -r \ 319b0088928SVladimir Kotal $WDIR $dst 2>${scp_err_msg} 32002d26c39SVladimir Kotal if (( $? != 0 )); then 321b0088928SVladimir Kotal print "Failed.\nERROR: scp failed" 322b0088928SVladimir Kotal print "src dir: '$WDIR'\ndst dir: '$dst'" 323b0088928SVladimir Kotal print "error messages:" 324b0088928SVladimir Kotal $SED 's/^/> /' ${scp_err_msg} 325b0088928SVladimir Kotal rm -f ${scp_err_msg} 32602d26c39SVladimir Kotal return 1 32702d26c39SVladimir Kotal fi 32802d26c39SVladimir Kotal 329b0088928SVladimir 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 336b0088928SVladimir Kotal# on failure. If first argument is 1 then perform the check of sftp return 337b0088928SVladimir Kotal# value otherwise ignore it. If second argument is present it means this run 338b0088928SVladimir Kotal# only performs deletion. 339ba44d8a2SVladimir Kotal# 340ba44d8a2SVladimir Kotalfunction delete_webrev 341ba44d8a2SVladimir Kotal{ 342b0088928SVladimir Kotal if (( $# < 1 )); then 343b0088928SVladimir Kotal print "delete_webrev: wrong number of arguments" 344b0088928SVladimir Kotal exit 1 345ba44d8a2SVladimir Kotal fi 346ba44d8a2SVladimir Kotal 347b0088928SVladimir Kotal integer -r check=$1 348b0088928SVladimir Kotal integer delete_only=0 349b0088928SVladimir Kotal if (( $# == 2 )); then 350b0088928SVladimir Kotal delete_only=1 351b0088928SVladimir Kotal fi 352b0088928SVladimir Kotal 353b0088928SVladimir Kotal # 354ba44d8a2SVladimir Kotal # Strip the transport specification part of remote target first. 355b0088928SVladimir 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 361b0088928SVladimir Kotal # 362ba44d8a2SVladimir Kotal # Do not accept an absolute path. 363b0088928SVladimir Kotal # 364ba44d8a2SVladimir Kotal if [[ ${dir_spec} == /* ]]; then 365ba44d8a2SVladimir Kotal return 1 366ba44d8a2SVladimir Kotal fi 367ba44d8a2SVladimir Kotal 368b0088928SVladimir Kotal # 369ba44d8a2SVladimir Kotal # Strip the ending slash. 370b0088928SVladimir 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 377b0088928SVladimir Kotal if (( ${delete_only} > 0 )); then 378b0088928SVladimir Kotal print " Removing: \c" 379b0088928SVladimir Kotal else 380b0088928SVladimir Kotal print "rmdir \c" 381b0088928SVladimir Kotal fi 382ba44d8a2SVladimir Kotal if [[ -z "$dir_rm" ]]; then 383b0088928SVladimir Kotal print "\nERROR: empty directory for removal" 384ba44d8a2SVladimir Kotal return 1 385ba44d8a2SVladimir Kotal fi 386ba44d8a2SVladimir Kotal 387b0088928SVladimir Kotal # 388ba44d8a2SVladimir Kotal # Prepare batch file. 389b0088928SVladimir Kotal # 390ba44d8a2SVladimir Kotal typeset -r batch_file_rm=$( $MKTEMP /tmp/webrev_remove.XXX ) 391ba44d8a2SVladimir Kotal if [[ -z $batch_file_rm ]]; then 392b0088928SVladimir 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 397b0088928SVladimir Kotal # 398ba44d8a2SVladimir Kotal # Perform remote deletion and remove the batch file. 399b0088928SVladimir Kotal # 400b0088928SVladimir Kotal typeset -r sftp_err_msg=$( $MKTEMP /tmp/webrev_scp_err.XXX ) 401b0088928SVladimir Kotal if [[ -z ${sftp_err_msg} ]]; then 402b0088928SVladimir Kotal print "\nERROR: delete_webrev:" \ 403b0088928SVladimir Kotal "cannot create temporary file for error messages" 404b0088928SVladimir Kotal return 1 405b0088928SVladimir Kotal fi 406b0088928SVladimir 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 410b0088928SVladimir Kotal print "Failed.\nERROR: failed to remove remote directories" 411b0088928SVladimir Kotal print "error messages:" 412b0088928SVladimir Kotal $SED 's/^/> /' ${sftp_err_msg} 413b0088928SVladimir Kotal rm -f ${sftp_err_msg} 414ba44d8a2SVladimir Kotal return $ret 415ba44d8a2SVladimir Kotal fi 416b0088928SVladimir Kotal rm -f ${sftp_err_msg} 417b0088928SVladimir Kotal if (( ${delete_only} > 0 )); then 418ba44d8a2SVladimir Kotal print "Done." 419b0088928SVladimir 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{ 429b0088928SVladimir Kotal integer ret 43002d26c39SVladimir Kotal 43102d26c39SVladimir Kotal if [[ ! -d "$WDIR" ]]; then 432b0088928SVladimir Kotal print "\nERROR: webrev directory '$WDIR' does not exist" 43302d26c39SVladimir Kotal return 1 43402d26c39SVladimir Kotal fi 43502d26c39SVladimir Kotal 436b0088928SVladimir 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. 440b0088928SVladimir 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 445b0088928SVladimir Kotal print "\nERROR: directory '$WDIR' contains" \ 446b0088928SVladimir Kotal "\"closed\" directory" 44702d26c39SVladimir Kotal return 1 44802d26c39SVladimir Kotal fi 44902d26c39SVladimir Kotal fi 45002d26c39SVladimir Kotal 451b0088928SVladimir Kotal 452b0088928SVladimir Kotal # 453b0088928SVladimir Kotal # We have the URI for remote destination now so let's start the upload. 454b0088928SVladimir Kotal # 45502d26c39SVladimir Kotal if [[ -n $tflag ]]; then 45602d26c39SVladimir Kotal if [[ "${remote_target}" == ${rsync_prefix}?* ]]; then 457b0088928SVladimir Kotal rsync_upload ${remote_target##$rsync_prefix} 1 458b0088928SVladimir Kotal ret=$? 459b0088928SVladimir Kotal return $ret 46002d26c39SVladimir Kotal elif [[ "${remote_target}" == ${ssh_prefix}?* ]]; then 46102d26c39SVladimir Kotal ssh_upload ${remote_target##$ssh_prefix} 462b0088928SVladimir Kotal ret=$? 463b0088928SVladimir Kotal return $ret 46402d26c39SVladimir Kotal fi 46502d26c39SVladimir Kotal else 466b0088928SVladimir Kotal # 467b0088928SVladimir Kotal # Try rsync first and fallback to SSH in case it fails. 468b0088928SVladimir Kotal # 469b0088928SVladimir Kotal rsync_upload ${remote_target} 0 470b0088928SVladimir Kotal ret=$? 471b0088928SVladimir Kotal if (( $ret != 0 )); then 472b0088928SVladimir Kotal print "Failed. (falling back to SSH)" 473ba44d8a2SVladimir Kotal ssh_upload ${remote_target} 474b0088928SVladimir Kotal ret=$? 47502d26c39SVladimir Kotal fi 476b0088928SVladimir 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{ 493b0088928SVladimir 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{ 510b0088928SVladimir 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{ 520b0088928SVladimir 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 534b0088928SVladimir 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 536b0088928SVladimir 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 885*8b3b7b16SMark J. Nelson <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> 911*8b3b7b16SMark J. Nelson <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?(/)}" 1056*8b3b7b16SMark J. Nelson 1057*8b3b7b16SMark J. Nelson # 1058*8b3b7b16SMark J. Nelson # If the first path was specified absolutely, and it does 1059*8b3b7b16SMark J. Nelson # not start with the second path, it's an error. 1060*8b3b7b16SMark J. Nelson # 1061*8b3b7b16SMark J. Nelson if [[ $1 =~ '^/.+' && "$cur" == "$1" ]]; then 1062daaffb31Sdp # Should never happen. 106314983201Sdp print -u2 "\nWARNING: relative_dir: \"$1\" not relative " 1064daaffb31Sdp print -u2 "to \"$2\". Check input paths. Framed webrev " 1065daaffb31Sdp print -u2 "will not be relocatable!" 1066daaffb31Sdp print $2 1067daaffb31Sdp return 1068daaffb31Sdp fi 1069daaffb31Sdp 1070*8b3b7b16SMark J. Nelson # 1071*8b3b7b16SMark J. Nelson # This is kind of ugly. The sed script will do the following: 1072*8b3b7b16SMark J. Nelson # 1073*8b3b7b16SMark J. Nelson # 1. Strip off a leading "." or "./": this is important to get 1074*8b3b7b16SMark J. Nelson # the correct arcnav links for files in $WDIR. 1075*8b3b7b16SMark J. Nelson # 2. Strip off a trailing "/": this is not strictly necessary, 1076*8b3b7b16SMark J. Nelson # but is kind of nice, since it doesn't end up in "//" at 1077*8b3b7b16SMark J. Nelson # the end of a relative path. 1078*8b3b7b16SMark J. Nelson # 3. Replace all remaining sequences of non-"/" with "..": the 1079*8b3b7b16SMark J. Nelson # assumption here is that each dirname represents another 1080*8b3b7b16SMark J. Nelson # level of relative separation. 1081*8b3b7b16SMark J. Nelson # 4. Append a trailing "/" only for non-empty paths: this way 1082*8b3b7b16SMark J. Nelson # the caller doesn't need to duplicate this logic, and does 1083*8b3b7b16SMark J. Nelson # not end up using $RTOP/file for files in $WDIR. 1084*8b3b7b16SMark J. Nelson # 1085*8b3b7b16SMark J. Nelson print $(print $cur | $SED -e '{ 1086*8b3b7b16SMark J. Nelson s:^\./*:: 1087*8b3b7b16SMark J. Nelson s:/$:: 1088*8b3b7b16SMark J. Nelson s:[^/][^/]*:..:g 1089*8b3b7b16SMark J. Nelson }' -e 's:^\(..*\)$:\1/:') 10907c478bd9Sstevel@tonic-gate} 10917c478bd9Sstevel@tonic-gate 1092daaffb31Sdp# 1093daaffb31Sdp# frame_nav_js 1094daaffb31Sdp# 1095daaffb31Sdp# Emit javascript for frame navigation 1096daaffb31Sdp# 1097daaffb31Sdpfunction frame_nav_js 10987c478bd9Sstevel@tonic-gate{ 10997c478bd9Sstevel@tonic-gatecat << \EOF 11007c478bd9Sstevel@tonic-gatevar myInt; 11017c478bd9Sstevel@tonic-gatevar scrolling=0; 1102daaffb31Sdpvar sfactor = 3; 11037c478bd9Sstevel@tonic-gatevar scount=10; 11047c478bd9Sstevel@tonic-gate 11057c478bd9Sstevel@tonic-gatefunction scrollByPix() { 11067c478bd9Sstevel@tonic-gate if (scount<=0) { 11077c478bd9Sstevel@tonic-gate sfactor*=1.2; 11087c478bd9Sstevel@tonic-gate scount=10; 11097c478bd9Sstevel@tonic-gate } 11107c478bd9Sstevel@tonic-gate parent.lhs.scrollBy(0,sfactor); 11117c478bd9Sstevel@tonic-gate parent.rhs.scrollBy(0,sfactor); 11127c478bd9Sstevel@tonic-gate scount--; 11137c478bd9Sstevel@tonic-gate} 11147c478bd9Sstevel@tonic-gate 1115daaffb31Sdpfunction scrollToAnc(num) { 1116daaffb31Sdp 1117daaffb31Sdp // Update the value of the anchor in the form which we use as 1118daaffb31Sdp // storage for this value. setAncValue() will take care of 1119daaffb31Sdp // correcting for overflow and underflow of the value and return 1120daaffb31Sdp // us the new value. 1121daaffb31Sdp num = setAncValue(num); 1122daaffb31Sdp 1123daaffb31Sdp // Set location and scroll back a little to expose previous 1124daaffb31Sdp // lines. 1125daaffb31Sdp // 1126daaffb31Sdp // Note that this could be improved: it is possible although 1127daaffb31Sdp // complex to compute the x and y position of an anchor, and to 1128daaffb31Sdp // scroll to that location directly. 1129daaffb31Sdp // 11307c478bd9Sstevel@tonic-gate parent.lhs.location.replace(parent.lhs.location.pathname + "#" + num); 11317c478bd9Sstevel@tonic-gate parent.rhs.location.replace(parent.rhs.location.pathname + "#" + num); 1132daaffb31Sdp 11337c478bd9Sstevel@tonic-gate parent.lhs.scrollBy(0,-30); 11347c478bd9Sstevel@tonic-gate parent.rhs.scrollBy(0,-30); 11357c478bd9Sstevel@tonic-gate} 11367c478bd9Sstevel@tonic-gate 1137daaffb31Sdpfunction getAncValue() 1138daaffb31Sdp{ 1139daaffb31Sdp return (parseInt(parent.nav.document.diff.real.value)); 1140daaffb31Sdp} 1141daaffb31Sdp 1142daaffb31Sdpfunction setAncValue(val) 1143daaffb31Sdp{ 1144daaffb31Sdp if (val <= 0) { 1145daaffb31Sdp val = 0; 1146daaffb31Sdp parent.nav.document.diff.real.value = val; 1147daaffb31Sdp parent.nav.document.diff.display.value = "BOF"; 1148daaffb31Sdp return (val); 1149daaffb31Sdp } 1150daaffb31Sdp 1151daaffb31Sdp // 1152daaffb31Sdp // The way we compute the max anchor value is to stash it 1153daaffb31Sdp // inline in the left and right hand side pages-- it's the same 1154daaffb31Sdp // on each side, so we pluck from the left. 1155daaffb31Sdp // 1156daaffb31Sdp maxval = parent.lhs.document.eof.value.value; 1157daaffb31Sdp if (val < maxval) { 1158daaffb31Sdp parent.nav.document.diff.real.value = val; 1159daaffb31Sdp parent.nav.document.diff.display.value = val.toString(); 1160daaffb31Sdp return (val); 1161daaffb31Sdp } 1162daaffb31Sdp 1163daaffb31Sdp // this must be: val >= maxval 1164daaffb31Sdp val = maxval; 1165daaffb31Sdp parent.nav.document.diff.real.value = val; 1166daaffb31Sdp parent.nav.document.diff.display.value = "EOF"; 1167daaffb31Sdp return (val); 1168daaffb31Sdp} 1169daaffb31Sdp 11707c478bd9Sstevel@tonic-gatefunction stopScroll() { 11717c478bd9Sstevel@tonic-gate if (scrolling==1) { 11727c478bd9Sstevel@tonic-gate clearInterval(myInt); 11737c478bd9Sstevel@tonic-gate scrolling=0; 11747c478bd9Sstevel@tonic-gate } 11757c478bd9Sstevel@tonic-gate} 11767c478bd9Sstevel@tonic-gate 11777c478bd9Sstevel@tonic-gatefunction startScroll() { 11787c478bd9Sstevel@tonic-gate stopScroll(); 11797c478bd9Sstevel@tonic-gate scrolling=1; 11807c478bd9Sstevel@tonic-gate myInt=setInterval("scrollByPix()",10); 11817c478bd9Sstevel@tonic-gate} 11827c478bd9Sstevel@tonic-gate 11837c478bd9Sstevel@tonic-gatefunction handlePress(b) { 1184daaffb31Sdp 11857c478bd9Sstevel@tonic-gate switch (b) { 11867c478bd9Sstevel@tonic-gate case 1 : 1187daaffb31Sdp scrollToAnc(-1); 11887c478bd9Sstevel@tonic-gate break; 11897c478bd9Sstevel@tonic-gate case 2 : 1190daaffb31Sdp scrollToAnc(getAncValue() - 1); 11917c478bd9Sstevel@tonic-gate break; 11927c478bd9Sstevel@tonic-gate case 3 : 11937c478bd9Sstevel@tonic-gate sfactor=-3; 11947c478bd9Sstevel@tonic-gate startScroll(); 11957c478bd9Sstevel@tonic-gate break; 11967c478bd9Sstevel@tonic-gate case 4 : 11977c478bd9Sstevel@tonic-gate sfactor=3; 11987c478bd9Sstevel@tonic-gate startScroll(); 11997c478bd9Sstevel@tonic-gate break; 12007c478bd9Sstevel@tonic-gate case 5 : 1201daaffb31Sdp scrollToAnc(getAncValue() + 1); 12027c478bd9Sstevel@tonic-gate break; 12037c478bd9Sstevel@tonic-gate case 6 : 1204daaffb31Sdp scrollToAnc(999999); 12057c478bd9Sstevel@tonic-gate break; 12067c478bd9Sstevel@tonic-gate } 12077c478bd9Sstevel@tonic-gate} 12087c478bd9Sstevel@tonic-gate 12097c478bd9Sstevel@tonic-gatefunction handleRelease(b) { 12107c478bd9Sstevel@tonic-gate stopScroll(); 12117c478bd9Sstevel@tonic-gate} 12127c478bd9Sstevel@tonic-gate 1213daaffb31Sdpfunction keypress(ev) { 1214daaffb31Sdp var keynum; 1215daaffb31Sdp var keychar; 1216daaffb31Sdp 1217daaffb31Sdp if (window.event) { // IE 1218daaffb31Sdp keynum = ev.keyCode; 1219daaffb31Sdp } else if (ev.which) { // non-IE 1220daaffb31Sdp keynum = ev.which; 1221daaffb31Sdp } 1222daaffb31Sdp 1223daaffb31Sdp keychar = String.fromCharCode(keynum); 1224daaffb31Sdp 1225daaffb31Sdp if (keychar == "k") { 1226daaffb31Sdp handlePress(2); 1227daaffb31Sdp return (0); 1228daaffb31Sdp } else if (keychar == "j" || keychar == " ") { 1229daaffb31Sdp handlePress(5); 1230daaffb31Sdp return (0); 1231daaffb31Sdp } 1232daaffb31Sdp return (1); 1233daaffb31Sdp} 1234daaffb31Sdp 12357c478bd9Sstevel@tonic-gatefunction ValidateDiffNum(){ 1236daaffb31Sdp val = parent.nav.document.diff.display.value; 1237daaffb31Sdp if (val == "EOF") { 1238daaffb31Sdp scrollToAnc(999999); 1239daaffb31Sdp return; 1240daaffb31Sdp } 1241daaffb31Sdp 1242daaffb31Sdp if (val == "BOF") { 1243daaffb31Sdp scrollToAnc(0); 1244daaffb31Sdp return; 1245daaffb31Sdp } 1246daaffb31Sdp 1247daaffb31Sdp i=parseInt(val); 12487c478bd9Sstevel@tonic-gate if (isNaN(i)) { 1249daaffb31Sdp parent.nav.document.diff.display.value = getAncValue(); 12507c478bd9Sstevel@tonic-gate } else { 1251daaffb31Sdp scrollToAnc(i); 12527c478bd9Sstevel@tonic-gate } 12537c478bd9Sstevel@tonic-gate return false; 12547c478bd9Sstevel@tonic-gate} 12557c478bd9Sstevel@tonic-gate 1256daaffb31SdpEOF 1257daaffb31Sdp} 1258daaffb31Sdp 1259daaffb31Sdp# 1260daaffb31Sdp# frame_navigation 1261daaffb31Sdp# 1262daaffb31Sdp# Output anchor navigation file for framed sdiffs. 1263daaffb31Sdp# 1264daaffb31Sdpfunction frame_navigation 1265daaffb31Sdp{ 1266daaffb31Sdp print "$HTML<head>$STDHEAD" 1267daaffb31Sdp 1268daaffb31Sdp cat << \EOF 1269daaffb31Sdp<title>Anchor Navigation</title> 1270daaffb31Sdp<meta http-equiv="Content-Script-Type" content="text/javascript"> 1271daaffb31Sdp<meta http-equiv="Content-Type" content="text/html"> 1272daaffb31Sdp 1273daaffb31Sdp<style type="text/css"> 1274daaffb31Sdp div.button td { padding-left: 5px; padding-right: 5px; 1275daaffb31Sdp background-color: #eee; text-align: center; 1276daaffb31Sdp border: 1px #444 outset; cursor: pointer; } 1277daaffb31Sdp div.button a { font-weight: bold; color: black } 1278daaffb31Sdp div.button td:hover { background: #ffcc99; } 1279daaffb31Sdp</style> 1280daaffb31SdpEOF 1281daaffb31Sdp 1282cac38512Smjnelson print "<script type=\"text/javascript\" src=\"ancnav.js\"></script>" 1283daaffb31Sdp 1284daaffb31Sdp cat << \EOF 12857c478bd9Sstevel@tonic-gate</head> 1286daaffb31Sdp<body id="SUNWwebrev" bgcolor="#eeeeee" onload="document.diff.real.focus();" 1287daaffb31Sdp onkeypress="keypress(event);"> 12887c478bd9Sstevel@tonic-gate <noscript lang="javascript"> 12897c478bd9Sstevel@tonic-gate <center> 1290cac38512Smjnelson <p><big>Framed Navigation controls require Javascript</big><br></br> 12917c478bd9Sstevel@tonic-gate Either this browser is incompatable or javascript is not enabled</p> 12927c478bd9Sstevel@tonic-gate </center> 12937c478bd9Sstevel@tonic-gate </noscript> 12947c478bd9Sstevel@tonic-gate <table width="100%" border="0" align="center"> 1295daaffb31Sdp <tr> 1296daaffb31Sdp <td valign="middle" width="25%">Diff navigation: 1297daaffb31Sdp Use 'j' and 'k' for next and previous diffs; or use buttons 1298daaffb31Sdp at right</td> 1299daaffb31Sdp <td align="center" valign="top" width="50%"> 13007c478bd9Sstevel@tonic-gate <div class="button"> 1301daaffb31Sdp <table border="0" align="center"> 1302daaffb31Sdp <tr> 1303daaffb31Sdp <td> 13047c478bd9Sstevel@tonic-gate <a onMouseDown="handlePress(1);return true;" 13057c478bd9Sstevel@tonic-gate onMouseUp="handleRelease(1);return true;" 13067c478bd9Sstevel@tonic-gate onMouseOut="handleRelease(1);return true;" 13077c478bd9Sstevel@tonic-gate onClick="return false;" 13087c478bd9Sstevel@tonic-gate title="Go to Beginning Of file">BOF</a></td> 1309daaffb31Sdp <td> 13107c478bd9Sstevel@tonic-gate <a onMouseDown="handlePress(3);return true;" 13117c478bd9Sstevel@tonic-gate onMouseUp="handleRelease(3);return true;" 13127c478bd9Sstevel@tonic-gate onMouseOut="handleRelease(3);return true;" 13137c478bd9Sstevel@tonic-gate title="Scroll Up: Press and Hold to accelerate" 1314daaffb31Sdp onClick="return false;">Scroll Up</a></td> 1315daaffb31Sdp <td> 13167c478bd9Sstevel@tonic-gate <a onMouseDown="handlePress(2);return true;" 13177c478bd9Sstevel@tonic-gate onMouseUp="handleRelease(2);return true;" 13187c478bd9Sstevel@tonic-gate onMouseOut="handleRelease(2);return true;" 13197c478bd9Sstevel@tonic-gate title="Go to previous Diff" 13207c478bd9Sstevel@tonic-gate onClick="return false;">Prev Diff</a> 13217c478bd9Sstevel@tonic-gate </td></tr> 1322daaffb31Sdp 13237c478bd9Sstevel@tonic-gate <tr> 1324daaffb31Sdp <td> 13257c478bd9Sstevel@tonic-gate <a onMouseDown="handlePress(6);return true;" 13267c478bd9Sstevel@tonic-gate onMouseUp="handleRelease(6);return true;" 13277c478bd9Sstevel@tonic-gate onMouseOut="handleRelease(6);return true;" 13287c478bd9Sstevel@tonic-gate onClick="return false;" 13297c478bd9Sstevel@tonic-gate title="Go to End Of File">EOF</a></td> 1330daaffb31Sdp <td> 13317c478bd9Sstevel@tonic-gate <a onMouseDown="handlePress(4);return true;" 13327c478bd9Sstevel@tonic-gate onMouseUp="handleRelease(4);return true;" 13337c478bd9Sstevel@tonic-gate onMouseOut="handleRelease(4);return true;" 13347c478bd9Sstevel@tonic-gate title="Scroll Down: Press and Hold to accelerate" 1335daaffb31Sdp onClick="return false;">Scroll Down</a></td> 1336daaffb31Sdp <td> 13377c478bd9Sstevel@tonic-gate <a onMouseDown="handlePress(5);return true;" 13387c478bd9Sstevel@tonic-gate onMouseUp="handleRelease(5);return true;" 13397c478bd9Sstevel@tonic-gate onMouseOut="handleRelease(5);return true;" 13407c478bd9Sstevel@tonic-gate title="Go to next Diff" 13417c478bd9Sstevel@tonic-gate onClick="return false;">Next Diff</a></td> 1342daaffb31Sdp </tr> 1343daaffb31Sdp </table> 1344daaffb31Sdp </div> 1345daaffb31Sdp </td> 13467c478bd9Sstevel@tonic-gate <th valign="middle" width="25%"> 1347daaffb31Sdp <form action="" name="diff" onsubmit="return ValidateDiffNum();"> 1348cac38512Smjnelson <input name="display" value="BOF" size="8" type="text"></input> 1349cac38512Smjnelson <input name="real" value="0" size="8" type="hidden"></input> 13507c478bd9Sstevel@tonic-gate </form> 13517c478bd9Sstevel@tonic-gate </th> 1352daaffb31Sdp </tr> 13537c478bd9Sstevel@tonic-gate </table> 13547c478bd9Sstevel@tonic-gate </body> 13557c478bd9Sstevel@tonic-gate</html> 13567c478bd9Sstevel@tonic-gateEOF 13577c478bd9Sstevel@tonic-gate} 13587c478bd9Sstevel@tonic-gate 13597c478bd9Sstevel@tonic-gate 1360daaffb31Sdp 1361daaffb31Sdp# 1362daaffb31Sdp# diff_to_html <filename> <filepath> { U | C } <comment> 1363daaffb31Sdp# 1364daaffb31Sdp# Processes the output of diff to produce an HTML file representing either 1365daaffb31Sdp# context or unified diffs. 1366daaffb31Sdp# 13677c478bd9Sstevel@tonic-gatediff_to_html() 13687c478bd9Sstevel@tonic-gate{ 13697c478bd9Sstevel@tonic-gate TNAME=$1 1370daaffb31Sdp TPATH=$2 1371daaffb31Sdp DIFFTYPE=$3 1372daaffb31Sdp COMMENT=$4 1373daaffb31Sdp 1374daaffb31Sdp print "$HTML<head>$STDHEAD" 1375daaffb31Sdp print "<title>$WNAME ${DIFFTYPE}diff $TPATH</title>" 1376daaffb31Sdp 1377daaffb31Sdp if [[ $DIFFTYPE == "U" ]]; then 1378daaffb31Sdp print "$UDIFFCSS" 1379daaffb31Sdp fi 1380daaffb31Sdp 1381daaffb31Sdp cat <<-EOF 1382daaffb31Sdp </head> 1383daaffb31Sdp <body id="SUNWwebrev"> 1384daaffb31Sdp <a class="print" href="javascript:print()">Print this page</a> 1385daaffb31Sdp <pre>$COMMENT</pre> 1386daaffb31Sdp <pre> 1387daaffb31Sdp EOF 13887c478bd9Sstevel@tonic-gate 1389cdf0c1d5Smjnelson html_quote | $AWK ' 1390daaffb31Sdp /^--- new/ { next } 1391daaffb31Sdp /^\+\+\+ new/ { next } 1392daaffb31Sdp /^--- old/ { next } 1393daaffb31Sdp /^\*\*\* old/ { next } 1394daaffb31Sdp /^\*\*\*\*/ { next } 13957c478bd9Sstevel@tonic-gate /^-------/ { printf "<center><h1>%s</h1></center>\n", $0; next } 1396cac38512Smjnelson /^\@\@.*\@\@$/ { printf "</pre><hr></hr><pre>\n"; 1397daaffb31Sdp printf "<span class=\"newmarker\">%s</span>\n", $0; 1398daaffb31Sdp next} 1399daaffb31Sdp 1400cac38512Smjnelson /^\*\*\*/ { printf "<hr></hr><span class=\"oldmarker\">%s</span>\n", $0; 1401daaffb31Sdp next} 1402daaffb31Sdp /^---/ { printf "<span class=\"newmarker\">%s</span>\n", $0; 1403daaffb31Sdp next} 1404daaffb31Sdp /^\+/ {printf "<span class=\"new\">%s</span>\n", $0; next} 1405daaffb31Sdp /^!/ {printf "<span class=\"changed\">%s</span>\n", $0; next} 1406daaffb31Sdp /^-/ {printf "<span class=\"removed\">%s</span>\n", $0; next} 1407daaffb31Sdp {printf "%s\n", $0; next} 14087c478bd9Sstevel@tonic-gate ' 1409daaffb31Sdp 1410daaffb31Sdp print "</pre></body></html>\n" 14117c478bd9Sstevel@tonic-gate} 14127c478bd9Sstevel@tonic-gate 14137c478bd9Sstevel@tonic-gate 1414daaffb31Sdp# 1415daaffb31Sdp# source_to_html { new | old } <filename> 1416daaffb31Sdp# 1417daaffb31Sdp# Process a plain vanilla source file to transform it into an HTML file. 1418daaffb31Sdp# 14197c478bd9Sstevel@tonic-gatesource_to_html() 14207c478bd9Sstevel@tonic-gate{ 14217c478bd9Sstevel@tonic-gate WHICH=$1 14227c478bd9Sstevel@tonic-gate TNAME=$2 14237c478bd9Sstevel@tonic-gate 1424daaffb31Sdp print "$HTML<head>$STDHEAD" 1425cdf0c1d5Smjnelson print "<title>$WNAME $WHICH $TNAME</title>" 1426daaffb31Sdp print "<body id=\"SUNWwebrev\">" 1427daaffb31Sdp print "<pre>" 1428cdf0c1d5Smjnelson html_quote | $AWK '{line += 1 ; printf "%4d %s\n", line, $0 }' 1429daaffb31Sdp print "</pre></body></html>" 14307c478bd9Sstevel@tonic-gate} 14317c478bd9Sstevel@tonic-gate 1432daaffb31Sdp# 1433cdf0c1d5Smjnelson# comments_from_teamware {text|html} parent-file child-file 1434daaffb31Sdp# 1435daaffb31Sdp# Find the first delta in the child that's not in the parent. Get the 1436daaffb31Sdp# newest delta from the parent, get all deltas from the child starting 1437daaffb31Sdp# with that delta, and then get all info starting with the second oldest 1438daaffb31Sdp# delta in that list (the first delta unique to the child). 14397c478bd9Sstevel@tonic-gate# 14407c478bd9Sstevel@tonic-gate# This code adapted from Bill Shannon's "spc" script 1441daaffb31Sdp# 1442daaffb31Sdpcomments_from_teamware() 14437c478bd9Sstevel@tonic-gate{ 1444daaffb31Sdp fmt=$1 1445daaffb31Sdp pfile=$PWS/$2 1446daaffb31Sdp cfile=$CWS/$3 14477c478bd9Sstevel@tonic-gate 1448cdf0c1d5Smjnelson if [[ ! -f $PWS/${2%/*}/SCCS/s.${2##*/} && -n $RWS ]]; then 1449cdf0c1d5Smjnelson pfile=$RWS/$2 1450cdf0c1d5Smjnelson fi 1451cdf0c1d5Smjnelson 1452daaffb31Sdp if [[ -f $pfile ]]; then 1453cdf0c1d5Smjnelson psid=$($SCCS prs -d:I: $pfile 2>/dev/null) 14547c478bd9Sstevel@tonic-gate else 14557c478bd9Sstevel@tonic-gate psid=1.1 14567c478bd9Sstevel@tonic-gate fi 14577c478bd9Sstevel@tonic-gate 1458cdf0c1d5Smjnelson set -A sids $($SCCS prs -l -r$psid -d:I: $cfile 2>/dev/null) 14597c478bd9Sstevel@tonic-gate N=${#sids[@]} 14607c478bd9Sstevel@tonic-gate 1461daaffb31Sdp nawkprg=' 1462daaffb31Sdp /^COMMENTS:/ {p=1; continue} 1463daaffb31Sdp /^D [0-9]+\.[0-9]+/ {printf "--- %s ---\n", $2; p=0; } 1464daaffb31Sdp NF == 0u { continue } 1465daaffb31Sdp {if (p==0) continue; print $0 }' 1466daaffb31Sdp 14677c478bd9Sstevel@tonic-gate if [[ $N -ge 2 ]]; then 14687c478bd9Sstevel@tonic-gate sid1=${sids[$((N-2))]} # Gets 2nd to last sid 14697c478bd9Sstevel@tonic-gate 1470daaffb31Sdp if [[ $fmt == "text" ]]; then 1471cdf0c1d5Smjnelson $SCCS prs -l -r$sid1 $cfile 2>/dev/null | \ 1472cdf0c1d5Smjnelson $AWK "$nawkprg" 1473daaffb31Sdp return 1474daaffb31Sdp fi 1475daaffb31Sdp 1476cdf0c1d5Smjnelson $SCCS prs -l -r$sid1 $cfile 2>/dev/null | \ 1477cdf0c1d5Smjnelson html_quote | bug2url | sac2url | $AWK "$nawkprg" 14787c478bd9Sstevel@tonic-gate fi 14797c478bd9Sstevel@tonic-gate} 14807c478bd9Sstevel@tonic-gate 1481daaffb31Sdp# 1482cdf0c1d5Smjnelson# comments_from_wx {text|html} filepath 1483daaffb31Sdp# 1484cdf0c1d5Smjnelson# Given the pathname of a file, find its location in a "wx" active 1485cdf0c1d5Smjnelson# file list and print the following comment. Output is either text or 1486cdf0c1d5Smjnelson# HTML; if the latter, embedded bugids (sequence of 5 or more digits) 1487cdf0c1d5Smjnelson# are turned into URLs. 1488cdf0c1d5Smjnelson# 1489cdf0c1d5Smjnelson# This is also used with Mercurial and the file list provided by hg-active. 1490daaffb31Sdp# 1491daaffb31Sdpcomments_from_wx() 14927c478bd9Sstevel@tonic-gate{ 1493daaffb31Sdp typeset fmt=$1 1494daaffb31Sdp typeset p=$2 14957c478bd9Sstevel@tonic-gate 1496cdf0c1d5Smjnelson comm=`$AWK ' 1497daaffb31Sdp $1 == "'$p'" { 14987c478bd9Sstevel@tonic-gate do getline ; while (NF > 0) 14997c478bd9Sstevel@tonic-gate getline 15007c478bd9Sstevel@tonic-gate while (NF > 0) { print ; getline } 15017c478bd9Sstevel@tonic-gate exit 1502daaffb31Sdp }' < $wxfile` 1503daaffb31Sdp 1504cdf0c1d5Smjnelson if [[ -z $comm ]]; then 1505cdf0c1d5Smjnelson comm="*** NO COMMENTS ***" 1506cdf0c1d5Smjnelson fi 1507cdf0c1d5Smjnelson 1508daaffb31Sdp if [[ $fmt == "text" ]]; then 1509cdf0c1d5Smjnelson print -- "$comm" 1510daaffb31Sdp return 1511daaffb31Sdp fi 1512daaffb31Sdp 1513cdf0c1d5Smjnelson print -- "$comm" | html_quote | bug2url | sac2url 1514cdf0c1d5Smjnelson 15157c478bd9Sstevel@tonic-gate} 15167c478bd9Sstevel@tonic-gate 15177c478bd9Sstevel@tonic-gate# 1518daaffb31Sdp# getcomments {text|html} filepath parentpath 1519daaffb31Sdp# 1520daaffb31Sdp# Fetch the comments depending on what SCM mode we're in. 1521daaffb31Sdp# 1522daaffb31Sdpgetcomments() 1523daaffb31Sdp{ 1524daaffb31Sdp typeset fmt=$1 1525daaffb31Sdp typeset p=$2 1526daaffb31Sdp typeset pp=$3 15277c478bd9Sstevel@tonic-gate 15283df69ef3SDarren Moffat if [[ -n $Nflag ]]; then 15293df69ef3SDarren Moffat return 15303df69ef3SDarren Moffat fi 1531cdf0c1d5Smjnelson # 1532cdf0c1d5Smjnelson # Mercurial support uses a file list in wx format, so this 1533cdf0c1d5Smjnelson # will be used there, too 1534cdf0c1d5Smjnelson # 1535daaffb31Sdp if [[ -n $wxfile ]]; then 1536daaffb31Sdp comments_from_wx $fmt $p 1537daaffb31Sdp else 1538daaffb31Sdp if [[ $SCM_MODE == "teamware" ]]; then 1539daaffb31Sdp comments_from_teamware $fmt $pp $p 1540daaffb31Sdp fi 1541daaffb31Sdp fi 1542daaffb31Sdp} 1543daaffb31Sdp 1544daaffb31Sdp# 1545daaffb31Sdp# printCI <total-changed> <inserted> <deleted> <modified> <unchanged> 1546daaffb31Sdp# 1547daaffb31Sdp# Print out Code Inspection figures similar to sccs-prt(1) format. 1548daaffb31Sdp# 1549daaffb31Sdpfunction printCI 1550daaffb31Sdp{ 1551daaffb31Sdp integer tot=$1 ins=$2 del=$3 mod=$4 unc=$5 1552daaffb31Sdp typeset str 1553daaffb31Sdp if (( tot == 1 )); then 1554daaffb31Sdp str="line" 1555daaffb31Sdp else 1556daaffb31Sdp str="lines" 1557daaffb31Sdp fi 1558daaffb31Sdp printf '%d %s changed: %d ins; %d del; %d mod; %d unchg\n' \ 1559daaffb31Sdp $tot $str $ins $del $mod $unc 1560daaffb31Sdp} 1561daaffb31Sdp 1562daaffb31Sdp 1563daaffb31Sdp# 1564daaffb31Sdp# difflines <oldfile> <newfile> 1565daaffb31Sdp# 1566daaffb31Sdp# Calculate and emit number of added, removed, modified and unchanged lines, 1567daaffb31Sdp# and total lines changed, the sum of added + removed + modified. 1568daaffb31Sdp# 15697c478bd9Sstevel@tonic-gatefunction difflines 15707c478bd9Sstevel@tonic-gate{ 1571daaffb31Sdp integer tot mod del ins unc err 15727c478bd9Sstevel@tonic-gate typeset filename 15737c478bd9Sstevel@tonic-gate 1574cdf0c1d5Smjnelson eval $( diff -e $1 $2 | $AWK ' 1575daaffb31Sdp # Change range of lines: N,Nc 15767c478bd9Sstevel@tonic-gate /^[0-9]*,[0-9]*c$/ { 15777c478bd9Sstevel@tonic-gate n=split(substr($1,1,length($1)-1), counts, ","); 15787c478bd9Sstevel@tonic-gate if (n != 2) { 15797c478bd9Sstevel@tonic-gate error=2 15807c478bd9Sstevel@tonic-gate exit; 15817c478bd9Sstevel@tonic-gate } 1582daaffb31Sdp # 1583daaffb31Sdp # 3,5c means lines 3 , 4 and 5 are changed, a total of 3 lines. 1584daaffb31Sdp # following would be 5 - 3 = 2! Hence +1 for correction. 1585daaffb31Sdp # 15867c478bd9Sstevel@tonic-gate r=(counts[2]-counts[1])+1; 1587daaffb31Sdp 1588daaffb31Sdp # 1589daaffb31Sdp # Now count replacement lines: each represents a change instead 1590daaffb31Sdp # of a delete, so increment c and decrement r. 1591daaffb31Sdp # 15927c478bd9Sstevel@tonic-gate while (getline != /^\.$/) { 15937c478bd9Sstevel@tonic-gate c++; 15947c478bd9Sstevel@tonic-gate r--; 15957c478bd9Sstevel@tonic-gate } 1596daaffb31Sdp # 1597daaffb31Sdp # If there were more replacement lines than original lines, 1598daaffb31Sdp # then r will be negative; in this case there are no deletions, 1599daaffb31Sdp # but there are r changes that should be counted as adds, and 1600daaffb31Sdp # since r is negative, subtract it from a and add it to c. 1601daaffb31Sdp # 16027c478bd9Sstevel@tonic-gate if (r < 0) { 16037c478bd9Sstevel@tonic-gate a-=r; 16047c478bd9Sstevel@tonic-gate c+=r; 16057c478bd9Sstevel@tonic-gate } 1606daaffb31Sdp 1607daaffb31Sdp # 1608daaffb31Sdp # If there were more original lines than replacement lines, then 1609daaffb31Sdp # r will be positive; in this case, increment d by that much. 1610daaffb31Sdp # 16117c478bd9Sstevel@tonic-gate if (r > 0) { 16127c478bd9Sstevel@tonic-gate d+=r; 16137c478bd9Sstevel@tonic-gate } 16147c478bd9Sstevel@tonic-gate next; 16157c478bd9Sstevel@tonic-gate } 16167c478bd9Sstevel@tonic-gate 1617daaffb31Sdp # Change lines: Nc 16187c478bd9Sstevel@tonic-gate /^[0-9].*c$/ { 1619daaffb31Sdp # The first line is a replacement; any more are additions. 16207c478bd9Sstevel@tonic-gate if (getline != /^\.$/) { 16217c478bd9Sstevel@tonic-gate c++; 16227c478bd9Sstevel@tonic-gate while (getline != /^\.$/) a++; 16237c478bd9Sstevel@tonic-gate } 16247c478bd9Sstevel@tonic-gate next; 16257c478bd9Sstevel@tonic-gate } 16267c478bd9Sstevel@tonic-gate 1627daaffb31Sdp # Add lines: both Na and N,Na 16287c478bd9Sstevel@tonic-gate /^[0-9].*a$/ { 16297c478bd9Sstevel@tonic-gate while (getline != /^\.$/) a++; 16307c478bd9Sstevel@tonic-gate next; 16317c478bd9Sstevel@tonic-gate } 16327c478bd9Sstevel@tonic-gate 1633daaffb31Sdp # Delete range of lines: N,Nd 16347c478bd9Sstevel@tonic-gate /^[0-9]*,[0-9]*d$/ { 16357c478bd9Sstevel@tonic-gate n=split(substr($1,1,length($1)-1), counts, ","); 16367c478bd9Sstevel@tonic-gate if (n != 2) { 16377c478bd9Sstevel@tonic-gate error=2 16387c478bd9Sstevel@tonic-gate exit; 16397c478bd9Sstevel@tonic-gate } 1640daaffb31Sdp # 1641daaffb31Sdp # 3,5d means lines 3 , 4 and 5 are deleted, a total of 3 lines. 1642daaffb31Sdp # following would be 5 - 3 = 2! Hence +1 for correction. 1643daaffb31Sdp # 16447c478bd9Sstevel@tonic-gate r=(counts[2]-counts[1])+1; 16457c478bd9Sstevel@tonic-gate d+=r; 16467c478bd9Sstevel@tonic-gate next; 16477c478bd9Sstevel@tonic-gate } 16487c478bd9Sstevel@tonic-gate 1649daaffb31Sdp # Delete line: Nd. For example 10d says line 10 is deleted. 16507c478bd9Sstevel@tonic-gate /^[0-9]*d$/ {d++; next} 16517c478bd9Sstevel@tonic-gate 1652daaffb31Sdp # Should not get here! 16537c478bd9Sstevel@tonic-gate { 16547c478bd9Sstevel@tonic-gate error=1; 16557c478bd9Sstevel@tonic-gate exit; 16567c478bd9Sstevel@tonic-gate } 16577c478bd9Sstevel@tonic-gate 1658daaffb31Sdp # Finish off - print results 16597c478bd9Sstevel@tonic-gate END { 1660daaffb31Sdp printf("tot=%d;mod=%d;del=%d;ins=%d;err=%d\n", 16617c478bd9Sstevel@tonic-gate (c+d+a), c, d, a, error); 16627c478bd9Sstevel@tonic-gate }' ) 16637c478bd9Sstevel@tonic-gate 1664cdf0c1d5Smjnelson # End of $AWK, Check to see if any trouble occurred. 16657c478bd9Sstevel@tonic-gate if (( $? > 0 || err > 0 )); then 1666daaffb31Sdp print "Unexpected Error occurred reading" \ 1667daaffb31Sdp "\`diff -e $1 $2\`: \$?=$?, err=" $err 1668daaffb31Sdp return 1669daaffb31Sdp fi 1670daaffb31Sdp 16717c478bd9Sstevel@tonic-gate # Accumulate totals 16727c478bd9Sstevel@tonic-gate (( TOTL += tot )) 1673daaffb31Sdp (( TMOD += mod )) 16747c478bd9Sstevel@tonic-gate (( TDEL += del )) 16757c478bd9Sstevel@tonic-gate (( TINS += ins )) 16767c478bd9Sstevel@tonic-gate # Calculate unchanged lines 1677cdf0c1d5Smjnelson unc=`wc -l < $1` 16787c478bd9Sstevel@tonic-gate if (( unc > 0 )); then 1679daaffb31Sdp (( unc -= del + mod )) 16807c478bd9Sstevel@tonic-gate (( TUNC += unc )) 16817c478bd9Sstevel@tonic-gate fi 16827c478bd9Sstevel@tonic-gate # print summary 1683daaffb31Sdp print "<span class=\"lineschanged\">" 1684daaffb31Sdp printCI $tot $ins $del $mod $unc 1685daaffb31Sdp print "</span>" 16867c478bd9Sstevel@tonic-gate} 16877c478bd9Sstevel@tonic-gate 1688daaffb31Sdp 16897c478bd9Sstevel@tonic-gate# 1690daaffb31Sdp# flist_from_wx 1691daaffb31Sdp# 1692daaffb31Sdp# Sets up webrev to source its information from a wx-formatted file. 1693daaffb31Sdp# Sets the global 'wxfile' variable. 1694daaffb31Sdp# 1695daaffb31Sdpfunction flist_from_wx 16967c478bd9Sstevel@tonic-gate{ 1697daaffb31Sdp typeset argfile=$1 1698daaffb31Sdp if [[ -n ${argfile%%/*} ]]; then 1699daaffb31Sdp # 1700daaffb31Sdp # If the wx file pathname is relative then make it absolute 1701daaffb31Sdp # because the webrev does a "cd" later on. 1702daaffb31Sdp # 1703daaffb31Sdp wxfile=$PWD/$argfile 17047c478bd9Sstevel@tonic-gate else 1705daaffb31Sdp wxfile=$argfile 17067c478bd9Sstevel@tonic-gate fi 17077c478bd9Sstevel@tonic-gate 1708cdf0c1d5Smjnelson $AWK '{ c = 1; print; 17097c478bd9Sstevel@tonic-gate while (getline) { 17107c478bd9Sstevel@tonic-gate if (NF == 0) { c = -c; continue } 17117c478bd9Sstevel@tonic-gate if (c > 0) print 17127c478bd9Sstevel@tonic-gate } 1713daaffb31Sdp }' $wxfile > $FLIST 17147c478bd9Sstevel@tonic-gate 1715daaffb31Sdp print " Done." 1716daaffb31Sdp} 17177c478bd9Sstevel@tonic-gate 1718daaffb31Sdp# 1719daaffb31Sdp# flist_from_teamware [ <args-to-putback-n> ] 1720daaffb31Sdp# 1721daaffb31Sdp# Generate the file list by extracting file names from a putback -n. Some 1722daaffb31Sdp# names may come from the "update/create" messages and others from the 1723daaffb31Sdp# "currently checked out" warning. Renames are detected here too. Extract 1724daaffb31Sdp# values for CODEMGR_WS and CODEMGR_PARENT from the output of the putback 1725daaffb31Sdp# -n as well, but remove them if they are already defined. 1726daaffb31Sdp# 1727daaffb31Sdpfunction flist_from_teamware 1728daaffb31Sdp{ 1729cdf0c1d5Smjnelson if [[ -n $codemgr_parent && -z $parent_webrev ]]; then 1730daaffb31Sdp if [[ ! -d $codemgr_parent/Codemgr_wsdata ]]; then 1731daaffb31Sdp print -u2 "parent $codemgr_parent doesn't look like a" \ 1732daaffb31Sdp "valid teamware workspace" 17337c478bd9Sstevel@tonic-gate exit 1 17347c478bd9Sstevel@tonic-gate fi 1735daaffb31Sdp parent_args="-p $codemgr_parent" 17367c478bd9Sstevel@tonic-gate fi 17377c478bd9Sstevel@tonic-gate 1738daaffb31Sdp print " File list from: 'putback -n $parent_args $*' ... \c" 17397c478bd9Sstevel@tonic-gate 1740daaffb31Sdp putback -n $parent_args $* 2>&1 | 1741cdf0c1d5Smjnelson $AWK ' 1742daaffb31Sdp /^update:|^create:/ {print $2} 1743daaffb31Sdp /^Parent workspace:/ {printf("CODEMGR_PARENT=%s\n",$3)} 1744daaffb31Sdp /^Child workspace:/ {printf("CODEMGR_WS=%s\n",$3)} 1745daaffb31Sdp /^The following files are currently checked out/ {p = 1; continue} 1746daaffb31Sdp NF == 0 {p=0 ; continue} 1747daaffb31Sdp /^rename/ {old=$3} 1748daaffb31Sdp $1 == "to:" {print $2, old} 1749daaffb31Sdp /^"/ {continue} 1750daaffb31Sdp p == 1 {print $1}' | 1751daaffb31Sdp sort -r -k 1,1 -u | sort > $FLIST 17527c478bd9Sstevel@tonic-gate 1753daaffb31Sdp print " Done." 1754daaffb31Sdp} 1755daaffb31Sdp 1756cdf0c1d5Smjnelson# 1757cdf0c1d5Smjnelson# Call hg-active to get the active list output in the wx active list format 1758cdf0c1d5Smjnelson# 1759cdf0c1d5Smjnelsonfunction hg_active_wxfile 1760cdf0c1d5Smjnelson{ 1761cdf0c1d5Smjnelson typeset child=$1 1762cdf0c1d5Smjnelson typeset parent=$2 1763cdf0c1d5Smjnelson 1764cdf0c1d5Smjnelson TMPFLIST=/tmp/$$.active 17659a70fc3bSMark J. Nelson $HG_ACTIVE -w $child -p $parent -o $TMPFLIST 1766cdf0c1d5Smjnelson wxfile=$TMPFLIST 1767cdf0c1d5Smjnelson} 1768cdf0c1d5Smjnelson 1769cdf0c1d5Smjnelson# 1770cdf0c1d5Smjnelson# flist_from_mercurial 1771cdf0c1d5Smjnelson# Call hg-active to get a wx-style active list, and hand it off to 1772cdf0c1d5Smjnelson# flist_from_wx 1773cdf0c1d5Smjnelson# 1774cdf0c1d5Smjnelsonfunction flist_from_mercurial 1775cdf0c1d5Smjnelson{ 1776cdf0c1d5Smjnelson typeset child=$1 1777cdf0c1d5Smjnelson typeset parent=$2 1778cdf0c1d5Smjnelson 1779cdf0c1d5Smjnelson print " File list from: hg-active -p $parent ...\c" 1780cdf0c1d5Smjnelson 1781cdf0c1d5Smjnelson if [[ ! -x $HG_ACTIVE ]]; then 1782cdf0c1d5Smjnelson print # Blank line for the \c above 1783cdf0c1d5Smjnelson print -u2 "Error: hg-active tool not found. Exiting" 1784cdf0c1d5Smjnelson exit 1 1785cdf0c1d5Smjnelson fi 1786cdf0c1d5Smjnelson hg_active_wxfile $child $parent 1787cdf0c1d5Smjnelson 1788cdf0c1d5Smjnelson # flist_from_wx prints the Done, so we don't have to. 1789cdf0c1d5Smjnelson flist_from_wx $TMPFLIST 1790cdf0c1d5Smjnelson} 1791cdf0c1d5Smjnelson 1792cdf0c1d5Smjnelson# 1793cdf0c1d5Smjnelson# flist_from_subversion 1794cdf0c1d5Smjnelson# 1795cdf0c1d5Smjnelson# Generate the file list by extracting file names from svn status. 1796cdf0c1d5Smjnelson# 1797cdf0c1d5Smjnelsonfunction flist_from_subversion 1798cdf0c1d5Smjnelson{ 1799cdf0c1d5Smjnelson CWS=$1 1800cdf0c1d5Smjnelson OLDPWD=$2 1801cdf0c1d5Smjnelson 1802cdf0c1d5Smjnelson cd $CWS 1803cdf0c1d5Smjnelson print -u2 " File list from: svn status ... \c" 1804cdf0c1d5Smjnelson svn status | $AWK '/^[ACDMR]/ { print $NF }' > $FLIST 1805cdf0c1d5Smjnelson print -u2 " Done." 1806cdf0c1d5Smjnelson cd $OLDPWD 1807cdf0c1d5Smjnelson} 1808cdf0c1d5Smjnelson 1809daaffb31Sdpfunction env_from_flist 1810daaffb31Sdp{ 1811daaffb31Sdp [[ -r $FLIST ]] || return 1812daaffb31Sdp 1813daaffb31Sdp # 1814daaffb31Sdp # Use "eval" to set env variables that are listed in the file 1815daaffb31Sdp # list. Then copy those into our local versions of those 1816daaffb31Sdp # variables if they have not been set already. 1817daaffb31Sdp # 1818b0088928SVladimir Kotal eval `$SED -e "s/#.*$//" $FLIST | $GREP = ` 18197c478bd9Sstevel@tonic-gate 1820cdf0c1d5Smjnelson if [[ -z $codemgr_ws && -n $CODEMGR_WS ]]; then 1821cdf0c1d5Smjnelson codemgr_ws=$CODEMGR_WS 1822cdf0c1d5Smjnelson export CODEMGR_WS 1823cdf0c1d5Smjnelson fi 18247c478bd9Sstevel@tonic-gate 1825daaffb31Sdp # 1826daaffb31Sdp # Check to see if CODEMGR_PARENT is set in the flist file. 1827daaffb31Sdp # 1828cdf0c1d5Smjnelson if [[ -z $codemgr_parent && -n $CODEMGR_PARENT ]]; then 1829daaffb31Sdp codemgr_parent=$CODEMGR_PARENT 1830cdf0c1d5Smjnelson export CODEMGR_PARENT 1831daaffb31Sdp fi 1832daaffb31Sdp} 1833daaffb31Sdp 183414983201Sdpfunction look_for_prog 183514983201Sdp{ 183614983201Sdp typeset path 183714983201Sdp typeset ppath 183814983201Sdp typeset progname=$1 183914983201Sdp 184014983201Sdp ppath=$PATH 184114983201Sdp ppath=$ppath:/usr/sfw/bin:/usr/bin:/usr/sbin 184214983201Sdp ppath=$ppath:/opt/teamware/bin:/opt/onbld/bin 1843cdf0c1d5Smjnelson ppath=$ppath:/opt/onbld/bin/`uname -p` 184414983201Sdp 184514983201Sdp PATH=$ppath prog=`whence $progname` 184614983201Sdp if [[ -n $prog ]]; then 184714983201Sdp print $prog 184814983201Sdp fi 184914983201Sdp} 185014983201Sdp 1851cdf0c1d5Smjnelsonfunction get_file_mode 1852cdf0c1d5Smjnelson{ 1853cdf0c1d5Smjnelson $PERL -e ' 1854cdf0c1d5Smjnelson if (@stat = stat($ARGV[0])) { 1855cdf0c1d5Smjnelson $mode = $stat[2] & 0777; 1856cdf0c1d5Smjnelson printf "%03o\n", $mode; 1857cdf0c1d5Smjnelson exit 0; 1858cdf0c1d5Smjnelson } else { 1859cdf0c1d5Smjnelson exit 1; 1860cdf0c1d5Smjnelson } 1861cdf0c1d5Smjnelson ' $1 1862cdf0c1d5Smjnelson} 1863cdf0c1d5Smjnelson 1864cdf0c1d5Smjnelsonfunction build_old_new_teamware 1865cdf0c1d5Smjnelson{ 1866cdf0c1d5Smjnelson typeset olddir="$1" 1867cdf0c1d5Smjnelson typeset newdir="$2" 1868cdf0c1d5Smjnelson 1869cdf0c1d5Smjnelson # If the child's version doesn't exist then 1870cdf0c1d5Smjnelson # get a readonly copy. 1871cdf0c1d5Smjnelson 1872cdf0c1d5Smjnelson if [[ ! -f $CWS/$DIR/$F && -f $CWS/$DIR/SCCS/s.$F ]]; then 1873cdf0c1d5Smjnelson $SCCS get -s -p $CWS/$DIR/$F > $CWS/$DIR/$F 1874cdf0c1d5Smjnelson fi 1875cdf0c1d5Smjnelson 1876cdf0c1d5Smjnelson # The following two sections propagate file permissions the 1877cdf0c1d5Smjnelson # same way SCCS does. If the file is already under version 1878cdf0c1d5Smjnelson # control, always use permissions from the SCCS/s.file. If 1879cdf0c1d5Smjnelson # the file is not under SCCS control, use permissions from the 1880cdf0c1d5Smjnelson # working copy. In all cases, the file copied to the webrev 1881cdf0c1d5Smjnelson # is set to read only, and group/other permissions are set to 1882cdf0c1d5Smjnelson # match those of the file owner. This way, even if the file 1883cdf0c1d5Smjnelson # is currently checked out, the webrev will display the final 1884cdf0c1d5Smjnelson # permissions that would result after check in. 1885cdf0c1d5Smjnelson 1886cdf0c1d5Smjnelson # 1887cdf0c1d5Smjnelson # Snag new version of file. 1888cdf0c1d5Smjnelson # 1889cdf0c1d5Smjnelson rm -f $newdir/$DIR/$F 1890cdf0c1d5Smjnelson cp $CWS/$DIR/$F $newdir/$DIR/$F 1891cdf0c1d5Smjnelson if [[ -f $CWS/$DIR/SCCS/s.$F ]]; then 1892cdf0c1d5Smjnelson chmod `get_file_mode $CWS/$DIR/SCCS/s.$F` \ 1893cdf0c1d5Smjnelson $newdir/$DIR/$F 1894cdf0c1d5Smjnelson fi 1895cdf0c1d5Smjnelson chmod u-w,go=u $newdir/$DIR/$F 1896cdf0c1d5Smjnelson 1897cdf0c1d5Smjnelson # 1898cdf0c1d5Smjnelson # Get the parent's version of the file. First see whether the 1899cdf0c1d5Smjnelson # child's version is checked out and get the parent's version 1900cdf0c1d5Smjnelson # with keywords expanded or unexpanded as appropriate. 1901cdf0c1d5Smjnelson # 1902cdf0c1d5Smjnelson if [[ -f $PWS/$PDIR/$PF && ! -f $PWS/$PDIR/SCCS/s.$PF && \ 1903cdf0c1d5Smjnelson ! -f $PWS/$PDIR/SCCS/p.$PF ]]; then 1904cdf0c1d5Smjnelson # Parent is not a real workspace, but just a raw 1905cdf0c1d5Smjnelson # directory tree - use the file that's there as 1906cdf0c1d5Smjnelson # the old file. 1907cdf0c1d5Smjnelson 1908cdf0c1d5Smjnelson rm -f $olddir/$PDIR/$PF 1909cdf0c1d5Smjnelson cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF 1910cdf0c1d5Smjnelson else 1911cdf0c1d5Smjnelson if [[ -f $PWS/$PDIR/SCCS/s.$PF ]]; then 1912cdf0c1d5Smjnelson real_parent=$PWS 1913cdf0c1d5Smjnelson else 1914cdf0c1d5Smjnelson real_parent=$RWS 1915cdf0c1d5Smjnelson fi 1916cdf0c1d5Smjnelson 1917cdf0c1d5Smjnelson rm -f $olddir/$PDIR/$PF 1918cdf0c1d5Smjnelson 1919cdf0c1d5Smjnelson if [[ -f $real_parent/$PDIR/$PF ]]; then 1920cdf0c1d5Smjnelson if [ -f $CWS/$DIR/SCCS/p.$F ]; then 1921cdf0c1d5Smjnelson $SCCS get -s -p -k $real_parent/$PDIR/$PF > \ 1922cdf0c1d5Smjnelson $olddir/$PDIR/$PF 1923cdf0c1d5Smjnelson else 1924cdf0c1d5Smjnelson $SCCS get -s -p $real_parent/$PDIR/$PF > \ 1925cdf0c1d5Smjnelson $olddir/$PDIR/$PF 1926cdf0c1d5Smjnelson fi 1927cdf0c1d5Smjnelson chmod `get_file_mode $real_parent/$PDIR/SCCS/s.$PF` \ 1928cdf0c1d5Smjnelson $olddir/$PDIR/$PF 1929cdf0c1d5Smjnelson fi 1930cdf0c1d5Smjnelson fi 1931cdf0c1d5Smjnelson if [[ -f $olddir/$PDIR/$PF ]]; then 1932cdf0c1d5Smjnelson chmod u-w,go=u $olddir/$PDIR/$PF 1933cdf0c1d5Smjnelson fi 1934cdf0c1d5Smjnelson} 1935cdf0c1d5Smjnelson 1936cdf0c1d5Smjnelsonfunction build_old_new_mercurial 1937cdf0c1d5Smjnelson{ 1938cdf0c1d5Smjnelson typeset olddir="$1" 1939cdf0c1d5Smjnelson typeset newdir="$2" 1940cdf0c1d5Smjnelson typeset old_mode= 1941cdf0c1d5Smjnelson typeset new_mode= 1942cdf0c1d5Smjnelson typeset file 1943cdf0c1d5Smjnelson 1944cdf0c1d5Smjnelson # 1945cdf0c1d5Smjnelson # Get old file mode, from the parent revision manifest entry. 1946cdf0c1d5Smjnelson # Mercurial only stores a "file is executable" flag, but the 1947cdf0c1d5Smjnelson # manifest will display an octal mode "644" or "755". 1948cdf0c1d5Smjnelson # 1949cdf0c1d5Smjnelson if [[ "$PDIR" == "." ]]; then 1950cdf0c1d5Smjnelson file="$PF" 1951cdf0c1d5Smjnelson else 1952cdf0c1d5Smjnelson file="$PDIR/$PF" 1953cdf0c1d5Smjnelson fi 1954b0088928SVladimir Kotal file=`echo $file | $SED 's#/#\\\/#g'` 1955cdf0c1d5Smjnelson # match the exact filename, and return only the permission digits 1956b0088928SVladimir Kotal old_mode=`$SED -n -e "/^\\(...\\) . ${file}$/s//\\1/p" \ 1957cdf0c1d5Smjnelson < $HG_PARENT_MANIFEST` 1958cdf0c1d5Smjnelson 1959cdf0c1d5Smjnelson # 1960cdf0c1d5Smjnelson # Get new file mode, directly from the filesystem. 1961cdf0c1d5Smjnelson # Normalize the mode to match Mercurial's behavior. 1962cdf0c1d5Smjnelson # 1963cdf0c1d5Smjnelson new_mode=`get_file_mode $CWS/$DIR/$F` 1964cdf0c1d5Smjnelson if [[ -n "$new_mode" ]]; then 1965cdf0c1d5Smjnelson if [[ "$new_mode" = *[1357]* ]]; then 1966cdf0c1d5Smjnelson new_mode=755 1967cdf0c1d5Smjnelson else 1968cdf0c1d5Smjnelson new_mode=644 1969cdf0c1d5Smjnelson fi 1970cdf0c1d5Smjnelson fi 1971cdf0c1d5Smjnelson 1972cdf0c1d5Smjnelson # 1973cdf0c1d5Smjnelson # new version of the file. 1974cdf0c1d5Smjnelson # 1975cdf0c1d5Smjnelson rm -rf $newdir/$DIR/$F 1976cdf0c1d5Smjnelson if [[ -e $CWS/$DIR/$F ]]; then 1977cdf0c1d5Smjnelson cp $CWS/$DIR/$F $newdir/$DIR/$F 1978cdf0c1d5Smjnelson if [[ -n $new_mode ]]; then 1979cdf0c1d5Smjnelson chmod $new_mode $newdir/$DIR/$F 1980cdf0c1d5Smjnelson else 1981cdf0c1d5Smjnelson # should never happen 1982cdf0c1d5Smjnelson print -u2 "ERROR: set mode of $newdir/$DIR/$F" 1983cdf0c1d5Smjnelson fi 1984cdf0c1d5Smjnelson fi 1985cdf0c1d5Smjnelson 1986cdf0c1d5Smjnelson # 1987cdf0c1d5Smjnelson # parent's version of the file 1988cdf0c1d5Smjnelson # 1989cdf0c1d5Smjnelson # Note that we get this from the last version common to both 1990cdf0c1d5Smjnelson # ourselves and the parent. References are via $CWS since we have no 1991cdf0c1d5Smjnelson # guarantee that the parent workspace is reachable via the filesystem. 1992cdf0c1d5Smjnelson # 1993cdf0c1d5Smjnelson if [[ -n $parent_webrev && -e $PWS/$PDIR/$PF ]]; then 1994cdf0c1d5Smjnelson cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF 1995cdf0c1d5Smjnelson elif [[ -n $HG_PARENT ]]; then 1996cdf0c1d5Smjnelson hg cat -R $CWS -r $HG_PARENT $CWS/$PDIR/$PF > \ 1997cdf0c1d5Smjnelson $olddir/$PDIR/$PF 2>/dev/null 1998cdf0c1d5Smjnelson 199902d26c39SVladimir Kotal if (( $? != 0 )); then 2000cdf0c1d5Smjnelson rm -f $olddir/$PDIR/$PF 2001cdf0c1d5Smjnelson else 2002cdf0c1d5Smjnelson if [[ -n $old_mode ]]; then 2003cdf0c1d5Smjnelson chmod $old_mode $olddir/$PDIR/$PF 2004cdf0c1d5Smjnelson else 2005cdf0c1d5Smjnelson # should never happen 2006cdf0c1d5Smjnelson print -u2 "ERROR: set mode of $olddir/$PDIR/$PF" 2007cdf0c1d5Smjnelson fi 2008cdf0c1d5Smjnelson fi 2009cdf0c1d5Smjnelson fi 2010cdf0c1d5Smjnelson} 2011cdf0c1d5Smjnelson 2012cdf0c1d5Smjnelsonfunction build_old_new_subversion 2013cdf0c1d5Smjnelson{ 2014cdf0c1d5Smjnelson typeset olddir="$1" 2015cdf0c1d5Smjnelson typeset newdir="$2" 2016cdf0c1d5Smjnelson 2017cdf0c1d5Smjnelson # Snag new version of file. 2018cdf0c1d5Smjnelson rm -f $newdir/$DIR/$F 2019cdf0c1d5Smjnelson [[ -e $CWS/$DIR/$F ]] && cp $CWS/$DIR/$F $newdir/$DIR/$F 2020cdf0c1d5Smjnelson 2021cdf0c1d5Smjnelson if [[ -n $PWS && -e $PWS/$PDIR/$PF ]]; then 2022cdf0c1d5Smjnelson cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF 2023cdf0c1d5Smjnelson else 2024cdf0c1d5Smjnelson # Get the parent's version of the file. 2025cdf0c1d5Smjnelson svn status $CWS/$DIR/$F | read stat file 2026cdf0c1d5Smjnelson if [[ $stat != "A" ]]; then 2027cdf0c1d5Smjnelson svn cat -r BASE $CWS/$DIR/$F > $olddir/$PDIR/$PF 2028cdf0c1d5Smjnelson fi 2029cdf0c1d5Smjnelson fi 2030cdf0c1d5Smjnelson} 2031cdf0c1d5Smjnelson 2032cdf0c1d5Smjnelsonfunction build_old_new_unknown 2033cdf0c1d5Smjnelson{ 2034cdf0c1d5Smjnelson typeset olddir="$1" 2035cdf0c1d5Smjnelson typeset newdir="$2" 2036cdf0c1d5Smjnelson 2037cdf0c1d5Smjnelson # 2038cdf0c1d5Smjnelson # Snag new version of file. 2039cdf0c1d5Smjnelson # 2040cdf0c1d5Smjnelson rm -f $newdir/$DIR/$F 2041cdf0c1d5Smjnelson [[ -e $CWS/$DIR/$F ]] && cp $CWS/$DIR/$F $newdir/$DIR/$F 2042cdf0c1d5Smjnelson 2043cdf0c1d5Smjnelson # 2044cdf0c1d5Smjnelson # Snag the parent's version of the file. 2045cdf0c1d5Smjnelson # 2046cdf0c1d5Smjnelson if [[ -f $PWS/$PDIR/$PF ]]; then 2047cdf0c1d5Smjnelson rm -f $olddir/$PDIR/$PF 2048cdf0c1d5Smjnelson cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF 2049cdf0c1d5Smjnelson fi 2050cdf0c1d5Smjnelson} 2051cdf0c1d5Smjnelson 2052cdf0c1d5Smjnelsonfunction build_old_new 2053cdf0c1d5Smjnelson{ 2054cdf0c1d5Smjnelson typeset WDIR=$1 2055cdf0c1d5Smjnelson typeset PWS=$2 2056cdf0c1d5Smjnelson typeset PDIR=$3 2057cdf0c1d5Smjnelson typeset PF=$4 2058cdf0c1d5Smjnelson typeset CWS=$5 2059cdf0c1d5Smjnelson typeset DIR=$6 2060cdf0c1d5Smjnelson typeset F=$7 2061cdf0c1d5Smjnelson 2062cdf0c1d5Smjnelson typeset olddir="$WDIR/raw_files/old" 2063cdf0c1d5Smjnelson typeset newdir="$WDIR/raw_files/new" 2064cdf0c1d5Smjnelson 2065cdf0c1d5Smjnelson mkdir -p $olddir/$PDIR 2066cdf0c1d5Smjnelson mkdir -p $newdir/$DIR 2067cdf0c1d5Smjnelson 2068cdf0c1d5Smjnelson if [[ $SCM_MODE == "teamware" ]]; then 2069cdf0c1d5Smjnelson build_old_new_teamware "$olddir" "$newdir" 2070cdf0c1d5Smjnelson elif [[ $SCM_MODE == "mercurial" ]]; then 2071cdf0c1d5Smjnelson build_old_new_mercurial "$olddir" "$newdir" 2072cdf0c1d5Smjnelson elif [[ $SCM_MODE == "subversion" ]]; then 2073cdf0c1d5Smjnelson build_old_new_subversion "$olddir" "$newdir" 2074cdf0c1d5Smjnelson elif [[ $SCM_MODE == "unknown" ]]; then 2075cdf0c1d5Smjnelson build_old_new_unknown "$olddir" "$newdir" 2076cdf0c1d5Smjnelson fi 2077cdf0c1d5Smjnelson 2078cdf0c1d5Smjnelson if [[ ! -f $olddir/$PDIR/$PF && ! -f $newdir/$DIR/$F ]]; then 2079cdf0c1d5Smjnelson print "*** Error: file not in parent or child" 2080cdf0c1d5Smjnelson return 1 2081cdf0c1d5Smjnelson fi 2082cdf0c1d5Smjnelson return 0 2083cdf0c1d5Smjnelson} 2084cdf0c1d5Smjnelson 2085cdf0c1d5Smjnelson 2086daaffb31Sdp# 2087daaffb31Sdp# Usage message. 2088daaffb31Sdp# 2089daaffb31Sdpfunction usage 2090daaffb31Sdp{ 2091daaffb31Sdp print 'Usage:\twebrev [common-options] 2092daaffb31Sdp webrev [common-options] ( <file> | - ) 2093daaffb31Sdp webrev [common-options] -w <wx file> 2094daaffb31Sdp 2095daaffb31SdpOptions: 2096ba44d8a2SVladimir Kotal -D: delete remote webrev 2097daaffb31Sdp -i <filename>: Include <filename> in the index.html file. 2098ba44d8a2SVladimir Kotal -n: do not generate the webrev (useful with -U) 2099ba44d8a2SVladimir Kotal -O: Print bugids/arc cases suitable for OpenSolaris. 2100daaffb31Sdp -o <outdir>: Output webrev to specified directory. 2101daaffb31Sdp -p <compare-against>: Use specified parent wkspc or basis for comparison 210202d26c39SVladimir Kotal -t <remote_target>: Specify remote destination for webrev upload 210302d26c39SVladimir Kotal -U: upload the webrev to remote destination 2104daaffb31Sdp -w <wxfile>: Use specified wx active file. 2105daaffb31Sdp 2106daaffb31SdpEnvironment: 2107daaffb31Sdp WDIR: Control the output directory. 2108daaffb31Sdp WEBREV_BUGURL: Control the URL prefix for bugids. 2109daaffb31Sdp WEBREV_SACURL: Control the URL prefix for ARC cases. 2110ba44d8a2SVladimir Kotal WEBREV_TRASH_DIR: Set directory for webrev delete. 2111daaffb31Sdp 2112cdf0c1d5SmjnelsonSCM Specific Options: 2113cdf0c1d5Smjnelson TeamWare: webrev [common-options] -l [arguments to 'putback'] 2114cdf0c1d5Smjnelson 2115daaffb31SdpSCM Environment: 2116cdf0c1d5Smjnelson CODEMGR_WS: Workspace location. 2117cdf0c1d5Smjnelson CODEMGR_PARENT: Parent workspace location. 2118daaffb31Sdp' 2119daaffb31Sdp 2120daaffb31Sdp exit 2 2121daaffb31Sdp} 2122daaffb31Sdp 2123daaffb31Sdp# 2124daaffb31Sdp# 2125daaffb31Sdp# Main program starts here 2126daaffb31Sdp# 2127daaffb31Sdp# 2128daaffb31Sdp 2129daaffb31Sdptrap "rm -f /tmp/$$.* ; exit" 0 1 2 3 15 2130daaffb31Sdp 2131daaffb31Sdpset +o noclobber 2132daaffb31Sdp 2133cdf0c1d5SmjnelsonPATH=$(dirname $(whence $0)):$PATH 2134cdf0c1d5Smjnelson 213514983201Sdp[[ -z $WDIFF ]] && WDIFF=`look_for_prog wdiff` 213614983201Sdp[[ -z $WX ]] && WX=`look_for_prog wx` 2137cdf0c1d5Smjnelson[[ -z $HG_ACTIVE ]] && HG_ACTIVE=`look_for_prog hg-active` 2138cdf0c1d5Smjnelson[[ -z $WHICH_SCM ]] && WHICH_SCM=`look_for_prog which_scm` 213914983201Sdp[[ -z $CODEREVIEW ]] && CODEREVIEW=`look_for_prog codereview` 214014983201Sdp[[ -z $PS2PDF ]] && PS2PDF=`look_for_prog ps2pdf` 214114983201Sdp[[ -z $PERL ]] && PERL=`look_for_prog perl` 214202d26c39SVladimir Kotal[[ -z $RSYNC ]] && RSYNC=`look_for_prog rsync` 2143cdf0c1d5Smjnelson[[ -z $SCCS ]] && SCCS=`look_for_prog sccs` 2144cdf0c1d5Smjnelson[[ -z $AWK ]] && AWK=`look_for_prog nawk` 2145cdf0c1d5Smjnelson[[ -z $AWK ]] && AWK=`look_for_prog gawk` 2146cdf0c1d5Smjnelson[[ -z $AWK ]] && AWK=`look_for_prog awk` 214702d26c39SVladimir Kotal[[ -z $SCP ]] && SCP=`look_for_prog scp` 2148b0088928SVladimir Kotal[[ -z $SED ]] && SED=`look_for_prog sed` 214902d26c39SVladimir Kotal[[ -z $SFTP ]] && SFTP=`look_for_prog sftp` 215002d26c39SVladimir Kotal[[ -z $MKTEMP ]] && MKTEMP=`look_for_prog mktemp` 215102d26c39SVladimir Kotal[[ -z $GREP ]] && GREP=`look_for_prog grep` 2152ba44d8a2SVladimir Kotal[[ -z $FIND ]] && FIND=`look_for_prog find` 2153cdf0c1d5Smjnelson 2154ba44d8a2SVladimir Kotal# set name of trash directory for remote webrev deletion 2155ba44d8a2SVladimir KotalTRASH_DIR=".trash" 2156ba44d8a2SVladimir Kotal[[ -n $WEBREV_TRASH_DIR ]] && TRASH_DIR=$WEBREV_TRASH_DIR 215714983201Sdp 215814983201Sdpif [[ ! -x $PERL ]]; then 215914983201Sdp print -u2 "Error: No perl interpreter found. Exiting." 216014983201Sdp exit 1 2161daaffb31Sdpfi 216214983201Sdp 2163cdf0c1d5Smjnelsonif [[ ! -x $WHICH_SCM ]]; then 2164cdf0c1d5Smjnelson print -u2 "Error: Could not find which_scm. Exiting." 2165cdf0c1d5Smjnelson exit 1 2166cdf0c1d5Smjnelsonfi 2167cdf0c1d5Smjnelson 216814983201Sdp# 216914983201Sdp# These aren't fatal, but we want to note them to the user. 217014983201Sdp# We don't warn on the absence of 'wx' until later when we've 217114983201Sdp# determined that we actually need to try to invoke it. 217214983201Sdp# 217314983201Sdp[[ ! -x $CODEREVIEW ]] && print -u2 "WARNING: codereview(1) not found." 217414983201Sdp[[ ! -x $PS2PDF ]] && print -u2 "WARNING: ps2pdf(1) not found." 217514983201Sdp[[ ! -x $WDIFF ]] && print -u2 "WARNING: wdiff not found." 2176daaffb31Sdp 2177daaffb31Sdp# Declare global total counters. 2178daaffb31Sdpinteger TOTL TINS TDEL TMOD TUNC 2179daaffb31Sdp 2180ba44d8a2SVladimir Kotal# default remote host for upload/delete 2181ba44d8a2SVladimir Kotaltypeset -r DEFAULT_REMOTE_HOST="cr.opensolaris.org" 2182b0088928SVladimir Kotal# prefixes for upload targets 2183b0088928SVladimir Kotaltypeset -r rsync_prefix="rsync://" 2184b0088928SVladimir Kotaltypeset -r ssh_prefix="ssh://" 2185ba44d8a2SVladimir Kotal 2186ba44d8a2SVladimir KotalDflag= 218714983201Sdpflist_mode= 218814983201Sdpflist_file= 2189daaffb31Sdpiflag= 219002d26c39SVladimir Kotallflag= 219102d26c39SVladimir KotalNflag= 219202d26c39SVladimir Kotalnflag= 219302d26c39SVladimir KotalOflag= 2194daaffb31Sdpoflag= 2195daaffb31Sdppflag= 219602d26c39SVladimir Kotaltflag= 219702d26c39SVladimir Kotaluflag= 219802d26c39SVladimir KotalUflag= 2199daaffb31Sdpwflag= 220002d26c39SVladimir Kotalremote_target= 2201ba44d8a2SVladimir Kotal 2202ba44d8a2SVladimir Kotal# 2203ba44d8a2SVladimir Kotal# NOTE: when adding/removing options it is necessary to sync the list 2204ba44d8a2SVladimir Kotal# with usr/src/tools/onbld/hgext/cdm.py 2205ba44d8a2SVladimir Kotal# 2206ba44d8a2SVladimir Kotalwhile getopts "i:o:p:lwONnt:UD" opt 2207daaffb31Sdpdo 2208daaffb31Sdp case $opt in 2209ba44d8a2SVladimir Kotal D) Dflag=1;; 2210ba44d8a2SVladimir Kotal 2211daaffb31Sdp i) iflag=1 2212daaffb31Sdp INCLUDE_FILE=$OPTARG;; 2213daaffb31Sdp 2214daaffb31Sdp # 2215daaffb31Sdp # If -l has been specified, we need to abort further options 2216daaffb31Sdp # processing, because subsequent arguments are going to be 2217daaffb31Sdp # arguments to 'putback -n'. 2218daaffb31Sdp # 2219daaffb31Sdp l) lflag=1 2220daaffb31Sdp break;; 2221daaffb31Sdp 222202d26c39SVladimir Kotal N) Nflag=1;; 222302d26c39SVladimir Kotal 222402d26c39SVladimir Kotal n) nflag=1;; 2225daaffb31Sdp 2226daaffb31Sdp O) Oflag=1;; 2227daaffb31Sdp 222802d26c39SVladimir Kotal o) oflag=1 222902d26c39SVladimir Kotal WDIR=$OPTARG;; 223002d26c39SVladimir Kotal 223102d26c39SVladimir Kotal p) pflag=1 223202d26c39SVladimir Kotal codemgr_parent=$OPTARG;; 223302d26c39SVladimir Kotal 223402d26c39SVladimir Kotal t) tflag=1 223502d26c39SVladimir Kotal remote_target=$OPTARG;; 223602d26c39SVladimir Kotal 223702d26c39SVladimir Kotal U) Uflag=1;; 223802d26c39SVladimir Kotal 223902d26c39SVladimir Kotal w) wflag=1;; 22403df69ef3SDarren Moffat 2241daaffb31Sdp ?) usage;; 2242daaffb31Sdp esac 2243daaffb31Sdpdone 2244daaffb31Sdp 2245daaffb31SdpFLIST=/tmp/$$.flist 2246daaffb31Sdp 2247daaffb31Sdpif [[ -n $wflag && -n $lflag ]]; then 2248daaffb31Sdp usage 2249daaffb31Sdpfi 2250daaffb31Sdp 225102d26c39SVladimir Kotal# more sanity checking 225202d26c39SVladimir Kotalif [[ -n $nflag && -z $Uflag ]]; then 2253ba44d8a2SVladimir Kotal print "it does not make sense to skip webrev generation" \ 2254ba44d8a2SVladimir Kotal "without -U" 225502d26c39SVladimir Kotal exit 1 225602d26c39SVladimir Kotalfi 225702d26c39SVladimir Kotal 2258ba44d8a2SVladimir Kotalif [[ -n $tflag && -z $Uflag && -z $Dflag ]]; then 2259ba44d8a2SVladimir Kotal echo "remote target has to be used only for upload or delete" 226002d26c39SVladimir Kotal exit 1 226102d26c39SVladimir Kotalfi 226202d26c39SVladimir Kotal 2263daaffb31Sdp# 2264daaffb31Sdp# If this manually set as the parent, and it appears to be an earlier webrev, 2265daaffb31Sdp# then note that fact and set the parent to the raw_files/new subdirectory. 2266daaffb31Sdp# 2267daaffb31Sdpif [[ -n $pflag && -d $codemgr_parent/raw_files/new ]]; then 2268daaffb31Sdp parent_webrev="$codemgr_parent" 2269daaffb31Sdp codemgr_parent="$codemgr_parent/raw_files/new" 2270daaffb31Sdpfi 2271daaffb31Sdp 2272daaffb31Sdpif [[ -z $wflag && -z $lflag ]]; then 2273daaffb31Sdp shift $(($OPTIND - 1)) 2274daaffb31Sdp 2275daaffb31Sdp if [[ $1 == "-" ]]; then 2276daaffb31Sdp cat > $FLIST 227714983201Sdp flist_mode="stdin" 227814983201Sdp flist_done=1 227914983201Sdp shift 2280daaffb31Sdp elif [[ -n $1 ]]; then 228114983201Sdp if [[ ! -r $1 ]]; then 2282daaffb31Sdp print -u2 "$1: no such file or not readable" 2283daaffb31Sdp usage 2284daaffb31Sdp fi 2285daaffb31Sdp cat $1 > $FLIST 228614983201Sdp flist_mode="file" 228714983201Sdp flist_file=$1 228814983201Sdp flist_done=1 228914983201Sdp shift 2290daaffb31Sdp else 229114983201Sdp flist_mode="auto" 2292daaffb31Sdp fi 2293daaffb31Sdpfi 2294daaffb31Sdp 2295daaffb31Sdp# 2296daaffb31Sdp# Before we go on to further consider -l and -w, work out which SCM we think 2297daaffb31Sdp# is in use. 2298daaffb31Sdp# 2299cdf0c1d5Smjnelson$WHICH_SCM | read SCM_MODE junk || exit 1 2300cdf0c1d5Smjnelsoncase "$SCM_MODE" in 2301cdf0c1d5Smjnelsonteamware|mercurial|subversion) 2302cdf0c1d5Smjnelson ;; 2303cdf0c1d5Smjnelsonunknown) 2304cdf0c1d5Smjnelson if [[ $flist_mode == "auto" ]]; then 2305cdf0c1d5Smjnelson print -u2 "Unable to determine SCM in use and file list not specified" 2306cdf0c1d5Smjnelson print -u2 "See which_scm(1) for SCM detection information." 23077c478bd9Sstevel@tonic-gate exit 1 23087c478bd9Sstevel@tonic-gate fi 2309cdf0c1d5Smjnelson ;; 2310cdf0c1d5Smjnelson*) 2311cdf0c1d5Smjnelson if [[ $flist_mode == "auto" ]]; then 2312cdf0c1d5Smjnelson print -u2 "Unsupported SCM in use ($SCM_MODE) and file list not specified" 2313cdf0c1d5Smjnelson exit 1 2314cdf0c1d5Smjnelson fi 2315cdf0c1d5Smjnelson ;; 2316cdf0c1d5Smjnelsonesac 23177c478bd9Sstevel@tonic-gate 2318daaffb31Sdpprint -u2 " SCM detected: $SCM_MODE" 2319daaffb31Sdp 2320daaffb31Sdpif [[ -n $lflag ]]; then 2321daaffb31Sdp # 2322daaffb31Sdp # If the -l flag is given instead of the name of a file list, 2323daaffb31Sdp # then generate the file list by extracting file names from a 2324daaffb31Sdp # putback -n. 2325daaffb31Sdp # 2326daaffb31Sdp shift $(($OPTIND - 1)) 2327cdf0c1d5Smjnelson if [[ $SCM_MODE == "teamware" ]]; then 2328daaffb31Sdp flist_from_teamware "$*" 2329cdf0c1d5Smjnelson else 2330cdf0c1d5Smjnelson print -u2 -- "Error: -l option only applies to TeamWare" 2331cdf0c1d5Smjnelson exit 1 2332cdf0c1d5Smjnelson fi 2333daaffb31Sdp flist_done=1 2334daaffb31Sdp shift $# 2335daaffb31Sdpelif [[ -n $wflag ]]; then 2336daaffb31Sdp # 2337daaffb31Sdp # If the -w is given then assume the file list is in Bonwick's "wx" 2338daaffb31Sdp # command format, i.e. pathname lines alternating with SCCS comment 2339daaffb31Sdp # lines with blank lines as separators. Use the SCCS comments later 2340daaffb31Sdp # in building the index.html file. 2341daaffb31Sdp # 2342daaffb31Sdp shift $(($OPTIND - 1)) 2343daaffb31Sdp wxfile=$1 2344daaffb31Sdp if [[ -z $wxfile && -n $CODEMGR_WS ]]; then 2345daaffb31Sdp if [[ -r $CODEMGR_WS/wx/active ]]; then 2346daaffb31Sdp wxfile=$CODEMGR_WS/wx/active 2347daaffb31Sdp fi 2348daaffb31Sdp fi 2349daaffb31Sdp 2350daaffb31Sdp [[ -z $wxfile ]] && print -u2 "wx file not specified, and could not " \ 2351daaffb31Sdp "be auto-detected (check \$CODEMGR_WS)" && exit 1 2352daaffb31Sdp 2353cdf0c1d5Smjnelson if [[ ! -r $wxfile ]]; then 2354cdf0c1d5Smjnelson print -u2 "$wxfile: no such file or not readable" 2355cdf0c1d5Smjnelson usage 2356cdf0c1d5Smjnelson fi 2357cdf0c1d5Smjnelson 2358daaffb31Sdp print -u2 " File list from: wx 'active' file '$wxfile' ... \c" 2359daaffb31Sdp flist_from_wx $wxfile 2360daaffb31Sdp flist_done=1 2361daaffb31Sdp if [[ -n "$*" ]]; then 2362daaffb31Sdp shift 2363daaffb31Sdp fi 236414983201Sdpelif [[ $flist_mode == "stdin" ]]; then 236514983201Sdp print -u2 " File list from: standard input" 236614983201Sdpelif [[ $flist_mode == "file" ]]; then 236714983201Sdp print -u2 " File list from: $flist_file" 2368daaffb31Sdpfi 2369daaffb31Sdp 2370daaffb31Sdpif [[ $# -gt 0 ]]; then 237114983201Sdp print -u2 "WARNING: unused arguments: $*" 2372daaffb31Sdpfi 2373daaffb31Sdp 2374daaffb31Sdpif [[ $SCM_MODE == "teamware" ]]; then 2375daaffb31Sdp # 2376daaffb31Sdp # Parent (internally $codemgr_parent) and workspace ($codemgr_ws) can 2377daaffb31Sdp # be set in a number of ways, in decreasing precedence: 2378daaffb31Sdp # 2379daaffb31Sdp # 1) on the command line (only for the parent) 2380daaffb31Sdp # 2) in the user environment 2381daaffb31Sdp # 3) in the flist 2382daaffb31Sdp # 4) automatically based on the workspace (only for the parent) 2383daaffb31Sdp # 2384daaffb31Sdp 2385daaffb31Sdp # 2386daaffb31Sdp # Here is case (2): the user environment 2387daaffb31Sdp # 2388daaffb31Sdp [[ -z $codemgr_ws && -n $CODEMGR_WS ]] && codemgr_ws=$CODEMGR_WS 2389daaffb31Sdp if [[ -n $codemgr_ws && ! -d $codemgr_ws ]]; then 2390daaffb31Sdp print -u2 "$codemgr_ws: no such workspace" 23917c478bd9Sstevel@tonic-gate exit 1 23927c478bd9Sstevel@tonic-gate fi 23937c478bd9Sstevel@tonic-gate 2394daaffb31Sdp [[ -z $codemgr_parent && -n $CODEMGR_PARENT ]] && \ 2395daaffb31Sdp codemgr_parent=$CODEMGR_PARENT 2396daaffb31Sdp if [[ -n $codemgr_parent && ! -d $codemgr_parent ]]; then 2397daaffb31Sdp print -u2 "$codemgr_parent: no such directory" 23987c478bd9Sstevel@tonic-gate exit 1 23997c478bd9Sstevel@tonic-gate fi 24007c478bd9Sstevel@tonic-gate 2401daaffb31Sdp # 2402daaffb31Sdp # If we're in auto-detect mode and we haven't already gotten the file 2403daaffb31Sdp # list, then see if we can get it by probing for wx. 2404daaffb31Sdp # 240514983201Sdp if [[ -z $flist_done && $flist_mode == "auto" && -n $codemgr_ws ]]; then 240614983201Sdp if [[ ! -x $WX ]]; then 240714983201Sdp print -u2 "WARNING: wx not found!" 2408daaffb31Sdp fi 24097c478bd9Sstevel@tonic-gate 2410daaffb31Sdp # 2411daaffb31Sdp # We need to use wx list -w so that we get renamed files, etc. 2412daaffb31Sdp # but only if a wx active file exists-- otherwise wx will 2413daaffb31Sdp # hang asking us to initialize our wx information. 2414daaffb31Sdp # 241514983201Sdp if [[ -x $WX && -f $codemgr_ws/wx/active ]]; then 2416daaffb31Sdp print -u2 " File list from: 'wx list -w' ... \c" 2417daaffb31Sdp $WX list -w > $FLIST 2418daaffb31Sdp $WX comments > /tmp/$$.wx_comments 2419daaffb31Sdp wxfile=/tmp/$$.wx_comments 2420daaffb31Sdp print -u2 "done" 2421daaffb31Sdp flist_done=1 2422daaffb31Sdp fi 2423daaffb31Sdp fi 2424daaffb31Sdp 2425daaffb31Sdp # 2426daaffb31Sdp # If by hook or by crook we've gotten a file list by now (perhaps 2427daaffb31Sdp # from the command line), eval it to extract environment variables from 2428daaffb31Sdp # it: This is step (3). 2429daaffb31Sdp # 2430daaffb31Sdp env_from_flist 2431daaffb31Sdp 2432daaffb31Sdp # 2433daaffb31Sdp # Continuing step (3): If we still have no file list, we'll try to get 2434daaffb31Sdp # it from teamware. 2435daaffb31Sdp # 2436daaffb31Sdp if [[ -z $flist_done ]]; then 2437daaffb31Sdp flist_from_teamware 2438daaffb31Sdp env_from_flist 2439daaffb31Sdp fi 2440daaffb31Sdp 2441daaffb31Sdp # 2442daaffb31Sdp # (4) If we still don't have a value for codemgr_parent, get it 2443daaffb31Sdp # from workspace. 2444daaffb31Sdp # 2445cdf0c1d5Smjnelson [[ -z $codemgr_ws ]] && codemgr_ws=`workspace name` 2446daaffb31Sdp [[ -z $codemgr_parent ]] && codemgr_parent=`workspace parent` 2447daaffb31Sdp if [[ ! -d $codemgr_parent ]]; then 2448daaffb31Sdp print -u2 "$CODEMGR_PARENT: no such parent workspace" 2449daaffb31Sdp exit 1 2450daaffb31Sdp fi 2451daaffb31Sdp 2452daaffb31Sdp # 2453cdf0c1d5Smjnelson # Observe true directory name of CODEMGR_WS, as used later in 2454cdf0c1d5Smjnelson # webrev title. 2455cdf0c1d5Smjnelson # 2456cdf0c1d5Smjnelson codemgr_ws=$(cd $codemgr_ws;print $PWD) 2457cdf0c1d5Smjnelson 2458cdf0c1d5Smjnelson # 2459daaffb31Sdp # Reset CODEMGR_WS to make sure teamware commands are happy. 2460daaffb31Sdp # 2461daaffb31Sdp CODEMGR_WS=$codemgr_ws 2462daaffb31Sdp CWS=$codemgr_ws 2463daaffb31Sdp PWS=$codemgr_parent 2464cdf0c1d5Smjnelson 2465cdf0c1d5Smjnelson [[ -n $parent_webrev ]] && RWS=$(workspace parent $CWS) 2466cdf0c1d5Smjnelson 2467cdf0c1d5Smjnelsonelif [[ $SCM_MODE == "mercurial" ]]; then 2468cdf0c1d5Smjnelson [[ -z $codemgr_ws && -n $CODEMGR_WS ]] && \ 2469cdf0c1d5Smjnelson codemgr_ws=`hg root -R $CODEMGR_WS 2>/dev/null` 2470cdf0c1d5Smjnelson 2471cdf0c1d5Smjnelson [[ -z $codemgr_ws ]] && codemgr_ws=`hg root 2>/dev/null` 2472cdf0c1d5Smjnelson 2473cdf0c1d5Smjnelson # 2474cdf0c1d5Smjnelson # Parent can either be specified with -p 2475cdf0c1d5Smjnelson # Specified with CODEMGR_PARENT in the environment 2476cdf0c1d5Smjnelson # or taken from hg's default path. 2477cdf0c1d5Smjnelson # 2478cdf0c1d5Smjnelson 2479cdf0c1d5Smjnelson if [[ -z $codemgr_parent && -n $CODEMGR_PARENT ]]; then 2480cdf0c1d5Smjnelson codemgr_parent=$CODEMGR_PARENT 2481cdf0c1d5Smjnelson fi 2482cdf0c1d5Smjnelson 2483cdf0c1d5Smjnelson if [[ -z $codemgr_parent ]]; then 2484cdf0c1d5Smjnelson codemgr_parent=`hg path -R $codemgr_ws default 2>/dev/null` 2485cdf0c1d5Smjnelson fi 2486cdf0c1d5Smjnelson 2487cdf0c1d5Smjnelson CWS_REV=`hg parent -R $codemgr_ws --template '{node|short}' 2>/dev/null` 2488cdf0c1d5Smjnelson CWS=$codemgr_ws 2489cdf0c1d5Smjnelson PWS=$codemgr_parent 2490cdf0c1d5Smjnelson 2491cdf0c1d5Smjnelson # 2492cdf0c1d5Smjnelson # If the parent is a webrev, we want to do some things against 2493cdf0c1d5Smjnelson # the natural workspace parent (file list, comments, etc) 2494cdf0c1d5Smjnelson # 2495cdf0c1d5Smjnelson if [[ -n $parent_webrev ]]; then 2496cdf0c1d5Smjnelson real_parent=$(hg path -R $codemgr_ws default 2>/dev/null) 2497cdf0c1d5Smjnelson else 2498cdf0c1d5Smjnelson real_parent=$PWS 2499cdf0c1d5Smjnelson fi 2500cdf0c1d5Smjnelson 2501cdf0c1d5Smjnelson # 2502cdf0c1d5Smjnelson # If hg-active exists, then we run it. In the case of no explicit 2503cdf0c1d5Smjnelson # flist given, we'll use it for our comments. In the case of an 2504cdf0c1d5Smjnelson # explicit flist given we'll try to use it for comments for any 2505cdf0c1d5Smjnelson # files mentioned in the flist. 2506cdf0c1d5Smjnelson # 2507cdf0c1d5Smjnelson if [[ -z $flist_done ]]; then 2508cdf0c1d5Smjnelson flist_from_mercurial $CWS $real_parent 2509cdf0c1d5Smjnelson flist_done=1 2510cdf0c1d5Smjnelson fi 2511cdf0c1d5Smjnelson 2512cdf0c1d5Smjnelson # 2513cdf0c1d5Smjnelson # If we have a file list now, pull out any variables set 2514cdf0c1d5Smjnelson # therein. We do this now (rather than when we possibly use 2515cdf0c1d5Smjnelson # hg-active to find comments) to avoid stomping specifications 2516cdf0c1d5Smjnelson # in the user-specified flist. 2517cdf0c1d5Smjnelson # 2518cdf0c1d5Smjnelson if [[ -n $flist_done ]]; then 2519cdf0c1d5Smjnelson env_from_flist 2520cdf0c1d5Smjnelson fi 2521cdf0c1d5Smjnelson 2522cdf0c1d5Smjnelson # 2523cdf0c1d5Smjnelson # Only call hg-active if we don't have a wx formatted file already 2524cdf0c1d5Smjnelson # 2525cdf0c1d5Smjnelson if [[ -x $HG_ACTIVE && -z $wxfile ]]; then 2526cdf0c1d5Smjnelson print " Comments from: hg-active -p $real_parent ...\c" 2527cdf0c1d5Smjnelson hg_active_wxfile $CWS $real_parent 2528cdf0c1d5Smjnelson print " Done." 2529cdf0c1d5Smjnelson fi 2530cdf0c1d5Smjnelson 2531cdf0c1d5Smjnelson # 2532cdf0c1d5Smjnelson # At this point we must have a wx flist either from hg-active, 2533cdf0c1d5Smjnelson # or in general. Use it to try and find our parent revision, 2534cdf0c1d5Smjnelson # if we don't have one. 2535cdf0c1d5Smjnelson # 2536cdf0c1d5Smjnelson if [[ -z $HG_PARENT ]]; then 2537b0088928SVladimir Kotal eval `$SED -e "s/#.*$//" $wxfile | $GREP HG_PARENT=` 2538cdf0c1d5Smjnelson fi 2539cdf0c1d5Smjnelson 2540cdf0c1d5Smjnelson # 2541cdf0c1d5Smjnelson # If we still don't have a parent, we must have been given a 2542cdf0c1d5Smjnelson # wx-style active list with no HG_PARENT specification, run 2543cdf0c1d5Smjnelson # hg-active and pull an HG_PARENT out of it, ignore the rest. 2544cdf0c1d5Smjnelson # 2545cdf0c1d5Smjnelson if [[ -z $HG_PARENT && -x $HG_ACTIVE ]]; then 2546cdf0c1d5Smjnelson $HG_ACTIVE -w $codemgr_ws -p $real_parent | \ 2547b0088928SVladimir Kotal eval `$SED -e "s/#.*$//" | $GREP HG_PARENT=` 2548cdf0c1d5Smjnelson elif [[ -z $HG_PARENT ]]; then 2549cdf0c1d5Smjnelson print -u2 "Error: Cannot discover parent revision" 2550cdf0c1d5Smjnelson exit 1 2551cdf0c1d5Smjnelson fi 2552cdf0c1d5Smjnelsonelif [[ $SCM_MODE == "subversion" ]]; then 2553cdf0c1d5Smjnelson if [[ -n $CODEMGR_WS && -d $CODEMGR_WS/.svn ]]; then 2554cdf0c1d5Smjnelson CWS=$CODEMGR_WS 2555cdf0c1d5Smjnelson else 2556cdf0c1d5Smjnelson svn info | while read line; do 2557cdf0c1d5Smjnelson if [[ $line == "URL: "* ]]; then 2558cdf0c1d5Smjnelson url=${line#URL: } 2559cdf0c1d5Smjnelson elif [[ $line == "Repository Root: "* ]]; then 2560cdf0c1d5Smjnelson repo=${line#Repository Root: } 2561cdf0c1d5Smjnelson fi 2562cdf0c1d5Smjnelson done 2563cdf0c1d5Smjnelson 2564cdf0c1d5Smjnelson rel=${url#$repo} 2565cdf0c1d5Smjnelson CWS=${PWD%$rel} 2566cdf0c1d5Smjnelson fi 2567cdf0c1d5Smjnelson 2568cdf0c1d5Smjnelson # 2569cdf0c1d5Smjnelson # We only will have a real parent workspace in the case one 2570cdf0c1d5Smjnelson # was specified (be it an older webrev, or another checkout). 2571cdf0c1d5Smjnelson # 2572cdf0c1d5Smjnelson [[ -n $codemgr_parent ]] && PWS=$codemgr_parent 2573cdf0c1d5Smjnelson 2574cdf0c1d5Smjnelson if [[ -z $flist_done && $flist_mode == "auto" ]]; then 2575cdf0c1d5Smjnelson flist_from_subversion $CWS $OLDPWD 2576cdf0c1d5Smjnelson fi 2577cdf0c1d5Smjnelsonelse 2578cdf0c1d5Smjnelson if [[ $SCM_MODE == "unknown" ]]; then 2579cdf0c1d5Smjnelson print -u2 " Unknown type of SCM in use" 2580cdf0c1d5Smjnelson else 2581cdf0c1d5Smjnelson print -u2 " Unsupported SCM in use: $SCM_MODE" 2582cdf0c1d5Smjnelson fi 2583cdf0c1d5Smjnelson 2584cdf0c1d5Smjnelson env_from_flist 2585cdf0c1d5Smjnelson 2586cdf0c1d5Smjnelson if [[ -z $CODEMGR_WS ]]; then 2587cdf0c1d5Smjnelson print -u2 "SCM not detected/supported and CODEMGR_WS not specified" 2588cdf0c1d5Smjnelson exit 1 2589cdf0c1d5Smjnelson fi 2590cdf0c1d5Smjnelson 2591cdf0c1d5Smjnelson if [[ -z $CODEMGR_PARENT ]]; then 2592cdf0c1d5Smjnelson print -u2 "SCM not detected/supported and CODEMGR_PARENT not specified" 2593cdf0c1d5Smjnelson exit 1 2594cdf0c1d5Smjnelson fi 2595cdf0c1d5Smjnelson 2596cdf0c1d5Smjnelson CWS=$CODEMGR_WS 2597cdf0c1d5Smjnelson PWS=$CODEMGR_PARENT 2598daaffb31Sdpfi 2599daaffb31Sdp 2600daaffb31Sdp# 2601daaffb31Sdp# If the user didn't specify a -i option, check to see if there is a 2602daaffb31Sdp# webrev-info file in the workspace directory. 2603daaffb31Sdp# 2604daaffb31Sdpif [[ -z $iflag && -r "$CWS/webrev-info" ]]; then 2605daaffb31Sdp iflag=1 2606daaffb31Sdp INCLUDE_FILE="$CWS/webrev-info" 2607daaffb31Sdpfi 2608daaffb31Sdp 2609daaffb31Sdpif [[ -n $iflag ]]; then 2610daaffb31Sdp if [[ ! -r $INCLUDE_FILE ]]; then 2611daaffb31Sdp print -u2 "include file '$INCLUDE_FILE' does not exist or is" \ 2612daaffb31Sdp "not readable." 2613daaffb31Sdp exit 1 2614daaffb31Sdp else 2615daaffb31Sdp # 2616daaffb31Sdp # $INCLUDE_FILE may be a relative path, and the script alters 2617daaffb31Sdp # PWD, so we just stash a copy in /tmp. 2618daaffb31Sdp # 2619daaffb31Sdp cp $INCLUDE_FILE /tmp/$$.include 2620daaffb31Sdp fi 2621daaffb31Sdpfi 2622daaffb31Sdp 2623daaffb31Sdp# 2624daaffb31Sdp# Output directory. 2625daaffb31Sdp# 2626daaffb31SdpWDIR=${WDIR:-$CWS/webrev} 2627daaffb31Sdp 2628daaffb31Sdp# 262902d26c39SVladimir Kotal# Name of the webrev, derived from the workspace name or output directory; 263002d26c39SVladimir Kotal# in the future this could potentially be an option. 2631daaffb31Sdp# 263202d26c39SVladimir Kotalif [[ -n $oflag ]]; then 263302d26c39SVladimir Kotal WNAME=${WDIR##*/} 263402d26c39SVladimir Kotalelse 2635daaffb31Sdp WNAME=${CWS##*/} 263602d26c39SVladimir Kotalfi 263702d26c39SVladimir Kotal 2638ba44d8a2SVladimir Kotal# Make sure remote target is well formed for remote upload/delete. 2639ba44d8a2SVladimir Kotalif [[ -n $Dflag || -n $Uflag ]]; then 2640b0088928SVladimir Kotal # 2641ba44d8a2SVladimir Kotal # If remote target is not specified, build it from scratch using 2642ba44d8a2SVladimir Kotal # the default values. 2643b0088928SVladimir Kotal # 2644ba44d8a2SVladimir Kotal if [[ -z $tflag ]]; then 2645ba44d8a2SVladimir Kotal remote_target=${DEFAULT_REMOTE_HOST}:${WNAME} 2646ba44d8a2SVladimir Kotal else 2647b0088928SVladimir Kotal # 2648b0088928SVladimir Kotal # Check upload target prefix first. 2649b0088928SVladimir Kotal # 2650b0088928SVladimir Kotal if [[ "${remote_target}" != ${rsync_prefix}* && 2651b0088928SVladimir Kotal "${remote_target}" != ${ssh_prefix}* ]]; then 2652b0088928SVladimir Kotal print "ERROR: invalid prefix of upload URI" \ 2653b0088928SVladimir Kotal "($remote_target)" 2654b0088928SVladimir Kotal exit 1 2655b0088928SVladimir Kotal fi 2656b0088928SVladimir Kotal # 2657ba44d8a2SVladimir Kotal # If destination specification is not in the form of 2658ba44d8a2SVladimir Kotal # host_spec:remote_dir then assume it is just remote hostname 2659ba44d8a2SVladimir Kotal # and append a colon and destination directory formed from 2660ba44d8a2SVladimir Kotal # local webrev directory name. 2661b0088928SVladimir Kotal # 2662b0088928SVladimir Kotal typeset target_no_prefix=${remote_target##*://} 2663b0088928SVladimir Kotal if [[ ${target_no_prefix} == *:* ]]; then 2664ba44d8a2SVladimir Kotal if [[ "${remote_target}" == *: ]]; then 2665b0088928SVladimir Kotal remote_target=${remote_target}${WNAME} 2666ba44d8a2SVladimir Kotal fi 2667b0088928SVladimir Kotal else 2668b0088928SVladimir Kotal if [[ ${target_no_prefix} == */* ]]; then 2669b0088928SVladimir Kotal print "ERROR: badly formed upload URI" \ 2670b0088928SVladimir Kotal "($remote_target)" 2671b0088928SVladimir Kotal exit 1 2672b0088928SVladimir Kotal else 2673b0088928SVladimir Kotal remote_target=${remote_target}:${WNAME} 2674ba44d8a2SVladimir Kotal fi 2675ba44d8a2SVladimir Kotal fi 2676ba44d8a2SVladimir Kotal fi 2677ba44d8a2SVladimir Kotal 2678b0088928SVladimir Kotal # 2679b0088928SVladimir Kotal # Strip trailing slash. Each upload method will deal with directory 2680b0088928SVladimir Kotal # specification separately. 2681b0088928SVladimir Kotal # 2682b0088928SVladimir Kotal remote_target=${remote_target%/} 2683b0088928SVladimir Kotalfi 2684b0088928SVladimir Kotal 2685b0088928SVladimir Kotal# 2686ba44d8a2SVladimir Kotal# Option -D by itself (option -U not present) implies no webrev generation. 2687b0088928SVladimir Kotal# 2688ba44d8a2SVladimir Kotalif [[ -z $Uflag && -n $Dflag ]]; then 2689b0088928SVladimir Kotal delete_webrev 1 1 2690ba44d8a2SVladimir Kotal exit $? 2691ba44d8a2SVladimir Kotalfi 2692ba44d8a2SVladimir Kotal 2693b0088928SVladimir Kotal# 2694ba44d8a2SVladimir Kotal# Do not generate the webrev, just upload it or delete it. 2695b0088928SVladimir Kotal# 2696ba44d8a2SVladimir Kotalif [[ -n $nflag ]]; then 2697ba44d8a2SVladimir Kotal if [[ -n $Dflag ]]; then 2698b0088928SVladimir Kotal delete_webrev 1 1 2699ba44d8a2SVladimir Kotal (( $? == 0 )) || exit $? 2700ba44d8a2SVladimir Kotal fi 2701ba44d8a2SVladimir Kotal if [[ -n $Uflag ]]; then 270202d26c39SVladimir Kotal upload_webrev 270302d26c39SVladimir Kotal exit $? 270402d26c39SVladimir Kotal fi 2705ba44d8a2SVladimir Kotalfi 2706daaffb31Sdp 2707e0e0293aSjmcpif [ "${WDIR%%/*}" ]; then 27087c478bd9Sstevel@tonic-gate WDIR=$PWD/$WDIR 27097c478bd9Sstevel@tonic-gatefi 2710daaffb31Sdp 2711daaffb31Sdpif [[ ! -d $WDIR ]]; then 2712daaffb31Sdp mkdir -p $WDIR 2713ba44d8a2SVladimir Kotal (( $? != 0 )) && exit 1 27147c478bd9Sstevel@tonic-gatefi 27157c478bd9Sstevel@tonic-gate 2716daaffb31Sdp# 2717daaffb31Sdp# Summarize what we're going to do. 2718daaffb31Sdp# 2719cdf0c1d5Smjnelsonif [[ -n $CWS_REV ]]; then 2720cdf0c1d5Smjnelson print " Workspace: $CWS (at $CWS_REV)" 2721cdf0c1d5Smjnelsonelse 2722daaffb31Sdp print " Workspace: $CWS" 2723cdf0c1d5Smjnelsonfi 2724daaffb31Sdpif [[ -n $parent_webrev ]]; then 2725daaffb31Sdp print "Compare against: webrev at $parent_webrev" 2726daaffb31Sdpelse 2727cdf0c1d5Smjnelson if [[ -n $HG_PARENT ]]; then 2728cdf0c1d5Smjnelson hg_parent_short=`echo $HG_PARENT \ 2729b0088928SVladimir Kotal | $SED -e 's/\([0-9a-f]\{12\}\).*/\1/'` 2730cdf0c1d5Smjnelson print "Compare against: $PWS (at $hg_parent_short)" 2731cdf0c1d5Smjnelson else 2732daaffb31Sdp print "Compare against: $PWS" 2733daaffb31Sdp fi 2734cdf0c1d5Smjnelsonfi 2735daaffb31Sdp 2736daaffb31Sdp[[ -n $INCLUDE_FILE ]] && print " Including: $INCLUDE_FILE" 2737daaffb31Sdpprint " Output to: $WDIR" 2738daaffb31Sdp 2739daaffb31Sdp# 27407c478bd9Sstevel@tonic-gate# Save the file list in the webrev dir 2741daaffb31Sdp# 2742daaffb31Sdp[[ ! $FLIST -ef $WDIR/file.list ]] && cp $FLIST $WDIR/file.list 27437c478bd9Sstevel@tonic-gate 2744daaffb31Sdp# 2745daaffb31Sdp# Bug IDs will be replaced by a URL. Order of precedence 2746daaffb31Sdp# is: default location, $WEBREV_BUGURL, the -O flag. 2747daaffb31Sdp# 2748daaffb31SdpBUGURL='http://monaco.sfbay.sun.com/detail.jsp?cr=' 2749daaffb31Sdp[[ -n $WEBREV_BUGURL ]] && BUGURL="$WEBREV_BUGURL" 2750daaffb31Sdp[[ -n "$Oflag" ]] && \ 2751daaffb31Sdp BUGURL='http://bugs.opensolaris.org/bugdatabase/view_bug.do?bug_id=' 27527c478bd9Sstevel@tonic-gate 2753daaffb31Sdp# 2754daaffb31Sdp# Likewise, ARC cases will be replaced by a URL. Order of precedence 2755daaffb31Sdp# is: default, $WEBREV_SACURL, the -O flag. 2756daaffb31Sdp# 2757daaffb31Sdp# Note that -O also triggers different substitution behavior for 2758daaffb31Sdp# SACURL. See sac2url(). 2759daaffb31Sdp# 2760daaffb31SdpSACURL='http://sac.eng.sun.com' 2761daaffb31Sdp[[ -n $WEBREV_SACURL ]] && SACURL="$WEBREV_SACURL" 2762e0e0293aSjmcp[[ -n "$Oflag" ]] && \ 2763daaffb31Sdp SACURL='http://www.opensolaris.org/os/community/arc/caselog' 27647c478bd9Sstevel@tonic-gate 2765daaffb31Sdprm -f $WDIR/$WNAME.patch 2766daaffb31Sdprm -f $WDIR/$WNAME.ps 2767daaffb31Sdprm -f $WDIR/$WNAME.pdf 27687c478bd9Sstevel@tonic-gate 2769daaffb31Sdptouch $WDIR/$WNAME.patch 27707c478bd9Sstevel@tonic-gate 2771daaffb31Sdpprint " Output Files:" 2772daaffb31Sdp 2773daaffb31Sdp# 2774daaffb31Sdp# Clean up the file list: Remove comments, blank lines and env variables. 2775daaffb31Sdp# 2776b0088928SVladimir Kotal$SED -e "s/#.*$//" -e "/=/d" -e "/^[ ]*$/d" $FLIST > /tmp/$$.flist.clean 2777daaffb31SdpFLIST=/tmp/$$.flist.clean 2778daaffb31Sdp 2779daaffb31Sdp# 2780cdf0c1d5Smjnelson# For Mercurial, create a cache of manifest entries. 2781cdf0c1d5Smjnelson# 2782cdf0c1d5Smjnelsonif [[ $SCM_MODE == "mercurial" ]]; then 2783cdf0c1d5Smjnelson # 2784cdf0c1d5Smjnelson # Transform the FLIST into a temporary sed script that matches 2785cdf0c1d5Smjnelson # relevant entries in the Mercurial manifest as follows: 2786cdf0c1d5Smjnelson # 1) The script will be used against the parent revision manifest, 2787cdf0c1d5Smjnelson # so for FLIST lines that have two filenames (a renamed file) 2788cdf0c1d5Smjnelson # keep only the old name. 2789cdf0c1d5Smjnelson # 2) Escape all forward slashes the filename. 2790cdf0c1d5Smjnelson # 3) Change the filename into another sed command that matches 2791cdf0c1d5Smjnelson # that file in "hg manifest -v" output: start of line, three 2792cdf0c1d5Smjnelson # octal digits for file permissions, space, a file type flag 2793cdf0c1d5Smjnelson # character, space, the filename, end of line. 2794cdf0c1d5Smjnelson # 2795cdf0c1d5Smjnelson SEDFILE=/tmp/$$.manifest.sed 2796b0088928SVladimir Kotal $SED ' 2797cdf0c1d5Smjnelson s#^[^ ]* ## 2798cdf0c1d5Smjnelson s#/#\\\/#g 2799cdf0c1d5Smjnelson s#^.*$#/^... . &$/p# 2800cdf0c1d5Smjnelson ' < $FLIST > $SEDFILE 2801cdf0c1d5Smjnelson 2802cdf0c1d5Smjnelson # 2803cdf0c1d5Smjnelson # Apply the generated script to the output of "hg manifest -v" 2804cdf0c1d5Smjnelson # to get the relevant subset for this webrev. 2805cdf0c1d5Smjnelson # 2806cdf0c1d5Smjnelson HG_PARENT_MANIFEST=/tmp/$$.manifest 2807cdf0c1d5Smjnelson hg -R $CWS manifest -v -r $HG_PARENT | 2808b0088928SVladimir Kotal $SED -n -f $SEDFILE > $HG_PARENT_MANIFEST 2809cdf0c1d5Smjnelsonfi 2810cdf0c1d5Smjnelson 2811cdf0c1d5Smjnelson# 2812daaffb31Sdp# First pass through the files: generate the per-file webrev HTML-files. 2813daaffb31Sdp# 2814daaffb31Sdpcat $FLIST | while read LINE 28157c478bd9Sstevel@tonic-gatedo 28167c478bd9Sstevel@tonic-gate set - $LINE 28177c478bd9Sstevel@tonic-gate P=$1 28187c478bd9Sstevel@tonic-gate 2819daaffb31Sdp # 2820daaffb31Sdp # Normally, each line in the file list is just a pathname of a 2821daaffb31Sdp # file that has been modified or created in the child. A file 2822daaffb31Sdp # that is renamed in the child workspace has two names on the 2823daaffb31Sdp # line: new name followed by the old name. 2824daaffb31Sdp # 2825daaffb31Sdp oldname="" 2826daaffb31Sdp oldpath="" 2827daaffb31Sdp rename= 2828daaffb31Sdp if [[ $# -eq 2 ]]; then 28297c478bd9Sstevel@tonic-gate PP=$2 # old filename 2830daaffb31Sdp oldname=" (was $PP)" 2831daaffb31Sdp oldpath="$PP" 2832daaffb31Sdp rename=1 28337c478bd9Sstevel@tonic-gate PDIR=${PP%/*} 2834daaffb31Sdp if [[ $PDIR == $PP ]]; then 28357c478bd9Sstevel@tonic-gate PDIR="." # File at root of workspace 28367c478bd9Sstevel@tonic-gate fi 28377c478bd9Sstevel@tonic-gate 28387c478bd9Sstevel@tonic-gate PF=${PP##*/} 28397c478bd9Sstevel@tonic-gate 28407c478bd9Sstevel@tonic-gate DIR=${P%/*} 2841daaffb31Sdp if [[ $DIR == $P ]]; then 28427c478bd9Sstevel@tonic-gate DIR="." # File at root of workspace 28437c478bd9Sstevel@tonic-gate fi 28447c478bd9Sstevel@tonic-gate 28457c478bd9Sstevel@tonic-gate F=${P##*/} 2846daaffb31Sdp 28477c478bd9Sstevel@tonic-gate else 28487c478bd9Sstevel@tonic-gate DIR=${P%/*} 2849daaffb31Sdp if [[ "$DIR" == "$P" ]]; then 28507c478bd9Sstevel@tonic-gate DIR="." # File at root of workspace 28517c478bd9Sstevel@tonic-gate fi 28527c478bd9Sstevel@tonic-gate 28537c478bd9Sstevel@tonic-gate F=${P##*/} 28547c478bd9Sstevel@tonic-gate 28557c478bd9Sstevel@tonic-gate PP=$P 28567c478bd9Sstevel@tonic-gate PDIR=$DIR 28577c478bd9Sstevel@tonic-gate PF=$F 28587c478bd9Sstevel@tonic-gate fi 28597c478bd9Sstevel@tonic-gate 2860daaffb31Sdp COMM=`getcomments html $P $PP` 28617c478bd9Sstevel@tonic-gate 2862daaffb31Sdp print "\t$P$oldname\n\t\t\c" 28637c478bd9Sstevel@tonic-gate 28647c478bd9Sstevel@tonic-gate # Make the webrev mirror directory if necessary 28657c478bd9Sstevel@tonic-gate mkdir -p $WDIR/$DIR 28667c478bd9Sstevel@tonic-gate 2867daaffb31Sdp # 2868daaffb31Sdp # If we're in OpenSolaris mode, we enforce a minor policy: 2869daaffb31Sdp # help to make sure the reviewer doesn't accidentally publish 2870e0e0293aSjmcp # source which is in usr/closed/* or deleted_files/usr/closed/* 2871daaffb31Sdp # 2872e0e0293aSjmcp if [[ -n "$Oflag" ]]; then 2873daaffb31Sdp pclosed=${P##usr/closed/} 2874e0e0293aSjmcp pdeleted=${P##deleted_files/usr/closed/} 2875e0e0293aSjmcp if [[ "$pclosed" != "$P" || "$pdeleted" != "$P" ]]; then 2876daaffb31Sdp print "*** Omitting closed source for OpenSolaris" \ 2877daaffb31Sdp "mode review" 2878daaffb31Sdp continue 2879daaffb31Sdp fi 2880daaffb31Sdp fi 2881daaffb31Sdp 2882daaffb31Sdp # 2883cdf0c1d5Smjnelson # We stash old and new files into parallel directories in $WDIR 2884daaffb31Sdp # and do our diffs there. This makes it possible to generate 2885daaffb31Sdp # clean looking diffs which don't have absolute paths present. 2886daaffb31Sdp # 2887daaffb31Sdp 2888cdf0c1d5Smjnelson build_old_new "$WDIR" "$PWS" "$PDIR" "$PF" "$CWS" "$DIR" "$F" || \ 28897c478bd9Sstevel@tonic-gate continue 28907c478bd9Sstevel@tonic-gate 2891cdf0c1d5Smjnelson # 2892cdf0c1d5Smjnelson # Keep the old PWD around, so we can safely switch back after 2893cdf0c1d5Smjnelson # diff generation, such that build_old_new runs in a 2894cdf0c1d5Smjnelson # consistent environment. 2895cdf0c1d5Smjnelson # 2896cdf0c1d5Smjnelson OWD=$PWD 2897daaffb31Sdp cd $WDIR/raw_files 2898daaffb31Sdp ofile=old/$PDIR/$PF 2899daaffb31Sdp nfile=new/$DIR/$F 29007c478bd9Sstevel@tonic-gate 2901daaffb31Sdp mv_but_nodiff= 2902daaffb31Sdp cmp $ofile $nfile > /dev/null 2>&1 2903daaffb31Sdp if [[ $? == 0 && $rename == 1 ]]; then 2904daaffb31Sdp mv_but_nodiff=1 2905daaffb31Sdp fi 2906daaffb31Sdp 2907daaffb31Sdp # 2908daaffb31Sdp # If we have old and new versions of the file then run the appropriate 2909daaffb31Sdp # diffs. This is complicated by a couple of factors: 2910daaffb31Sdp # 2911daaffb31Sdp # - renames must be handled specially: we emit a 'remove' 2912daaffb31Sdp # diff and an 'add' diff 2913daaffb31Sdp # - new files and deleted files must be handled specially 2914daaffb31Sdp # - Solaris patch(1m) can't cope with file creation 2915daaffb31Sdp # (and hence renames) as of this writing. 2916daaffb31Sdp # - To make matters worse, gnu patch doesn't interpret the 2917daaffb31Sdp # output of Solaris diff properly when it comes to 2918daaffb31Sdp # adds and deletes. We need to do some "cleansing" 2919daaffb31Sdp # transformations: 2920daaffb31Sdp # [to add a file] @@ -1,0 +X,Y @@ --> @@ -0,0 +X,Y @@ 2921daaffb31Sdp # [to del a file] @@ -X,Y +1,0 @@ --> @@ -X,Y +0,0 @@ 2922daaffb31Sdp # 2923b0088928SVladimir Kotal cleanse_rmfile="$SED 's/^\(@@ [0-9+,-]*\) [0-9+,-]* @@$/\1 +0,0 @@/'" 2924b0088928SVladimir Kotal cleanse_newfile="$SED 's/^@@ [0-9+,-]* \([0-9+,-]* @@\)$/@@ -0,0 \1/'" 2925daaffb31Sdp 2926daaffb31Sdp rm -f $WDIR/$DIR/$F.patch 2927daaffb31Sdp if [[ -z $rename ]]; then 2928e0e0293aSjmcp if [ ! -f "$ofile" ]; then 2929daaffb31Sdp diff -u /dev/null $nfile | sh -c "$cleanse_newfile" \ 2930daaffb31Sdp > $WDIR/$DIR/$F.patch 2931e0e0293aSjmcp elif [ ! -f "$nfile" ]; then 2932daaffb31Sdp diff -u $ofile /dev/null | sh -c "$cleanse_rmfile" \ 2933daaffb31Sdp > $WDIR/$DIR/$F.patch 2934daaffb31Sdp else 2935daaffb31Sdp diff -u $ofile $nfile > $WDIR/$DIR/$F.patch 2936daaffb31Sdp fi 2937daaffb31Sdp else 2938daaffb31Sdp diff -u $ofile /dev/null | sh -c "$cleanse_rmfile" \ 2939daaffb31Sdp > $WDIR/$DIR/$F.patch 2940daaffb31Sdp 2941daaffb31Sdp diff -u /dev/null $nfile | sh -c "$cleanse_newfile" \ 2942daaffb31Sdp >> $WDIR/$DIR/$F.patch 2943daaffb31Sdp 2944daaffb31Sdp fi 2945daaffb31Sdp 2946daaffb31Sdp # 2947daaffb31Sdp # Tack the patch we just made onto the accumulated patch for the 2948daaffb31Sdp # whole wad. 2949daaffb31Sdp # 2950daaffb31Sdp cat $WDIR/$DIR/$F.patch >> $WDIR/$WNAME.patch 2951daaffb31Sdp 2952daaffb31Sdp print " patch\c" 2953daaffb31Sdp 2954daaffb31Sdp if [[ -f $ofile && -f $nfile && -z $mv_but_nodiff ]]; then 2955daaffb31Sdp 2956daaffb31Sdp ${CDIFFCMD:-diff -bt -C 5} $ofile $nfile > $WDIR/$DIR/$F.cdiff 2957daaffb31Sdp diff_to_html $F $DIR/$F "C" "$COMM" < $WDIR/$DIR/$F.cdiff \ 2958daaffb31Sdp > $WDIR/$DIR/$F.cdiff.html 29597c478bd9Sstevel@tonic-gate print " cdiffs\c" 29607c478bd9Sstevel@tonic-gate 2961daaffb31Sdp ${UDIFFCMD:-diff -bt -U 5} $ofile $nfile > $WDIR/$DIR/$F.udiff 2962daaffb31Sdp diff_to_html $F $DIR/$F "U" "$COMM" < $WDIR/$DIR/$F.udiff \ 2963daaffb31Sdp > $WDIR/$DIR/$F.udiff.html 2964daaffb31Sdp 29657c478bd9Sstevel@tonic-gate print " udiffs\c" 29667c478bd9Sstevel@tonic-gate 29677c478bd9Sstevel@tonic-gate if [[ -x $WDIFF ]]; then 2968daaffb31Sdp $WDIFF -c "$COMM" \ 2969daaffb31Sdp -t "$WNAME Wdiff $DIR/$F" $ofile $nfile > \ 2970daaffb31Sdp $WDIR/$DIR/$F.wdiff.html 2>/dev/null 2971daaffb31Sdp if [[ $? -eq 0 ]]; then 29727c478bd9Sstevel@tonic-gate print " wdiffs\c" 2973daaffb31Sdp else 2974daaffb31Sdp print " wdiffs[fail]\c" 2975daaffb31Sdp fi 29767c478bd9Sstevel@tonic-gate fi 29777c478bd9Sstevel@tonic-gate 2978daaffb31Sdp sdiff_to_html $ofile $nfile $F $DIR "$COMM" \ 2979daaffb31Sdp > $WDIR/$DIR/$F.sdiff.html 29807c478bd9Sstevel@tonic-gate print " sdiffs\c" 29817c478bd9Sstevel@tonic-gate 29827c478bd9Sstevel@tonic-gate print " frames\c" 29837c478bd9Sstevel@tonic-gate 29847c478bd9Sstevel@tonic-gate rm -f $WDIR/$DIR/$F.cdiff $WDIR/$DIR/$F.udiff 29857c478bd9Sstevel@tonic-gate 2986daaffb31Sdp difflines $ofile $nfile > $WDIR/$DIR/$F.count 2987daaffb31Sdp 2988daaffb31Sdp elif [[ -f $ofile && -f $nfile && -n $mv_but_nodiff ]]; then 2989daaffb31Sdp # renamed file: may also have differences 2990daaffb31Sdp difflines $ofile $nfile > $WDIR/$DIR/$F.count 2991daaffb31Sdp elif [[ -f $nfile ]]; then 29927c478bd9Sstevel@tonic-gate # new file: count added lines 2993daaffb31Sdp difflines /dev/null $nfile > $WDIR/$DIR/$F.count 2994daaffb31Sdp elif [[ -f $ofile ]]; then 29957c478bd9Sstevel@tonic-gate # old file: count deleted lines 2996daaffb31Sdp difflines $ofile /dev/null > $WDIR/$DIR/$F.count 29977c478bd9Sstevel@tonic-gate fi 29987c478bd9Sstevel@tonic-gate 2999daaffb31Sdp # 3000daaffb31Sdp # Now we generate the postscript for this file. We generate diffs 3001daaffb31Sdp # only in the event that there is delta, or the file is new (it seems 3002daaffb31Sdp # tree-killing to print out the contents of deleted files). 3003daaffb31Sdp # 3004daaffb31Sdp if [[ -f $nfile ]]; then 3005daaffb31Sdp ocr=$ofile 3006daaffb31Sdp [[ ! -f $ofile ]] && ocr=/dev/null 3007daaffb31Sdp 3008daaffb31Sdp if [[ -z $mv_but_nodiff ]]; then 3009daaffb31Sdp textcomm=`getcomments text $P $PP` 301014983201Sdp if [[ -x $CODEREVIEW ]]; then 301114983201Sdp $CODEREVIEW -y "$textcomm" \ 301214983201Sdp -e $ocr $nfile \ 301314983201Sdp > /tmp/$$.psfile 2>/dev/null && 301414983201Sdp cat /tmp/$$.psfile >> $WDIR/$WNAME.ps 3015daaffb31Sdp if [[ $? -eq 0 ]]; then 3016daaffb31Sdp print " ps\c" 3017daaffb31Sdp else 3018daaffb31Sdp print " ps[fail]\c" 3019daaffb31Sdp fi 3020daaffb31Sdp fi 3021daaffb31Sdp fi 302214983201Sdp fi 3023daaffb31Sdp 3024cdf0c1d5Smjnelson if [[ -f $ofile ]]; then 3025cdf0c1d5Smjnelson source_to_html Old $PP < $ofile > $WDIR/$DIR/$F-.html 30267c478bd9Sstevel@tonic-gate print " old\c" 30277c478bd9Sstevel@tonic-gate fi 30287c478bd9Sstevel@tonic-gate 3029daaffb31Sdp if [[ -f $nfile ]]; then 3030daaffb31Sdp source_to_html New $P < $nfile > $WDIR/$DIR/$F.html 30317c478bd9Sstevel@tonic-gate print " new\c" 30327c478bd9Sstevel@tonic-gate fi 30337c478bd9Sstevel@tonic-gate 3034cdf0c1d5Smjnelson cd $OWD 3035cdf0c1d5Smjnelson 3036daaffb31Sdp print 30377c478bd9Sstevel@tonic-gatedone 30387c478bd9Sstevel@tonic-gate 3039daaffb31Sdpframe_nav_js > $WDIR/ancnav.js 30407c478bd9Sstevel@tonic-gateframe_navigation > $WDIR/ancnav.html 3041daaffb31Sdp 304214983201Sdpif [[ ! -f $WDIR/$WNAME.ps ]]; then 304314983201Sdp print " Generating PDF: Skipped: no output available" 304414983201Sdpelif [[ -x $CODEREVIEW && -x $PS2PDF ]]; then 304514983201Sdp print " Generating PDF: \c" 304614983201Sdp fix_postscript $WDIR/$WNAME.ps | $PS2PDF - > $WDIR/$WNAME.pdf 3047daaffb31Sdp print "Done." 304814983201Sdpelse 304914983201Sdp print " Generating PDF: Skipped: missing 'ps2pdf' or 'codereview'" 305014983201Sdpfi 30517c478bd9Sstevel@tonic-gate 3052e0e0293aSjmcp# If we're in OpenSolaris mode and there's a closed dir under $WDIR, 3053e0e0293aSjmcp# delete it - prevent accidental publishing of closed source 3054e0e0293aSjmcp 3055e0e0293aSjmcpif [[ -n "$Oflag" ]]; then 3056ba44d8a2SVladimir Kotal $FIND $WDIR -type d -name closed -exec /bin/rm -rf {} \; 3057e0e0293aSjmcpfi 3058e0e0293aSjmcp 30597c478bd9Sstevel@tonic-gate# Now build the index.html file that contains 30607c478bd9Sstevel@tonic-gate# links to the source files and their diffs. 30617c478bd9Sstevel@tonic-gate 30627c478bd9Sstevel@tonic-gatecd $CWS 30637c478bd9Sstevel@tonic-gate 30647c478bd9Sstevel@tonic-gate# Save total changed lines for Code Inspection. 3065daaffb31Sdpprint "$TOTL" > $WDIR/TotalChangedLines 30667c478bd9Sstevel@tonic-gate 3067daaffb31Sdpprint " index.html: \c" 30687c478bd9Sstevel@tonic-gateINDEXFILE=$WDIR/index.html 30697c478bd9Sstevel@tonic-gateexec 3<&1 # duplicate stdout to FD3. 30707c478bd9Sstevel@tonic-gateexec 1<&- # Close stdout. 30717c478bd9Sstevel@tonic-gateexec > $INDEXFILE # Open stdout to index file. 30727c478bd9Sstevel@tonic-gate 3073daaffb31Sdpprint "$HTML<head>$STDHEAD" 3074daaffb31Sdpprint "<title>$WNAME</title>" 3075daaffb31Sdpprint "</head>" 3076daaffb31Sdpprint "<body id=\"SUNWwebrev\">" 3077daaffb31Sdpprint "<div class=\"summary\">" 3078daaffb31Sdpprint "<h2>Code Review for $WNAME</h2>" 30797c478bd9Sstevel@tonic-gate 3080daaffb31Sdpprint "<table>" 30817c478bd9Sstevel@tonic-gate 3082daaffb31Sdp# 3083cdf0c1d5Smjnelson# Get the preparer's name: 3084daaffb31Sdp# 3085cdf0c1d5Smjnelson# If the SCM detected is Mercurial, and the configuration property 3086cdf0c1d5Smjnelson# ui.username is available, use that, but be careful to properly escape 3087cdf0c1d5Smjnelson# angle brackets (HTML syntax characters) in the email address. 3088cdf0c1d5Smjnelson# 3089cdf0c1d5Smjnelson# Otherwise, use the current userid in the form "John Doe (jdoe)", but 3090cdf0c1d5Smjnelson# to maintain compatibility with passwd(4), we must support '&' substitutions. 3091cdf0c1d5Smjnelson# 3092cdf0c1d5Smjnelsonpreparer= 3093cdf0c1d5Smjnelsonif [[ "$SCM_MODE" == mercurial ]]; then 3094cdf0c1d5Smjnelson preparer=`hg showconfig ui.username 2>/dev/null` 3095cdf0c1d5Smjnelson if [[ -n "$preparer" ]]; then 3096cdf0c1d5Smjnelson preparer="$(echo "$preparer" | html_quote)" 3097cdf0c1d5Smjnelson fi 3098cdf0c1d5Smjnelsonfi 3099cdf0c1d5Smjnelsonif [[ -z "$preparer" ]]; then 3100cdf0c1d5Smjnelson preparer=$( 3101cdf0c1d5Smjnelson $PERL -e ' 3102cdf0c1d5Smjnelson ($login, $pw, $uid, $gid, $quota, $cmt, $gcos) = getpwuid($<); 3103cdf0c1d5Smjnelson if ($login) { 3104cdf0c1d5Smjnelson $gcos =~ s/\&/ucfirst($login)/e; 3105cdf0c1d5Smjnelson printf "%s (%s)\n", $gcos, $login; 3106cdf0c1d5Smjnelson } else { 3107cdf0c1d5Smjnelson printf "(unknown)\n"; 3108cdf0c1d5Smjnelson } 3109cdf0c1d5Smjnelson ') 3110daaffb31Sdpfi 3111daaffb31Sdp 3112cdf0c1d5Smjnelsonprint "<tr><th>Prepared by:</th><td>$preparer on `date`</td></tr>" 3113cdf0c1d5Smjnelsonprint "<tr><th>Workspace:</th><td>$CWS" 3114cdf0c1d5Smjnelsonif [[ -n $CWS_REV ]]; then 3115cdf0c1d5Smjnelson print "(at $CWS_REV)" 3116cdf0c1d5Smjnelsonfi 3117cdf0c1d5Smjnelsonprint "</td></tr>" 3118daaffb31Sdpprint "<tr><th>Compare against:</th><td>" 3119daaffb31Sdpif [[ -n $parent_webrev ]]; then 3120daaffb31Sdp print "webrev at $parent_webrev" 3121daaffb31Sdpelse 3122daaffb31Sdp print "$PWS" 3123cdf0c1d5Smjnelson if [[ -n $hg_parent_short ]]; then 3124cdf0c1d5Smjnelson print "(at $hg_parent_short)" 3125cdf0c1d5Smjnelson fi 3126daaffb31Sdpfi 3127daaffb31Sdpprint "</td></tr>" 3128daaffb31Sdpprint "<tr><th>Summary of changes:</th><td>" 3129daaffb31SdpprintCI $TOTL $TINS $TDEL $TMOD $TUNC 3130daaffb31Sdpprint "</td></tr>" 3131daaffb31Sdp 3132daaffb31Sdpif [[ -f $WDIR/$WNAME.patch ]]; then 3133371d72daSLubomir Sedlacik wpatch_url="$(print $WNAME.patch | url_encode)" 3134daaffb31Sdp print "<tr><th>Patch of changes:</th><td>" 3135371d72daSLubomir Sedlacik print "<a href=\"$wpatch_url\">$WNAME.patch</a></td></tr>" 3136daaffb31Sdpfi 3137daaffb31Sdpif [[ -f $WDIR/$WNAME.pdf ]]; then 3138371d72daSLubomir Sedlacik wpdf_url="$(print $WNAME.pdf | url_encode)" 3139daaffb31Sdp print "<tr><th>Printable review:</th><td>" 3140371d72daSLubomir Sedlacik print "<a href=\"$wpdf_url\">$WNAME.pdf</a></td></tr>" 3141daaffb31Sdpfi 3142daaffb31Sdp 3143daaffb31Sdpif [[ -n "$iflag" ]]; then 3144daaffb31Sdp print "<tr><th>Author comments:</th><td><div>" 3145daaffb31Sdp cat /tmp/$$.include 3146daaffb31Sdp print "</div></td></tr>" 3147daaffb31Sdpfi 3148daaffb31Sdpprint "</table>" 3149daaffb31Sdpprint "</div>" 3150daaffb31Sdp 3151daaffb31Sdp# 3152daaffb31Sdp# Second pass through the files: generate the rest of the index file 3153daaffb31Sdp# 3154daaffb31Sdpcat $FLIST | while read LINE 31557c478bd9Sstevel@tonic-gatedo 31567c478bd9Sstevel@tonic-gate set - $LINE 31577c478bd9Sstevel@tonic-gate P=$1 31587c478bd9Sstevel@tonic-gate 3159daaffb31Sdp if [[ $# == 2 ]]; then 31607c478bd9Sstevel@tonic-gate PP=$2 3161cdf0c1d5Smjnelson oldname="$PP" 31627c478bd9Sstevel@tonic-gate else 31637c478bd9Sstevel@tonic-gate PP=$P 3164daaffb31Sdp oldname="" 3165daaffb31Sdp fi 3166daaffb31Sdp 3167cdf0c1d5Smjnelson mv_but_nodiff= 3168cdf0c1d5Smjnelson cmp $WDIR/raw_files/old/$PP $WDIR/raw_files/new/$P > /dev/null 2>&1 3169cdf0c1d5Smjnelson if [[ $? == 0 && -n "$oldname" ]]; then 3170cdf0c1d5Smjnelson mv_but_nodiff=1 3171cdf0c1d5Smjnelson fi 3172cdf0c1d5Smjnelson 3173daaffb31Sdp DIR=${P%/*} 3174daaffb31Sdp if [[ $DIR == $P ]]; then 3175daaffb31Sdp DIR="." # File at root of workspace 31767c478bd9Sstevel@tonic-gate fi 31777c478bd9Sstevel@tonic-gate 31787c478bd9Sstevel@tonic-gate # Avoid processing the same file twice. 31797c478bd9Sstevel@tonic-gate # It's possible for renamed files to 31807c478bd9Sstevel@tonic-gate # appear twice in the file list 31817c478bd9Sstevel@tonic-gate 31827c478bd9Sstevel@tonic-gate F=$WDIR/$P 31837c478bd9Sstevel@tonic-gate 3184daaffb31Sdp print "<p>" 31857c478bd9Sstevel@tonic-gate 31867c478bd9Sstevel@tonic-gate # If there's a diffs file, make diffs links 31877c478bd9Sstevel@tonic-gate 3188daaffb31Sdp if [[ -f $F.cdiff.html ]]; then 3189371d72daSLubomir Sedlacik cdiff_url="$(print $P.cdiff.html | url_encode)" 3190371d72daSLubomir Sedlacik udiff_url="$(print $P.udiff.html | url_encode)" 3191371d72daSLubomir Sedlacik print "<a href=\"$cdiff_url\">Cdiffs</a>" 3192371d72daSLubomir Sedlacik print "<a href=\"$udiff_url\">Udiffs</a>" 31937c478bd9Sstevel@tonic-gate 3194daaffb31Sdp if [[ -f $F.wdiff.html && -x $WDIFF ]]; then 3195371d72daSLubomir Sedlacik wdiff_url="$(print $P.wdiff.html | url_encode)" 3196371d72daSLubomir Sedlacik print "<a href=\"$wdiff_url\">Wdiffs</a>" 31977c478bd9Sstevel@tonic-gate fi 31987c478bd9Sstevel@tonic-gate 3199371d72daSLubomir Sedlacik sdiff_url="$(print $P.sdiff.html | url_encode)" 3200371d72daSLubomir Sedlacik print "<a href=\"$sdiff_url\">Sdiffs</a>" 32017c478bd9Sstevel@tonic-gate 3202371d72daSLubomir Sedlacik frames_url="$(print $P.frames.html | url_encode)" 3203371d72daSLubomir Sedlacik print "<a href=\"$frames_url\">Frames</a>" 32047c478bd9Sstevel@tonic-gate else 3205daaffb31Sdp print " ------ ------ ------" 32067c478bd9Sstevel@tonic-gate 3207daaffb31Sdp if [[ -x $WDIFF ]]; then 32087c478bd9Sstevel@tonic-gate print " ------" 32097c478bd9Sstevel@tonic-gate fi 3210daaffb31Sdp 3211daaffb31Sdp print " ------" 32127c478bd9Sstevel@tonic-gate fi 32137c478bd9Sstevel@tonic-gate 32147c478bd9Sstevel@tonic-gate # If there's an old file, make the link 32157c478bd9Sstevel@tonic-gate 3216daaffb31Sdp if [[ -f $F-.html ]]; then 3217371d72daSLubomir Sedlacik oldfile_url="$(print $P-.html | url_encode)" 3218371d72daSLubomir Sedlacik print "<a href=\"$oldfile_url\">Old</a>" 32197c478bd9Sstevel@tonic-gate else 3220daaffb31Sdp print " ---" 32217c478bd9Sstevel@tonic-gate fi 32227c478bd9Sstevel@tonic-gate 32237c478bd9Sstevel@tonic-gate # If there's an new file, make the link 32247c478bd9Sstevel@tonic-gate 3225daaffb31Sdp if [[ -f $F.html ]]; then 3226371d72daSLubomir Sedlacik newfile_url="$(print $P.html | url_encode)" 3227371d72daSLubomir Sedlacik print "<a href=\"$newfile_url\">New</a>" 32287c478bd9Sstevel@tonic-gate else 3229daaffb31Sdp print " ---" 32307c478bd9Sstevel@tonic-gate fi 32317c478bd9Sstevel@tonic-gate 3232daaffb31Sdp if [[ -f $F.patch ]]; then 3233371d72daSLubomir Sedlacik patch_url="$(print $P.patch | url_encode)" 3234371d72daSLubomir Sedlacik print "<a href=\"$patch_url\">Patch</a>" 3235daaffb31Sdp else 3236daaffb31Sdp print " -----" 3237daaffb31Sdp fi 3238daaffb31Sdp 3239daaffb31Sdp if [[ -f $WDIR/raw_files/new/$P ]]; then 3240371d72daSLubomir Sedlacik rawfiles_url="$(print raw_files/new/$P | url_encode)" 3241371d72daSLubomir Sedlacik print "<a href=\"$rawfiles_url\">Raw</a>" 3242daaffb31Sdp else 3243daaffb31Sdp print " ---" 3244daaffb31Sdp fi 3245daaffb31Sdp 3246cdf0c1d5Smjnelson print "<b>$P</b>" 3247cdf0c1d5Smjnelson 3248cdf0c1d5Smjnelson # For renamed files, clearly state whether or not they are modified 3249cdf0c1d5Smjnelson if [[ -n "$oldname" ]]; then 3250cdf0c1d5Smjnelson if [[ -n "$mv_but_nodiff" ]]; then 3251cdf0c1d5Smjnelson print "<i>(renamed only, was $oldname)</i>" 3252cdf0c1d5Smjnelson else 3253cdf0c1d5Smjnelson print "<i>(modified and renamed, was $oldname)</i>" 3254cdf0c1d5Smjnelson fi 3255cdf0c1d5Smjnelson fi 3256cdf0c1d5Smjnelson 3257cdf0c1d5Smjnelson # If there's an old file, but no new file, the file was deleted 3258cdf0c1d5Smjnelson if [[ -f $F-.html && ! -f $F.html ]]; then 3259cdf0c1d5Smjnelson print " <i>(deleted)</i>" 3260cdf0c1d5Smjnelson fi 3261daaffb31Sdp 3262daaffb31Sdp # 3263e0e0293aSjmcp # Check for usr/closed and deleted_files/usr/closed 3264daaffb31Sdp # 3265daaffb31Sdp if [ ! -z "$Oflag" ]; then 3266e0e0293aSjmcp if [[ $P == usr/closed/* || \ 3267e0e0293aSjmcp $P == deleted_files/usr/closed/* ]]; then 3268daaffb31Sdp print " <i>Closed source: omitted from" \ 3269daaffb31Sdp "this review</i>" 3270daaffb31Sdp fi 3271daaffb31Sdp fi 3272daaffb31Sdp 3273daaffb31Sdp print "</p>" 32747c478bd9Sstevel@tonic-gate # Insert delta comments 32757c478bd9Sstevel@tonic-gate 3276daaffb31Sdp print "<blockquote><pre>" 3277daaffb31Sdp getcomments html $P $PP 3278daaffb31Sdp print "</pre>" 32797c478bd9Sstevel@tonic-gate 32807c478bd9Sstevel@tonic-gate # Add additional comments comment 32817c478bd9Sstevel@tonic-gate 3282daaffb31Sdp print "<!-- Add comments to explain changes in $P here -->" 32837c478bd9Sstevel@tonic-gate 32847c478bd9Sstevel@tonic-gate # Add count of changes. 32857c478bd9Sstevel@tonic-gate 3286daaffb31Sdp if [[ -f $F.count ]]; then 32877c478bd9Sstevel@tonic-gate cat $F.count 32887c478bd9Sstevel@tonic-gate rm $F.count 32897c478bd9Sstevel@tonic-gate fi 3290cdf0c1d5Smjnelson 3291cdf0c1d5Smjnelson if [[ $SCM_MODE == "teamware" || 3292cdf0c1d5Smjnelson $SCM_MODE == "mercurial" || 3293cdf0c1d5Smjnelson $SCM_MODE == "unknown" ]]; then 3294cdf0c1d5Smjnelson 3295cdf0c1d5Smjnelson # Include warnings for important file mode situations: 3296cdf0c1d5Smjnelson # 1) New executable files 3297cdf0c1d5Smjnelson # 2) Permission changes of any kind 3298cdf0c1d5Smjnelson # 3) Existing executable files 3299cdf0c1d5Smjnelson 3300cdf0c1d5Smjnelson old_mode= 3301cdf0c1d5Smjnelson if [[ -f $WDIR/raw_files/old/$PP ]]; then 3302cdf0c1d5Smjnelson old_mode=`get_file_mode $WDIR/raw_files/old/$PP` 3303cdf0c1d5Smjnelson fi 3304cdf0c1d5Smjnelson 3305cdf0c1d5Smjnelson new_mode= 3306cdf0c1d5Smjnelson if [[ -f $WDIR/raw_files/new/$P ]]; then 3307cdf0c1d5Smjnelson new_mode=`get_file_mode $WDIR/raw_files/new/$P` 3308cdf0c1d5Smjnelson fi 3309cdf0c1d5Smjnelson 3310cdf0c1d5Smjnelson if [[ -z "$old_mode" && "$new_mode" = *[1357]* ]]; then 3311cdf0c1d5Smjnelson print "<span class=\"chmod\">" 3312cdf0c1d5Smjnelson print "<p>new executable file: mode $new_mode</p>" 3313cdf0c1d5Smjnelson print "</span>" 3314cdf0c1d5Smjnelson elif [[ -n "$old_mode" && -n "$new_mode" && 3315cdf0c1d5Smjnelson "$old_mode" != "$new_mode" ]]; then 3316cdf0c1d5Smjnelson print "<span class=\"chmod\">" 3317cdf0c1d5Smjnelson print "<p>mode change: $old_mode to $new_mode</p>" 3318cdf0c1d5Smjnelson print "</span>" 3319cdf0c1d5Smjnelson elif [[ "$new_mode" = *[1357]* ]]; then 3320cdf0c1d5Smjnelson print "<span class=\"chmod\">" 3321cdf0c1d5Smjnelson print "<p>executable file: mode $new_mode</p>" 3322cdf0c1d5Smjnelson print "</span>" 3323cdf0c1d5Smjnelson fi 3324cdf0c1d5Smjnelson fi 3325cdf0c1d5Smjnelson 3326daaffb31Sdp print "</blockquote>" 33277c478bd9Sstevel@tonic-gatedone 33287c478bd9Sstevel@tonic-gate 3329daaffb31Sdpprint 3330daaffb31Sdpprint 3331cac38512Smjnelsonprint "<hr></hr>" 3332daaffb31Sdpprint "<p style=\"font-size: small\">" 33339a70fc3bSMark J. Nelsonprint "This code review page was prepared using <b>$0</b>." 3334daaffb31Sdpprint "Webrev is maintained by the <a href=\"http://www.opensolaris.org\">" 3335daaffb31Sdpprint "OpenSolaris</a> project. The latest version may be obtained" 3336e9e2cfb2Sfr80241print "<a href=\"http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/tools/scripts/webrev.sh\">here</a>.</p>" 3337daaffb31Sdpprint "</body>" 3338daaffb31Sdpprint "</html>" 33397c478bd9Sstevel@tonic-gate 33407c478bd9Sstevel@tonic-gateexec 1<&- # Close FD 1. 33417c478bd9Sstevel@tonic-gateexec 1<&3 # dup FD 3 to restore stdout. 33427c478bd9Sstevel@tonic-gateexec 3<&- # close FD 3. 33437c478bd9Sstevel@tonic-gate 3344daaffb31Sdpprint "Done." 334502d26c39SVladimir Kotal 3346b0088928SVladimir Kotal# 3347ba44d8a2SVladimir Kotal# If remote deletion was specified and fails do not continue. 3348b0088928SVladimir Kotal# 3349ba44d8a2SVladimir Kotalif [[ -n $Dflag ]]; then 3350b0088928SVladimir Kotal delete_webrev 1 1 3351ba44d8a2SVladimir Kotal (( $? == 0 )) || exit $? 3352ba44d8a2SVladimir Kotalfi 3353ba44d8a2SVladimir Kotal 335402d26c39SVladimir Kotalif [[ -n $Uflag ]]; then 335502d26c39SVladimir Kotal upload_webrev 335602d26c39SVladimir Kotal exit $? 335702d26c39SVladimir Kotalfi 3358