148fe8920SMark J. Nelson#!/usr/bin/ksh93 -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# 2478add226Sjmcp# Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. 257c478bd9Sstevel@tonic-gate# 26cdf0c1d5Smjnelson 27*2f54b716SRichard Lowe# Copyright 2008, 2010, Richard Lowe 28*2f54b716SRichard Lowe 29cdf0c1d5Smjnelson# 30daaffb31Sdp# This script takes a file list and a workspace and builds a set of html files 31daaffb31Sdp# suitable for doing a code review of source changes via a web page. 32daaffb31Sdp# Documentation is available via the manual page, webrev.1, or just 33daaffb31Sdp# type 'webrev -h'. 347c478bd9Sstevel@tonic-gate# 35daaffb31Sdp# Acknowledgements to contributors to webrev are listed in the webrev(1) 36daaffb31Sdp# man page. 377c478bd9Sstevel@tonic-gate# 38daaffb31Sdp 397c478bd9Sstevel@tonic-gateREMOVED_COLOR=brown 407c478bd9Sstevel@tonic-gateCHANGED_COLOR=blue 417c478bd9Sstevel@tonic-gateNEW_COLOR=blue 427c478bd9Sstevel@tonic-gate 43daaffb31SdpHTML='<?xml version="1.0"?> 44daaffb31Sdp<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 45daaffb31Sdp "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 46daaffb31Sdp<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">\n' 47daaffb31Sdp 48daaffb31SdpFRAMEHTML='<?xml version="1.0"?> 49daaffb31Sdp<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" 50daaffb31Sdp "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd"> 51daaffb31Sdp<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">\n' 52daaffb31Sdp 53cac38512SmjnelsonSTDHEAD='<meta http-equiv="cache-control" content="no-cache"></meta> 54cac38512Smjnelson<meta http-equiv="Pragma" content="no-cache"></meta> 55cac38512Smjnelson<meta http-equiv="Expires" content="-1"></meta> 56daaffb31Sdp<!-- 57daaffb31Sdp Note to customizers: the body of the webrev is IDed as SUNWwebrev 58daaffb31Sdp to allow easy overriding by users of webrev via the userContent.css 59daaffb31Sdp mechanism available in some browsers. 60daaffb31Sdp 61daaffb31Sdp For example, to have all "removed" information be red instead of 62daaffb31Sdp brown, set a rule in your userContent.css file like: 63daaffb31Sdp 64daaffb31Sdp body#SUNWwebrev span.removed { color: red ! important; } 65daaffb31Sdp--> 66daaffb31Sdp<style type="text/css" media="screen"> 67daaffb31Sdpbody { 68daaffb31Sdp background-color: #eeeeee; 69daaffb31Sdp} 70daaffb31Sdphr { 71daaffb31Sdp border: none 0; 72daaffb31Sdp border-top: 1px solid #aaa; 73daaffb31Sdp height: 1px; 74daaffb31Sdp} 75daaffb31Sdpdiv.summary { 76daaffb31Sdp font-size: .8em; 77daaffb31Sdp border-bottom: 1px solid #aaa; 78daaffb31Sdp padding-left: 1em; 79daaffb31Sdp padding-right: 1em; 80daaffb31Sdp} 81daaffb31Sdpdiv.summary h2 { 82daaffb31Sdp margin-bottom: 0.3em; 83daaffb31Sdp} 84daaffb31Sdpdiv.summary table th { 85daaffb31Sdp text-align: right; 86daaffb31Sdp vertical-align: top; 87daaffb31Sdp white-space: nowrap; 88daaffb31Sdp} 89daaffb31Sdpspan.lineschanged { 90daaffb31Sdp font-size: 0.7em; 91daaffb31Sdp} 92daaffb31Sdpspan.oldmarker { 93daaffb31Sdp color: red; 94daaffb31Sdp font-size: large; 95daaffb31Sdp font-weight: bold; 96daaffb31Sdp} 97daaffb31Sdpspan.newmarker { 98daaffb31Sdp color: green; 99daaffb31Sdp font-size: large; 100daaffb31Sdp font-weight: bold; 101daaffb31Sdp} 102daaffb31Sdpspan.removed { 103daaffb31Sdp color: brown; 104daaffb31Sdp} 105daaffb31Sdpspan.changed { 106daaffb31Sdp color: blue; 107daaffb31Sdp} 108daaffb31Sdpspan.new { 109daaffb31Sdp color: blue; 110daaffb31Sdp font-weight: bold; 111daaffb31Sdp} 112cdf0c1d5Smjnelsonspan.chmod { 113cdf0c1d5Smjnelson font-size: 0.7em; 114cdf0c1d5Smjnelson color: #db7800; 115cdf0c1d5Smjnelson} 116daaffb31Sdpa.print { font-size: x-small; } 117daaffb31Sdpa:hover { background-color: #ffcc99; } 118daaffb31Sdp</style> 119daaffb31Sdp 120daaffb31Sdp<style type="text/css" media="print"> 121daaffb31Sdppre { font-size: 0.8em; font-family: courier, monospace; } 122daaffb31Sdpspan.removed { color: #444; font-style: italic } 123daaffb31Sdpspan.changed { font-weight: bold; } 124daaffb31Sdpspan.new { font-weight: bold; } 125daaffb31Sdpspan.newmarker { font-size: 1.2em; font-weight: bold; } 126daaffb31Sdpspan.oldmarker { font-size: 1.2em; font-weight: bold; } 127daaffb31Sdpa.print {display: none} 128daaffb31Sdphr { border: none 0; border-top: 1px solid #aaa; height: 1px; } 129daaffb31Sdp</style> 130daaffb31Sdp' 131daaffb31Sdp 132daaffb31Sdp# 133daaffb31Sdp# UDiffs need a slightly different CSS rule for 'new' items (we don't 134daaffb31Sdp# want them to be bolded as we do in cdiffs or sdiffs). 135daaffb31Sdp# 136daaffb31SdpUDIFFCSS=' 137daaffb31Sdp<style type="text/css" media="screen"> 138daaffb31Sdpspan.new { 139daaffb31Sdp color: blue; 140daaffb31Sdp font-weight: normal; 141daaffb31Sdp} 142daaffb31Sdp</style> 143daaffb31Sdp' 144daaffb31Sdp 145b0088928SVladimir Kotal# 146b0088928SVladimir Kotal# Display remote target with prefix and trailing slash. 147b0088928SVladimir Kotal# 148b0088928SVladimir Kotalfunction print_upload_header 149b0088928SVladimir Kotal{ 150b0088928SVladimir Kotal typeset -r prefix=$1 151b0088928SVladimir Kotal typeset display_target 152b0088928SVladimir Kotal 153b0088928SVladimir Kotal if [[ -z $tflag ]]; then 154b0088928SVladimir Kotal display_target=${prefix}${remote_target} 155b0088928SVladimir Kotal else 156b0088928SVladimir Kotal display_target=${remote_target} 157b0088928SVladimir Kotal fi 158b0088928SVladimir Kotal 159b0088928SVladimir Kotal if [[ ${display_target} != */ ]]; then 160b0088928SVladimir Kotal display_target=${display_target}/ 161b0088928SVladimir Kotal fi 162b0088928SVladimir Kotal 163b0088928SVladimir Kotal print " Upload to: ${display_target}\n" \ 164b0088928SVladimir Kotal " Uploading: \c" 165b0088928SVladimir Kotal} 166b0088928SVladimir Kotal 167b0088928SVladimir Kotal# 16802d26c39SVladimir Kotal# Upload the webrev via rsync. Return 0 on success, 1 on error. 169b0088928SVladimir Kotal# 170ba44d8a2SVladimir Kotalfunction rsync_upload 17102d26c39SVladimir Kotal{ 172b0088928SVladimir Kotal if (( $# != 2 )); then 173b0088928SVladimir Kotal print "\nERROR: rsync_upload: wrong usage ($#)" 174b0088928SVladimir Kotal exit 1 17502d26c39SVladimir Kotal fi 17602d26c39SVladimir Kotal 177b0088928SVladimir Kotal typeset -r dst=$1 178b0088928SVladimir Kotal integer -r print_err_msg=$2 17902d26c39SVladimir Kotal 180b0088928SVladimir Kotal print_upload_header ${rsync_prefix} 181b0088928SVladimir Kotal print "rsync ... \c" 1828a34f8dcSVladimir Kotal typeset -r err_msg=$( $MKTEMP /tmp/rsync_err.XXXXXX ) 183b0088928SVladimir Kotal if [[ -z $err_msg ]]; then 184b0088928SVladimir Kotal print "\nERROR: rsync_upload: cannot create temporary file" 185b0088928SVladimir Kotal return 1 186b0088928SVladimir Kotal fi 187b0088928SVladimir Kotal # 188b0088928SVladimir Kotal # The source directory must end with a slash in order to copy just 189b0088928SVladimir Kotal # directory contents, not the whole directory. 190b0088928SVladimir Kotal # 191b0088928SVladimir Kotal typeset src_dir=$WDIR 192b0088928SVladimir Kotal if [[ ${src_dir} != */ ]]; then 193b0088928SVladimir Kotal src_dir=${src_dir}/ 194b0088928SVladimir Kotal fi 195b0088928SVladimir Kotal $RSYNC -r -q ${src_dir} $dst 2>$err_msg 19602d26c39SVladimir Kotal if (( $? != 0 )); then 197b0088928SVladimir Kotal if (( ${print_err_msg} > 0 )); then 198b0088928SVladimir Kotal print "Failed.\nERROR: rsync failed" 199b0088928SVladimir Kotal print "src dir: '${src_dir}'\ndst dir: '$dst'" 200b0088928SVladimir Kotal print "error messages:" 201b0088928SVladimir Kotal $SED 's/^/> /' $err_msg 202b0088928SVladimir Kotal rm -f $err_msg 203b0088928SVladimir Kotal fi 20402d26c39SVladimir Kotal return 1 20502d26c39SVladimir Kotal fi 20602d26c39SVladimir Kotal 207b0088928SVladimir Kotal rm -f $err_msg 20802d26c39SVladimir Kotal print "Done." 20902d26c39SVladimir Kotal return 0 21002d26c39SVladimir Kotal} 21102d26c39SVladimir Kotal 212b0088928SVladimir Kotal# 213b0088928SVladimir Kotal# Create directories on remote host using SFTP. Return 0 on success, 214b0088928SVladimir Kotal# 1 on failure. 215b0088928SVladimir Kotal# 216b0088928SVladimir Kotalfunction remote_mkdirs 217b0088928SVladimir Kotal{ 218b0088928SVladimir Kotal typeset -r dir_spec=$1 2199d3952abSVladimir Kotal typeset -r host_spec=$2 220b0088928SVladimir Kotal 221b0088928SVladimir Kotal # 222b0088928SVladimir Kotal # If the supplied path is absolute we assume all directories are 223b0088928SVladimir Kotal # created, otherwise try to create all directories in the path 224b0088928SVladimir Kotal # except the last one which will be created by scp. 225b0088928SVladimir Kotal # 226b0088928SVladimir Kotal if [[ "${dir_spec}" == */* && "${dir_spec}" != /* ]]; then 227b0088928SVladimir Kotal print "mkdirs \c" 228b0088928SVladimir Kotal # 229b0088928SVladimir Kotal # Remove the last directory from directory specification. 230b0088928SVladimir Kotal # 231b0088928SVladimir Kotal typeset -r dirs_mk=${dir_spec%/*} 2328a34f8dcSVladimir Kotal typeset -r batch_file_mkdir=$( $MKTEMP \ 2338a34f8dcSVladimir Kotal /tmp/webrev_mkdir.XXXXXX ) 234b0088928SVladimir Kotal if [[ -z $batch_file_mkdir ]]; then 235b0088928SVladimir Kotal print "\nERROR: remote_mkdirs:" \ 236b0088928SVladimir Kotal "cannot create temporary file for batch file" 237b0088928SVladimir Kotal return 1 238b0088928SVladimir Kotal fi 239b0088928SVladimir Kotal OLDIFS=$IFS 240b0088928SVladimir Kotal IFS=/ 241b0088928SVladimir Kotal typeset dir 242b0088928SVladimir Kotal for dir in ${dirs_mk}; do 243b0088928SVladimir Kotal # 244b0088928SVladimir Kotal # Use the '-' prefix to ignore mkdir errors in order 245b0088928SVladimir Kotal # to avoid an error in case the directory already 246b0088928SVladimir Kotal # exists. We check the directory with chdir to be sure 247b0088928SVladimir Kotal # there is one. 248b0088928SVladimir Kotal # 249b0088928SVladimir Kotal print -- "-mkdir ${dir}" >> ${batch_file_mkdir} 250b0088928SVladimir Kotal print "chdir ${dir}" >> ${batch_file_mkdir} 251b0088928SVladimir Kotal done 252b0088928SVladimir Kotal IFS=$OLDIFS 2538a34f8dcSVladimir Kotal typeset -r sftp_err_msg=$( $MKTEMP /tmp/webrev_scp_err.XXXXXX ) 254b0088928SVladimir Kotal if [[ -z ${sftp_err_msg} ]]; then 255b0088928SVladimir Kotal print "\nERROR: remote_mkdirs:" \ 256b0088928SVladimir Kotal "cannot create temporary file for error messages" 257b0088928SVladimir Kotal return 1 258b0088928SVladimir Kotal fi 259b0088928SVladimir Kotal $SFTP -b ${batch_file_mkdir} ${host_spec} 2>${sftp_err_msg} 1>&2 260b0088928SVladimir Kotal if (( $? != 0 )); then 261b0088928SVladimir Kotal print "\nERROR: failed to create remote directories" 262b0088928SVladimir Kotal print "error messages:" 263b0088928SVladimir Kotal $SED 's/^/> /' ${sftp_err_msg} 264b0088928SVladimir Kotal rm -f ${sftp_err_msg} ${batch_file_mkdir} 265b0088928SVladimir Kotal return 1 266b0088928SVladimir Kotal fi 267b0088928SVladimir Kotal rm -f ${sftp_err_msg} ${batch_file_mkdir} 268b0088928SVladimir Kotal fi 269b0088928SVladimir Kotal 270b0088928SVladimir Kotal return 0 271b0088928SVladimir Kotal} 272b0088928SVladimir Kotal 273b0088928SVladimir Kotal# 27402d26c39SVladimir Kotal# Upload the webrev via SSH. Return 0 on success, 1 on error. 275b0088928SVladimir Kotal# 276ba44d8a2SVladimir Kotalfunction ssh_upload 27702d26c39SVladimir Kotal{ 27802d26c39SVladimir Kotal if (( $# != 1 )); then 279b0088928SVladimir Kotal print "\nERROR: ssh_upload: wrong number of arguments" 280b0088928SVladimir Kotal exit 1 28102d26c39SVladimir Kotal fi 28202d26c39SVladimir Kotal 28302d26c39SVladimir Kotal typeset dst=$1 28402d26c39SVladimir Kotal typeset -r host_spec=${dst%%:*} 285ba44d8a2SVladimir Kotal typeset -r dir_spec=${dst#*:} 28602d26c39SVladimir Kotal 287b0088928SVladimir Kotal # 288b0088928SVladimir Kotal # Display the upload information before calling delete_webrev 289b0088928SVladimir Kotal # because it will also print its progress. 290b0088928SVladimir Kotal # 291b0088928SVladimir Kotal print_upload_header ${ssh_prefix} 292b0088928SVladimir Kotal 293b0088928SVladimir Kotal # 294b0088928SVladimir Kotal # If the deletion was explicitly requested there is no need 295b0088928SVladimir Kotal # to perform it again. 296b0088928SVladimir Kotal # 297ba44d8a2SVladimir Kotal if [[ -z $Dflag ]]; then 298b0088928SVladimir Kotal # 299b0088928SVladimir Kotal # We do not care about return value because this might be 300b0088928SVladimir Kotal # the first time this directory is uploaded. 301b0088928SVladimir Kotal # 302ba44d8a2SVladimir Kotal delete_webrev 0 30302d26c39SVladimir Kotal fi 30402d26c39SVladimir Kotal 305b0088928SVladimir Kotal # 306b0088928SVladimir Kotal # Create remote directories. Any error reporting will be done 307b0088928SVladimir Kotal # in remote_mkdirs function. 308b0088928SVladimir Kotal # 3099d3952abSVladimir Kotal remote_mkdirs ${dir_spec} ${host_spec} 31002d26c39SVladimir Kotal if (( $? != 0 )); then 31102d26c39SVladimir Kotal return 1 31202d26c39SVladimir Kotal fi 31302d26c39SVladimir Kotal 314b0088928SVladimir Kotal print "upload ... \c" 3158a34f8dcSVladimir Kotal typeset -r scp_err_msg=$( $MKTEMP /tmp/scp_err.XXXXXX ) 316b0088928SVladimir Kotal if [[ -z ${scp_err_msg} ]]; then 317b0088928SVladimir Kotal print "\nERROR: ssh_upload:" \ 318b0088928SVladimir Kotal "cannot create temporary file for error messages" 319b0088928SVladimir Kotal return 1 320b0088928SVladimir Kotal fi 32102d26c39SVladimir Kotal $SCP -q -C -B -o PreferredAuthentications=publickey -r \ 322b0088928SVladimir Kotal $WDIR $dst 2>${scp_err_msg} 32302d26c39SVladimir Kotal if (( $? != 0 )); then 324b0088928SVladimir Kotal print "Failed.\nERROR: scp failed" 325b0088928SVladimir Kotal print "src dir: '$WDIR'\ndst dir: '$dst'" 326b0088928SVladimir Kotal print "error messages:" 327b0088928SVladimir Kotal $SED 's/^/> /' ${scp_err_msg} 328b0088928SVladimir Kotal rm -f ${scp_err_msg} 32902d26c39SVladimir Kotal return 1 33002d26c39SVladimir Kotal fi 33102d26c39SVladimir Kotal 332b0088928SVladimir Kotal rm -f ${scp_err_msg} 33302d26c39SVladimir Kotal print "Done." 33402d26c39SVladimir Kotal return 0 33502d26c39SVladimir Kotal} 33602d26c39SVladimir Kotal 33702d26c39SVladimir Kotal# 338ba44d8a2SVladimir Kotal# Delete webrev at remote site. Return 0 on success, 1 or exit code from sftp 339b0088928SVladimir Kotal# on failure. If first argument is 1 then perform the check of sftp return 340b0088928SVladimir Kotal# value otherwise ignore it. If second argument is present it means this run 341b0088928SVladimir Kotal# only performs deletion. 342ba44d8a2SVladimir Kotal# 343ba44d8a2SVladimir Kotalfunction delete_webrev 344ba44d8a2SVladimir Kotal{ 345b0088928SVladimir Kotal if (( $# < 1 )); then 346b0088928SVladimir Kotal print "delete_webrev: wrong number of arguments" 347b0088928SVladimir Kotal exit 1 348ba44d8a2SVladimir Kotal fi 349ba44d8a2SVladimir Kotal 350b0088928SVladimir Kotal integer -r check=$1 351b0088928SVladimir Kotal integer delete_only=0 352b0088928SVladimir Kotal if (( $# == 2 )); then 353b0088928SVladimir Kotal delete_only=1 354b0088928SVladimir Kotal fi 355b0088928SVladimir Kotal 356b0088928SVladimir Kotal # 357ba44d8a2SVladimir Kotal # Strip the transport specification part of remote target first. 358b0088928SVladimir Kotal # 359ba44d8a2SVladimir Kotal typeset -r stripped_target=${remote_target##*://} 360ba44d8a2SVladimir Kotal typeset -r host_spec=${stripped_target%%:*} 361ba44d8a2SVladimir Kotal typeset -r dir_spec=${stripped_target#*:} 362ba44d8a2SVladimir Kotal typeset dir_rm 363ba44d8a2SVladimir Kotal 364b0088928SVladimir Kotal # 365ba44d8a2SVladimir Kotal # Do not accept an absolute path. 366b0088928SVladimir Kotal # 367ba44d8a2SVladimir Kotal if [[ ${dir_spec} == /* ]]; then 368ba44d8a2SVladimir Kotal return 1 369ba44d8a2SVladimir Kotal fi 370ba44d8a2SVladimir Kotal 371b0088928SVladimir Kotal # 372ba44d8a2SVladimir Kotal # Strip the ending slash. 373b0088928SVladimir Kotal # 374ba44d8a2SVladimir Kotal if [[ ${dir_spec} == */ ]]; then 375ba44d8a2SVladimir Kotal dir_rm=${dir_spec%%/} 376ba44d8a2SVladimir Kotal else 377ba44d8a2SVladimir Kotal dir_rm=${dir_spec} 378ba44d8a2SVladimir Kotal fi 379ba44d8a2SVladimir Kotal 380b0088928SVladimir Kotal if (( ${delete_only} > 0 )); then 381b0088928SVladimir Kotal print " Removing: \c" 382b0088928SVladimir Kotal else 383b0088928SVladimir Kotal print "rmdir \c" 384b0088928SVladimir Kotal fi 385ba44d8a2SVladimir Kotal if [[ -z "$dir_rm" ]]; then 386b0088928SVladimir Kotal print "\nERROR: empty directory for removal" 387ba44d8a2SVladimir Kotal return 1 388ba44d8a2SVladimir Kotal fi 389ba44d8a2SVladimir Kotal 390b0088928SVladimir Kotal # 391ba44d8a2SVladimir Kotal # Prepare batch file. 392b0088928SVladimir Kotal # 3938a34f8dcSVladimir Kotal typeset -r batch_file_rm=$( $MKTEMP /tmp/webrev_remove.XXXXXX ) 394ba44d8a2SVladimir Kotal if [[ -z $batch_file_rm ]]; then 395b0088928SVladimir Kotal print "\nERROR: delete_webrev: cannot create temporary file" 396ba44d8a2SVladimir Kotal return 1 397ba44d8a2SVladimir Kotal fi 398ba44d8a2SVladimir Kotal print "rename $dir_rm $TRASH_DIR/removed.$$" > $batch_file_rm 399ba44d8a2SVladimir Kotal 400b0088928SVladimir Kotal # 401ba44d8a2SVladimir Kotal # Perform remote deletion and remove the batch file. 402b0088928SVladimir Kotal # 4038a34f8dcSVladimir Kotal typeset -r sftp_err_msg=$( $MKTEMP /tmp/webrev_scp_err.XXXXXX ) 404b0088928SVladimir Kotal if [[ -z ${sftp_err_msg} ]]; then 405b0088928SVladimir Kotal print "\nERROR: delete_webrev:" \ 406b0088928SVladimir Kotal "cannot create temporary file for error messages" 407b0088928SVladimir Kotal return 1 408b0088928SVladimir Kotal fi 409b0088928SVladimir Kotal $SFTP -b $batch_file_rm $host_spec 2>${sftp_err_msg} 1>&2 410ba44d8a2SVladimir Kotal integer -r ret=$? 411ba44d8a2SVladimir Kotal rm -f $batch_file_rm 412ba44d8a2SVladimir Kotal if (( $ret != 0 && $check > 0 )); then 413b0088928SVladimir Kotal print "Failed.\nERROR: failed to remove remote directories" 414b0088928SVladimir Kotal print "error messages:" 415b0088928SVladimir Kotal $SED 's/^/> /' ${sftp_err_msg} 416b0088928SVladimir Kotal rm -f ${sftp_err_msg} 417ba44d8a2SVladimir Kotal return $ret 418ba44d8a2SVladimir Kotal fi 419b0088928SVladimir Kotal rm -f ${sftp_err_msg} 420b0088928SVladimir Kotal if (( ${delete_only} > 0 )); then 421ba44d8a2SVladimir Kotal print "Done." 422b0088928SVladimir Kotal fi 423ba44d8a2SVladimir Kotal 424ba44d8a2SVladimir Kotal return 0 425ba44d8a2SVladimir Kotal} 426ba44d8a2SVladimir Kotal 427ba44d8a2SVladimir Kotal# 42802d26c39SVladimir Kotal# Upload webrev to remote site 42902d26c39SVladimir Kotal# 430ba44d8a2SVladimir Kotalfunction upload_webrev 43102d26c39SVladimir Kotal{ 432b0088928SVladimir Kotal integer ret 43302d26c39SVladimir Kotal 43402d26c39SVladimir Kotal if [[ ! -d "$WDIR" ]]; then 435b0088928SVladimir Kotal print "\nERROR: webrev directory '$WDIR' does not exist" 43602d26c39SVladimir Kotal return 1 43702d26c39SVladimir Kotal fi 43802d26c39SVladimir Kotal 439b0088928SVladimir Kotal # 44002d26c39SVladimir Kotal # Perform a late check to make sure we do not upload closed source 44102d26c39SVladimir Kotal # to remote target when -n is used. If the user used custom remote 44202d26c39SVladimir Kotal # target he probably knows what he is doing. 443b0088928SVladimir Kotal # 44402d26c39SVladimir Kotal if [[ -n $nflag && -z $tflag ]]; then 445ba44d8a2SVladimir Kotal $FIND $WDIR -type d -name closed \ 44602d26c39SVladimir Kotal | $GREP closed >/dev/null 44702d26c39SVladimir Kotal if (( $? == 0 )); then 448b0088928SVladimir Kotal print "\nERROR: directory '$WDIR' contains" \ 449b0088928SVladimir Kotal "\"closed\" directory" 45002d26c39SVladimir Kotal return 1 45102d26c39SVladimir Kotal fi 45202d26c39SVladimir Kotal fi 45302d26c39SVladimir Kotal 454b0088928SVladimir Kotal 455b0088928SVladimir Kotal # 456b0088928SVladimir Kotal # We have the URI for remote destination now so let's start the upload. 457b0088928SVladimir Kotal # 45802d26c39SVladimir Kotal if [[ -n $tflag ]]; then 45902d26c39SVladimir Kotal if [[ "${remote_target}" == ${rsync_prefix}?* ]]; then 460b0088928SVladimir Kotal rsync_upload ${remote_target##$rsync_prefix} 1 461b0088928SVladimir Kotal ret=$? 462b0088928SVladimir Kotal return $ret 46302d26c39SVladimir Kotal elif [[ "${remote_target}" == ${ssh_prefix}?* ]]; then 46402d26c39SVladimir Kotal ssh_upload ${remote_target##$ssh_prefix} 465b0088928SVladimir Kotal ret=$? 466b0088928SVladimir Kotal return $ret 46702d26c39SVladimir Kotal fi 46802d26c39SVladimir Kotal else 469b0088928SVladimir Kotal # 470b0088928SVladimir Kotal # Try rsync first and fallback to SSH in case it fails. 471b0088928SVladimir Kotal # 472b0088928SVladimir Kotal rsync_upload ${remote_target} 0 473b0088928SVladimir Kotal ret=$? 474b0088928SVladimir Kotal if (( $ret != 0 )); then 475b0088928SVladimir Kotal print "Failed. (falling back to SSH)" 476ba44d8a2SVladimir Kotal ssh_upload ${remote_target} 477b0088928SVladimir Kotal ret=$? 47802d26c39SVladimir Kotal fi 479b0088928SVladimir Kotal return $ret 48002d26c39SVladimir Kotal fi 48102d26c39SVladimir Kotal} 48202d26c39SVladimir Kotal 483daaffb31Sdp# 484371d72daSLubomir Sedlacik# input_cmd | url_encode | output_cmd 485371d72daSLubomir Sedlacik# 486371d72daSLubomir Sedlacik# URL-encode (percent-encode) reserved characters as defined in RFC 3986. 487371d72daSLubomir Sedlacik# 488371d72daSLubomir Sedlacik# Reserved characters are: :/?#[]@!$&'()*+,;= 489371d72daSLubomir Sedlacik# 490371d72daSLubomir Sedlacik# While not a reserved character itself, percent '%' is reserved by definition 491371d72daSLubomir Sedlacik# so encode it first to avoid recursive transformation, and skip '/' which is 492371d72daSLubomir Sedlacik# a path delimiter. 493371d72daSLubomir Sedlacik# 49425cc4e45SVladimir Kotal# The quotation character is deliberately not escaped in order to make 49525cc4e45SVladimir Kotal# the substitution work with GNU sed. 49625cc4e45SVladimir Kotal# 497371d72daSLubomir Sedlacikfunction url_encode 498371d72daSLubomir Sedlacik{ 499b0088928SVladimir Kotal $SED -e "s|%|%25|g" -e "s|:|%3A|g" -e "s|\&|%26|g" \ 500371d72daSLubomir Sedlacik -e "s|?|%3F|g" -e "s|#|%23|g" -e "s|\[|%5B|g" \ 501371d72daSLubomir Sedlacik -e "s|*|%2A|g" -e "s|@|%40|g" -e "s|\!|%21|g" \ 502371d72daSLubomir Sedlacik -e "s|=|%3D|g" -e "s|;|%3B|g" -e "s|\]|%5D|g" \ 50325cc4e45SVladimir Kotal -e "s|(|%28|g" -e "s|)|%29|g" -e "s|'|%27|g" \ 504371d72daSLubomir Sedlacik -e "s|+|%2B|g" -e "s|\,|%2C|g" -e "s|\\\$|%24|g" 505371d72daSLubomir Sedlacik} 506371d72daSLubomir Sedlacik 507371d72daSLubomir Sedlacik# 508daaffb31Sdp# input_cmd | html_quote | output_cmd 509daaffb31Sdp# or 510daaffb31Sdp# html_quote filename | output_cmd 5117c478bd9Sstevel@tonic-gate# 5127c478bd9Sstevel@tonic-gate# Make a piece of source code safe for display in an HTML <pre> block. 5137c478bd9Sstevel@tonic-gate# 5147c478bd9Sstevel@tonic-gatehtml_quote() 5157c478bd9Sstevel@tonic-gate{ 516b0088928SVladimir Kotal $SED -e "s/&/\&/g" -e "s/</\</g" -e "s/>/\>/g" "$@" | expand 5177c478bd9Sstevel@tonic-gate} 5187c478bd9Sstevel@tonic-gate 519daaffb31Sdp# 5200fd2682eSMark J. Nelson# input_cmd | its2url | output_cmd 521daaffb31Sdp# 5220fd2682eSMark J. Nelson# Scan for information tracking system references and insert <a> links to the 5230fd2682eSMark J. Nelson# relevant databases. 524daaffb31Sdp# 5250fd2682eSMark J. Nelsonits2url() 5267c478bd9Sstevel@tonic-gate{ 5270fd2682eSMark J. Nelson $SED -f ${its_sed_script} 528daaffb31Sdp} 529daaffb31Sdp 5307c478bd9Sstevel@tonic-gate# 531daaffb31Sdp# strip_unchanged <infile> | output_cmd 5327c478bd9Sstevel@tonic-gate# 533daaffb31Sdp# Removes chunks of sdiff documents that have not changed. This makes it 534daaffb31Sdp# easier for a code reviewer to find the bits that have changed. 5357c478bd9Sstevel@tonic-gate# 536daaffb31Sdp# Deleted lines of text are replaced by a horizontal rule. Some 537daaffb31Sdp# identical lines are retained before and after the changed lines to 538daaffb31Sdp# provide some context. The number of these lines is controlled by the 539cdf0c1d5Smjnelson# variable C in the $AWK script below. 540daaffb31Sdp# 541daaffb31Sdp# The script detects changed lines as any line that has a "<span class=" 542daaffb31Sdp# string embedded (unchanged lines have no particular class and are not 543daaffb31Sdp# part of a <span>). Blank lines (without a sequence number) are also 544daaffb31Sdp# detected since they flag lines that have been inserted or deleted. 545daaffb31Sdp# 546daaffb31Sdpstrip_unchanged() 547daaffb31Sdp{ 548cdf0c1d5Smjnelson $AWK ' 549daaffb31Sdp BEGIN { C = c = 20 } 550cdf0c1d5Smjnelson NF == 0 || /<span class="/ { 551daaffb31Sdp if (c > C) { 552daaffb31Sdp c -= C 553daaffb31Sdp inx = 0 554daaffb31Sdp if (c > C) { 555cac38512Smjnelson print "\n</pre><hr></hr><pre>" 556daaffb31Sdp inx = c % C 557daaffb31Sdp c = C 558daaffb31Sdp } 559daaffb31Sdp 560daaffb31Sdp for (i = 0; i < c; i++) 561daaffb31Sdp print ln[(inx + i) % C] 562daaffb31Sdp } 563daaffb31Sdp c = 0; 564daaffb31Sdp print 565daaffb31Sdp next 566daaffb31Sdp } 567daaffb31Sdp { if (c >= C) { 568daaffb31Sdp ln[c % C] = $0 569daaffb31Sdp c++; 570daaffb31Sdp next; 571daaffb31Sdp } 572daaffb31Sdp c++; 573daaffb31Sdp print 574daaffb31Sdp } 575cac38512Smjnelson END { if (c > (C * 2)) print "\n</pre><hr></hr>" } 576daaffb31Sdp 577daaffb31Sdp ' $1 578daaffb31Sdp} 579daaffb31Sdp 580daaffb31Sdp# 581daaffb31Sdp# sdiff_to_html 582daaffb31Sdp# 583daaffb31Sdp# This function takes two files as arguments, obtains their diff, and 584daaffb31Sdp# processes the diff output to present the files as an HTML document with 585daaffb31Sdp# the files displayed side-by-side, differences shown in color. It also 586daaffb31Sdp# takes a delta comment, rendered as an HTML snippet, as the third 587daaffb31Sdp# argument. The function takes two files as arguments, then the name of 588daaffb31Sdp# file, the path, and the comment. The HTML will be delivered on stdout, 589daaffb31Sdp# e.g. 590daaffb31Sdp# 591daaffb31Sdp# $ sdiff_to_html old/usr/src/tools/scripts/webrev.sh \ 592daaffb31Sdp# new/usr/src/tools/scripts/webrev.sh \ 593daaffb31Sdp# webrev.sh usr/src/tools/scripts \ 594daaffb31Sdp# '<a href="http://monaco.sfbay.sun.com/detail.jsp?cr=1234567"> 595daaffb31Sdp# 1234567</a> my bugid' > <file>.html 596daaffb31Sdp# 597daaffb31Sdp# framed_sdiff() is then called which creates $2.frames.html 598daaffb31Sdp# in the webrev tree. 599daaffb31Sdp# 600daaffb31Sdp# FYI: This function is rather unusual in its use of awk. The initial 601daaffb31Sdp# diff run produces conventional diff output showing changed lines mixed 602daaffb31Sdp# with editing codes. The changed lines are ignored - we're interested in 603daaffb31Sdp# the editing codes, e.g. 6047c478bd9Sstevel@tonic-gate# 6057c478bd9Sstevel@tonic-gate# 8c8 6067c478bd9Sstevel@tonic-gate# 57a61 6077c478bd9Sstevel@tonic-gate# 63c66,76 6087c478bd9Sstevel@tonic-gate# 68,93d80 6097c478bd9Sstevel@tonic-gate# 106d90 6107c478bd9Sstevel@tonic-gate# 108,110d91 6117c478bd9Sstevel@tonic-gate# 612daaffb31Sdp# These editing codes are parsed by the awk script and used to generate 613daaffb31Sdp# another awk script that generates HTML, e.g the above lines would turn 614daaffb31Sdp# into something like this: 6157c478bd9Sstevel@tonic-gate# 6167c478bd9Sstevel@tonic-gate# BEGIN { printf "<pre>\n" } 6177c478bd9Sstevel@tonic-gate# function sp(n) {for (i=0;i<n;i++)printf "\n"} 618daaffb31Sdp# function wl(n) {printf "<font color=%s>%4d %s </font>\n", n, NR, $0} 6197c478bd9Sstevel@tonic-gate# NR==8 {wl("#7A7ADD");next} 6207c478bd9Sstevel@tonic-gate# NR==54 {wl("#7A7ADD");sp(3);next} 6217c478bd9Sstevel@tonic-gate# NR==56 {wl("#7A7ADD");next} 6227c478bd9Sstevel@tonic-gate# NR==57 {wl("black");printf "\n"; next} 6237c478bd9Sstevel@tonic-gate# : : 6247c478bd9Sstevel@tonic-gate# 625daaffb31Sdp# This script is then run on the original source file to generate the 626daaffb31Sdp# HTML that corresponds to the source file. 6277c478bd9Sstevel@tonic-gate# 628daaffb31Sdp# The two HTML files are then combined into a single piece of HTML that 629daaffb31Sdp# uses an HTML table construct to present the files side by side. You'll 630daaffb31Sdp# notice that the changes are color-coded: 6317c478bd9Sstevel@tonic-gate# 6327c478bd9Sstevel@tonic-gate# black - unchanged lines 6337c478bd9Sstevel@tonic-gate# blue - changed lines 6347c478bd9Sstevel@tonic-gate# bold blue - new lines 6357c478bd9Sstevel@tonic-gate# brown - deleted lines 6367c478bd9Sstevel@tonic-gate# 637daaffb31Sdp# Blank lines are inserted in each file to keep unchanged lines in sync 638daaffb31Sdp# (side-by-side). This format is familiar to users of sdiff(1) or 639daaffb31Sdp# Teamware's filemerge tool. 640daaffb31Sdp# 641daaffb31Sdpsdiff_to_html() 642daaffb31Sdp{ 6437c478bd9Sstevel@tonic-gate diff -b $1 $2 > /tmp/$$.diffs 6447c478bd9Sstevel@tonic-gate 645daaffb31Sdp TNAME=$3 646daaffb31Sdp TPATH=$4 647daaffb31Sdp COMMENT=$5 648daaffb31Sdp 6497c478bd9Sstevel@tonic-gate # 6507c478bd9Sstevel@tonic-gate # Now we have the diffs, generate the HTML for the old file. 6517c478bd9Sstevel@tonic-gate # 652cdf0c1d5Smjnelson $AWK ' 6537c478bd9Sstevel@tonic-gate BEGIN { 6547c478bd9Sstevel@tonic-gate printf "function sp(n) {for (i=0;i<n;i++)printf \"\\n\"}\n" 655daaffb31Sdp printf "function removed() " 656daaffb31Sdp printf "{printf \"<span class=\\\"removed\\\">%%4d %%s</span>\\n\", NR, $0}\n" 657daaffb31Sdp printf "function changed() " 658daaffb31Sdp printf "{printf \"<span class=\\\"changed\\\">%%4d %%s</span>\\n\", NR, $0}\n" 659daaffb31Sdp printf "function bl() {printf \"%%4d %%s\\n\", NR, $0}\n" 6607c478bd9Sstevel@tonic-gate} 6617c478bd9Sstevel@tonic-gate /^</ {next} 6627c478bd9Sstevel@tonic-gate /^>/ {next} 6637c478bd9Sstevel@tonic-gate /^---/ {next} 664daaffb31Sdp 6657c478bd9Sstevel@tonic-gate { 6667c478bd9Sstevel@tonic-gate split($1, a, /[cad]/) ; 6677c478bd9Sstevel@tonic-gate if (index($1, "a")) { 6687c478bd9Sstevel@tonic-gate if (a[1] == 0) { 6697c478bd9Sstevel@tonic-gate n = split(a[2], r, /,/); 6707c478bd9Sstevel@tonic-gate if (n == 1) 6717c478bd9Sstevel@tonic-gate printf "BEGIN\t\t{sp(1)}\n" 6727c478bd9Sstevel@tonic-gate else 6737c478bd9Sstevel@tonic-gate printf "BEGIN\t\t{sp(%d)}\n",\ 6747c478bd9Sstevel@tonic-gate (r[2] - r[1]) + 1 6757c478bd9Sstevel@tonic-gate next 6767c478bd9Sstevel@tonic-gate } 6777c478bd9Sstevel@tonic-gate 6787c478bd9Sstevel@tonic-gate printf "NR==%s\t\t{", a[1] 6797c478bd9Sstevel@tonic-gate n = split(a[2], r, /,/); 6807c478bd9Sstevel@tonic-gate s = r[1]; 6817c478bd9Sstevel@tonic-gate if (n == 1) 6827c478bd9Sstevel@tonic-gate printf "bl();printf \"\\n\"; next}\n" 6837c478bd9Sstevel@tonic-gate else { 6847c478bd9Sstevel@tonic-gate n = r[2] - r[1] 6857c478bd9Sstevel@tonic-gate printf "bl();sp(%d);next}\n",\ 6867c478bd9Sstevel@tonic-gate (r[2] - r[1]) + 1 6877c478bd9Sstevel@tonic-gate } 6887c478bd9Sstevel@tonic-gate next 6897c478bd9Sstevel@tonic-gate } 6907c478bd9Sstevel@tonic-gate if (index($1, "d")) { 6917c478bd9Sstevel@tonic-gate n = split(a[1], r, /,/); 6927c478bd9Sstevel@tonic-gate n1 = r[1] 6937c478bd9Sstevel@tonic-gate n2 = r[2] 6947c478bd9Sstevel@tonic-gate if (n == 1) 695daaffb31Sdp printf "NR==%s\t\t{removed(); next}\n" , n1 6967c478bd9Sstevel@tonic-gate else 697daaffb31Sdp printf "NR==%s,NR==%s\t{removed(); next}\n" , n1, n2 6987c478bd9Sstevel@tonic-gate next 6997c478bd9Sstevel@tonic-gate } 7007c478bd9Sstevel@tonic-gate if (index($1, "c")) { 7017c478bd9Sstevel@tonic-gate n = split(a[1], r, /,/); 7027c478bd9Sstevel@tonic-gate n1 = r[1] 7037c478bd9Sstevel@tonic-gate n2 = r[2] 7047c478bd9Sstevel@tonic-gate final = n2 7057c478bd9Sstevel@tonic-gate d1 = 0 7067c478bd9Sstevel@tonic-gate if (n == 1) 707daaffb31Sdp printf "NR==%s\t\t{changed();" , n1 7087c478bd9Sstevel@tonic-gate else { 7097c478bd9Sstevel@tonic-gate d1 = n2 - n1 710daaffb31Sdp printf "NR==%s,NR==%s\t{changed();" , n1, n2 7117c478bd9Sstevel@tonic-gate } 7127c478bd9Sstevel@tonic-gate m = split(a[2], r, /,/); 7137c478bd9Sstevel@tonic-gate n1 = r[1] 7147c478bd9Sstevel@tonic-gate n2 = r[2] 7157c478bd9Sstevel@tonic-gate if (m > 1) { 7167c478bd9Sstevel@tonic-gate d2 = n2 - n1 7177c478bd9Sstevel@tonic-gate if (d2 > d1) { 7187c478bd9Sstevel@tonic-gate if (n > 1) printf "if (NR==%d)", final 7197c478bd9Sstevel@tonic-gate printf "sp(%d);", d2 - d1 7207c478bd9Sstevel@tonic-gate } 7217c478bd9Sstevel@tonic-gate } 7227c478bd9Sstevel@tonic-gate printf "next}\n" ; 7237c478bd9Sstevel@tonic-gate 7247c478bd9Sstevel@tonic-gate next 7257c478bd9Sstevel@tonic-gate } 7267c478bd9Sstevel@tonic-gate } 7277c478bd9Sstevel@tonic-gate 728daaffb31Sdp END { printf "{printf \"%%4d %%s\\n\", NR, $0 }\n" } 729daaffb31Sdp ' /tmp/$$.diffs > /tmp/$$.file1 7307c478bd9Sstevel@tonic-gate 7317c478bd9Sstevel@tonic-gate # 7327c478bd9Sstevel@tonic-gate # Now generate the HTML for the new file 7337c478bd9Sstevel@tonic-gate # 734cdf0c1d5Smjnelson $AWK ' 7357c478bd9Sstevel@tonic-gate BEGIN { 7367c478bd9Sstevel@tonic-gate printf "function sp(n) {for (i=0;i<n;i++)printf \"\\n\"}\n" 737daaffb31Sdp printf "function new() " 738daaffb31Sdp printf "{printf \"<span class=\\\"new\\\">%%4d %%s</span>\\n\", NR, $0}\n" 739daaffb31Sdp printf "function changed() " 740daaffb31Sdp printf "{printf \"<span class=\\\"changed\\\">%%4d %%s</span>\\n\", NR, $0}\n" 741daaffb31Sdp printf "function bl() {printf \"%%4d %%s\\n\", NR, $0}\n" 7427c478bd9Sstevel@tonic-gate } 743daaffb31Sdp 7447c478bd9Sstevel@tonic-gate /^</ {next} 7457c478bd9Sstevel@tonic-gate /^>/ {next} 7467c478bd9Sstevel@tonic-gate /^---/ {next} 747daaffb31Sdp 7487c478bd9Sstevel@tonic-gate { 7497c478bd9Sstevel@tonic-gate split($1, a, /[cad]/) ; 7507c478bd9Sstevel@tonic-gate if (index($1, "d")) { 7517c478bd9Sstevel@tonic-gate if (a[2] == 0) { 7527c478bd9Sstevel@tonic-gate n = split(a[1], r, /,/); 7537c478bd9Sstevel@tonic-gate if (n == 1) 7547c478bd9Sstevel@tonic-gate printf "BEGIN\t\t{sp(1)}\n" 7557c478bd9Sstevel@tonic-gate else 7567c478bd9Sstevel@tonic-gate printf "BEGIN\t\t{sp(%d)}\n",\ 7577c478bd9Sstevel@tonic-gate (r[2] - r[1]) + 1 7587c478bd9Sstevel@tonic-gate next 7597c478bd9Sstevel@tonic-gate } 7607c478bd9Sstevel@tonic-gate 7617c478bd9Sstevel@tonic-gate printf "NR==%s\t\t{", a[2] 7627c478bd9Sstevel@tonic-gate n = split(a[1], r, /,/); 7637c478bd9Sstevel@tonic-gate s = r[1]; 7647c478bd9Sstevel@tonic-gate if (n == 1) 7657c478bd9Sstevel@tonic-gate printf "bl();printf \"\\n\"; next}\n" 7667c478bd9Sstevel@tonic-gate else { 7677c478bd9Sstevel@tonic-gate n = r[2] - r[1] 7687c478bd9Sstevel@tonic-gate printf "bl();sp(%d);next}\n",\ 7697c478bd9Sstevel@tonic-gate (r[2] - r[1]) + 1 7707c478bd9Sstevel@tonic-gate } 7717c478bd9Sstevel@tonic-gate next 7727c478bd9Sstevel@tonic-gate } 7737c478bd9Sstevel@tonic-gate if (index($1, "a")) { 7747c478bd9Sstevel@tonic-gate n = split(a[2], r, /,/); 7757c478bd9Sstevel@tonic-gate n1 = r[1] 7767c478bd9Sstevel@tonic-gate n2 = r[2] 7777c478bd9Sstevel@tonic-gate if (n == 1) 778daaffb31Sdp printf "NR==%s\t\t{new() ; next}\n" , n1 7797c478bd9Sstevel@tonic-gate else 780daaffb31Sdp printf "NR==%s,NR==%s\t{new() ; next}\n" , n1, n2 7817c478bd9Sstevel@tonic-gate next 7827c478bd9Sstevel@tonic-gate } 7837c478bd9Sstevel@tonic-gate if (index($1, "c")) { 7847c478bd9Sstevel@tonic-gate n = split(a[2], r, /,/); 7857c478bd9Sstevel@tonic-gate n1 = r[1] 7867c478bd9Sstevel@tonic-gate n2 = r[2] 7877c478bd9Sstevel@tonic-gate final = n2 7887c478bd9Sstevel@tonic-gate d2 = 0; 7897c478bd9Sstevel@tonic-gate if (n == 1) { 7907c478bd9Sstevel@tonic-gate final = n1 791daaffb31Sdp printf "NR==%s\t\t{changed();" , n1 7927c478bd9Sstevel@tonic-gate } else { 7937c478bd9Sstevel@tonic-gate d2 = n2 - n1 794daaffb31Sdp printf "NR==%s,NR==%s\t{changed();" , n1, n2 7957c478bd9Sstevel@tonic-gate } 7967c478bd9Sstevel@tonic-gate m = split(a[1], r, /,/); 7977c478bd9Sstevel@tonic-gate n1 = r[1] 7987c478bd9Sstevel@tonic-gate n2 = r[2] 7997c478bd9Sstevel@tonic-gate if (m > 1) { 8007c478bd9Sstevel@tonic-gate d1 = n2 - n1 8017c478bd9Sstevel@tonic-gate if (d1 > d2) { 8027c478bd9Sstevel@tonic-gate if (n > 1) printf "if (NR==%d)", final 8037c478bd9Sstevel@tonic-gate printf "sp(%d);", d1 - d2 8047c478bd9Sstevel@tonic-gate } 8057c478bd9Sstevel@tonic-gate } 8067c478bd9Sstevel@tonic-gate printf "next}\n" ; 8077c478bd9Sstevel@tonic-gate next 8087c478bd9Sstevel@tonic-gate } 8097c478bd9Sstevel@tonic-gate } 810daaffb31Sdp END { printf "{printf \"%%4d %%s\\n\", NR, $0 }\n" } 8117c478bd9Sstevel@tonic-gate ' /tmp/$$.diffs > /tmp/$$.file2 8127c478bd9Sstevel@tonic-gate 813daaffb31Sdp # 814cdf0c1d5Smjnelson # Post-process the HTML files by running them back through $AWK 815daaffb31Sdp # 816cdf0c1d5Smjnelson html_quote < $1 | $AWK -f /tmp/$$.file1 > /tmp/$$.file1.html 8177c478bd9Sstevel@tonic-gate 818cdf0c1d5Smjnelson html_quote < $2 | $AWK -f /tmp/$$.file2 > /tmp/$$.file2.html 8197c478bd9Sstevel@tonic-gate 820daaffb31Sdp # 821daaffb31Sdp # Now combine into a valid HTML file and side-by-side into a table 822daaffb31Sdp # 823daaffb31Sdp print "$HTML<head>$STDHEAD" 824cdf0c1d5Smjnelson print "<title>$WNAME Sdiff $TPATH/$TNAME</title>" 825daaffb31Sdp print "</head><body id=\"SUNWwebrev\">" 826daaffb31Sdp print "<a class=\"print\" href=\"javascript:print()\">Print this page</a>" 827daaffb31Sdp print "<pre>$COMMENT</pre>\n" 828daaffb31Sdp print "<table><tr valign=\"top\">" 829daaffb31Sdp print "<td><pre>" 8307c478bd9Sstevel@tonic-gate 8317c478bd9Sstevel@tonic-gate strip_unchanged /tmp/$$.file1.html 8327c478bd9Sstevel@tonic-gate 833daaffb31Sdp print "</pre></td><td><pre>" 8347c478bd9Sstevel@tonic-gate 8357c478bd9Sstevel@tonic-gate strip_unchanged /tmp/$$.file2.html 8367c478bd9Sstevel@tonic-gate 837daaffb31Sdp print "</pre></td>" 838daaffb31Sdp print "</tr></table>" 839daaffb31Sdp print "</body></html>" 8407c478bd9Sstevel@tonic-gate 841daaffb31Sdp framed_sdiff $TNAME $TPATH /tmp/$$.file1.html /tmp/$$.file2.html \ 842daaffb31Sdp "$COMMENT" 8437c478bd9Sstevel@tonic-gate} 8447c478bd9Sstevel@tonic-gate 8457c478bd9Sstevel@tonic-gate 846daaffb31Sdp# 847daaffb31Sdp# framed_sdiff <filename> <filepath> <lhsfile> <rhsfile> <comment> 848daaffb31Sdp# 849daaffb31Sdp# Expects lefthand and righthand side html files created by sdiff_to_html. 850daaffb31Sdp# We use insert_anchors() to augment those with HTML navigation anchors, 851daaffb31Sdp# and then emit the main frame. Content is placed into: 852daaffb31Sdp# 853daaffb31Sdp# $WDIR/DIR/$TNAME.lhs.html 854daaffb31Sdp# $WDIR/DIR/$TNAME.rhs.html 855daaffb31Sdp# $WDIR/DIR/$TNAME.frames.html 856daaffb31Sdp# 857daaffb31Sdp# NOTE: We rely on standard usage of $WDIR and $DIR. 858daaffb31Sdp# 8597c478bd9Sstevel@tonic-gatefunction framed_sdiff 8607c478bd9Sstevel@tonic-gate{ 8617c478bd9Sstevel@tonic-gate typeset TNAME=$1 862daaffb31Sdp typeset TPATH=$2 863daaffb31Sdp typeset lhsfile=$3 864daaffb31Sdp typeset rhsfile=$4 865daaffb31Sdp typeset comments=$5 8667c478bd9Sstevel@tonic-gate typeset RTOP 867daaffb31Sdp 8687c478bd9Sstevel@tonic-gate # Enable html files to access WDIR via a relative path. 869daaffb31Sdp RTOP=$(relative_dir $TPATH $WDIR) 870daaffb31Sdp 871daaffb31Sdp # Make the rhs/lhs files and output the frameset file. 872daaffb31Sdp print "$HTML<head>$STDHEAD" > $WDIR/$DIR/$TNAME.lhs.html 873daaffb31Sdp 874daaffb31Sdp cat >> $WDIR/$DIR/$TNAME.lhs.html <<-EOF 8758b3b7b16SMark J. Nelson <script type="text/javascript" src="${RTOP}ancnav.js"></script> 8767c478bd9Sstevel@tonic-gate </head> 877daaffb31Sdp <body id="SUNWwebrev" onkeypress="keypress(event);"> 878cac38512Smjnelson <a name="0"></a> 879cac38512Smjnelson <pre>$comments</pre><hr></hr> 880daaffb31Sdp EOF 881daaffb31Sdp 882daaffb31Sdp cp $WDIR/$DIR/$TNAME.lhs.html $WDIR/$DIR/$TNAME.rhs.html 883daaffb31Sdp 884daaffb31Sdp insert_anchors $lhsfile >> $WDIR/$DIR/$TNAME.lhs.html 885daaffb31Sdp insert_anchors $rhsfile >> $WDIR/$DIR/$TNAME.rhs.html 886daaffb31Sdp 887daaffb31Sdp close='</body></html>' 888daaffb31Sdp 889daaffb31Sdp print $close >> $WDIR/$DIR/$TNAME.lhs.html 890daaffb31Sdp print $close >> $WDIR/$DIR/$TNAME.rhs.html 891daaffb31Sdp 892daaffb31Sdp print "$FRAMEHTML<head>$STDHEAD" > $WDIR/$DIR/$TNAME.frames.html 893daaffb31Sdp print "<title>$WNAME Framed-Sdiff " \ 894daaffb31Sdp "$TPATH/$TNAME</title> </head>" >> $WDIR/$DIR/$TNAME.frames.html 895daaffb31Sdp cat >> $WDIR/$DIR/$TNAME.frames.html <<-EOF 896daaffb31Sdp <frameset rows="*,60"> 897daaffb31Sdp <frameset cols="50%,50%"> 898cac38512Smjnelson <frame src="$TNAME.lhs.html" scrolling="auto" name="lhs"></frame> 899cac38512Smjnelson <frame src="$TNAME.rhs.html" scrolling="auto" name="rhs"></frame> 900daaffb31Sdp </frameset> 9018b3b7b16SMark J. Nelson <frame src="${RTOP}ancnav.html" scrolling="no" marginwidth="0" 902cac38512Smjnelson marginheight="0" name="nav"></frame> 903daaffb31Sdp <noframes> 904daaffb31Sdp <body id="SUNWwebrev"> 905daaffb31Sdp Alas 'frames' webrev requires that your browser supports frames 9067c478bd9Sstevel@tonic-gate and has the feature enabled. 907daaffb31Sdp </body> 908daaffb31Sdp </noframes> 909daaffb31Sdp </frameset> 9107c478bd9Sstevel@tonic-gate </html> 9117c478bd9Sstevel@tonic-gate EOF 9127c478bd9Sstevel@tonic-gate} 9137c478bd9Sstevel@tonic-gate 9147c478bd9Sstevel@tonic-gate 915daaffb31Sdp# 916daaffb31Sdp# fix_postscript 917daaffb31Sdp# 918daaffb31Sdp# Merge codereview output files to a single conforming postscript file, by: 919daaffb31Sdp# - removing all extraneous headers/trailers 920daaffb31Sdp# - making the page numbers right 921daaffb31Sdp# - removing pages devoid of contents which confuse some 922daaffb31Sdp# postscript readers. 923daaffb31Sdp# 924daaffb31Sdp# From Casper. 925daaffb31Sdp# 926daaffb31Sdpfunction fix_postscript 9277c478bd9Sstevel@tonic-gate{ 928daaffb31Sdp infile=$1 9297c478bd9Sstevel@tonic-gate 930daaffb31Sdp cat > /tmp/$$.crmerge.pl << \EOF 9317c478bd9Sstevel@tonic-gate 932daaffb31Sdp print scalar(<>); # %!PS-Adobe--- 933daaffb31Sdp print "%%Orientation: Landscape\n"; 9347c478bd9Sstevel@tonic-gate 935daaffb31Sdp $pno = 0; 936daaffb31Sdp $doprint = 1; 937daaffb31Sdp 938daaffb31Sdp $page = ""; 939daaffb31Sdp 940daaffb31Sdp while (<>) { 941daaffb31Sdp next if (/^%%Pages:\s*\d+/); 942daaffb31Sdp 943daaffb31Sdp if (/^%%Page:/) { 944daaffb31Sdp if ($pno == 0 || $page =~ /\)S/) { 945daaffb31Sdp # Header or single page containing text 946daaffb31Sdp print "%%Page: ? $pno\n" if ($pno > 0); 947daaffb31Sdp print $page; 948daaffb31Sdp $pno++; 949daaffb31Sdp } else { 950daaffb31Sdp # Empty page, skip it. 9517c478bd9Sstevel@tonic-gate } 952daaffb31Sdp $page = ""; 953daaffb31Sdp $doprint = 1; 9547c478bd9Sstevel@tonic-gate next; 9557c478bd9Sstevel@tonic-gate } 9567c478bd9Sstevel@tonic-gate 957daaffb31Sdp # Skip from %%Trailer of one document to Endprolog 958daaffb31Sdp # %%Page of the next 959daaffb31Sdp $doprint = 0 if (/^%%Trailer/); 960daaffb31Sdp $page .= $_ if ($doprint); 9617c478bd9Sstevel@tonic-gate } 9627c478bd9Sstevel@tonic-gate 963daaffb31Sdp if ($page =~ /\)S/) { 964daaffb31Sdp print "%%Page: ? $pno\n"; 965daaffb31Sdp print $page; 966daaffb31Sdp } else { 967daaffb31Sdp $pno--; 968daaffb31Sdp } 969daaffb31Sdp print "%%Trailer\n%%Pages: $pno\n"; 970daaffb31SdpEOF 971daaffb31Sdp 97214983201Sdp $PERL /tmp/$$.crmerge.pl < $infile 973daaffb31Sdp} 974daaffb31Sdp 975daaffb31Sdp 976daaffb31Sdp# 977daaffb31Sdp# input_cmd | insert_anchors | output_cmd 978daaffb31Sdp# 9797c478bd9Sstevel@tonic-gate# Flag blocks of difference with sequentially numbered invisible 980daaffb31Sdp# anchors. These are used to drive the frames version of the 9817c478bd9Sstevel@tonic-gate# sdiffs output. 9827c478bd9Sstevel@tonic-gate# 9837c478bd9Sstevel@tonic-gate# NOTE: Anchor zero flags the top of the file irrespective of changes, 9847c478bd9Sstevel@tonic-gate# an additional anchor is also appended to flag the bottom. 9857c478bd9Sstevel@tonic-gate# 986daaffb31Sdp# The script detects changed lines as any line that has a "<span 987daaffb31Sdp# class=" string embedded (unchanged lines have no class set and are 988daaffb31Sdp# not part of a <span>. Blank lines (without a sequence number) 9897c478bd9Sstevel@tonic-gate# are also detected since they flag lines that have been inserted or 9907c478bd9Sstevel@tonic-gate# deleted. 9917c478bd9Sstevel@tonic-gate# 992daaffb31Sdpfunction insert_anchors 993daaffb31Sdp{ 994cdf0c1d5Smjnelson $AWK ' 9957c478bd9Sstevel@tonic-gate function ia() { 996daaffb31Sdp printf "<a name=\"%d\" id=\"anc%d\"></a>", anc, anc++; 9977c478bd9Sstevel@tonic-gate } 998daaffb31Sdp 9997c478bd9Sstevel@tonic-gate BEGIN { 1000daaffb31Sdp anc=1; 10017c478bd9Sstevel@tonic-gate inblock=1; 1002daaffb31Sdp printf "<pre>\n"; 10037c478bd9Sstevel@tonic-gate } 1004daaffb31Sdp NF == 0 || /^<span class=/ { 10057c478bd9Sstevel@tonic-gate if (inblock == 0) { 10067c478bd9Sstevel@tonic-gate ia(); 10077c478bd9Sstevel@tonic-gate inblock=1; 10087c478bd9Sstevel@tonic-gate } 10097c478bd9Sstevel@tonic-gate print; 10107c478bd9Sstevel@tonic-gate next; 10117c478bd9Sstevel@tonic-gate } 10127c478bd9Sstevel@tonic-gate { 10137c478bd9Sstevel@tonic-gate inblock=0; 10147c478bd9Sstevel@tonic-gate print; 10157c478bd9Sstevel@tonic-gate } 10167c478bd9Sstevel@tonic-gate END { 10177c478bd9Sstevel@tonic-gate ia(); 1018daaffb31Sdp 1019daaffb31Sdp printf "<b style=\"font-size: large; color: red\">"; 1020daaffb31Sdp printf "--- EOF ---</b>" 10217c478bd9Sstevel@tonic-gate for(i=0;i<8;i++) printf "\n\n\n\n\n\n\n\n\n\n"; 1022daaffb31Sdp printf "</pre>" 1023daaffb31Sdp printf "<form name=\"eof\">"; 1024cac38512Smjnelson printf "<input name=\"value\" value=\"%d\" " \ 1025cac38512Smjnelson "type=\"hidden\"></input>", anc - 1; 1026daaffb31Sdp printf "</form>"; 10277c478bd9Sstevel@tonic-gate } 10287c478bd9Sstevel@tonic-gate ' $1 10297c478bd9Sstevel@tonic-gate} 10307c478bd9Sstevel@tonic-gate 10317c478bd9Sstevel@tonic-gate 1032daaffb31Sdp# 1033daaffb31Sdp# relative_dir 1034daaffb31Sdp# 1035daaffb31Sdp# Print a relative return path from $1 to $2. For example if 1036daaffb31Sdp# $1=/tmp/myreview/raw_files/usr/src/tools/scripts and $2=/tmp/myreview, 1037daaffb31Sdp# this function would print "../../../../". 1038daaffb31Sdp# 1039daaffb31Sdp# In the event that $1 is not in $2 a warning is printed to stderr, 1040daaffb31Sdp# and $2 is returned-- the result of this is that the resulting webrev 1041daaffb31Sdp# is not relocatable. 1042daaffb31Sdp# 1043daaffb31Sdpfunction relative_dir 10447c478bd9Sstevel@tonic-gate{ 1045daaffb31Sdp typeset cur="${1##$2?(/)}" 10468b3b7b16SMark J. Nelson 10478b3b7b16SMark J. Nelson # 10488b3b7b16SMark J. Nelson # If the first path was specified absolutely, and it does 10498b3b7b16SMark J. Nelson # not start with the second path, it's an error. 10508b3b7b16SMark J. Nelson # 10510fd2682eSMark J. Nelson if [[ "$cur" = "/${1#/}" ]]; then 1052daaffb31Sdp # Should never happen. 105314983201Sdp print -u2 "\nWARNING: relative_dir: \"$1\" not relative " 1054daaffb31Sdp print -u2 "to \"$2\". Check input paths. Framed webrev " 1055daaffb31Sdp print -u2 "will not be relocatable!" 1056daaffb31Sdp print $2 1057daaffb31Sdp return 1058daaffb31Sdp fi 1059daaffb31Sdp 10608b3b7b16SMark J. Nelson # 10618b3b7b16SMark J. Nelson # This is kind of ugly. The sed script will do the following: 10628b3b7b16SMark J. Nelson # 10638b3b7b16SMark J. Nelson # 1. Strip off a leading "." or "./": this is important to get 10648b3b7b16SMark J. Nelson # the correct arcnav links for files in $WDIR. 10658b3b7b16SMark J. Nelson # 2. Strip off a trailing "/": this is not strictly necessary, 10668b3b7b16SMark J. Nelson # but is kind of nice, since it doesn't end up in "//" at 10678b3b7b16SMark J. Nelson # the end of a relative path. 10688b3b7b16SMark J. Nelson # 3. Replace all remaining sequences of non-"/" with "..": the 10698b3b7b16SMark J. Nelson # assumption here is that each dirname represents another 10708b3b7b16SMark J. Nelson # level of relative separation. 10718b3b7b16SMark J. Nelson # 4. Append a trailing "/" only for non-empty paths: this way 10728b3b7b16SMark J. Nelson # the caller doesn't need to duplicate this logic, and does 10738b3b7b16SMark J. Nelson # not end up using $RTOP/file for files in $WDIR. 10748b3b7b16SMark J. Nelson # 10750fd2682eSMark J. Nelson print $cur | $SED -e '{ 10768b3b7b16SMark J. Nelson s:^\./*:: 10778b3b7b16SMark J. Nelson s:/$:: 10788b3b7b16SMark J. Nelson s:[^/][^/]*:..:g 10790fd2682eSMark J. Nelson s:^\(..*\)$:\1/: 10800fd2682eSMark J. Nelson }' 10817c478bd9Sstevel@tonic-gate} 10827c478bd9Sstevel@tonic-gate 1083daaffb31Sdp# 1084daaffb31Sdp# frame_nav_js 1085daaffb31Sdp# 1086daaffb31Sdp# Emit javascript for frame navigation 1087daaffb31Sdp# 1088daaffb31Sdpfunction frame_nav_js 10897c478bd9Sstevel@tonic-gate{ 10907c478bd9Sstevel@tonic-gatecat << \EOF 10917c478bd9Sstevel@tonic-gatevar myInt; 10927c478bd9Sstevel@tonic-gatevar scrolling=0; 1093daaffb31Sdpvar sfactor = 3; 10947c478bd9Sstevel@tonic-gatevar scount=10; 10957c478bd9Sstevel@tonic-gate 10967c478bd9Sstevel@tonic-gatefunction scrollByPix() { 10977c478bd9Sstevel@tonic-gate if (scount<=0) { 10987c478bd9Sstevel@tonic-gate sfactor*=1.2; 10997c478bd9Sstevel@tonic-gate scount=10; 11007c478bd9Sstevel@tonic-gate } 11017c478bd9Sstevel@tonic-gate parent.lhs.scrollBy(0,sfactor); 11027c478bd9Sstevel@tonic-gate parent.rhs.scrollBy(0,sfactor); 11037c478bd9Sstevel@tonic-gate scount--; 11047c478bd9Sstevel@tonic-gate} 11057c478bd9Sstevel@tonic-gate 1106daaffb31Sdpfunction scrollToAnc(num) { 1107daaffb31Sdp 1108daaffb31Sdp // Update the value of the anchor in the form which we use as 1109daaffb31Sdp // storage for this value. setAncValue() will take care of 1110daaffb31Sdp // correcting for overflow and underflow of the value and return 1111daaffb31Sdp // us the new value. 1112daaffb31Sdp num = setAncValue(num); 1113daaffb31Sdp 1114daaffb31Sdp // Set location and scroll back a little to expose previous 1115daaffb31Sdp // lines. 1116daaffb31Sdp // 1117daaffb31Sdp // Note that this could be improved: it is possible although 1118daaffb31Sdp // complex to compute the x and y position of an anchor, and to 1119daaffb31Sdp // scroll to that location directly. 1120daaffb31Sdp // 11217c478bd9Sstevel@tonic-gate parent.lhs.location.replace(parent.lhs.location.pathname + "#" + num); 11227c478bd9Sstevel@tonic-gate parent.rhs.location.replace(parent.rhs.location.pathname + "#" + num); 1123daaffb31Sdp 11247c478bd9Sstevel@tonic-gate parent.lhs.scrollBy(0,-30); 11257c478bd9Sstevel@tonic-gate parent.rhs.scrollBy(0,-30); 11267c478bd9Sstevel@tonic-gate} 11277c478bd9Sstevel@tonic-gate 1128daaffb31Sdpfunction getAncValue() 1129daaffb31Sdp{ 1130daaffb31Sdp return (parseInt(parent.nav.document.diff.real.value)); 1131daaffb31Sdp} 1132daaffb31Sdp 1133daaffb31Sdpfunction setAncValue(val) 1134daaffb31Sdp{ 1135daaffb31Sdp if (val <= 0) { 1136daaffb31Sdp val = 0; 1137daaffb31Sdp parent.nav.document.diff.real.value = val; 1138daaffb31Sdp parent.nav.document.diff.display.value = "BOF"; 1139daaffb31Sdp return (val); 1140daaffb31Sdp } 1141daaffb31Sdp 1142daaffb31Sdp // 1143daaffb31Sdp // The way we compute the max anchor value is to stash it 1144daaffb31Sdp // inline in the left and right hand side pages-- it's the same 1145daaffb31Sdp // on each side, so we pluck from the left. 1146daaffb31Sdp // 1147daaffb31Sdp maxval = parent.lhs.document.eof.value.value; 1148daaffb31Sdp if (val < maxval) { 1149daaffb31Sdp parent.nav.document.diff.real.value = val; 1150daaffb31Sdp parent.nav.document.diff.display.value = val.toString(); 1151daaffb31Sdp return (val); 1152daaffb31Sdp } 1153daaffb31Sdp 1154daaffb31Sdp // this must be: val >= maxval 1155daaffb31Sdp val = maxval; 1156daaffb31Sdp parent.nav.document.diff.real.value = val; 1157daaffb31Sdp parent.nav.document.diff.display.value = "EOF"; 1158daaffb31Sdp return (val); 1159daaffb31Sdp} 1160daaffb31Sdp 11617c478bd9Sstevel@tonic-gatefunction stopScroll() { 11627c478bd9Sstevel@tonic-gate if (scrolling==1) { 11637c478bd9Sstevel@tonic-gate clearInterval(myInt); 11647c478bd9Sstevel@tonic-gate scrolling=0; 11657c478bd9Sstevel@tonic-gate } 11667c478bd9Sstevel@tonic-gate} 11677c478bd9Sstevel@tonic-gate 11687c478bd9Sstevel@tonic-gatefunction startScroll() { 11697c478bd9Sstevel@tonic-gate stopScroll(); 11707c478bd9Sstevel@tonic-gate scrolling=1; 11717c478bd9Sstevel@tonic-gate myInt=setInterval("scrollByPix()",10); 11727c478bd9Sstevel@tonic-gate} 11737c478bd9Sstevel@tonic-gate 11747c478bd9Sstevel@tonic-gatefunction handlePress(b) { 1175daaffb31Sdp 11767c478bd9Sstevel@tonic-gate switch (b) { 11777c478bd9Sstevel@tonic-gate case 1 : 1178daaffb31Sdp scrollToAnc(-1); 11797c478bd9Sstevel@tonic-gate break; 11807c478bd9Sstevel@tonic-gate case 2 : 1181daaffb31Sdp scrollToAnc(getAncValue() - 1); 11827c478bd9Sstevel@tonic-gate break; 11837c478bd9Sstevel@tonic-gate case 3 : 11847c478bd9Sstevel@tonic-gate sfactor=-3; 11857c478bd9Sstevel@tonic-gate startScroll(); 11867c478bd9Sstevel@tonic-gate break; 11877c478bd9Sstevel@tonic-gate case 4 : 11887c478bd9Sstevel@tonic-gate sfactor=3; 11897c478bd9Sstevel@tonic-gate startScroll(); 11907c478bd9Sstevel@tonic-gate break; 11917c478bd9Sstevel@tonic-gate case 5 : 1192daaffb31Sdp scrollToAnc(getAncValue() + 1); 11937c478bd9Sstevel@tonic-gate break; 11947c478bd9Sstevel@tonic-gate case 6 : 1195daaffb31Sdp scrollToAnc(999999); 11967c478bd9Sstevel@tonic-gate break; 11977c478bd9Sstevel@tonic-gate } 11987c478bd9Sstevel@tonic-gate} 11997c478bd9Sstevel@tonic-gate 12007c478bd9Sstevel@tonic-gatefunction handleRelease(b) { 12017c478bd9Sstevel@tonic-gate stopScroll(); 12027c478bd9Sstevel@tonic-gate} 12037c478bd9Sstevel@tonic-gate 1204daaffb31Sdpfunction keypress(ev) { 1205daaffb31Sdp var keynum; 1206daaffb31Sdp var keychar; 1207daaffb31Sdp 1208daaffb31Sdp if (window.event) { // IE 1209daaffb31Sdp keynum = ev.keyCode; 1210daaffb31Sdp } else if (ev.which) { // non-IE 1211daaffb31Sdp keynum = ev.which; 1212daaffb31Sdp } 1213daaffb31Sdp 1214daaffb31Sdp keychar = String.fromCharCode(keynum); 1215daaffb31Sdp 1216daaffb31Sdp if (keychar == "k") { 1217daaffb31Sdp handlePress(2); 1218daaffb31Sdp return (0); 1219daaffb31Sdp } else if (keychar == "j" || keychar == " ") { 1220daaffb31Sdp handlePress(5); 1221daaffb31Sdp return (0); 1222daaffb31Sdp } 1223daaffb31Sdp return (1); 1224daaffb31Sdp} 1225daaffb31Sdp 12267c478bd9Sstevel@tonic-gatefunction ValidateDiffNum(){ 1227daaffb31Sdp val = parent.nav.document.diff.display.value; 1228daaffb31Sdp if (val == "EOF") { 1229daaffb31Sdp scrollToAnc(999999); 1230daaffb31Sdp return; 1231daaffb31Sdp } 1232daaffb31Sdp 1233daaffb31Sdp if (val == "BOF") { 1234daaffb31Sdp scrollToAnc(0); 1235daaffb31Sdp return; 1236daaffb31Sdp } 1237daaffb31Sdp 1238daaffb31Sdp i=parseInt(val); 12397c478bd9Sstevel@tonic-gate if (isNaN(i)) { 1240daaffb31Sdp parent.nav.document.diff.display.value = getAncValue(); 12417c478bd9Sstevel@tonic-gate } else { 1242daaffb31Sdp scrollToAnc(i); 12437c478bd9Sstevel@tonic-gate } 12447c478bd9Sstevel@tonic-gate return false; 12457c478bd9Sstevel@tonic-gate} 12467c478bd9Sstevel@tonic-gate 1247daaffb31SdpEOF 1248daaffb31Sdp} 1249daaffb31Sdp 1250daaffb31Sdp# 1251daaffb31Sdp# frame_navigation 1252daaffb31Sdp# 1253daaffb31Sdp# Output anchor navigation file for framed sdiffs. 1254daaffb31Sdp# 1255daaffb31Sdpfunction frame_navigation 1256daaffb31Sdp{ 1257daaffb31Sdp print "$HTML<head>$STDHEAD" 1258daaffb31Sdp 1259daaffb31Sdp cat << \EOF 1260daaffb31Sdp<title>Anchor Navigation</title> 1261daaffb31Sdp<meta http-equiv="Content-Script-Type" content="text/javascript"> 1262daaffb31Sdp<meta http-equiv="Content-Type" content="text/html"> 1263daaffb31Sdp 1264daaffb31Sdp<style type="text/css"> 1265daaffb31Sdp div.button td { padding-left: 5px; padding-right: 5px; 1266daaffb31Sdp background-color: #eee; text-align: center; 1267daaffb31Sdp border: 1px #444 outset; cursor: pointer; } 1268daaffb31Sdp div.button a { font-weight: bold; color: black } 1269daaffb31Sdp div.button td:hover { background: #ffcc99; } 1270daaffb31Sdp</style> 1271daaffb31SdpEOF 1272daaffb31Sdp 1273cac38512Smjnelson print "<script type=\"text/javascript\" src=\"ancnav.js\"></script>" 1274daaffb31Sdp 1275daaffb31Sdp cat << \EOF 12767c478bd9Sstevel@tonic-gate</head> 1277daaffb31Sdp<body id="SUNWwebrev" bgcolor="#eeeeee" onload="document.diff.real.focus();" 1278daaffb31Sdp onkeypress="keypress(event);"> 12797c478bd9Sstevel@tonic-gate <noscript lang="javascript"> 12807c478bd9Sstevel@tonic-gate <center> 1281cac38512Smjnelson <p><big>Framed Navigation controls require Javascript</big><br></br> 12827c478bd9Sstevel@tonic-gate Either this browser is incompatable or javascript is not enabled</p> 12837c478bd9Sstevel@tonic-gate </center> 12847c478bd9Sstevel@tonic-gate </noscript> 12857c478bd9Sstevel@tonic-gate <table width="100%" border="0" align="center"> 1286daaffb31Sdp <tr> 1287daaffb31Sdp <td valign="middle" width="25%">Diff navigation: 1288daaffb31Sdp Use 'j' and 'k' for next and previous diffs; or use buttons 1289daaffb31Sdp at right</td> 1290daaffb31Sdp <td align="center" valign="top" width="50%"> 12917c478bd9Sstevel@tonic-gate <div class="button"> 1292daaffb31Sdp <table border="0" align="center"> 1293daaffb31Sdp <tr> 1294daaffb31Sdp <td> 12957c478bd9Sstevel@tonic-gate <a onMouseDown="handlePress(1);return true;" 12967c478bd9Sstevel@tonic-gate onMouseUp="handleRelease(1);return true;" 12977c478bd9Sstevel@tonic-gate onMouseOut="handleRelease(1);return true;" 12987c478bd9Sstevel@tonic-gate onClick="return false;" 12997c478bd9Sstevel@tonic-gate title="Go to Beginning Of file">BOF</a></td> 1300daaffb31Sdp <td> 13017c478bd9Sstevel@tonic-gate <a onMouseDown="handlePress(3);return true;" 13027c478bd9Sstevel@tonic-gate onMouseUp="handleRelease(3);return true;" 13037c478bd9Sstevel@tonic-gate onMouseOut="handleRelease(3);return true;" 13047c478bd9Sstevel@tonic-gate title="Scroll Up: Press and Hold to accelerate" 1305daaffb31Sdp onClick="return false;">Scroll Up</a></td> 1306daaffb31Sdp <td> 13077c478bd9Sstevel@tonic-gate <a onMouseDown="handlePress(2);return true;" 13087c478bd9Sstevel@tonic-gate onMouseUp="handleRelease(2);return true;" 13097c478bd9Sstevel@tonic-gate onMouseOut="handleRelease(2);return true;" 13107c478bd9Sstevel@tonic-gate title="Go to previous Diff" 13117c478bd9Sstevel@tonic-gate onClick="return false;">Prev Diff</a> 13127c478bd9Sstevel@tonic-gate </td></tr> 1313daaffb31Sdp 13147c478bd9Sstevel@tonic-gate <tr> 1315daaffb31Sdp <td> 13167c478bd9Sstevel@tonic-gate <a onMouseDown="handlePress(6);return true;" 13177c478bd9Sstevel@tonic-gate onMouseUp="handleRelease(6);return true;" 13187c478bd9Sstevel@tonic-gate onMouseOut="handleRelease(6);return true;" 13197c478bd9Sstevel@tonic-gate onClick="return false;" 13207c478bd9Sstevel@tonic-gate title="Go to End Of File">EOF</a></td> 1321daaffb31Sdp <td> 13227c478bd9Sstevel@tonic-gate <a onMouseDown="handlePress(4);return true;" 13237c478bd9Sstevel@tonic-gate onMouseUp="handleRelease(4);return true;" 13247c478bd9Sstevel@tonic-gate onMouseOut="handleRelease(4);return true;" 13257c478bd9Sstevel@tonic-gate title="Scroll Down: Press and Hold to accelerate" 1326daaffb31Sdp onClick="return false;">Scroll Down</a></td> 1327daaffb31Sdp <td> 13287c478bd9Sstevel@tonic-gate <a onMouseDown="handlePress(5);return true;" 13297c478bd9Sstevel@tonic-gate onMouseUp="handleRelease(5);return true;" 13307c478bd9Sstevel@tonic-gate onMouseOut="handleRelease(5);return true;" 13317c478bd9Sstevel@tonic-gate title="Go to next Diff" 13327c478bd9Sstevel@tonic-gate onClick="return false;">Next Diff</a></td> 1333daaffb31Sdp </tr> 1334daaffb31Sdp </table> 1335daaffb31Sdp </div> 1336daaffb31Sdp </td> 13377c478bd9Sstevel@tonic-gate <th valign="middle" width="25%"> 1338daaffb31Sdp <form action="" name="diff" onsubmit="return ValidateDiffNum();"> 1339cac38512Smjnelson <input name="display" value="BOF" size="8" type="text"></input> 1340cac38512Smjnelson <input name="real" value="0" size="8" type="hidden"></input> 13417c478bd9Sstevel@tonic-gate </form> 13427c478bd9Sstevel@tonic-gate </th> 1343daaffb31Sdp </tr> 13447c478bd9Sstevel@tonic-gate </table> 13457c478bd9Sstevel@tonic-gate </body> 13467c478bd9Sstevel@tonic-gate</html> 13477c478bd9Sstevel@tonic-gateEOF 13487c478bd9Sstevel@tonic-gate} 13497c478bd9Sstevel@tonic-gate 13507c478bd9Sstevel@tonic-gate 1351daaffb31Sdp 1352daaffb31Sdp# 1353daaffb31Sdp# diff_to_html <filename> <filepath> { U | C } <comment> 1354daaffb31Sdp# 1355daaffb31Sdp# Processes the output of diff to produce an HTML file representing either 1356daaffb31Sdp# context or unified diffs. 1357daaffb31Sdp# 13587c478bd9Sstevel@tonic-gatediff_to_html() 13597c478bd9Sstevel@tonic-gate{ 13607c478bd9Sstevel@tonic-gate TNAME=$1 1361daaffb31Sdp TPATH=$2 1362daaffb31Sdp DIFFTYPE=$3 1363daaffb31Sdp COMMENT=$4 1364daaffb31Sdp 1365daaffb31Sdp print "$HTML<head>$STDHEAD" 1366daaffb31Sdp print "<title>$WNAME ${DIFFTYPE}diff $TPATH</title>" 1367daaffb31Sdp 1368daaffb31Sdp if [[ $DIFFTYPE == "U" ]]; then 1369daaffb31Sdp print "$UDIFFCSS" 1370daaffb31Sdp fi 1371daaffb31Sdp 1372daaffb31Sdp cat <<-EOF 1373daaffb31Sdp </head> 1374daaffb31Sdp <body id="SUNWwebrev"> 1375daaffb31Sdp <a class="print" href="javascript:print()">Print this page</a> 1376daaffb31Sdp <pre>$COMMENT</pre> 1377daaffb31Sdp <pre> 1378daaffb31Sdp EOF 13797c478bd9Sstevel@tonic-gate 1380cdf0c1d5Smjnelson html_quote | $AWK ' 1381daaffb31Sdp /^--- new/ { next } 1382daaffb31Sdp /^\+\+\+ new/ { next } 1383daaffb31Sdp /^--- old/ { next } 1384daaffb31Sdp /^\*\*\* old/ { next } 1385daaffb31Sdp /^\*\*\*\*/ { next } 13867c478bd9Sstevel@tonic-gate /^-------/ { printf "<center><h1>%s</h1></center>\n", $0; next } 1387cac38512Smjnelson /^\@\@.*\@\@$/ { printf "</pre><hr></hr><pre>\n"; 1388daaffb31Sdp printf "<span class=\"newmarker\">%s</span>\n", $0; 1389daaffb31Sdp next} 1390daaffb31Sdp 1391cac38512Smjnelson /^\*\*\*/ { printf "<hr></hr><span class=\"oldmarker\">%s</span>\n", $0; 1392daaffb31Sdp next} 1393daaffb31Sdp /^---/ { printf "<span class=\"newmarker\">%s</span>\n", $0; 1394daaffb31Sdp next} 1395daaffb31Sdp /^\+/ {printf "<span class=\"new\">%s</span>\n", $0; next} 1396daaffb31Sdp /^!/ {printf "<span class=\"changed\">%s</span>\n", $0; next} 1397daaffb31Sdp /^-/ {printf "<span class=\"removed\">%s</span>\n", $0; next} 1398daaffb31Sdp {printf "%s\n", $0; next} 13997c478bd9Sstevel@tonic-gate ' 1400daaffb31Sdp 1401daaffb31Sdp print "</pre></body></html>\n" 14027c478bd9Sstevel@tonic-gate} 14037c478bd9Sstevel@tonic-gate 14047c478bd9Sstevel@tonic-gate 1405daaffb31Sdp# 1406daaffb31Sdp# source_to_html { new | old } <filename> 1407daaffb31Sdp# 1408daaffb31Sdp# Process a plain vanilla source file to transform it into an HTML file. 1409daaffb31Sdp# 14107c478bd9Sstevel@tonic-gatesource_to_html() 14117c478bd9Sstevel@tonic-gate{ 14127c478bd9Sstevel@tonic-gate WHICH=$1 14137c478bd9Sstevel@tonic-gate TNAME=$2 14147c478bd9Sstevel@tonic-gate 1415daaffb31Sdp print "$HTML<head>$STDHEAD" 1416cdf0c1d5Smjnelson print "<title>$WNAME $WHICH $TNAME</title>" 1417daaffb31Sdp print "<body id=\"SUNWwebrev\">" 1418daaffb31Sdp print "<pre>" 1419cdf0c1d5Smjnelson html_quote | $AWK '{line += 1 ; printf "%4d %s\n", line, $0 }' 1420daaffb31Sdp print "</pre></body></html>" 14217c478bd9Sstevel@tonic-gate} 14227c478bd9Sstevel@tonic-gate 1423daaffb31Sdp# 1424cdf0c1d5Smjnelson# comments_from_teamware {text|html} parent-file child-file 1425daaffb31Sdp# 1426daaffb31Sdp# Find the first delta in the child that's not in the parent. Get the 1427daaffb31Sdp# newest delta from the parent, get all deltas from the child starting 1428daaffb31Sdp# with that delta, and then get all info starting with the second oldest 1429daaffb31Sdp# delta in that list (the first delta unique to the child). 14307c478bd9Sstevel@tonic-gate# 14317c478bd9Sstevel@tonic-gate# This code adapted from Bill Shannon's "spc" script 1432daaffb31Sdp# 1433daaffb31Sdpcomments_from_teamware() 14347c478bd9Sstevel@tonic-gate{ 1435daaffb31Sdp fmt=$1 1436daaffb31Sdp pfile=$PWS/$2 1437daaffb31Sdp cfile=$CWS/$3 14387c478bd9Sstevel@tonic-gate 1439cdf0c1d5Smjnelson if [[ ! -f $PWS/${2%/*}/SCCS/s.${2##*/} && -n $RWS ]]; then 1440cdf0c1d5Smjnelson pfile=$RWS/$2 1441cdf0c1d5Smjnelson fi 1442cdf0c1d5Smjnelson 1443daaffb31Sdp if [[ -f $pfile ]]; then 1444cdf0c1d5Smjnelson psid=$($SCCS prs -d:I: $pfile 2>/dev/null) 14457c478bd9Sstevel@tonic-gate else 14467c478bd9Sstevel@tonic-gate psid=1.1 14477c478bd9Sstevel@tonic-gate fi 14487c478bd9Sstevel@tonic-gate 1449cdf0c1d5Smjnelson set -A sids $($SCCS prs -l -r$psid -d:I: $cfile 2>/dev/null) 14507c478bd9Sstevel@tonic-gate N=${#sids[@]} 14517c478bd9Sstevel@tonic-gate 1452daaffb31Sdp nawkprg=' 1453daaffb31Sdp /^COMMENTS:/ {p=1; continue} 1454daaffb31Sdp /^D [0-9]+\.[0-9]+/ {printf "--- %s ---\n", $2; p=0; } 1455daaffb31Sdp NF == 0u { continue } 1456daaffb31Sdp {if (p==0) continue; print $0 }' 1457daaffb31Sdp 14587c478bd9Sstevel@tonic-gate if [[ $N -ge 2 ]]; then 14597c478bd9Sstevel@tonic-gate sid1=${sids[$((N-2))]} # Gets 2nd to last sid 14607c478bd9Sstevel@tonic-gate 1461daaffb31Sdp if [[ $fmt == "text" ]]; then 1462cdf0c1d5Smjnelson $SCCS prs -l -r$sid1 $cfile 2>/dev/null | \ 1463cdf0c1d5Smjnelson $AWK "$nawkprg" 1464daaffb31Sdp return 1465daaffb31Sdp fi 1466daaffb31Sdp 1467cdf0c1d5Smjnelson $SCCS prs -l -r$sid1 $cfile 2>/dev/null | \ 14680fd2682eSMark J. Nelson html_quote | its2url | $AWK "$nawkprg" 14697c478bd9Sstevel@tonic-gate fi 14707c478bd9Sstevel@tonic-gate} 14717c478bd9Sstevel@tonic-gate 1472daaffb31Sdp# 1473cdf0c1d5Smjnelson# comments_from_wx {text|html} filepath 1474daaffb31Sdp# 1475cdf0c1d5Smjnelson# Given the pathname of a file, find its location in a "wx" active 1476cdf0c1d5Smjnelson# file list and print the following comment. Output is either text or 1477cdf0c1d5Smjnelson# HTML; if the latter, embedded bugids (sequence of 5 or more digits) 1478cdf0c1d5Smjnelson# are turned into URLs. 1479cdf0c1d5Smjnelson# 1480cdf0c1d5Smjnelson# This is also used with Mercurial and the file list provided by hg-active. 1481daaffb31Sdp# 1482daaffb31Sdpcomments_from_wx() 14837c478bd9Sstevel@tonic-gate{ 1484daaffb31Sdp typeset fmt=$1 1485daaffb31Sdp typeset p=$2 14867c478bd9Sstevel@tonic-gate 1487cdf0c1d5Smjnelson comm=`$AWK ' 1488daaffb31Sdp $1 == "'$p'" { 14897c478bd9Sstevel@tonic-gate do getline ; while (NF > 0) 14907c478bd9Sstevel@tonic-gate getline 14917c478bd9Sstevel@tonic-gate while (NF > 0) { print ; getline } 14927c478bd9Sstevel@tonic-gate exit 1493daaffb31Sdp }' < $wxfile` 1494daaffb31Sdp 1495cdf0c1d5Smjnelson if [[ -z $comm ]]; then 1496cdf0c1d5Smjnelson comm="*** NO COMMENTS ***" 1497cdf0c1d5Smjnelson fi 1498cdf0c1d5Smjnelson 1499daaffb31Sdp if [[ $fmt == "text" ]]; then 1500cdf0c1d5Smjnelson print -- "$comm" 1501daaffb31Sdp return 1502daaffb31Sdp fi 1503daaffb31Sdp 15040fd2682eSMark J. Nelson print -- "$comm" | html_quote | its2url 1505cdf0c1d5Smjnelson 15067c478bd9Sstevel@tonic-gate} 15077c478bd9Sstevel@tonic-gate 15087c478bd9Sstevel@tonic-gate# 1509daaffb31Sdp# getcomments {text|html} filepath parentpath 1510daaffb31Sdp# 1511daaffb31Sdp# Fetch the comments depending on what SCM mode we're in. 1512daaffb31Sdp# 1513daaffb31Sdpgetcomments() 1514daaffb31Sdp{ 1515daaffb31Sdp typeset fmt=$1 1516daaffb31Sdp typeset p=$2 1517daaffb31Sdp typeset pp=$3 15187c478bd9Sstevel@tonic-gate 15193df69ef3SDarren Moffat if [[ -n $Nflag ]]; then 15203df69ef3SDarren Moffat return 15213df69ef3SDarren Moffat fi 1522cdf0c1d5Smjnelson # 1523cdf0c1d5Smjnelson # Mercurial support uses a file list in wx format, so this 1524cdf0c1d5Smjnelson # will be used there, too 1525cdf0c1d5Smjnelson # 1526daaffb31Sdp if [[ -n $wxfile ]]; then 1527daaffb31Sdp comments_from_wx $fmt $p 1528daaffb31Sdp else 1529daaffb31Sdp if [[ $SCM_MODE == "teamware" ]]; then 1530daaffb31Sdp comments_from_teamware $fmt $pp $p 1531daaffb31Sdp fi 1532daaffb31Sdp fi 1533daaffb31Sdp} 1534daaffb31Sdp 1535daaffb31Sdp# 1536daaffb31Sdp# printCI <total-changed> <inserted> <deleted> <modified> <unchanged> 1537daaffb31Sdp# 1538daaffb31Sdp# Print out Code Inspection figures similar to sccs-prt(1) format. 1539daaffb31Sdp# 1540daaffb31Sdpfunction printCI 1541daaffb31Sdp{ 1542daaffb31Sdp integer tot=$1 ins=$2 del=$3 mod=$4 unc=$5 1543daaffb31Sdp typeset str 1544daaffb31Sdp if (( tot == 1 )); then 1545daaffb31Sdp str="line" 1546daaffb31Sdp else 1547daaffb31Sdp str="lines" 1548daaffb31Sdp fi 1549daaffb31Sdp printf '%d %s changed: %d ins; %d del; %d mod; %d unchg\n' \ 1550daaffb31Sdp $tot $str $ins $del $mod $unc 1551daaffb31Sdp} 1552daaffb31Sdp 1553daaffb31Sdp 1554daaffb31Sdp# 1555daaffb31Sdp# difflines <oldfile> <newfile> 1556daaffb31Sdp# 1557daaffb31Sdp# Calculate and emit number of added, removed, modified and unchanged lines, 1558daaffb31Sdp# and total lines changed, the sum of added + removed + modified. 1559daaffb31Sdp# 15607c478bd9Sstevel@tonic-gatefunction difflines 15617c478bd9Sstevel@tonic-gate{ 1562daaffb31Sdp integer tot mod del ins unc err 15637c478bd9Sstevel@tonic-gate typeset filename 15647c478bd9Sstevel@tonic-gate 1565cdf0c1d5Smjnelson eval $( diff -e $1 $2 | $AWK ' 1566daaffb31Sdp # Change range of lines: N,Nc 15677c478bd9Sstevel@tonic-gate /^[0-9]*,[0-9]*c$/ { 15687c478bd9Sstevel@tonic-gate n=split(substr($1,1,length($1)-1), counts, ","); 15697c478bd9Sstevel@tonic-gate if (n != 2) { 15707c478bd9Sstevel@tonic-gate error=2 15717c478bd9Sstevel@tonic-gate exit; 15727c478bd9Sstevel@tonic-gate } 1573daaffb31Sdp # 1574daaffb31Sdp # 3,5c means lines 3 , 4 and 5 are changed, a total of 3 lines. 1575daaffb31Sdp # following would be 5 - 3 = 2! Hence +1 for correction. 1576daaffb31Sdp # 15777c478bd9Sstevel@tonic-gate r=(counts[2]-counts[1])+1; 1578daaffb31Sdp 1579daaffb31Sdp # 1580daaffb31Sdp # Now count replacement lines: each represents a change instead 1581daaffb31Sdp # of a delete, so increment c and decrement r. 1582daaffb31Sdp # 15837c478bd9Sstevel@tonic-gate while (getline != /^\.$/) { 15847c478bd9Sstevel@tonic-gate c++; 15857c478bd9Sstevel@tonic-gate r--; 15867c478bd9Sstevel@tonic-gate } 1587daaffb31Sdp # 1588daaffb31Sdp # If there were more replacement lines than original lines, 1589daaffb31Sdp # then r will be negative; in this case there are no deletions, 1590daaffb31Sdp # but there are r changes that should be counted as adds, and 1591daaffb31Sdp # since r is negative, subtract it from a and add it to c. 1592daaffb31Sdp # 15937c478bd9Sstevel@tonic-gate if (r < 0) { 15947c478bd9Sstevel@tonic-gate a-=r; 15957c478bd9Sstevel@tonic-gate c+=r; 15967c478bd9Sstevel@tonic-gate } 1597daaffb31Sdp 1598daaffb31Sdp # 1599daaffb31Sdp # If there were more original lines than replacement lines, then 1600daaffb31Sdp # r will be positive; in this case, increment d by that much. 1601daaffb31Sdp # 16027c478bd9Sstevel@tonic-gate if (r > 0) { 16037c478bd9Sstevel@tonic-gate d+=r; 16047c478bd9Sstevel@tonic-gate } 16057c478bd9Sstevel@tonic-gate next; 16067c478bd9Sstevel@tonic-gate } 16077c478bd9Sstevel@tonic-gate 1608daaffb31Sdp # Change lines: Nc 16097c478bd9Sstevel@tonic-gate /^[0-9].*c$/ { 1610daaffb31Sdp # The first line is a replacement; any more are additions. 16117c478bd9Sstevel@tonic-gate if (getline != /^\.$/) { 16127c478bd9Sstevel@tonic-gate c++; 16137c478bd9Sstevel@tonic-gate while (getline != /^\.$/) a++; 16147c478bd9Sstevel@tonic-gate } 16157c478bd9Sstevel@tonic-gate next; 16167c478bd9Sstevel@tonic-gate } 16177c478bd9Sstevel@tonic-gate 1618daaffb31Sdp # Add lines: both Na and N,Na 16197c478bd9Sstevel@tonic-gate /^[0-9].*a$/ { 16207c478bd9Sstevel@tonic-gate while (getline != /^\.$/) a++; 16217c478bd9Sstevel@tonic-gate next; 16227c478bd9Sstevel@tonic-gate } 16237c478bd9Sstevel@tonic-gate 1624daaffb31Sdp # Delete range of lines: N,Nd 16257c478bd9Sstevel@tonic-gate /^[0-9]*,[0-9]*d$/ { 16267c478bd9Sstevel@tonic-gate n=split(substr($1,1,length($1)-1), counts, ","); 16277c478bd9Sstevel@tonic-gate if (n != 2) { 16287c478bd9Sstevel@tonic-gate error=2 16297c478bd9Sstevel@tonic-gate exit; 16307c478bd9Sstevel@tonic-gate } 1631daaffb31Sdp # 1632daaffb31Sdp # 3,5d means lines 3 , 4 and 5 are deleted, a total of 3 lines. 1633daaffb31Sdp # following would be 5 - 3 = 2! Hence +1 for correction. 1634daaffb31Sdp # 16357c478bd9Sstevel@tonic-gate r=(counts[2]-counts[1])+1; 16367c478bd9Sstevel@tonic-gate d+=r; 16377c478bd9Sstevel@tonic-gate next; 16387c478bd9Sstevel@tonic-gate } 16397c478bd9Sstevel@tonic-gate 1640daaffb31Sdp # Delete line: Nd. For example 10d says line 10 is deleted. 16417c478bd9Sstevel@tonic-gate /^[0-9]*d$/ {d++; next} 16427c478bd9Sstevel@tonic-gate 1643daaffb31Sdp # Should not get here! 16447c478bd9Sstevel@tonic-gate { 16457c478bd9Sstevel@tonic-gate error=1; 16467c478bd9Sstevel@tonic-gate exit; 16477c478bd9Sstevel@tonic-gate } 16487c478bd9Sstevel@tonic-gate 1649daaffb31Sdp # Finish off - print results 16507c478bd9Sstevel@tonic-gate END { 1651daaffb31Sdp printf("tot=%d;mod=%d;del=%d;ins=%d;err=%d\n", 16527c478bd9Sstevel@tonic-gate (c+d+a), c, d, a, error); 16537c478bd9Sstevel@tonic-gate }' ) 16547c478bd9Sstevel@tonic-gate 1655cdf0c1d5Smjnelson # End of $AWK, Check to see if any trouble occurred. 16567c478bd9Sstevel@tonic-gate if (( $? > 0 || err > 0 )); then 1657daaffb31Sdp print "Unexpected Error occurred reading" \ 1658daaffb31Sdp "\`diff -e $1 $2\`: \$?=$?, err=" $err 1659daaffb31Sdp return 1660daaffb31Sdp fi 1661daaffb31Sdp 16627c478bd9Sstevel@tonic-gate # Accumulate totals 16637c478bd9Sstevel@tonic-gate (( TOTL += tot )) 1664daaffb31Sdp (( TMOD += mod )) 16657c478bd9Sstevel@tonic-gate (( TDEL += del )) 16667c478bd9Sstevel@tonic-gate (( TINS += ins )) 16677c478bd9Sstevel@tonic-gate # Calculate unchanged lines 1668cdf0c1d5Smjnelson unc=`wc -l < $1` 16697c478bd9Sstevel@tonic-gate if (( unc > 0 )); then 1670daaffb31Sdp (( unc -= del + mod )) 16717c478bd9Sstevel@tonic-gate (( TUNC += unc )) 16727c478bd9Sstevel@tonic-gate fi 16737c478bd9Sstevel@tonic-gate # print summary 1674daaffb31Sdp print "<span class=\"lineschanged\">" 1675daaffb31Sdp printCI $tot $ins $del $mod $unc 1676daaffb31Sdp print "</span>" 16777c478bd9Sstevel@tonic-gate} 16787c478bd9Sstevel@tonic-gate 1679daaffb31Sdp 16807c478bd9Sstevel@tonic-gate# 1681daaffb31Sdp# flist_from_wx 1682daaffb31Sdp# 1683daaffb31Sdp# Sets up webrev to source its information from a wx-formatted file. 1684daaffb31Sdp# Sets the global 'wxfile' variable. 1685daaffb31Sdp# 1686daaffb31Sdpfunction flist_from_wx 16877c478bd9Sstevel@tonic-gate{ 1688daaffb31Sdp typeset argfile=$1 1689daaffb31Sdp if [[ -n ${argfile%%/*} ]]; then 1690daaffb31Sdp # 1691daaffb31Sdp # If the wx file pathname is relative then make it absolute 1692daaffb31Sdp # because the webrev does a "cd" later on. 1693daaffb31Sdp # 1694daaffb31Sdp wxfile=$PWD/$argfile 16957c478bd9Sstevel@tonic-gate else 1696daaffb31Sdp wxfile=$argfile 16977c478bd9Sstevel@tonic-gate fi 16987c478bd9Sstevel@tonic-gate 1699cdf0c1d5Smjnelson $AWK '{ c = 1; print; 17007c478bd9Sstevel@tonic-gate while (getline) { 17017c478bd9Sstevel@tonic-gate if (NF == 0) { c = -c; continue } 17027c478bd9Sstevel@tonic-gate if (c > 0) print 17037c478bd9Sstevel@tonic-gate } 1704daaffb31Sdp }' $wxfile > $FLIST 17057c478bd9Sstevel@tonic-gate 1706daaffb31Sdp print " Done." 1707daaffb31Sdp} 17087c478bd9Sstevel@tonic-gate 1709daaffb31Sdp# 1710daaffb31Sdp# flist_from_teamware [ <args-to-putback-n> ] 1711daaffb31Sdp# 1712daaffb31Sdp# Generate the file list by extracting file names from a putback -n. Some 1713daaffb31Sdp# names may come from the "update/create" messages and others from the 1714daaffb31Sdp# "currently checked out" warning. Renames are detected here too. Extract 1715daaffb31Sdp# values for CODEMGR_WS and CODEMGR_PARENT from the output of the putback 1716daaffb31Sdp# -n as well, but remove them if they are already defined. 1717daaffb31Sdp# 1718daaffb31Sdpfunction flist_from_teamware 1719daaffb31Sdp{ 1720cdf0c1d5Smjnelson if [[ -n $codemgr_parent && -z $parent_webrev ]]; then 1721daaffb31Sdp if [[ ! -d $codemgr_parent/Codemgr_wsdata ]]; then 1722daaffb31Sdp print -u2 "parent $codemgr_parent doesn't look like a" \ 1723daaffb31Sdp "valid teamware workspace" 17247c478bd9Sstevel@tonic-gate exit 1 17257c478bd9Sstevel@tonic-gate fi 1726daaffb31Sdp parent_args="-p $codemgr_parent" 17277c478bd9Sstevel@tonic-gate fi 17287c478bd9Sstevel@tonic-gate 1729daaffb31Sdp print " File list from: 'putback -n $parent_args $*' ... \c" 17307c478bd9Sstevel@tonic-gate 1731daaffb31Sdp putback -n $parent_args $* 2>&1 | 1732cdf0c1d5Smjnelson $AWK ' 1733daaffb31Sdp /^update:|^create:/ {print $2} 1734daaffb31Sdp /^Parent workspace:/ {printf("CODEMGR_PARENT=%s\n",$3)} 1735daaffb31Sdp /^Child workspace:/ {printf("CODEMGR_WS=%s\n",$3)} 1736daaffb31Sdp /^The following files are currently checked out/ {p = 1; continue} 1737daaffb31Sdp NF == 0 {p=0 ; continue} 1738daaffb31Sdp /^rename/ {old=$3} 1739daaffb31Sdp $1 == "to:" {print $2, old} 1740daaffb31Sdp /^"/ {continue} 1741daaffb31Sdp p == 1 {print $1}' | 1742daaffb31Sdp sort -r -k 1,1 -u | sort > $FLIST 17437c478bd9Sstevel@tonic-gate 1744daaffb31Sdp print " Done." 1745daaffb31Sdp} 1746daaffb31Sdp 1747cdf0c1d5Smjnelson# 1748cdf0c1d5Smjnelson# Call hg-active to get the active list output in the wx active list format 1749cdf0c1d5Smjnelson# 1750cdf0c1d5Smjnelsonfunction hg_active_wxfile 1751cdf0c1d5Smjnelson{ 1752cdf0c1d5Smjnelson typeset child=$1 1753cdf0c1d5Smjnelson typeset parent=$2 1754cdf0c1d5Smjnelson 1755cdf0c1d5Smjnelson TMPFLIST=/tmp/$$.active 17569a70fc3bSMark J. Nelson $HG_ACTIVE -w $child -p $parent -o $TMPFLIST 1757cdf0c1d5Smjnelson wxfile=$TMPFLIST 1758cdf0c1d5Smjnelson} 1759cdf0c1d5Smjnelson 1760cdf0c1d5Smjnelson# 1761cdf0c1d5Smjnelson# flist_from_mercurial 1762cdf0c1d5Smjnelson# Call hg-active to get a wx-style active list, and hand it off to 1763cdf0c1d5Smjnelson# flist_from_wx 1764cdf0c1d5Smjnelson# 1765cdf0c1d5Smjnelsonfunction flist_from_mercurial 1766cdf0c1d5Smjnelson{ 1767cdf0c1d5Smjnelson typeset child=$1 1768cdf0c1d5Smjnelson typeset parent=$2 1769cdf0c1d5Smjnelson 1770cdf0c1d5Smjnelson print " File list from: hg-active -p $parent ...\c" 1771cdf0c1d5Smjnelson if [[ ! -x $HG_ACTIVE ]]; then 1772cdf0c1d5Smjnelson print # Blank line for the \c above 1773cdf0c1d5Smjnelson print -u2 "Error: hg-active tool not found. Exiting" 1774cdf0c1d5Smjnelson exit 1 1775cdf0c1d5Smjnelson fi 1776cdf0c1d5Smjnelson hg_active_wxfile $child $parent 1777cdf0c1d5Smjnelson 1778cdf0c1d5Smjnelson # flist_from_wx prints the Done, so we don't have to. 1779cdf0c1d5Smjnelson flist_from_wx $TMPFLIST 1780cdf0c1d5Smjnelson} 1781cdf0c1d5Smjnelson 1782cdf0c1d5Smjnelson# 1783cdf0c1d5Smjnelson# flist_from_subversion 1784cdf0c1d5Smjnelson# 1785cdf0c1d5Smjnelson# Generate the file list by extracting file names from svn status. 1786cdf0c1d5Smjnelson# 1787cdf0c1d5Smjnelsonfunction flist_from_subversion 1788cdf0c1d5Smjnelson{ 1789cdf0c1d5Smjnelson CWS=$1 1790cdf0c1d5Smjnelson OLDPWD=$2 1791cdf0c1d5Smjnelson 1792cdf0c1d5Smjnelson cd $CWS 1793cdf0c1d5Smjnelson print -u2 " File list from: svn status ... \c" 1794cdf0c1d5Smjnelson svn status | $AWK '/^[ACDMR]/ { print $NF }' > $FLIST 1795cdf0c1d5Smjnelson print -u2 " Done." 1796cdf0c1d5Smjnelson cd $OLDPWD 1797cdf0c1d5Smjnelson} 1798cdf0c1d5Smjnelson 1799daaffb31Sdpfunction env_from_flist 1800daaffb31Sdp{ 1801daaffb31Sdp [[ -r $FLIST ]] || return 1802daaffb31Sdp 1803daaffb31Sdp # 1804daaffb31Sdp # Use "eval" to set env variables that are listed in the file 1805daaffb31Sdp # list. Then copy those into our local versions of those 1806daaffb31Sdp # variables if they have not been set already. 1807daaffb31Sdp # 1808b0088928SVladimir Kotal eval `$SED -e "s/#.*$//" $FLIST | $GREP = ` 18097c478bd9Sstevel@tonic-gate 1810cdf0c1d5Smjnelson if [[ -z $codemgr_ws && -n $CODEMGR_WS ]]; then 1811cdf0c1d5Smjnelson codemgr_ws=$CODEMGR_WS 1812cdf0c1d5Smjnelson export CODEMGR_WS 1813cdf0c1d5Smjnelson fi 18147c478bd9Sstevel@tonic-gate 1815daaffb31Sdp # 1816daaffb31Sdp # Check to see if CODEMGR_PARENT is set in the flist file. 1817daaffb31Sdp # 1818cdf0c1d5Smjnelson if [[ -z $codemgr_parent && -n $CODEMGR_PARENT ]]; then 1819daaffb31Sdp codemgr_parent=$CODEMGR_PARENT 1820cdf0c1d5Smjnelson export CODEMGR_PARENT 1821daaffb31Sdp fi 1822daaffb31Sdp} 1823daaffb31Sdp 182414983201Sdpfunction look_for_prog 182514983201Sdp{ 182614983201Sdp typeset path 182714983201Sdp typeset ppath 182814983201Sdp typeset progname=$1 182914983201Sdp 183014983201Sdp ppath=$PATH 183114983201Sdp ppath=$ppath:/usr/sfw/bin:/usr/bin:/usr/sbin 183214983201Sdp ppath=$ppath:/opt/teamware/bin:/opt/onbld/bin 1833cdf0c1d5Smjnelson ppath=$ppath:/opt/onbld/bin/`uname -p` 183414983201Sdp 183514983201Sdp PATH=$ppath prog=`whence $progname` 183614983201Sdp if [[ -n $prog ]]; then 183714983201Sdp print $prog 183814983201Sdp fi 183914983201Sdp} 184014983201Sdp 1841cdf0c1d5Smjnelsonfunction get_file_mode 1842cdf0c1d5Smjnelson{ 1843cdf0c1d5Smjnelson $PERL -e ' 1844cdf0c1d5Smjnelson if (@stat = stat($ARGV[0])) { 1845cdf0c1d5Smjnelson $mode = $stat[2] & 0777; 1846cdf0c1d5Smjnelson printf "%03o\n", $mode; 1847cdf0c1d5Smjnelson exit 0; 1848cdf0c1d5Smjnelson } else { 1849cdf0c1d5Smjnelson exit 1; 1850cdf0c1d5Smjnelson } 1851cdf0c1d5Smjnelson ' $1 1852cdf0c1d5Smjnelson} 1853cdf0c1d5Smjnelson 1854cdf0c1d5Smjnelsonfunction build_old_new_teamware 1855cdf0c1d5Smjnelson{ 1856cdf0c1d5Smjnelson typeset olddir="$1" 1857cdf0c1d5Smjnelson typeset newdir="$2" 1858cdf0c1d5Smjnelson 1859cdf0c1d5Smjnelson # If the child's version doesn't exist then 1860cdf0c1d5Smjnelson # get a readonly copy. 1861cdf0c1d5Smjnelson 1862cdf0c1d5Smjnelson if [[ ! -f $CWS/$DIR/$F && -f $CWS/$DIR/SCCS/s.$F ]]; then 1863cdf0c1d5Smjnelson $SCCS get -s -p $CWS/$DIR/$F > $CWS/$DIR/$F 1864cdf0c1d5Smjnelson fi 1865cdf0c1d5Smjnelson 1866cdf0c1d5Smjnelson # The following two sections propagate file permissions the 1867cdf0c1d5Smjnelson # same way SCCS does. If the file is already under version 1868cdf0c1d5Smjnelson # control, always use permissions from the SCCS/s.file. If 1869cdf0c1d5Smjnelson # the file is not under SCCS control, use permissions from the 1870cdf0c1d5Smjnelson # working copy. In all cases, the file copied to the webrev 1871cdf0c1d5Smjnelson # is set to read only, and group/other permissions are set to 1872cdf0c1d5Smjnelson # match those of the file owner. This way, even if the file 1873cdf0c1d5Smjnelson # is currently checked out, the webrev will display the final 1874cdf0c1d5Smjnelson # permissions that would result after check in. 1875cdf0c1d5Smjnelson 1876cdf0c1d5Smjnelson # 1877cdf0c1d5Smjnelson # Snag new version of file. 1878cdf0c1d5Smjnelson # 1879cdf0c1d5Smjnelson rm -f $newdir/$DIR/$F 1880cdf0c1d5Smjnelson cp $CWS/$DIR/$F $newdir/$DIR/$F 1881cdf0c1d5Smjnelson if [[ -f $CWS/$DIR/SCCS/s.$F ]]; then 1882cdf0c1d5Smjnelson chmod `get_file_mode $CWS/$DIR/SCCS/s.$F` \ 1883cdf0c1d5Smjnelson $newdir/$DIR/$F 1884cdf0c1d5Smjnelson fi 1885cdf0c1d5Smjnelson chmod u-w,go=u $newdir/$DIR/$F 1886cdf0c1d5Smjnelson 1887cdf0c1d5Smjnelson # 1888cdf0c1d5Smjnelson # Get the parent's version of the file. First see whether the 1889cdf0c1d5Smjnelson # child's version is checked out and get the parent's version 1890cdf0c1d5Smjnelson # with keywords expanded or unexpanded as appropriate. 1891cdf0c1d5Smjnelson # 1892cdf0c1d5Smjnelson if [[ -f $PWS/$PDIR/$PF && ! -f $PWS/$PDIR/SCCS/s.$PF && \ 1893cdf0c1d5Smjnelson ! -f $PWS/$PDIR/SCCS/p.$PF ]]; then 1894cdf0c1d5Smjnelson # Parent is not a real workspace, but just a raw 1895cdf0c1d5Smjnelson # directory tree - use the file that's there as 1896cdf0c1d5Smjnelson # the old file. 1897cdf0c1d5Smjnelson 1898cdf0c1d5Smjnelson rm -f $olddir/$PDIR/$PF 1899cdf0c1d5Smjnelson cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF 1900cdf0c1d5Smjnelson else 1901cdf0c1d5Smjnelson if [[ -f $PWS/$PDIR/SCCS/s.$PF ]]; then 1902cdf0c1d5Smjnelson real_parent=$PWS 1903cdf0c1d5Smjnelson else 1904cdf0c1d5Smjnelson real_parent=$RWS 1905cdf0c1d5Smjnelson fi 1906cdf0c1d5Smjnelson 1907cdf0c1d5Smjnelson rm -f $olddir/$PDIR/$PF 1908cdf0c1d5Smjnelson 1909cdf0c1d5Smjnelson if [[ -f $real_parent/$PDIR/$PF ]]; then 1910cdf0c1d5Smjnelson if [ -f $CWS/$DIR/SCCS/p.$F ]; then 1911cdf0c1d5Smjnelson $SCCS get -s -p -k $real_parent/$PDIR/$PF > \ 1912cdf0c1d5Smjnelson $olddir/$PDIR/$PF 1913cdf0c1d5Smjnelson else 1914cdf0c1d5Smjnelson $SCCS get -s -p $real_parent/$PDIR/$PF > \ 1915cdf0c1d5Smjnelson $olddir/$PDIR/$PF 1916cdf0c1d5Smjnelson fi 1917cdf0c1d5Smjnelson chmod `get_file_mode $real_parent/$PDIR/SCCS/s.$PF` \ 1918cdf0c1d5Smjnelson $olddir/$PDIR/$PF 1919cdf0c1d5Smjnelson fi 1920cdf0c1d5Smjnelson fi 1921cdf0c1d5Smjnelson if [[ -f $olddir/$PDIR/$PF ]]; then 1922cdf0c1d5Smjnelson chmod u-w,go=u $olddir/$PDIR/$PF 1923cdf0c1d5Smjnelson fi 1924cdf0c1d5Smjnelson} 1925cdf0c1d5Smjnelson 1926cdf0c1d5Smjnelsonfunction build_old_new_mercurial 1927cdf0c1d5Smjnelson{ 1928cdf0c1d5Smjnelson typeset olddir="$1" 1929cdf0c1d5Smjnelson typeset newdir="$2" 1930cdf0c1d5Smjnelson typeset old_mode= 1931cdf0c1d5Smjnelson typeset new_mode= 1932cdf0c1d5Smjnelson typeset file 1933cdf0c1d5Smjnelson 1934cdf0c1d5Smjnelson # 1935cdf0c1d5Smjnelson # Get old file mode, from the parent revision manifest entry. 1936cdf0c1d5Smjnelson # Mercurial only stores a "file is executable" flag, but the 1937cdf0c1d5Smjnelson # manifest will display an octal mode "644" or "755". 1938cdf0c1d5Smjnelson # 1939cdf0c1d5Smjnelson if [[ "$PDIR" == "." ]]; then 1940cdf0c1d5Smjnelson file="$PF" 1941cdf0c1d5Smjnelson else 1942cdf0c1d5Smjnelson file="$PDIR/$PF" 1943cdf0c1d5Smjnelson fi 1944b0088928SVladimir Kotal file=`echo $file | $SED 's#/#\\\/#g'` 1945cdf0c1d5Smjnelson # match the exact filename, and return only the permission digits 1946b0088928SVladimir Kotal old_mode=`$SED -n -e "/^\\(...\\) . ${file}$/s//\\1/p" \ 1947cdf0c1d5Smjnelson < $HG_PARENT_MANIFEST` 1948cdf0c1d5Smjnelson 1949cdf0c1d5Smjnelson # 1950cdf0c1d5Smjnelson # Get new file mode, directly from the filesystem. 1951cdf0c1d5Smjnelson # Normalize the mode to match Mercurial's behavior. 1952cdf0c1d5Smjnelson # 1953cdf0c1d5Smjnelson new_mode=`get_file_mode $CWS/$DIR/$F` 1954cdf0c1d5Smjnelson if [[ -n "$new_mode" ]]; then 1955cdf0c1d5Smjnelson if [[ "$new_mode" = *[1357]* ]]; then 1956cdf0c1d5Smjnelson new_mode=755 1957cdf0c1d5Smjnelson else 1958cdf0c1d5Smjnelson new_mode=644 1959cdf0c1d5Smjnelson fi 1960cdf0c1d5Smjnelson fi 1961cdf0c1d5Smjnelson 1962cdf0c1d5Smjnelson # 1963cdf0c1d5Smjnelson # new version of the file. 1964cdf0c1d5Smjnelson # 1965cdf0c1d5Smjnelson rm -rf $newdir/$DIR/$F 1966cdf0c1d5Smjnelson if [[ -e $CWS/$DIR/$F ]]; then 1967cdf0c1d5Smjnelson cp $CWS/$DIR/$F $newdir/$DIR/$F 1968cdf0c1d5Smjnelson if [[ -n $new_mode ]]; then 1969cdf0c1d5Smjnelson chmod $new_mode $newdir/$DIR/$F 1970cdf0c1d5Smjnelson else 1971cdf0c1d5Smjnelson # should never happen 1972cdf0c1d5Smjnelson print -u2 "ERROR: set mode of $newdir/$DIR/$F" 1973cdf0c1d5Smjnelson fi 1974cdf0c1d5Smjnelson fi 1975cdf0c1d5Smjnelson 1976cdf0c1d5Smjnelson # 1977cdf0c1d5Smjnelson # parent's version of the file 1978cdf0c1d5Smjnelson # 1979cdf0c1d5Smjnelson # Note that we get this from the last version common to both 1980cdf0c1d5Smjnelson # ourselves and the parent. References are via $CWS since we have no 1981cdf0c1d5Smjnelson # guarantee that the parent workspace is reachable via the filesystem. 1982cdf0c1d5Smjnelson # 1983cdf0c1d5Smjnelson if [[ -n $parent_webrev && -e $PWS/$PDIR/$PF ]]; then 1984cdf0c1d5Smjnelson cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF 1985cdf0c1d5Smjnelson elif [[ -n $HG_PARENT ]]; then 1986cdf0c1d5Smjnelson hg cat -R $CWS -r $HG_PARENT $CWS/$PDIR/$PF > \ 1987cdf0c1d5Smjnelson $olddir/$PDIR/$PF 2>/dev/null 1988cdf0c1d5Smjnelson 198902d26c39SVladimir Kotal if (( $? != 0 )); then 1990cdf0c1d5Smjnelson rm -f $olddir/$PDIR/$PF 1991cdf0c1d5Smjnelson else 1992cdf0c1d5Smjnelson if [[ -n $old_mode ]]; then 1993cdf0c1d5Smjnelson chmod $old_mode $olddir/$PDIR/$PF 1994cdf0c1d5Smjnelson else 1995cdf0c1d5Smjnelson # should never happen 1996cdf0c1d5Smjnelson print -u2 "ERROR: set mode of $olddir/$PDIR/$PF" 1997cdf0c1d5Smjnelson fi 1998cdf0c1d5Smjnelson fi 1999cdf0c1d5Smjnelson fi 2000cdf0c1d5Smjnelson} 2001cdf0c1d5Smjnelson 2002cdf0c1d5Smjnelsonfunction build_old_new_subversion 2003cdf0c1d5Smjnelson{ 2004cdf0c1d5Smjnelson typeset olddir="$1" 2005cdf0c1d5Smjnelson typeset newdir="$2" 2006cdf0c1d5Smjnelson 2007cdf0c1d5Smjnelson # Snag new version of file. 2008cdf0c1d5Smjnelson rm -f $newdir/$DIR/$F 2009cdf0c1d5Smjnelson [[ -e $CWS/$DIR/$F ]] && cp $CWS/$DIR/$F $newdir/$DIR/$F 2010cdf0c1d5Smjnelson 2011cdf0c1d5Smjnelson if [[ -n $PWS && -e $PWS/$PDIR/$PF ]]; then 2012cdf0c1d5Smjnelson cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF 2013cdf0c1d5Smjnelson else 2014cdf0c1d5Smjnelson # Get the parent's version of the file. 2015cdf0c1d5Smjnelson svn status $CWS/$DIR/$F | read stat file 2016cdf0c1d5Smjnelson if [[ $stat != "A" ]]; then 2017cdf0c1d5Smjnelson svn cat -r BASE $CWS/$DIR/$F > $olddir/$PDIR/$PF 2018cdf0c1d5Smjnelson fi 2019cdf0c1d5Smjnelson fi 2020cdf0c1d5Smjnelson} 2021cdf0c1d5Smjnelson 2022cdf0c1d5Smjnelsonfunction build_old_new_unknown 2023cdf0c1d5Smjnelson{ 2024cdf0c1d5Smjnelson typeset olddir="$1" 2025cdf0c1d5Smjnelson typeset newdir="$2" 2026cdf0c1d5Smjnelson 2027cdf0c1d5Smjnelson # 2028cdf0c1d5Smjnelson # Snag new version of file. 2029cdf0c1d5Smjnelson # 2030cdf0c1d5Smjnelson rm -f $newdir/$DIR/$F 2031cdf0c1d5Smjnelson [[ -e $CWS/$DIR/$F ]] && cp $CWS/$DIR/$F $newdir/$DIR/$F 2032cdf0c1d5Smjnelson 2033cdf0c1d5Smjnelson # 2034cdf0c1d5Smjnelson # Snag the parent's version of the file. 2035cdf0c1d5Smjnelson # 2036cdf0c1d5Smjnelson if [[ -f $PWS/$PDIR/$PF ]]; then 2037cdf0c1d5Smjnelson rm -f $olddir/$PDIR/$PF 2038cdf0c1d5Smjnelson cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF 2039cdf0c1d5Smjnelson fi 2040cdf0c1d5Smjnelson} 2041cdf0c1d5Smjnelson 2042cdf0c1d5Smjnelsonfunction build_old_new 2043cdf0c1d5Smjnelson{ 2044cdf0c1d5Smjnelson typeset WDIR=$1 2045cdf0c1d5Smjnelson typeset PWS=$2 2046cdf0c1d5Smjnelson typeset PDIR=$3 2047cdf0c1d5Smjnelson typeset PF=$4 2048cdf0c1d5Smjnelson typeset CWS=$5 2049cdf0c1d5Smjnelson typeset DIR=$6 2050cdf0c1d5Smjnelson typeset F=$7 2051cdf0c1d5Smjnelson 2052cdf0c1d5Smjnelson typeset olddir="$WDIR/raw_files/old" 2053cdf0c1d5Smjnelson typeset newdir="$WDIR/raw_files/new" 2054cdf0c1d5Smjnelson 2055cdf0c1d5Smjnelson mkdir -p $olddir/$PDIR 2056cdf0c1d5Smjnelson mkdir -p $newdir/$DIR 2057cdf0c1d5Smjnelson 2058cdf0c1d5Smjnelson if [[ $SCM_MODE == "teamware" ]]; then 2059cdf0c1d5Smjnelson build_old_new_teamware "$olddir" "$newdir" 2060cdf0c1d5Smjnelson elif [[ $SCM_MODE == "mercurial" ]]; then 2061cdf0c1d5Smjnelson build_old_new_mercurial "$olddir" "$newdir" 2062cdf0c1d5Smjnelson elif [[ $SCM_MODE == "subversion" ]]; then 2063cdf0c1d5Smjnelson build_old_new_subversion "$olddir" "$newdir" 2064cdf0c1d5Smjnelson elif [[ $SCM_MODE == "unknown" ]]; then 2065cdf0c1d5Smjnelson build_old_new_unknown "$olddir" "$newdir" 2066cdf0c1d5Smjnelson fi 2067cdf0c1d5Smjnelson 2068cdf0c1d5Smjnelson if [[ ! -f $olddir/$PDIR/$PF && ! -f $newdir/$DIR/$F ]]; then 2069cdf0c1d5Smjnelson print "*** Error: file not in parent or child" 2070cdf0c1d5Smjnelson return 1 2071cdf0c1d5Smjnelson fi 2072cdf0c1d5Smjnelson return 0 2073cdf0c1d5Smjnelson} 2074cdf0c1d5Smjnelson 2075cdf0c1d5Smjnelson 2076daaffb31Sdp# 2077daaffb31Sdp# Usage message. 2078daaffb31Sdp# 2079daaffb31Sdpfunction usage 2080daaffb31Sdp{ 2081daaffb31Sdp print 'Usage:\twebrev [common-options] 2082daaffb31Sdp webrev [common-options] ( <file> | - ) 2083daaffb31Sdp webrev [common-options] -w <wx file> 2084daaffb31Sdp 2085daaffb31SdpOptions: 20860fd2682eSMark J. Nelson -C <filename>: Use <filename> for the information tracking configuration. 2087ba44d8a2SVladimir Kotal -D: delete remote webrev 2088daaffb31Sdp -i <filename>: Include <filename> in the index.html file. 20890fd2682eSMark J. Nelson -I <filename>: Use <filename> for the information tracking registry. 2090ba44d8a2SVladimir Kotal -n: do not generate the webrev (useful with -U) 2091ba44d8a2SVladimir Kotal -O: Print bugids/arc cases suitable for OpenSolaris. 2092daaffb31Sdp -o <outdir>: Output webrev to specified directory. 2093daaffb31Sdp -p <compare-against>: Use specified parent wkspc or basis for comparison 209402d26c39SVladimir Kotal -t <remote_target>: Specify remote destination for webrev upload 209502d26c39SVladimir Kotal -U: upload the webrev to remote destination 2096daaffb31Sdp -w <wxfile>: Use specified wx active file. 2097daaffb31Sdp 2098daaffb31SdpEnvironment: 2099daaffb31Sdp WDIR: Control the output directory. 2100ba44d8a2SVladimir Kotal WEBREV_TRASH_DIR: Set directory for webrev delete. 2101daaffb31Sdp 2102cdf0c1d5SmjnelsonSCM Specific Options: 2103cdf0c1d5Smjnelson TeamWare: webrev [common-options] -l [arguments to 'putback'] 2104cdf0c1d5Smjnelson 2105daaffb31SdpSCM Environment: 2106cdf0c1d5Smjnelson CODEMGR_WS: Workspace location. 2107cdf0c1d5Smjnelson CODEMGR_PARENT: Parent workspace location. 2108daaffb31Sdp' 2109daaffb31Sdp 2110daaffb31Sdp exit 2 2111daaffb31Sdp} 2112daaffb31Sdp 2113daaffb31Sdp# 2114daaffb31Sdp# 2115daaffb31Sdp# Main program starts here 2116daaffb31Sdp# 2117daaffb31Sdp# 2118daaffb31Sdp 2119daaffb31Sdptrap "rm -f /tmp/$$.* ; exit" 0 1 2 3 15 2120daaffb31Sdp 2121daaffb31Sdpset +o noclobber 2122daaffb31Sdp 2123cdf0c1d5SmjnelsonPATH=$(dirname $(whence $0)):$PATH 2124cdf0c1d5Smjnelson 212514983201Sdp[[ -z $WDIFF ]] && WDIFF=`look_for_prog wdiff` 212614983201Sdp[[ -z $WX ]] && WX=`look_for_prog wx` 2127cdf0c1d5Smjnelson[[ -z $HG_ACTIVE ]] && HG_ACTIVE=`look_for_prog hg-active` 2128cdf0c1d5Smjnelson[[ -z $WHICH_SCM ]] && WHICH_SCM=`look_for_prog which_scm` 212914983201Sdp[[ -z $CODEREVIEW ]] && CODEREVIEW=`look_for_prog codereview` 213014983201Sdp[[ -z $PS2PDF ]] && PS2PDF=`look_for_prog ps2pdf` 213114983201Sdp[[ -z $PERL ]] && PERL=`look_for_prog perl` 213202d26c39SVladimir Kotal[[ -z $RSYNC ]] && RSYNC=`look_for_prog rsync` 2133cdf0c1d5Smjnelson[[ -z $SCCS ]] && SCCS=`look_for_prog sccs` 2134cdf0c1d5Smjnelson[[ -z $AWK ]] && AWK=`look_for_prog nawk` 2135cdf0c1d5Smjnelson[[ -z $AWK ]] && AWK=`look_for_prog gawk` 2136cdf0c1d5Smjnelson[[ -z $AWK ]] && AWK=`look_for_prog awk` 213702d26c39SVladimir Kotal[[ -z $SCP ]] && SCP=`look_for_prog scp` 2138b0088928SVladimir Kotal[[ -z $SED ]] && SED=`look_for_prog sed` 213902d26c39SVladimir Kotal[[ -z $SFTP ]] && SFTP=`look_for_prog sftp` 2140e6ccc173SEdward Pilatowicz[[ -z $SORT ]] && SORT=`look_for_prog sort` 214102d26c39SVladimir Kotal[[ -z $MKTEMP ]] && MKTEMP=`look_for_prog mktemp` 214202d26c39SVladimir Kotal[[ -z $GREP ]] && GREP=`look_for_prog grep` 2143ba44d8a2SVladimir Kotal[[ -z $FIND ]] && FIND=`look_for_prog find` 2144cdf0c1d5Smjnelson 2145ba44d8a2SVladimir Kotal# set name of trash directory for remote webrev deletion 2146ba44d8a2SVladimir KotalTRASH_DIR=".trash" 2147ba44d8a2SVladimir Kotal[[ -n $WEBREV_TRASH_DIR ]] && TRASH_DIR=$WEBREV_TRASH_DIR 214814983201Sdp 214914983201Sdpif [[ ! -x $PERL ]]; then 215014983201Sdp print -u2 "Error: No perl interpreter found. Exiting." 215114983201Sdp exit 1 2152daaffb31Sdpfi 215314983201Sdp 2154cdf0c1d5Smjnelsonif [[ ! -x $WHICH_SCM ]]; then 2155cdf0c1d5Smjnelson print -u2 "Error: Could not find which_scm. Exiting." 2156cdf0c1d5Smjnelson exit 1 2157cdf0c1d5Smjnelsonfi 2158cdf0c1d5Smjnelson 215914983201Sdp# 216014983201Sdp# These aren't fatal, but we want to note them to the user. 216114983201Sdp# We don't warn on the absence of 'wx' until later when we've 216214983201Sdp# determined that we actually need to try to invoke it. 216314983201Sdp# 216414983201Sdp[[ ! -x $CODEREVIEW ]] && print -u2 "WARNING: codereview(1) not found." 216514983201Sdp[[ ! -x $PS2PDF ]] && print -u2 "WARNING: ps2pdf(1) not found." 216614983201Sdp[[ ! -x $WDIFF ]] && print -u2 "WARNING: wdiff not found." 2167daaffb31Sdp 2168daaffb31Sdp# Declare global total counters. 2169daaffb31Sdpinteger TOTL TINS TDEL TMOD TUNC 2170daaffb31Sdp 2171ba44d8a2SVladimir Kotal# default remote host for upload/delete 2172ba44d8a2SVladimir Kotaltypeset -r DEFAULT_REMOTE_HOST="cr.opensolaris.org" 2173b0088928SVladimir Kotal# prefixes for upload targets 2174b0088928SVladimir Kotaltypeset -r rsync_prefix="rsync://" 2175b0088928SVladimir Kotaltypeset -r ssh_prefix="ssh://" 2176ba44d8a2SVladimir Kotal 21770fd2682eSMark J. NelsonCflag= 2178ba44d8a2SVladimir KotalDflag= 217914983201Sdpflist_mode= 218014983201Sdpflist_file= 2181daaffb31Sdpiflag= 21820fd2682eSMark J. NelsonIflag= 218302d26c39SVladimir Kotallflag= 218402d26c39SVladimir KotalNflag= 218502d26c39SVladimir Kotalnflag= 218602d26c39SVladimir KotalOflag= 2187daaffb31Sdpoflag= 2188daaffb31Sdppflag= 218902d26c39SVladimir Kotaltflag= 219002d26c39SVladimir Kotaluflag= 219102d26c39SVladimir KotalUflag= 2192daaffb31Sdpwflag= 219302d26c39SVladimir Kotalremote_target= 2194ba44d8a2SVladimir Kotal 2195ba44d8a2SVladimir Kotal# 2196ba44d8a2SVladimir Kotal# NOTE: when adding/removing options it is necessary to sync the list 2197ba44d8a2SVladimir Kotal# with usr/src/tools/onbld/hgext/cdm.py 2198ba44d8a2SVladimir Kotal# 219925cc4e45SVladimir Kotalwhile getopts "C:Di:I:lnNo:Op:t:Uw" opt 2200daaffb31Sdpdo 2201daaffb31Sdp case $opt in 22020fd2682eSMark J. Nelson C) Cflag=1 22030fd2682eSMark J. Nelson ITSCONF=$OPTARG;; 22040fd2682eSMark J. Nelson 2205ba44d8a2SVladimir Kotal D) Dflag=1;; 2206ba44d8a2SVladimir Kotal 2207daaffb31Sdp i) iflag=1 2208daaffb31Sdp INCLUDE_FILE=$OPTARG;; 2209daaffb31Sdp 22100fd2682eSMark J. Nelson I) Iflag=1 22110fd2682eSMark J. Nelson ITSREG=$OPTARG;; 22120fd2682eSMark J. Nelson 2213daaffb31Sdp # 2214daaffb31Sdp # If -l has been specified, we need to abort further options 2215daaffb31Sdp # processing, because subsequent arguments are going to be 2216daaffb31Sdp # arguments to 'putback -n'. 2217daaffb31Sdp # 2218daaffb31Sdp l) lflag=1 2219daaffb31Sdp break;; 2220daaffb31Sdp 222102d26c39SVladimir Kotal N) Nflag=1;; 222202d26c39SVladimir Kotal 222302d26c39SVladimir Kotal n) nflag=1;; 2224daaffb31Sdp 2225daaffb31Sdp O) Oflag=1;; 2226daaffb31Sdp 222702d26c39SVladimir Kotal o) oflag=1 22289d3952abSVladimir Kotal # Strip the trailing slash to correctly form remote target. 22299d3952abSVladimir 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# 22642d9224a3SMark J. Nelson# For the invocation "webrev -n -U" with no other options, webrev will assume 22652d9224a3SMark J. Nelson# that the webrev exists in ${CWS}/webrev, but will upload it using the name 22662d9224a3SMark J. Nelson# $(basename ${CWS}). So we need to get CWS set before we skip any remaining 22672d9224a3SMark J. Nelson# logic. 22682d9224a3SMark J. Nelson# 22692d9224a3SMark J. Nelson$WHICH_SCM | read SCM_MODE junk || exit 1 22702d9224a3SMark J. Nelsonif [[ $SCM_MODE == "teamware" ]]; then 22712d9224a3SMark J. Nelson # 22722d9224a3SMark J. Nelson # Teamware priorities: 22732d9224a3SMark J. Nelson # 1. CODEMGR_WS from the environment 22742d9224a3SMark J. Nelson # 2. workspace name 22752d9224a3SMark J. Nelson # 22762d9224a3SMark J. Nelson [[ -z $codemgr_ws && -n $CODEMGR_WS ]] && codemgr_ws=$CODEMGR_WS 22772d9224a3SMark J. Nelson if [[ -n $codemgr_ws && ! -d $codemgr_ws ]]; then 22782d9224a3SMark J. Nelson print -u2 "$codemgr_ws: no such workspace" 22792d9224a3SMark J. Nelson exit 1 22802d9224a3SMark J. Nelson fi 22812d9224a3SMark J. Nelson [[ -z $codemgr_ws ]] && codemgr_ws=$(workspace name) 22822d9224a3SMark J. Nelson codemgr_ws=$(cd $codemgr_ws;print $PWD) 22832d9224a3SMark J. Nelson CODEMGR_WS=$codemgr_ws 22842d9224a3SMark J. Nelson CWS=$codemgr_ws 22852d9224a3SMark J. Nelsonelif [[ $SCM_MODE == "mercurial" ]]; then 22862d9224a3SMark J. Nelson # 22872d9224a3SMark J. Nelson # Mercurial priorities: 22882d9224a3SMark J. Nelson # 1. hg root from CODEMGR_WS environment variable 228978add226Sjmcp # 1a. hg root from CODEMGR_WS/usr/closed if we're somewhere under 229078add226Sjmcp # usr/closed when we run webrev 22912d9224a3SMark J. Nelson # 2. hg root from directory of invocation 22922d9224a3SMark J. Nelson # 229378add226Sjmcp if [[ ${PWD} =~ "usr/closed" ]]; then 229478add226Sjmcp testparent=${CODEMGR_WS}/usr/closed 229578add226Sjmcp # If we're in OpenSolaris mode, we enforce a minor policy: 229678add226Sjmcp # help to make sure the reviewer doesn't accidentally publish 229778add226Sjmcp # source which is under usr/closed 229878add226Sjmcp if [[ -n "$Oflag" ]]; then 229978add226Sjmcp print -u2 "OpenSolaris output not permitted with" \ 230078add226Sjmcp "usr/closed changes" 230178add226Sjmcp exit 1 230278add226Sjmcp fi 230378add226Sjmcp else 230478add226Sjmcp testparent=${CODEMGR_WS} 230578add226Sjmcp fi 230678add226Sjmcp [[ -z $codemgr_ws && -n $testparent ]] && \ 230778add226Sjmcp codemgr_ws=$(hg root -R $testparent 2>/dev/null) 23082d9224a3SMark J. Nelson [[ -z $codemgr_ws ]] && codemgr_ws=$(hg root 2>/dev/null) 23092d9224a3SMark J. Nelson CWS=$codemgr_ws 23102d9224a3SMark J. Nelsonelif [[ $SCM_MODE == "subversion" ]]; then 23112d9224a3SMark J. Nelson # 23122d9224a3SMark J. Nelson # Subversion priorities: 23132d9224a3SMark J. Nelson # 1. CODEMGR_WS from environment 23142d9224a3SMark J. Nelson # 2. Relative path from current directory to SVN repository root 23152d9224a3SMark J. Nelson # 23162d9224a3SMark J. Nelson if [[ -n $CODEMGR_WS && -d $CODEMGR_WS/.svn ]]; then 23172d9224a3SMark J. Nelson CWS=$CODEMGR_WS 23182d9224a3SMark J. Nelson else 23192d9224a3SMark J. Nelson svn info | while read line; do 23202d9224a3SMark J. Nelson if [[ $line == "URL: "* ]]; then 23212d9224a3SMark J. Nelson url=${line#URL: } 23222d9224a3SMark J. Nelson elif [[ $line == "Repository Root: "* ]]; then 23232d9224a3SMark J. Nelson repo=${line#Repository Root: } 23242d9224a3SMark J. Nelson fi 23252d9224a3SMark J. Nelson done 23262d9224a3SMark J. Nelson 23272d9224a3SMark J. Nelson rel=${url#$repo} 23282d9224a3SMark J. Nelson CWS=${PWD%$rel} 23292d9224a3SMark J. Nelson fi 23302d9224a3SMark J. Nelsonfi 23312d9224a3SMark J. Nelson 23322d9224a3SMark J. Nelson# 23332d9224a3SMark J. Nelson# If no SCM has been determined, take either the environment setting 23342d9224a3SMark J. Nelson# setting for CODEMGR_WS, or the current directory if that wasn't set. 23352d9224a3SMark J. Nelson# 23362d9224a3SMark J. Nelsonif [[ -z ${CWS} ]]; then 23372d9224a3SMark J. Nelson CWS=${CODEMGR_WS:-.} 23382d9224a3SMark J. Nelsonfi 23392d9224a3SMark J. Nelson 23402d9224a3SMark J. Nelson# 23410fd2682eSMark J. Nelson# If the command line options indicate no webrev generation, either 23420fd2682eSMark J. Nelson# explicitly (-n) or implicitly (-D but not -U), then there's a whole 23430fd2682eSMark J. Nelson# ton of logic we can skip. 23440fd2682eSMark J. Nelson# 23450fd2682eSMark J. Nelson# Instead of increasing indentation, we intentionally leave this loop 23460fd2682eSMark J. Nelson# body open here, and exit via break from multiple points within. 23470fd2682eSMark J. Nelson# Search for DO_EVERYTHING below to find the break points and closure. 23480fd2682eSMark J. Nelson# 23490fd2682eSMark J. Nelsonfor do_everything in 1; do 23500fd2682eSMark J. Nelson 23510fd2682eSMark J. Nelson# DO_EVERYTHING: break point 23520fd2682eSMark J. Nelsonif [[ -n $nflag || ( -z $Uflag && -n $Dflag ) ]]; then 23530fd2682eSMark J. Nelson break 23540fd2682eSMark J. Nelsonfi 23550fd2682eSMark J. Nelson 23560fd2682eSMark J. Nelson# 2357daaffb31Sdp# If this manually set as the parent, and it appears to be an earlier webrev, 2358daaffb31Sdp# then note that fact and set the parent to the raw_files/new subdirectory. 2359daaffb31Sdp# 2360daaffb31Sdpif [[ -n $pflag && -d $codemgr_parent/raw_files/new ]]; then 2361daaffb31Sdp parent_webrev="$codemgr_parent" 2362daaffb31Sdp codemgr_parent="$codemgr_parent/raw_files/new" 2363daaffb31Sdpfi 2364daaffb31Sdp 2365daaffb31Sdpif [[ -z $wflag && -z $lflag ]]; then 2366daaffb31Sdp shift $(($OPTIND - 1)) 2367daaffb31Sdp 2368daaffb31Sdp if [[ $1 == "-" ]]; then 2369daaffb31Sdp cat > $FLIST 237014983201Sdp flist_mode="stdin" 237114983201Sdp flist_done=1 237214983201Sdp shift 2373daaffb31Sdp elif [[ -n $1 ]]; then 237414983201Sdp if [[ ! -r $1 ]]; then 2375daaffb31Sdp print -u2 "$1: no such file or not readable" 2376daaffb31Sdp usage 2377daaffb31Sdp fi 2378daaffb31Sdp cat $1 > $FLIST 237914983201Sdp flist_mode="file" 238014983201Sdp flist_file=$1 238114983201Sdp flist_done=1 238214983201Sdp shift 2383daaffb31Sdp else 238414983201Sdp flist_mode="auto" 2385daaffb31Sdp fi 2386daaffb31Sdpfi 2387daaffb31Sdp 2388daaffb31Sdp# 2389daaffb31Sdp# Before we go on to further consider -l and -w, work out which SCM we think 2390daaffb31Sdp# is in use. 2391daaffb31Sdp# 2392cdf0c1d5Smjnelsoncase "$SCM_MODE" in 2393cdf0c1d5Smjnelsonteamware|mercurial|subversion) 2394cdf0c1d5Smjnelson ;; 2395cdf0c1d5Smjnelsonunknown) 2396cdf0c1d5Smjnelson if [[ $flist_mode == "auto" ]]; then 2397cdf0c1d5Smjnelson print -u2 "Unable to determine SCM in use and file list not specified" 2398cdf0c1d5Smjnelson print -u2 "See which_scm(1) for SCM detection information." 23997c478bd9Sstevel@tonic-gate exit 1 24007c478bd9Sstevel@tonic-gate fi 2401cdf0c1d5Smjnelson ;; 2402cdf0c1d5Smjnelson*) 2403cdf0c1d5Smjnelson if [[ $flist_mode == "auto" ]]; then 2404cdf0c1d5Smjnelson print -u2 "Unsupported SCM in use ($SCM_MODE) and file list not specified" 2405cdf0c1d5Smjnelson exit 1 2406cdf0c1d5Smjnelson fi 2407cdf0c1d5Smjnelson ;; 2408cdf0c1d5Smjnelsonesac 24097c478bd9Sstevel@tonic-gate 2410daaffb31Sdpprint -u2 " SCM detected: $SCM_MODE" 2411daaffb31Sdp 2412daaffb31Sdpif [[ -n $lflag ]]; then 2413daaffb31Sdp # 2414daaffb31Sdp # If the -l flag is given instead of the name of a file list, 2415daaffb31Sdp # then generate the file list by extracting file names from a 2416daaffb31Sdp # putback -n. 2417daaffb31Sdp # 2418daaffb31Sdp shift $(($OPTIND - 1)) 2419cdf0c1d5Smjnelson if [[ $SCM_MODE == "teamware" ]]; then 2420daaffb31Sdp flist_from_teamware "$*" 2421cdf0c1d5Smjnelson else 2422cdf0c1d5Smjnelson print -u2 -- "Error: -l option only applies to TeamWare" 2423cdf0c1d5Smjnelson exit 1 2424cdf0c1d5Smjnelson fi 2425daaffb31Sdp flist_done=1 2426daaffb31Sdp shift $# 2427daaffb31Sdpelif [[ -n $wflag ]]; then 2428daaffb31Sdp # 2429daaffb31Sdp # If the -w is given then assume the file list is in Bonwick's "wx" 2430daaffb31Sdp # command format, i.e. pathname lines alternating with SCCS comment 2431daaffb31Sdp # lines with blank lines as separators. Use the SCCS comments later 2432daaffb31Sdp # in building the index.html file. 2433daaffb31Sdp # 2434daaffb31Sdp shift $(($OPTIND - 1)) 2435daaffb31Sdp wxfile=$1 2436daaffb31Sdp if [[ -z $wxfile && -n $CODEMGR_WS ]]; then 2437daaffb31Sdp if [[ -r $CODEMGR_WS/wx/active ]]; then 2438daaffb31Sdp wxfile=$CODEMGR_WS/wx/active 2439daaffb31Sdp fi 2440daaffb31Sdp fi 2441daaffb31Sdp 2442daaffb31Sdp [[ -z $wxfile ]] && print -u2 "wx file not specified, and could not " \ 2443daaffb31Sdp "be auto-detected (check \$CODEMGR_WS)" && exit 1 2444daaffb31Sdp 2445cdf0c1d5Smjnelson if [[ ! -r $wxfile ]]; then 2446cdf0c1d5Smjnelson print -u2 "$wxfile: no such file or not readable" 2447cdf0c1d5Smjnelson usage 2448cdf0c1d5Smjnelson fi 2449cdf0c1d5Smjnelson 2450daaffb31Sdp print -u2 " File list from: wx 'active' file '$wxfile' ... \c" 2451daaffb31Sdp flist_from_wx $wxfile 2452daaffb31Sdp flist_done=1 2453daaffb31Sdp if [[ -n "$*" ]]; then 2454daaffb31Sdp shift 2455daaffb31Sdp fi 245614983201Sdpelif [[ $flist_mode == "stdin" ]]; then 245714983201Sdp print -u2 " File list from: standard input" 245814983201Sdpelif [[ $flist_mode == "file" ]]; then 245914983201Sdp print -u2 " File list from: $flist_file" 2460daaffb31Sdpfi 2461daaffb31Sdp 2462daaffb31Sdpif [[ $# -gt 0 ]]; then 246314983201Sdp print -u2 "WARNING: unused arguments: $*" 2464daaffb31Sdpfi 2465daaffb31Sdp 24662d9224a3SMark J. Nelson# 24672d9224a3SMark J. Nelson# Before we entered the DO_EVERYTHING loop, we should have already set CWS 24682d9224a3SMark J. Nelson# and CODEMGR_WS as needed. Here, we set the parent workspace. 24692d9224a3SMark J. Nelson# 24702d9224a3SMark J. Nelson 2471daaffb31Sdpif [[ $SCM_MODE == "teamware" ]]; then 24722d9224a3SMark J. Nelson 2473daaffb31Sdp # 24742d9224a3SMark J. Nelson # Teamware priorities: 2475daaffb31Sdp # 24762d9224a3SMark J. Nelson # 1) via -p command line option 2477daaffb31Sdp # 2) in the user environment 2478daaffb31Sdp # 3) in the flist 24792d9224a3SMark J. Nelson # 4) automatically based on the workspace 2480daaffb31Sdp # 2481daaffb31Sdp 2482daaffb31Sdp # 24832d9224a3SMark J. Nelson # For 1, codemgr_parent will already be set. Here's 2: 2484daaffb31Sdp # 2485daaffb31Sdp [[ -z $codemgr_parent && -n $CODEMGR_PARENT ]] && \ 2486daaffb31Sdp codemgr_parent=$CODEMGR_PARENT 2487daaffb31Sdp if [[ -n $codemgr_parent && ! -d $codemgr_parent ]]; then 2488daaffb31Sdp print -u2 "$codemgr_parent: no such directory" 24897c478bd9Sstevel@tonic-gate exit 1 24907c478bd9Sstevel@tonic-gate fi 24917c478bd9Sstevel@tonic-gate 2492daaffb31Sdp # 2493daaffb31Sdp # If we're in auto-detect mode and we haven't already gotten the file 2494daaffb31Sdp # list, then see if we can get it by probing for wx. 2495daaffb31Sdp # 249614983201Sdp if [[ -z $flist_done && $flist_mode == "auto" && -n $codemgr_ws ]]; then 249714983201Sdp if [[ ! -x $WX ]]; then 249814983201Sdp print -u2 "WARNING: wx not found!" 2499daaffb31Sdp fi 25007c478bd9Sstevel@tonic-gate 2501daaffb31Sdp # 2502daaffb31Sdp # We need to use wx list -w so that we get renamed files, etc. 2503daaffb31Sdp # but only if a wx active file exists-- otherwise wx will 2504daaffb31Sdp # hang asking us to initialize our wx information. 2505daaffb31Sdp # 250614983201Sdp if [[ -x $WX && -f $codemgr_ws/wx/active ]]; then 2507daaffb31Sdp print -u2 " File list from: 'wx list -w' ... \c" 2508daaffb31Sdp $WX list -w > $FLIST 2509daaffb31Sdp $WX comments > /tmp/$$.wx_comments 2510daaffb31Sdp wxfile=/tmp/$$.wx_comments 2511daaffb31Sdp print -u2 "done" 2512daaffb31Sdp flist_done=1 2513daaffb31Sdp fi 2514daaffb31Sdp fi 2515daaffb31Sdp 2516daaffb31Sdp # 2517daaffb31Sdp # If by hook or by crook we've gotten a file list by now (perhaps 2518daaffb31Sdp # from the command line), eval it to extract environment variables from 25192d9224a3SMark J. Nelson # it: This is method 3 for finding the parent. 2520daaffb31Sdp # 2521daaffb31Sdp if [[ -z $flist_done ]]; then 2522daaffb31Sdp flist_from_teamware 2523daaffb31Sdp fi 25242d9224a3SMark J. Nelson env_from_flist 2525daaffb31Sdp 2526daaffb31Sdp # 2527daaffb31Sdp # (4) If we still don't have a value for codemgr_parent, get it 2528daaffb31Sdp # from workspace. 2529daaffb31Sdp # 2530daaffb31Sdp [[ -z $codemgr_parent ]] && codemgr_parent=`workspace parent` 2531daaffb31Sdp if [[ ! -d $codemgr_parent ]]; then 2532daaffb31Sdp print -u2 "$CODEMGR_PARENT: no such parent workspace" 2533daaffb31Sdp exit 1 2534daaffb31Sdp fi 2535daaffb31Sdp 2536daaffb31Sdp PWS=$codemgr_parent 2537cdf0c1d5Smjnelson 2538cdf0c1d5Smjnelson [[ -n $parent_webrev ]] && RWS=$(workspace parent $CWS) 2539cdf0c1d5Smjnelson 2540cdf0c1d5Smjnelsonelif [[ $SCM_MODE == "mercurial" ]]; then 2541cdf0c1d5Smjnelson # 2542cdf0c1d5Smjnelson # Parent can either be specified with -p 2543cdf0c1d5Smjnelson # Specified with CODEMGR_PARENT in the environment 2544cdf0c1d5Smjnelson # or taken from hg's default path. 2545cdf0c1d5Smjnelson # 2546cdf0c1d5Smjnelson 2547cdf0c1d5Smjnelson if [[ -z $codemgr_parent && -n $CODEMGR_PARENT ]]; then 2548cdf0c1d5Smjnelson codemgr_parent=$CODEMGR_PARENT 2549cdf0c1d5Smjnelson fi 2550cdf0c1d5Smjnelson 2551cdf0c1d5Smjnelson if [[ -z $codemgr_parent ]]; then 2552cdf0c1d5Smjnelson codemgr_parent=`hg path -R $codemgr_ws default 2>/dev/null` 2553cdf0c1d5Smjnelson fi 2554cdf0c1d5Smjnelson 2555cdf0c1d5Smjnelson CWS_REV=`hg parent -R $codemgr_ws --template '{node|short}' 2>/dev/null` 2556cdf0c1d5Smjnelson PWS=$codemgr_parent 2557cdf0c1d5Smjnelson 2558cdf0c1d5Smjnelson # 2559cdf0c1d5Smjnelson # If the parent is a webrev, we want to do some things against 2560cdf0c1d5Smjnelson # the natural workspace parent (file list, comments, etc) 2561cdf0c1d5Smjnelson # 2562cdf0c1d5Smjnelson if [[ -n $parent_webrev ]]; then 2563cdf0c1d5Smjnelson real_parent=$(hg path -R $codemgr_ws default 2>/dev/null) 2564cdf0c1d5Smjnelson else 2565cdf0c1d5Smjnelson real_parent=$PWS 2566cdf0c1d5Smjnelson fi 2567cdf0c1d5Smjnelson 2568cdf0c1d5Smjnelson # 2569cdf0c1d5Smjnelson # If hg-active exists, then we run it. In the case of no explicit 2570cdf0c1d5Smjnelson # flist given, we'll use it for our comments. In the case of an 2571cdf0c1d5Smjnelson # explicit flist given we'll try to use it for comments for any 2572cdf0c1d5Smjnelson # files mentioned in the flist. 2573cdf0c1d5Smjnelson # 2574cdf0c1d5Smjnelson if [[ -z $flist_done ]]; then 2575cdf0c1d5Smjnelson flist_from_mercurial $CWS $real_parent 2576cdf0c1d5Smjnelson flist_done=1 2577cdf0c1d5Smjnelson fi 2578cdf0c1d5Smjnelson 2579cdf0c1d5Smjnelson # 2580cdf0c1d5Smjnelson # If we have a file list now, pull out any variables set 2581cdf0c1d5Smjnelson # therein. We do this now (rather than when we possibly use 2582cdf0c1d5Smjnelson # hg-active to find comments) to avoid stomping specifications 2583cdf0c1d5Smjnelson # in the user-specified flist. 2584cdf0c1d5Smjnelson # 2585cdf0c1d5Smjnelson if [[ -n $flist_done ]]; then 2586cdf0c1d5Smjnelson env_from_flist 2587cdf0c1d5Smjnelson fi 2588cdf0c1d5Smjnelson 2589cdf0c1d5Smjnelson # 2590cdf0c1d5Smjnelson # Only call hg-active if we don't have a wx formatted file already 2591cdf0c1d5Smjnelson # 2592cdf0c1d5Smjnelson if [[ -x $HG_ACTIVE && -z $wxfile ]]; then 2593cdf0c1d5Smjnelson print " Comments from: hg-active -p $real_parent ...\c" 2594cdf0c1d5Smjnelson hg_active_wxfile $CWS $real_parent 2595cdf0c1d5Smjnelson print " Done." 2596cdf0c1d5Smjnelson fi 2597cdf0c1d5Smjnelson 2598cdf0c1d5Smjnelson # 2599cdf0c1d5Smjnelson # At this point we must have a wx flist either from hg-active, 2600cdf0c1d5Smjnelson # or in general. Use it to try and find our parent revision, 2601cdf0c1d5Smjnelson # if we don't have one. 2602cdf0c1d5Smjnelson # 2603cdf0c1d5Smjnelson if [[ -z $HG_PARENT ]]; then 2604b0088928SVladimir Kotal eval `$SED -e "s/#.*$//" $wxfile | $GREP HG_PARENT=` 2605cdf0c1d5Smjnelson fi 2606cdf0c1d5Smjnelson 2607cdf0c1d5Smjnelson # 2608cdf0c1d5Smjnelson # If we still don't have a parent, we must have been given a 2609cdf0c1d5Smjnelson # wx-style active list with no HG_PARENT specification, run 2610cdf0c1d5Smjnelson # hg-active and pull an HG_PARENT out of it, ignore the rest. 2611cdf0c1d5Smjnelson # 2612cdf0c1d5Smjnelson if [[ -z $HG_PARENT && -x $HG_ACTIVE ]]; then 2613cdf0c1d5Smjnelson $HG_ACTIVE -w $codemgr_ws -p $real_parent | \ 2614b0088928SVladimir Kotal eval `$SED -e "s/#.*$//" | $GREP HG_PARENT=` 2615cdf0c1d5Smjnelson elif [[ -z $HG_PARENT ]]; then 2616cdf0c1d5Smjnelson print -u2 "Error: Cannot discover parent revision" 2617cdf0c1d5Smjnelson exit 1 2618cdf0c1d5Smjnelson fi 2619cdf0c1d5Smjnelsonelif [[ $SCM_MODE == "subversion" ]]; then 2620cdf0c1d5Smjnelson 2621cdf0c1d5Smjnelson # 2622cdf0c1d5Smjnelson # We only will have a real parent workspace in the case one 2623cdf0c1d5Smjnelson # was specified (be it an older webrev, or another checkout). 2624cdf0c1d5Smjnelson # 2625cdf0c1d5Smjnelson [[ -n $codemgr_parent ]] && PWS=$codemgr_parent 2626cdf0c1d5Smjnelson 2627cdf0c1d5Smjnelson if [[ -z $flist_done && $flist_mode == "auto" ]]; then 2628cdf0c1d5Smjnelson flist_from_subversion $CWS $OLDPWD 2629cdf0c1d5Smjnelson fi 2630cdf0c1d5Smjnelsonelse 2631cdf0c1d5Smjnelson if [[ $SCM_MODE == "unknown" ]]; then 2632cdf0c1d5Smjnelson print -u2 " Unknown type of SCM in use" 2633cdf0c1d5Smjnelson else 2634cdf0c1d5Smjnelson print -u2 " Unsupported SCM in use: $SCM_MODE" 2635cdf0c1d5Smjnelson fi 2636cdf0c1d5Smjnelson 2637cdf0c1d5Smjnelson env_from_flist 2638cdf0c1d5Smjnelson 2639cdf0c1d5Smjnelson if [[ -z $CODEMGR_WS ]]; then 2640cdf0c1d5Smjnelson print -u2 "SCM not detected/supported and CODEMGR_WS not specified" 2641cdf0c1d5Smjnelson exit 1 2642cdf0c1d5Smjnelson fi 2643cdf0c1d5Smjnelson 2644cdf0c1d5Smjnelson if [[ -z $CODEMGR_PARENT ]]; then 2645cdf0c1d5Smjnelson print -u2 "SCM not detected/supported and CODEMGR_PARENT not specified" 2646cdf0c1d5Smjnelson exit 1 2647cdf0c1d5Smjnelson fi 2648cdf0c1d5Smjnelson 2649cdf0c1d5Smjnelson CWS=$CODEMGR_WS 2650cdf0c1d5Smjnelson PWS=$CODEMGR_PARENT 2651daaffb31Sdpfi 2652daaffb31Sdp 2653daaffb31Sdp# 2654daaffb31Sdp# If the user didn't specify a -i option, check to see if there is a 2655daaffb31Sdp# webrev-info file in the workspace directory. 2656daaffb31Sdp# 2657daaffb31Sdpif [[ -z $iflag && -r "$CWS/webrev-info" ]]; then 2658daaffb31Sdp iflag=1 2659daaffb31Sdp INCLUDE_FILE="$CWS/webrev-info" 2660daaffb31Sdpfi 2661daaffb31Sdp 2662daaffb31Sdpif [[ -n $iflag ]]; then 2663daaffb31Sdp if [[ ! -r $INCLUDE_FILE ]]; then 2664daaffb31Sdp print -u2 "include file '$INCLUDE_FILE' does not exist or is" \ 2665daaffb31Sdp "not readable." 2666daaffb31Sdp exit 1 2667daaffb31Sdp else 2668daaffb31Sdp # 2669daaffb31Sdp # $INCLUDE_FILE may be a relative path, and the script alters 2670daaffb31Sdp # PWD, so we just stash a copy in /tmp. 2671daaffb31Sdp # 2672daaffb31Sdp cp $INCLUDE_FILE /tmp/$$.include 2673daaffb31Sdp fi 2674daaffb31Sdpfi 2675daaffb31Sdp 26760fd2682eSMark J. Nelson# DO_EVERYTHING: break point 26770fd2682eSMark J. Nelsonif [[ -n $Nflag ]]; then 26780fd2682eSMark J. Nelson break 26790fd2682eSMark J. Nelsonfi 26800fd2682eSMark J. Nelson 26810fd2682eSMark J. Nelsontypeset -A itsinfo 26820fd2682eSMark J. Nelsontypeset -r its_sed_script=/tmp/$$.its_sed 26830fd2682eSMark J. Nelsonvalid_prefixes= 26840fd2682eSMark J. Nelsonif [[ -z $nflag ]]; then 26850fd2682eSMark J. Nelson DEFREGFILE="$(dirname $(whence $0))/../etc/its.reg" 26860fd2682eSMark J. Nelson if [[ -n $Iflag ]]; then 26870fd2682eSMark J. Nelson REGFILE=$ITSREG 26880fd2682eSMark J. Nelson elif [[ -r $HOME/.its.reg ]]; then 26890fd2682eSMark J. Nelson REGFILE=$HOME/.its.reg 26900fd2682eSMark J. Nelson else 26910fd2682eSMark J. Nelson REGFILE=$DEFREGFILE 26920fd2682eSMark J. Nelson fi 26930fd2682eSMark J. Nelson if [[ ! -r $REGFILE ]]; then 26940fd2682eSMark J. Nelson print "ERROR: Unable to read database registry file $REGFILE" 26950fd2682eSMark J. Nelson exit 1 26960fd2682eSMark J. Nelson elif [[ $REGFILE != $DEFREGFILE ]]; then 26970fd2682eSMark J. Nelson print " its.reg from: $REGFILE" 26980fd2682eSMark J. Nelson fi 26990fd2682eSMark J. Nelson 27000fd2682eSMark J. Nelson $SED -e '/^#/d' -e '/^[ ]*$/d' $REGFILE | while read LINE; do 27010fd2682eSMark J. Nelson 27020fd2682eSMark J. Nelson name=${LINE%%=*} 27030fd2682eSMark J. Nelson value="${LINE#*=}" 27040fd2682eSMark J. Nelson 27050fd2682eSMark J. Nelson if [[ $name == PREFIX ]]; then 27060fd2682eSMark J. Nelson p=${value} 27070fd2682eSMark J. Nelson valid_prefixes="${p} ${valid_prefixes}" 27080fd2682eSMark J. Nelson else 27090fd2682eSMark J. Nelson itsinfo["${p}_${name}"]="${value}" 27100fd2682eSMark J. Nelson fi 27110fd2682eSMark J. Nelson done 27120fd2682eSMark J. Nelson 27130fd2682eSMark J. Nelson 27140fd2682eSMark J. Nelson DEFCONFFILE="$(dirname $(whence $0))/../etc/its.conf" 27150fd2682eSMark J. Nelson CONFFILES=$DEFCONFFILE 27160fd2682eSMark J. Nelson if [[ -r $HOME/.its.conf ]]; then 27170fd2682eSMark J. Nelson CONFFILES="${CONFFILES} $HOME/.its.conf" 27180fd2682eSMark J. Nelson fi 27190fd2682eSMark J. Nelson if [[ -n $Cflag ]]; then 27200fd2682eSMark J. Nelson CONFFILES="${CONFFILES} ${ITSCONF}" 27210fd2682eSMark J. Nelson fi 27220fd2682eSMark J. Nelson its_domain= 27230fd2682eSMark J. Nelson its_priority= 27240fd2682eSMark J. Nelson for cf in ${CONFFILES}; do 27250fd2682eSMark J. Nelson if [[ ! -r $cf ]]; then 27260fd2682eSMark J. Nelson print "ERROR: Unable to read database configuration file $cf" 27270fd2682eSMark J. Nelson exit 1 27280fd2682eSMark J. Nelson elif [[ $cf != $DEFCONFFILE ]]; then 27290fd2682eSMark J. Nelson print " its.conf: reading $cf" 27300fd2682eSMark J. Nelson fi 27310fd2682eSMark J. Nelson $SED -e '/^#/d' -e '/^[ ]*$/d' $cf | while read LINE; do 27320fd2682eSMark J. Nelson eval "${LINE}" 27330fd2682eSMark J. Nelson done 27340fd2682eSMark J. Nelson done 27350fd2682eSMark J. Nelson 27360fd2682eSMark J. Nelson # 27370fd2682eSMark J. Nelson # If an information tracking system is explicitly identified by prefix, 27380fd2682eSMark J. Nelson # we want to disregard the specified priorities and resolve it accordingly. 27390fd2682eSMark J. Nelson # 27400fd2682eSMark J. Nelson # To that end, we'll build a sed script to do each valid prefix in turn. 27410fd2682eSMark J. Nelson # 27420fd2682eSMark J. Nelson for p in ${valid_prefixes}; do 27430fd2682eSMark J. Nelson # 27440fd2682eSMark J. Nelson # When an informational URL was provided, translate it to a 27450fd2682eSMark J. Nelson # hyperlink. When omitted, simply use the prefix text. 27460fd2682eSMark J. Nelson # 27470fd2682eSMark J. Nelson if [[ -z ${itsinfo["${p}_INFO"]} ]]; then 27480fd2682eSMark J. Nelson itsinfo["${p}_INFO"]=${p} 27490fd2682eSMark J. Nelson else 27500fd2682eSMark J. Nelson itsinfo["${p}_INFO"]="<a href=\\\"${itsinfo["${p}_INFO"]}\\\">${p}</a>" 27510fd2682eSMark J. Nelson fi 27520fd2682eSMark J. Nelson 27530fd2682eSMark J. Nelson # 27540fd2682eSMark J. Nelson # Assume that, for this invocation of webrev, all references 27550fd2682eSMark J. Nelson # to this information tracking system should resolve through 27560fd2682eSMark J. Nelson # the same URL. 27570fd2682eSMark J. Nelson # 27580fd2682eSMark J. Nelson # If the caller specified -O, then always use EXTERNAL_URL. 27590fd2682eSMark J. Nelson # 27600fd2682eSMark J. Nelson # Otherwise, look in the list of domains for a matching 27610fd2682eSMark J. Nelson # INTERNAL_URL. 27620fd2682eSMark J. Nelson # 27630fd2682eSMark J. Nelson [[ -z $Oflag ]] && for d in ${its_domain}; do 27640fd2682eSMark J. Nelson if [[ -n ${itsinfo["${p}_INTERNAL_URL_${d}"]} ]]; then 27650fd2682eSMark J. Nelson itsinfo["${p}_URL"]="${itsinfo[${p}_INTERNAL_URL_${d}]}" 27660fd2682eSMark J. Nelson break 27670fd2682eSMark J. Nelson fi 27680fd2682eSMark J. Nelson done 27690fd2682eSMark J. Nelson if [[ -z ${itsinfo["${p}_URL"]} ]]; then 27700fd2682eSMark J. Nelson itsinfo["${p}_URL"]="${itsinfo[${p}_EXTERNAL_URL]}" 27710fd2682eSMark J. Nelson fi 27720fd2682eSMark J. Nelson 27730fd2682eSMark J. Nelson # 27740fd2682eSMark J. Nelson # Turn the destination URL into a hyperlink 27750fd2682eSMark J. Nelson # 27760fd2682eSMark J. Nelson itsinfo["${p}_URL"]="<a href=\\\"${itsinfo[${p}_URL]}\\\">&</a>" 27770fd2682eSMark J. Nelson 2778*2f54b716SRichard Lowe # The character class below contains a literal tab 2779*2f54b716SRichard Lowe print "/^${p}[: ]/ { 27800fd2682eSMark J. Nelson s;${itsinfo[${p}_REGEX]};${itsinfo[${p}_URL]};g 27810fd2682eSMark J. Nelson s;^${p};${itsinfo[${p}_INFO]}; 27820fd2682eSMark J. Nelson }" >> ${its_sed_script} 27830fd2682eSMark J. Nelson done 27840fd2682eSMark J. Nelson 27850fd2682eSMark J. Nelson # 27860fd2682eSMark J. Nelson # The previous loop took care of explicit specification. Now use 27870fd2682eSMark J. Nelson # the configured priorities to attempt implicit translations. 27880fd2682eSMark J. Nelson # 27890fd2682eSMark J. Nelson for p in ${its_priority}; do 27900fd2682eSMark J. Nelson print "/^${itsinfo[${p}_REGEX]}[ ]/ { 2791*2f54b716SRichard Lowe s;^${itsinfo[${p}_REGEX]};${itsinfo[${p}_URL]};g 27920fd2682eSMark J. Nelson }" >> ${its_sed_script} 27930fd2682eSMark J. Nelson done 27940fd2682eSMark J. Nelsonfi 27950fd2682eSMark J. Nelson 27960fd2682eSMark J. Nelson# 27970fd2682eSMark J. Nelson# Search for DO_EVERYTHING above for matching "for" statement 27980fd2682eSMark J. Nelson# and explanation of this terminator. 27990fd2682eSMark J. Nelson# 28000fd2682eSMark J. Nelsondone 28010fd2682eSMark J. Nelson 2802daaffb31Sdp# 2803daaffb31Sdp# Output directory. 2804daaffb31Sdp# 2805daaffb31SdpWDIR=${WDIR:-$CWS/webrev} 2806daaffb31Sdp 2807daaffb31Sdp# 280802d26c39SVladimir Kotal# Name of the webrev, derived from the workspace name or output directory; 280902d26c39SVladimir Kotal# in the future this could potentially be an option. 2810daaffb31Sdp# 281102d26c39SVladimir Kotalif [[ -n $oflag ]]; then 281202d26c39SVladimir Kotal WNAME=${WDIR##*/} 281302d26c39SVladimir Kotalelse 2814daaffb31Sdp WNAME=${CWS##*/} 281502d26c39SVladimir Kotalfi 281602d26c39SVladimir Kotal 2817ba44d8a2SVladimir Kotal# Make sure remote target is well formed for remote upload/delete. 2818ba44d8a2SVladimir Kotalif [[ -n $Dflag || -n $Uflag ]]; then 2819b0088928SVladimir Kotal # 2820ba44d8a2SVladimir Kotal # If remote target is not specified, build it from scratch using 2821ba44d8a2SVladimir Kotal # the default values. 2822b0088928SVladimir Kotal # 2823ba44d8a2SVladimir Kotal if [[ -z $tflag ]]; then 2824ba44d8a2SVladimir Kotal remote_target=${DEFAULT_REMOTE_HOST}:${WNAME} 2825ba44d8a2SVladimir Kotal else 2826b0088928SVladimir Kotal # 2827b0088928SVladimir Kotal # Check upload target prefix first. 2828b0088928SVladimir Kotal # 2829b0088928SVladimir Kotal if [[ "${remote_target}" != ${rsync_prefix}* && 2830b0088928SVladimir Kotal "${remote_target}" != ${ssh_prefix}* ]]; then 2831b0088928SVladimir Kotal print "ERROR: invalid prefix of upload URI" \ 2832b0088928SVladimir Kotal "($remote_target)" 2833b0088928SVladimir Kotal exit 1 2834b0088928SVladimir Kotal fi 2835b0088928SVladimir Kotal # 2836ba44d8a2SVladimir Kotal # If destination specification is not in the form of 2837ba44d8a2SVladimir Kotal # host_spec:remote_dir then assume it is just remote hostname 2838ba44d8a2SVladimir Kotal # and append a colon and destination directory formed from 2839ba44d8a2SVladimir Kotal # local webrev directory name. 2840b0088928SVladimir Kotal # 2841b0088928SVladimir Kotal typeset target_no_prefix=${remote_target##*://} 2842b0088928SVladimir Kotal if [[ ${target_no_prefix} == *:* ]]; then 2843ba44d8a2SVladimir Kotal if [[ "${remote_target}" == *: ]]; then 2844b0088928SVladimir Kotal remote_target=${remote_target}${WNAME} 2845ba44d8a2SVladimir Kotal fi 2846b0088928SVladimir Kotal else 2847b0088928SVladimir Kotal if [[ ${target_no_prefix} == */* ]]; then 2848b0088928SVladimir Kotal print "ERROR: badly formed upload URI" \ 2849b0088928SVladimir Kotal "($remote_target)" 2850b0088928SVladimir Kotal exit 1 2851b0088928SVladimir Kotal else 2852b0088928SVladimir Kotal remote_target=${remote_target}:${WNAME} 2853ba44d8a2SVladimir Kotal fi 2854ba44d8a2SVladimir Kotal fi 2855ba44d8a2SVladimir Kotal fi 2856ba44d8a2SVladimir Kotal 2857b0088928SVladimir Kotal # 2858b0088928SVladimir Kotal # Strip trailing slash. Each upload method will deal with directory 2859b0088928SVladimir Kotal # specification separately. 2860b0088928SVladimir Kotal # 2861b0088928SVladimir Kotal remote_target=${remote_target%/} 2862b0088928SVladimir Kotalfi 2863b0088928SVladimir Kotal 2864b0088928SVladimir Kotal# 2865ba44d8a2SVladimir Kotal# Option -D by itself (option -U not present) implies no webrev generation. 2866b0088928SVladimir Kotal# 2867ba44d8a2SVladimir Kotalif [[ -z $Uflag && -n $Dflag ]]; then 2868b0088928SVladimir Kotal delete_webrev 1 1 2869ba44d8a2SVladimir Kotal exit $? 2870ba44d8a2SVladimir Kotalfi 2871ba44d8a2SVladimir Kotal 2872b0088928SVladimir Kotal# 2873ba44d8a2SVladimir Kotal# Do not generate the webrev, just upload it or delete it. 2874b0088928SVladimir Kotal# 2875ba44d8a2SVladimir Kotalif [[ -n $nflag ]]; then 2876ba44d8a2SVladimir Kotal if [[ -n $Dflag ]]; then 2877b0088928SVladimir Kotal delete_webrev 1 1 2878ba44d8a2SVladimir Kotal (( $? == 0 )) || exit $? 2879ba44d8a2SVladimir Kotal fi 2880ba44d8a2SVladimir Kotal if [[ -n $Uflag ]]; then 288102d26c39SVladimir Kotal upload_webrev 288202d26c39SVladimir Kotal exit $? 288302d26c39SVladimir Kotal fi 2884ba44d8a2SVladimir Kotalfi 2885daaffb31Sdp 2886e0e0293aSjmcpif [ "${WDIR%%/*}" ]; then 28877c478bd9Sstevel@tonic-gate WDIR=$PWD/$WDIR 28887c478bd9Sstevel@tonic-gatefi 2889daaffb31Sdp 2890daaffb31Sdpif [[ ! -d $WDIR ]]; then 2891daaffb31Sdp mkdir -p $WDIR 2892ba44d8a2SVladimir Kotal (( $? != 0 )) && exit 1 28937c478bd9Sstevel@tonic-gatefi 28947c478bd9Sstevel@tonic-gate 2895daaffb31Sdp# 2896daaffb31Sdp# Summarize what we're going to do. 2897daaffb31Sdp# 2898cdf0c1d5Smjnelsonif [[ -n $CWS_REV ]]; then 2899cdf0c1d5Smjnelson print " Workspace: $CWS (at $CWS_REV)" 2900cdf0c1d5Smjnelsonelse 2901daaffb31Sdp print " Workspace: $CWS" 2902cdf0c1d5Smjnelsonfi 2903daaffb31Sdpif [[ -n $parent_webrev ]]; then 2904daaffb31Sdp print "Compare against: webrev at $parent_webrev" 2905daaffb31Sdpelse 2906cdf0c1d5Smjnelson if [[ -n $HG_PARENT ]]; then 2907cdf0c1d5Smjnelson hg_parent_short=`echo $HG_PARENT \ 2908b0088928SVladimir Kotal | $SED -e 's/\([0-9a-f]\{12\}\).*/\1/'` 2909cdf0c1d5Smjnelson print "Compare against: $PWS (at $hg_parent_short)" 2910cdf0c1d5Smjnelson else 2911daaffb31Sdp print "Compare against: $PWS" 2912daaffb31Sdp fi 2913cdf0c1d5Smjnelsonfi 2914daaffb31Sdp 2915daaffb31Sdp[[ -n $INCLUDE_FILE ]] && print " Including: $INCLUDE_FILE" 2916daaffb31Sdpprint " Output to: $WDIR" 2917daaffb31Sdp 2918daaffb31Sdp# 29197c478bd9Sstevel@tonic-gate# Save the file list in the webrev dir 2920daaffb31Sdp# 2921daaffb31Sdp[[ ! $FLIST -ef $WDIR/file.list ]] && cp $FLIST $WDIR/file.list 29227c478bd9Sstevel@tonic-gate 2923daaffb31Sdprm -f $WDIR/$WNAME.patch 2924daaffb31Sdprm -f $WDIR/$WNAME.ps 2925daaffb31Sdprm -f $WDIR/$WNAME.pdf 29267c478bd9Sstevel@tonic-gate 2927daaffb31Sdptouch $WDIR/$WNAME.patch 29287c478bd9Sstevel@tonic-gate 2929daaffb31Sdpprint " Output Files:" 2930daaffb31Sdp 2931daaffb31Sdp# 2932daaffb31Sdp# Clean up the file list: Remove comments, blank lines and env variables. 2933daaffb31Sdp# 2934b0088928SVladimir Kotal$SED -e "s/#.*$//" -e "/=/d" -e "/^[ ]*$/d" $FLIST > /tmp/$$.flist.clean 2935daaffb31SdpFLIST=/tmp/$$.flist.clean 2936daaffb31Sdp 2937daaffb31Sdp# 2938cdf0c1d5Smjnelson# For Mercurial, create a cache of manifest entries. 2939cdf0c1d5Smjnelson# 2940cdf0c1d5Smjnelsonif [[ $SCM_MODE == "mercurial" ]]; then 2941cdf0c1d5Smjnelson # 2942cdf0c1d5Smjnelson # Transform the FLIST into a temporary sed script that matches 2943cdf0c1d5Smjnelson # relevant entries in the Mercurial manifest as follows: 2944cdf0c1d5Smjnelson # 1) The script will be used against the parent revision manifest, 2945cdf0c1d5Smjnelson # so for FLIST lines that have two filenames (a renamed file) 2946cdf0c1d5Smjnelson # keep only the old name. 2947cdf0c1d5Smjnelson # 2) Escape all forward slashes the filename. 2948cdf0c1d5Smjnelson # 3) Change the filename into another sed command that matches 2949cdf0c1d5Smjnelson # that file in "hg manifest -v" output: start of line, three 2950cdf0c1d5Smjnelson # octal digits for file permissions, space, a file type flag 2951cdf0c1d5Smjnelson # character, space, the filename, end of line. 2952e6ccc173SEdward Pilatowicz # 4) Eliminate any duplicate entries. (This can occur if a 2953e6ccc173SEdward Pilatowicz # file has been used as the source of an hg cp and it's 2954e6ccc173SEdward Pilatowicz # also been modified in the same changeset.) 2955cdf0c1d5Smjnelson # 2956cdf0c1d5Smjnelson SEDFILE=/tmp/$$.manifest.sed 2957b0088928SVladimir Kotal $SED ' 2958cdf0c1d5Smjnelson s#^[^ ]* ## 2959cdf0c1d5Smjnelson s#/#\\\/#g 2960cdf0c1d5Smjnelson s#^.*$#/^... . &$/p# 2961e6ccc173SEdward Pilatowicz ' < $FLIST | $SORT -u > $SEDFILE 2962cdf0c1d5Smjnelson 2963cdf0c1d5Smjnelson # 2964cdf0c1d5Smjnelson # Apply the generated script to the output of "hg manifest -v" 2965cdf0c1d5Smjnelson # to get the relevant subset for this webrev. 2966cdf0c1d5Smjnelson # 2967cdf0c1d5Smjnelson HG_PARENT_MANIFEST=/tmp/$$.manifest 2968cdf0c1d5Smjnelson hg -R $CWS manifest -v -r $HG_PARENT | 2969b0088928SVladimir Kotal $SED -n -f $SEDFILE > $HG_PARENT_MANIFEST 2970cdf0c1d5Smjnelsonfi 2971cdf0c1d5Smjnelson 2972cdf0c1d5Smjnelson# 2973daaffb31Sdp# First pass through the files: generate the per-file webrev HTML-files. 2974daaffb31Sdp# 2975daaffb31Sdpcat $FLIST | while read LINE 29767c478bd9Sstevel@tonic-gatedo 29777c478bd9Sstevel@tonic-gate set - $LINE 29787c478bd9Sstevel@tonic-gate P=$1 29797c478bd9Sstevel@tonic-gate 2980daaffb31Sdp # 2981daaffb31Sdp # Normally, each line in the file list is just a pathname of a 2982daaffb31Sdp # file that has been modified or created in the child. A file 2983daaffb31Sdp # that is renamed in the child workspace has two names on the 2984daaffb31Sdp # line: new name followed by the old name. 2985daaffb31Sdp # 2986daaffb31Sdp oldname="" 2987daaffb31Sdp oldpath="" 2988daaffb31Sdp rename= 2989daaffb31Sdp if [[ $# -eq 2 ]]; then 29907c478bd9Sstevel@tonic-gate PP=$2 # old filename 2991e6ccc173SEdward Pilatowicz if [[ -f $PP ]]; then 2992e6ccc173SEdward Pilatowicz oldname=" (copied from $PP)" 2993e6ccc173SEdward Pilatowicz else 2994e6ccc173SEdward Pilatowicz oldname=" (renamed from $PP)" 2995e6ccc173SEdward Pilatowicz fi 2996daaffb31Sdp oldpath="$PP" 2997daaffb31Sdp rename=1 29987c478bd9Sstevel@tonic-gate PDIR=${PP%/*} 2999daaffb31Sdp if [[ $PDIR == $PP ]]; then 30007c478bd9Sstevel@tonic-gate PDIR="." # File at root of workspace 30017c478bd9Sstevel@tonic-gate fi 30027c478bd9Sstevel@tonic-gate 30037c478bd9Sstevel@tonic-gate PF=${PP##*/} 30047c478bd9Sstevel@tonic-gate 30057c478bd9Sstevel@tonic-gate DIR=${P%/*} 3006daaffb31Sdp if [[ $DIR == $P ]]; then 30077c478bd9Sstevel@tonic-gate DIR="." # File at root of workspace 30087c478bd9Sstevel@tonic-gate fi 30097c478bd9Sstevel@tonic-gate 30107c478bd9Sstevel@tonic-gate F=${P##*/} 3011daaffb31Sdp 30127c478bd9Sstevel@tonic-gate else 30137c478bd9Sstevel@tonic-gate DIR=${P%/*} 3014daaffb31Sdp if [[ "$DIR" == "$P" ]]; then 30157c478bd9Sstevel@tonic-gate DIR="." # File at root of workspace 30167c478bd9Sstevel@tonic-gate fi 30177c478bd9Sstevel@tonic-gate 30187c478bd9Sstevel@tonic-gate F=${P##*/} 30197c478bd9Sstevel@tonic-gate 30207c478bd9Sstevel@tonic-gate PP=$P 30217c478bd9Sstevel@tonic-gate PDIR=$DIR 30227c478bd9Sstevel@tonic-gate PF=$F 30237c478bd9Sstevel@tonic-gate fi 30247c478bd9Sstevel@tonic-gate 3025daaffb31Sdp COMM=`getcomments html $P $PP` 30267c478bd9Sstevel@tonic-gate 3027daaffb31Sdp print "\t$P$oldname\n\t\t\c" 30287c478bd9Sstevel@tonic-gate 30297c478bd9Sstevel@tonic-gate # Make the webrev mirror directory if necessary 30307c478bd9Sstevel@tonic-gate mkdir -p $WDIR/$DIR 30317c478bd9Sstevel@tonic-gate 3032daaffb31Sdp # 3033cdf0c1d5Smjnelson # We stash old and new files into parallel directories in $WDIR 3034daaffb31Sdp # and do our diffs there. This makes it possible to generate 3035daaffb31Sdp # clean looking diffs which don't have absolute paths present. 3036daaffb31Sdp # 3037daaffb31Sdp 3038cdf0c1d5Smjnelson build_old_new "$WDIR" "$PWS" "$PDIR" "$PF" "$CWS" "$DIR" "$F" || \ 30397c478bd9Sstevel@tonic-gate continue 30407c478bd9Sstevel@tonic-gate 3041cdf0c1d5Smjnelson # 3042cdf0c1d5Smjnelson # Keep the old PWD around, so we can safely switch back after 3043cdf0c1d5Smjnelson # diff generation, such that build_old_new runs in a 3044cdf0c1d5Smjnelson # consistent environment. 3045cdf0c1d5Smjnelson # 3046cdf0c1d5Smjnelson OWD=$PWD 3047daaffb31Sdp cd $WDIR/raw_files 3048daaffb31Sdp ofile=old/$PDIR/$PF 3049daaffb31Sdp nfile=new/$DIR/$F 30507c478bd9Sstevel@tonic-gate 3051daaffb31Sdp mv_but_nodiff= 3052daaffb31Sdp cmp $ofile $nfile > /dev/null 2>&1 3053daaffb31Sdp if [[ $? == 0 && $rename == 1 ]]; then 3054daaffb31Sdp mv_but_nodiff=1 3055daaffb31Sdp fi 3056daaffb31Sdp 3057daaffb31Sdp # 3058daaffb31Sdp # If we have old and new versions of the file then run the appropriate 3059daaffb31Sdp # diffs. This is complicated by a couple of factors: 3060daaffb31Sdp # 3061daaffb31Sdp # - renames must be handled specially: we emit a 'remove' 3062daaffb31Sdp # diff and an 'add' diff 3063daaffb31Sdp # - new files and deleted files must be handled specially 3064daaffb31Sdp # - Solaris patch(1m) can't cope with file creation 3065daaffb31Sdp # (and hence renames) as of this writing. 3066daaffb31Sdp # - To make matters worse, gnu patch doesn't interpret the 3067daaffb31Sdp # output of Solaris diff properly when it comes to 3068daaffb31Sdp # adds and deletes. We need to do some "cleansing" 3069daaffb31Sdp # transformations: 3070daaffb31Sdp # [to add a file] @@ -1,0 +X,Y @@ --> @@ -0,0 +X,Y @@ 3071daaffb31Sdp # [to del a file] @@ -X,Y +1,0 @@ --> @@ -X,Y +0,0 @@ 3072daaffb31Sdp # 3073b0088928SVladimir Kotal cleanse_rmfile="$SED 's/^\(@@ [0-9+,-]*\) [0-9+,-]* @@$/\1 +0,0 @@/'" 3074b0088928SVladimir Kotal cleanse_newfile="$SED 's/^@@ [0-9+,-]* \([0-9+,-]* @@\)$/@@ -0,0 \1/'" 3075daaffb31Sdp 3076daaffb31Sdp rm -f $WDIR/$DIR/$F.patch 3077daaffb31Sdp if [[ -z $rename ]]; then 3078e0e0293aSjmcp if [ ! -f "$ofile" ]; then 3079daaffb31Sdp diff -u /dev/null $nfile | sh -c "$cleanse_newfile" \ 3080daaffb31Sdp > $WDIR/$DIR/$F.patch 3081e0e0293aSjmcp elif [ ! -f "$nfile" ]; then 3082daaffb31Sdp diff -u $ofile /dev/null | sh -c "$cleanse_rmfile" \ 3083daaffb31Sdp > $WDIR/$DIR/$F.patch 3084daaffb31Sdp else 3085daaffb31Sdp diff -u $ofile $nfile > $WDIR/$DIR/$F.patch 3086daaffb31Sdp fi 3087daaffb31Sdp else 3088daaffb31Sdp diff -u $ofile /dev/null | sh -c "$cleanse_rmfile" \ 3089daaffb31Sdp > $WDIR/$DIR/$F.patch 3090daaffb31Sdp 3091daaffb31Sdp diff -u /dev/null $nfile | sh -c "$cleanse_newfile" \ 3092daaffb31Sdp >> $WDIR/$DIR/$F.patch 3093daaffb31Sdp fi 3094daaffb31Sdp 3095daaffb31Sdp # 3096daaffb31Sdp # Tack the patch we just made onto the accumulated patch for the 3097daaffb31Sdp # whole wad. 3098daaffb31Sdp # 3099daaffb31Sdp cat $WDIR/$DIR/$F.patch >> $WDIR/$WNAME.patch 3100daaffb31Sdp 3101daaffb31Sdp print " patch\c" 3102daaffb31Sdp 3103daaffb31Sdp if [[ -f $ofile && -f $nfile && -z $mv_but_nodiff ]]; then 3104daaffb31Sdp 3105daaffb31Sdp ${CDIFFCMD:-diff -bt -C 5} $ofile $nfile > $WDIR/$DIR/$F.cdiff 3106daaffb31Sdp diff_to_html $F $DIR/$F "C" "$COMM" < $WDIR/$DIR/$F.cdiff \ 3107daaffb31Sdp > $WDIR/$DIR/$F.cdiff.html 31087c478bd9Sstevel@tonic-gate print " cdiffs\c" 31097c478bd9Sstevel@tonic-gate 3110daaffb31Sdp ${UDIFFCMD:-diff -bt -U 5} $ofile $nfile > $WDIR/$DIR/$F.udiff 3111daaffb31Sdp diff_to_html $F $DIR/$F "U" "$COMM" < $WDIR/$DIR/$F.udiff \ 3112daaffb31Sdp > $WDIR/$DIR/$F.udiff.html 3113daaffb31Sdp 31147c478bd9Sstevel@tonic-gate print " udiffs\c" 31157c478bd9Sstevel@tonic-gate 31167c478bd9Sstevel@tonic-gate if [[ -x $WDIFF ]]; then 3117daaffb31Sdp $WDIFF -c "$COMM" \ 3118daaffb31Sdp -t "$WNAME Wdiff $DIR/$F" $ofile $nfile > \ 3119daaffb31Sdp $WDIR/$DIR/$F.wdiff.html 2>/dev/null 3120daaffb31Sdp if [[ $? -eq 0 ]]; then 31217c478bd9Sstevel@tonic-gate print " wdiffs\c" 3122daaffb31Sdp else 3123daaffb31Sdp print " wdiffs[fail]\c" 3124daaffb31Sdp fi 31257c478bd9Sstevel@tonic-gate fi 31267c478bd9Sstevel@tonic-gate 3127daaffb31Sdp sdiff_to_html $ofile $nfile $F $DIR "$COMM" \ 3128daaffb31Sdp > $WDIR/$DIR/$F.sdiff.html 31297c478bd9Sstevel@tonic-gate print " sdiffs\c" 31307c478bd9Sstevel@tonic-gate 31317c478bd9Sstevel@tonic-gate print " frames\c" 31327c478bd9Sstevel@tonic-gate 31337c478bd9Sstevel@tonic-gate rm -f $WDIR/$DIR/$F.cdiff $WDIR/$DIR/$F.udiff 31347c478bd9Sstevel@tonic-gate 3135daaffb31Sdp difflines $ofile $nfile > $WDIR/$DIR/$F.count 3136daaffb31Sdp 3137daaffb31Sdp elif [[ -f $ofile && -f $nfile && -n $mv_but_nodiff ]]; then 3138daaffb31Sdp # renamed file: may also have differences 3139daaffb31Sdp difflines $ofile $nfile > $WDIR/$DIR/$F.count 3140daaffb31Sdp elif [[ -f $nfile ]]; then 31417c478bd9Sstevel@tonic-gate # new file: count added lines 3142daaffb31Sdp difflines /dev/null $nfile > $WDIR/$DIR/$F.count 3143daaffb31Sdp elif [[ -f $ofile ]]; then 31447c478bd9Sstevel@tonic-gate # old file: count deleted lines 3145daaffb31Sdp difflines $ofile /dev/null > $WDIR/$DIR/$F.count 31467c478bd9Sstevel@tonic-gate fi 31477c478bd9Sstevel@tonic-gate 3148daaffb31Sdp # 3149daaffb31Sdp # Now we generate the postscript for this file. We generate diffs 3150daaffb31Sdp # only in the event that there is delta, or the file is new (it seems 3151daaffb31Sdp # tree-killing to print out the contents of deleted files). 3152daaffb31Sdp # 3153daaffb31Sdp if [[ -f $nfile ]]; then 3154daaffb31Sdp ocr=$ofile 3155daaffb31Sdp [[ ! -f $ofile ]] && ocr=/dev/null 3156daaffb31Sdp 3157daaffb31Sdp if [[ -z $mv_but_nodiff ]]; then 3158daaffb31Sdp textcomm=`getcomments text $P $PP` 315914983201Sdp if [[ -x $CODEREVIEW ]]; then 316014983201Sdp $CODEREVIEW -y "$textcomm" \ 316114983201Sdp -e $ocr $nfile \ 316214983201Sdp > /tmp/$$.psfile 2>/dev/null && 316314983201Sdp cat /tmp/$$.psfile >> $WDIR/$WNAME.ps 3164daaffb31Sdp if [[ $? -eq 0 ]]; then 3165daaffb31Sdp print " ps\c" 3166daaffb31Sdp else 3167daaffb31Sdp print " ps[fail]\c" 3168daaffb31Sdp fi 3169daaffb31Sdp fi 3170daaffb31Sdp fi 317114983201Sdp fi 3172daaffb31Sdp 3173cdf0c1d5Smjnelson if [[ -f $ofile ]]; then 3174cdf0c1d5Smjnelson source_to_html Old $PP < $ofile > $WDIR/$DIR/$F-.html 31757c478bd9Sstevel@tonic-gate print " old\c" 31767c478bd9Sstevel@tonic-gate fi 31777c478bd9Sstevel@tonic-gate 3178daaffb31Sdp if [[ -f $nfile ]]; then 3179daaffb31Sdp source_to_html New $P < $nfile > $WDIR/$DIR/$F.html 31807c478bd9Sstevel@tonic-gate print " new\c" 31817c478bd9Sstevel@tonic-gate fi 31827c478bd9Sstevel@tonic-gate 3183cdf0c1d5Smjnelson cd $OWD 3184cdf0c1d5Smjnelson 3185daaffb31Sdp print 31867c478bd9Sstevel@tonic-gatedone 31877c478bd9Sstevel@tonic-gate 3188daaffb31Sdpframe_nav_js > $WDIR/ancnav.js 31897c478bd9Sstevel@tonic-gateframe_navigation > $WDIR/ancnav.html 3190daaffb31Sdp 319114983201Sdpif [[ ! -f $WDIR/$WNAME.ps ]]; then 319214983201Sdp print " Generating PDF: Skipped: no output available" 319314983201Sdpelif [[ -x $CODEREVIEW && -x $PS2PDF ]]; then 319414983201Sdp print " Generating PDF: \c" 319514983201Sdp fix_postscript $WDIR/$WNAME.ps | $PS2PDF - > $WDIR/$WNAME.pdf 3196daaffb31Sdp print "Done." 319714983201Sdpelse 319814983201Sdp print " Generating PDF: Skipped: missing 'ps2pdf' or 'codereview'" 319914983201Sdpfi 32007c478bd9Sstevel@tonic-gate 3201e0e0293aSjmcp# If we're in OpenSolaris mode and there's a closed dir under $WDIR, 3202e0e0293aSjmcp# delete it - prevent accidental publishing of closed source 3203e0e0293aSjmcp 3204e0e0293aSjmcpif [[ -n "$Oflag" ]]; then 3205ba44d8a2SVladimir Kotal $FIND $WDIR -type d -name closed -exec /bin/rm -rf {} \; 3206e0e0293aSjmcpfi 3207e0e0293aSjmcp 32087c478bd9Sstevel@tonic-gate# Now build the index.html file that contains 32097c478bd9Sstevel@tonic-gate# links to the source files and their diffs. 32107c478bd9Sstevel@tonic-gate 32117c478bd9Sstevel@tonic-gatecd $CWS 32127c478bd9Sstevel@tonic-gate 32137c478bd9Sstevel@tonic-gate# Save total changed lines for Code Inspection. 3214daaffb31Sdpprint "$TOTL" > $WDIR/TotalChangedLines 32157c478bd9Sstevel@tonic-gate 3216daaffb31Sdpprint " index.html: \c" 32177c478bd9Sstevel@tonic-gateINDEXFILE=$WDIR/index.html 32187c478bd9Sstevel@tonic-gateexec 3<&1 # duplicate stdout to FD3. 32197c478bd9Sstevel@tonic-gateexec 1<&- # Close stdout. 32207c478bd9Sstevel@tonic-gateexec > $INDEXFILE # Open stdout to index file. 32217c478bd9Sstevel@tonic-gate 3222daaffb31Sdpprint "$HTML<head>$STDHEAD" 3223daaffb31Sdpprint "<title>$WNAME</title>" 3224daaffb31Sdpprint "</head>" 3225daaffb31Sdpprint "<body id=\"SUNWwebrev\">" 3226daaffb31Sdpprint "<div class=\"summary\">" 3227daaffb31Sdpprint "<h2>Code Review for $WNAME</h2>" 32287c478bd9Sstevel@tonic-gate 3229daaffb31Sdpprint "<table>" 32307c478bd9Sstevel@tonic-gate 3231daaffb31Sdp# 3232cdf0c1d5Smjnelson# Get the preparer's name: 3233daaffb31Sdp# 3234cdf0c1d5Smjnelson# If the SCM detected is Mercurial, and the configuration property 3235cdf0c1d5Smjnelson# ui.username is available, use that, but be careful to properly escape 3236cdf0c1d5Smjnelson# angle brackets (HTML syntax characters) in the email address. 3237cdf0c1d5Smjnelson# 3238cdf0c1d5Smjnelson# Otherwise, use the current userid in the form "John Doe (jdoe)", but 3239cdf0c1d5Smjnelson# to maintain compatibility with passwd(4), we must support '&' substitutions. 3240cdf0c1d5Smjnelson# 3241cdf0c1d5Smjnelsonpreparer= 3242cdf0c1d5Smjnelsonif [[ "$SCM_MODE" == mercurial ]]; then 3243cdf0c1d5Smjnelson preparer=`hg showconfig ui.username 2>/dev/null` 3244cdf0c1d5Smjnelson if [[ -n "$preparer" ]]; then 3245cdf0c1d5Smjnelson preparer="$(echo "$preparer" | html_quote)" 3246cdf0c1d5Smjnelson fi 3247cdf0c1d5Smjnelsonfi 3248cdf0c1d5Smjnelsonif [[ -z "$preparer" ]]; then 3249cdf0c1d5Smjnelson preparer=$( 3250cdf0c1d5Smjnelson $PERL -e ' 3251cdf0c1d5Smjnelson ($login, $pw, $uid, $gid, $quota, $cmt, $gcos) = getpwuid($<); 3252cdf0c1d5Smjnelson if ($login) { 3253cdf0c1d5Smjnelson $gcos =~ s/\&/ucfirst($login)/e; 3254cdf0c1d5Smjnelson printf "%s (%s)\n", $gcos, $login; 3255cdf0c1d5Smjnelson } else { 3256cdf0c1d5Smjnelson printf "(unknown)\n"; 3257cdf0c1d5Smjnelson } 3258cdf0c1d5Smjnelson ') 3259daaffb31Sdpfi 3260daaffb31Sdp 326148bc00d6SjmcpPREPDATE=$(LC_ALL=C /usr/bin/date +%Y-%b-%d\ %R\ %z\ %Z) 326248bc00d6Sjmcpprint "<tr><th>Prepared by:</th><td>$preparer on $PREPDATE</td></tr>" 3263cdf0c1d5Smjnelsonprint "<tr><th>Workspace:</th><td>$CWS" 3264cdf0c1d5Smjnelsonif [[ -n $CWS_REV ]]; then 3265cdf0c1d5Smjnelson print "(at $CWS_REV)" 3266cdf0c1d5Smjnelsonfi 3267cdf0c1d5Smjnelsonprint "</td></tr>" 3268daaffb31Sdpprint "<tr><th>Compare against:</th><td>" 3269daaffb31Sdpif [[ -n $parent_webrev ]]; then 3270daaffb31Sdp print "webrev at $parent_webrev" 3271daaffb31Sdpelse 3272daaffb31Sdp print "$PWS" 3273cdf0c1d5Smjnelson if [[ -n $hg_parent_short ]]; then 3274cdf0c1d5Smjnelson print "(at $hg_parent_short)" 3275cdf0c1d5Smjnelson fi 3276daaffb31Sdpfi 3277daaffb31Sdpprint "</td></tr>" 3278daaffb31Sdpprint "<tr><th>Summary of changes:</th><td>" 3279daaffb31SdpprintCI $TOTL $TINS $TDEL $TMOD $TUNC 3280daaffb31Sdpprint "</td></tr>" 3281daaffb31Sdp 3282daaffb31Sdpif [[ -f $WDIR/$WNAME.patch ]]; then 3283371d72daSLubomir Sedlacik wpatch_url="$(print $WNAME.patch | url_encode)" 3284daaffb31Sdp print "<tr><th>Patch of changes:</th><td>" 3285371d72daSLubomir Sedlacik print "<a href=\"$wpatch_url\">$WNAME.patch</a></td></tr>" 3286daaffb31Sdpfi 3287daaffb31Sdpif [[ -f $WDIR/$WNAME.pdf ]]; then 3288371d72daSLubomir Sedlacik wpdf_url="$(print $WNAME.pdf | url_encode)" 3289daaffb31Sdp print "<tr><th>Printable review:</th><td>" 3290371d72daSLubomir Sedlacik print "<a href=\"$wpdf_url\">$WNAME.pdf</a></td></tr>" 3291daaffb31Sdpfi 3292daaffb31Sdp 3293daaffb31Sdpif [[ -n "$iflag" ]]; then 3294daaffb31Sdp print "<tr><th>Author comments:</th><td><div>" 3295daaffb31Sdp cat /tmp/$$.include 3296daaffb31Sdp print "</div></td></tr>" 3297daaffb31Sdpfi 3298daaffb31Sdpprint "</table>" 3299daaffb31Sdpprint "</div>" 3300daaffb31Sdp 3301daaffb31Sdp# 3302daaffb31Sdp# Second pass through the files: generate the rest of the index file 3303daaffb31Sdp# 3304daaffb31Sdpcat $FLIST | while read LINE 33057c478bd9Sstevel@tonic-gatedo 33067c478bd9Sstevel@tonic-gate set - $LINE 33077c478bd9Sstevel@tonic-gate P=$1 33087c478bd9Sstevel@tonic-gate 3309daaffb31Sdp if [[ $# == 2 ]]; then 33107c478bd9Sstevel@tonic-gate PP=$2 3311cdf0c1d5Smjnelson oldname="$PP" 33127c478bd9Sstevel@tonic-gate else 33137c478bd9Sstevel@tonic-gate PP=$P 3314daaffb31Sdp oldname="" 3315daaffb31Sdp fi 3316daaffb31Sdp 3317cdf0c1d5Smjnelson mv_but_nodiff= 3318cdf0c1d5Smjnelson cmp $WDIR/raw_files/old/$PP $WDIR/raw_files/new/$P > /dev/null 2>&1 3319cdf0c1d5Smjnelson if [[ $? == 0 && -n "$oldname" ]]; then 3320cdf0c1d5Smjnelson mv_but_nodiff=1 3321cdf0c1d5Smjnelson fi 3322cdf0c1d5Smjnelson 3323daaffb31Sdp DIR=${P%/*} 3324daaffb31Sdp if [[ $DIR == $P ]]; then 3325daaffb31Sdp DIR="." # File at root of workspace 33267c478bd9Sstevel@tonic-gate fi 33277c478bd9Sstevel@tonic-gate 33287c478bd9Sstevel@tonic-gate # Avoid processing the same file twice. 33297c478bd9Sstevel@tonic-gate # It's possible for renamed files to 33307c478bd9Sstevel@tonic-gate # appear twice in the file list 33317c478bd9Sstevel@tonic-gate 33327c478bd9Sstevel@tonic-gate F=$WDIR/$P 33337c478bd9Sstevel@tonic-gate 3334daaffb31Sdp print "<p>" 33357c478bd9Sstevel@tonic-gate 33367c478bd9Sstevel@tonic-gate # If there's a diffs file, make diffs links 33377c478bd9Sstevel@tonic-gate 3338daaffb31Sdp if [[ -f $F.cdiff.html ]]; then 3339371d72daSLubomir Sedlacik cdiff_url="$(print $P.cdiff.html | url_encode)" 3340371d72daSLubomir Sedlacik udiff_url="$(print $P.udiff.html | url_encode)" 3341371d72daSLubomir Sedlacik print "<a href=\"$cdiff_url\">Cdiffs</a>" 3342371d72daSLubomir Sedlacik print "<a href=\"$udiff_url\">Udiffs</a>" 33437c478bd9Sstevel@tonic-gate 3344daaffb31Sdp if [[ -f $F.wdiff.html && -x $WDIFF ]]; then 3345371d72daSLubomir Sedlacik wdiff_url="$(print $P.wdiff.html | url_encode)" 3346371d72daSLubomir Sedlacik print "<a href=\"$wdiff_url\">Wdiffs</a>" 33477c478bd9Sstevel@tonic-gate fi 33487c478bd9Sstevel@tonic-gate 3349371d72daSLubomir Sedlacik sdiff_url="$(print $P.sdiff.html | url_encode)" 3350371d72daSLubomir Sedlacik print "<a href=\"$sdiff_url\">Sdiffs</a>" 33517c478bd9Sstevel@tonic-gate 3352371d72daSLubomir Sedlacik frames_url="$(print $P.frames.html | url_encode)" 3353371d72daSLubomir Sedlacik print "<a href=\"$frames_url\">Frames</a>" 33547c478bd9Sstevel@tonic-gate else 3355daaffb31Sdp print " ------ ------ ------" 33567c478bd9Sstevel@tonic-gate 3357daaffb31Sdp if [[ -x $WDIFF ]]; then 33587c478bd9Sstevel@tonic-gate print " ------" 33597c478bd9Sstevel@tonic-gate fi 3360daaffb31Sdp 3361daaffb31Sdp print " ------" 33627c478bd9Sstevel@tonic-gate fi 33637c478bd9Sstevel@tonic-gate 33647c478bd9Sstevel@tonic-gate # If there's an old file, make the link 33657c478bd9Sstevel@tonic-gate 3366daaffb31Sdp if [[ -f $F-.html ]]; then 3367371d72daSLubomir Sedlacik oldfile_url="$(print $P-.html | url_encode)" 3368371d72daSLubomir Sedlacik print "<a href=\"$oldfile_url\">Old</a>" 33697c478bd9Sstevel@tonic-gate else 3370daaffb31Sdp print " ---" 33717c478bd9Sstevel@tonic-gate fi 33727c478bd9Sstevel@tonic-gate 33737c478bd9Sstevel@tonic-gate # If there's an new file, make the link 33747c478bd9Sstevel@tonic-gate 3375daaffb31Sdp if [[ -f $F.html ]]; then 3376371d72daSLubomir Sedlacik newfile_url="$(print $P.html | url_encode)" 3377371d72daSLubomir Sedlacik print "<a href=\"$newfile_url\">New</a>" 33787c478bd9Sstevel@tonic-gate else 3379daaffb31Sdp print " ---" 33807c478bd9Sstevel@tonic-gate fi 33817c478bd9Sstevel@tonic-gate 3382daaffb31Sdp if [[ -f $F.patch ]]; then 3383371d72daSLubomir Sedlacik patch_url="$(print $P.patch | url_encode)" 3384371d72daSLubomir Sedlacik print "<a href=\"$patch_url\">Patch</a>" 3385daaffb31Sdp else 3386daaffb31Sdp print " -----" 3387daaffb31Sdp fi 3388daaffb31Sdp 3389daaffb31Sdp if [[ -f $WDIR/raw_files/new/$P ]]; then 3390371d72daSLubomir Sedlacik rawfiles_url="$(print raw_files/new/$P | url_encode)" 3391371d72daSLubomir Sedlacik print "<a href=\"$rawfiles_url\">Raw</a>" 3392daaffb31Sdp else 3393daaffb31Sdp print " ---" 3394daaffb31Sdp fi 3395daaffb31Sdp 3396cdf0c1d5Smjnelson print "<b>$P</b>" 3397cdf0c1d5Smjnelson 3398cdf0c1d5Smjnelson # For renamed files, clearly state whether or not they are modified 3399e6ccc173SEdward Pilatowicz if [[ -f "$oldname" ]]; then 3400cdf0c1d5Smjnelson if [[ -n "$mv_but_nodiff" ]]; then 3401e6ccc173SEdward Pilatowicz print "<i>(copied from $oldname)</i>" 3402cdf0c1d5Smjnelson else 3403e6ccc173SEdward Pilatowicz print "<i>(copied and modified from $oldname)</i>" 3404e6ccc173SEdward Pilatowicz fi 3405e6ccc173SEdward Pilatowicz elif [[ -n "$oldname" ]]; then 3406e6ccc173SEdward Pilatowicz if [[ -n "$mv_but_nodiff" ]]; then 3407e6ccc173SEdward Pilatowicz print "<i>(renamed from $oldname)</i>" 3408e6ccc173SEdward Pilatowicz else 3409e6ccc173SEdward Pilatowicz print "<i>(renamed and modified from $oldname)</i>" 3410cdf0c1d5Smjnelson fi 3411cdf0c1d5Smjnelson fi 3412cdf0c1d5Smjnelson 3413cdf0c1d5Smjnelson # If there's an old file, but no new file, the file was deleted 3414cdf0c1d5Smjnelson if [[ -f $F-.html && ! -f $F.html ]]; then 3415cdf0c1d5Smjnelson print " <i>(deleted)</i>" 3416cdf0c1d5Smjnelson fi 3417daaffb31Sdp 3418daaffb31Sdp # 3419e0e0293aSjmcp # Check for usr/closed and deleted_files/usr/closed 3420daaffb31Sdp # 3421daaffb31Sdp if [ ! -z "$Oflag" ]; then 3422e0e0293aSjmcp if [[ $P == usr/closed/* || \ 3423e0e0293aSjmcp $P == deleted_files/usr/closed/* ]]; then 3424daaffb31Sdp print " <i>Closed source: omitted from" \ 3425daaffb31Sdp "this review</i>" 3426daaffb31Sdp fi 3427daaffb31Sdp fi 3428daaffb31Sdp 3429daaffb31Sdp print "</p>" 34307c478bd9Sstevel@tonic-gate # Insert delta comments 34317c478bd9Sstevel@tonic-gate 3432daaffb31Sdp print "<blockquote><pre>" 3433daaffb31Sdp getcomments html $P $PP 3434daaffb31Sdp print "</pre>" 34357c478bd9Sstevel@tonic-gate 34367c478bd9Sstevel@tonic-gate # Add additional comments comment 34377c478bd9Sstevel@tonic-gate 3438daaffb31Sdp print "<!-- Add comments to explain changes in $P here -->" 34397c478bd9Sstevel@tonic-gate 34407c478bd9Sstevel@tonic-gate # Add count of changes. 34417c478bd9Sstevel@tonic-gate 3442daaffb31Sdp if [[ -f $F.count ]]; then 34437c478bd9Sstevel@tonic-gate cat $F.count 34447c478bd9Sstevel@tonic-gate rm $F.count 34457c478bd9Sstevel@tonic-gate fi 3446cdf0c1d5Smjnelson 3447cdf0c1d5Smjnelson if [[ $SCM_MODE == "teamware" || 3448cdf0c1d5Smjnelson $SCM_MODE == "mercurial" || 3449cdf0c1d5Smjnelson $SCM_MODE == "unknown" ]]; then 3450cdf0c1d5Smjnelson 3451cdf0c1d5Smjnelson # Include warnings for important file mode situations: 3452cdf0c1d5Smjnelson # 1) New executable files 3453cdf0c1d5Smjnelson # 2) Permission changes of any kind 3454cdf0c1d5Smjnelson # 3) Existing executable files 3455cdf0c1d5Smjnelson 3456cdf0c1d5Smjnelson old_mode= 3457cdf0c1d5Smjnelson if [[ -f $WDIR/raw_files/old/$PP ]]; then 3458cdf0c1d5Smjnelson old_mode=`get_file_mode $WDIR/raw_files/old/$PP` 3459cdf0c1d5Smjnelson fi 3460cdf0c1d5Smjnelson 3461cdf0c1d5Smjnelson new_mode= 3462cdf0c1d5Smjnelson if [[ -f $WDIR/raw_files/new/$P ]]; then 3463cdf0c1d5Smjnelson new_mode=`get_file_mode $WDIR/raw_files/new/$P` 3464cdf0c1d5Smjnelson fi 3465cdf0c1d5Smjnelson 3466cdf0c1d5Smjnelson if [[ -z "$old_mode" && "$new_mode" = *[1357]* ]]; then 3467cdf0c1d5Smjnelson print "<span class=\"chmod\">" 3468cdf0c1d5Smjnelson print "<p>new executable file: mode $new_mode</p>" 3469cdf0c1d5Smjnelson print "</span>" 3470cdf0c1d5Smjnelson elif [[ -n "$old_mode" && -n "$new_mode" && 3471cdf0c1d5Smjnelson "$old_mode" != "$new_mode" ]]; then 3472cdf0c1d5Smjnelson print "<span class=\"chmod\">" 3473cdf0c1d5Smjnelson print "<p>mode change: $old_mode to $new_mode</p>" 3474cdf0c1d5Smjnelson print "</span>" 3475cdf0c1d5Smjnelson elif [[ "$new_mode" = *[1357]* ]]; then 3476cdf0c1d5Smjnelson print "<span class=\"chmod\">" 3477cdf0c1d5Smjnelson print "<p>executable file: mode $new_mode</p>" 3478cdf0c1d5Smjnelson print "</span>" 3479cdf0c1d5Smjnelson fi 3480cdf0c1d5Smjnelson fi 3481cdf0c1d5Smjnelson 3482daaffb31Sdp print "</blockquote>" 34837c478bd9Sstevel@tonic-gatedone 34847c478bd9Sstevel@tonic-gate 3485daaffb31Sdpprint 3486daaffb31Sdpprint 3487cac38512Smjnelsonprint "<hr></hr>" 3488daaffb31Sdpprint "<p style=\"font-size: small\">" 34899a70fc3bSMark J. Nelsonprint "This code review page was prepared using <b>$0</b>." 3490daaffb31Sdpprint "Webrev is maintained by the <a href=\"http://www.opensolaris.org\">" 3491daaffb31Sdpprint "OpenSolaris</a> project. The latest version may be obtained" 3492e9e2cfb2Sfr80241print "<a href=\"http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/tools/scripts/webrev.sh\">here</a>.</p>" 3493daaffb31Sdpprint "</body>" 3494daaffb31Sdpprint "</html>" 34957c478bd9Sstevel@tonic-gate 34967c478bd9Sstevel@tonic-gateexec 1<&- # Close FD 1. 34977c478bd9Sstevel@tonic-gateexec 1<&3 # dup FD 3 to restore stdout. 34987c478bd9Sstevel@tonic-gateexec 3<&- # close FD 3. 34997c478bd9Sstevel@tonic-gate 3500daaffb31Sdpprint "Done." 350102d26c39SVladimir Kotal 3502b0088928SVladimir Kotal# 3503ba44d8a2SVladimir Kotal# If remote deletion was specified and fails do not continue. 3504b0088928SVladimir Kotal# 3505ba44d8a2SVladimir Kotalif [[ -n $Dflag ]]; then 3506b0088928SVladimir Kotal delete_webrev 1 1 3507ba44d8a2SVladimir Kotal (( $? == 0 )) || exit $? 3508ba44d8a2SVladimir Kotalfi 3509ba44d8a2SVladimir Kotal 351002d26c39SVladimir Kotalif [[ -n $Uflag ]]; then 351102d26c39SVladimir Kotal upload_webrev 351202d26c39SVladimir Kotal exit $? 351302d26c39SVladimir Kotalfi 3514