17c478bd9Sstevel@tonic-gate#!/usr/bin/ksh -p 27c478bd9Sstevel@tonic-gate# 37c478bd9Sstevel@tonic-gate# CDDL HEADER START 47c478bd9Sstevel@tonic-gate# 57c478bd9Sstevel@tonic-gate# The contents of this file are subject to the terms of the 6daaffb31Sdp# Common Development and Distribution License (the "License"). 7daaffb31Sdp# You may not use this file except in compliance with the License. 87c478bd9Sstevel@tonic-gate# 97c478bd9Sstevel@tonic-gate# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate# or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate# See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate# and limitations under the License. 137c478bd9Sstevel@tonic-gate# 147c478bd9Sstevel@tonic-gate# When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate# If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate# fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate# information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate# 207c478bd9Sstevel@tonic-gate# CDDL HEADER END 217c478bd9Sstevel@tonic-gate# 229a70fc3bSMark J. Nelson 237c478bd9Sstevel@tonic-gate# 24371d72daSLubomir Sedlacik# Copyright 2009 Sun Microsystems, Inc. All rights reserved. 257c478bd9Sstevel@tonic-gate# Use is subject to license terms. 267c478bd9Sstevel@tonic-gate# 27cdf0c1d5Smjnelson 28cdf0c1d5Smjnelson# 29daaffb31Sdp# This script takes a file list and a workspace and builds a set of html files 30daaffb31Sdp# suitable for doing a code review of source changes via a web page. 31daaffb31Sdp# Documentation is available via the manual page, webrev.1, or just 32daaffb31Sdp# type 'webrev -h'. 337c478bd9Sstevel@tonic-gate# 34daaffb31Sdp# Acknowledgements to contributors to webrev are listed in the webrev(1) 35daaffb31Sdp# man page. 367c478bd9Sstevel@tonic-gate# 37daaffb31Sdp 387c478bd9Sstevel@tonic-gateREMOVED_COLOR=brown 397c478bd9Sstevel@tonic-gateCHANGED_COLOR=blue 407c478bd9Sstevel@tonic-gateNEW_COLOR=blue 417c478bd9Sstevel@tonic-gate 42daaffb31SdpHTML='<?xml version="1.0"?> 43daaffb31Sdp<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 44daaffb31Sdp "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 45daaffb31Sdp<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">\n' 46daaffb31Sdp 47daaffb31SdpFRAMEHTML='<?xml version="1.0"?> 48daaffb31Sdp<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" 49daaffb31Sdp "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd"> 50daaffb31Sdp<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">\n' 51daaffb31Sdp 52cac38512SmjnelsonSTDHEAD='<meta http-equiv="cache-control" content="no-cache"></meta> 53cac38512Smjnelson<meta http-equiv="Pragma" content="no-cache"></meta> 54cac38512Smjnelson<meta http-equiv="Expires" content="-1"></meta> 55daaffb31Sdp<!-- 56daaffb31Sdp Note to customizers: the body of the webrev is IDed as SUNWwebrev 57daaffb31Sdp to allow easy overriding by users of webrev via the userContent.css 58daaffb31Sdp mechanism available in some browsers. 59daaffb31Sdp 60daaffb31Sdp For example, to have all "removed" information be red instead of 61daaffb31Sdp brown, set a rule in your userContent.css file like: 62daaffb31Sdp 63daaffb31Sdp body#SUNWwebrev span.removed { color: red ! important; } 64daaffb31Sdp--> 65daaffb31Sdp<style type="text/css" media="screen"> 66daaffb31Sdpbody { 67daaffb31Sdp background-color: #eeeeee; 68daaffb31Sdp} 69daaffb31Sdphr { 70daaffb31Sdp border: none 0; 71daaffb31Sdp border-top: 1px solid #aaa; 72daaffb31Sdp height: 1px; 73daaffb31Sdp} 74daaffb31Sdpdiv.summary { 75daaffb31Sdp font-size: .8em; 76daaffb31Sdp border-bottom: 1px solid #aaa; 77daaffb31Sdp padding-left: 1em; 78daaffb31Sdp padding-right: 1em; 79daaffb31Sdp} 80daaffb31Sdpdiv.summary h2 { 81daaffb31Sdp margin-bottom: 0.3em; 82daaffb31Sdp} 83daaffb31Sdpdiv.summary table th { 84daaffb31Sdp text-align: right; 85daaffb31Sdp vertical-align: top; 86daaffb31Sdp white-space: nowrap; 87daaffb31Sdp} 88daaffb31Sdpspan.lineschanged { 89daaffb31Sdp font-size: 0.7em; 90daaffb31Sdp} 91daaffb31Sdpspan.oldmarker { 92daaffb31Sdp color: red; 93daaffb31Sdp font-size: large; 94daaffb31Sdp font-weight: bold; 95daaffb31Sdp} 96daaffb31Sdpspan.newmarker { 97daaffb31Sdp color: green; 98daaffb31Sdp font-size: large; 99daaffb31Sdp font-weight: bold; 100daaffb31Sdp} 101daaffb31Sdpspan.removed { 102daaffb31Sdp color: brown; 103daaffb31Sdp} 104daaffb31Sdpspan.changed { 105daaffb31Sdp color: blue; 106daaffb31Sdp} 107daaffb31Sdpspan.new { 108daaffb31Sdp color: blue; 109daaffb31Sdp font-weight: bold; 110daaffb31Sdp} 111cdf0c1d5Smjnelsonspan.chmod { 112cdf0c1d5Smjnelson font-size: 0.7em; 113cdf0c1d5Smjnelson color: #db7800; 114cdf0c1d5Smjnelson} 115daaffb31Sdpa.print { font-size: x-small; } 116daaffb31Sdpa:hover { background-color: #ffcc99; } 117daaffb31Sdp</style> 118daaffb31Sdp 119daaffb31Sdp<style type="text/css" media="print"> 120daaffb31Sdppre { font-size: 0.8em; font-family: courier, monospace; } 121daaffb31Sdpspan.removed { color: #444; font-style: italic } 122daaffb31Sdpspan.changed { font-weight: bold; } 123daaffb31Sdpspan.new { font-weight: bold; } 124daaffb31Sdpspan.newmarker { font-size: 1.2em; font-weight: bold; } 125daaffb31Sdpspan.oldmarker { font-size: 1.2em; font-weight: bold; } 126daaffb31Sdpa.print {display: none} 127daaffb31Sdphr { border: none 0; border-top: 1px solid #aaa; height: 1px; } 128daaffb31Sdp</style> 129daaffb31Sdp' 130daaffb31Sdp 131daaffb31Sdp# 132daaffb31Sdp# UDiffs need a slightly different CSS rule for 'new' items (we don't 133daaffb31Sdp# want them to be bolded as we do in cdiffs or sdiffs). 134daaffb31Sdp# 135daaffb31SdpUDIFFCSS=' 136daaffb31Sdp<style type="text/css" media="screen"> 137daaffb31Sdpspan.new { 138daaffb31Sdp color: blue; 139daaffb31Sdp font-weight: normal; 140daaffb31Sdp} 141daaffb31Sdp</style> 142daaffb31Sdp' 143daaffb31Sdp 144b0088928SVladimir Kotal# 145b0088928SVladimir Kotal# Display remote target with prefix and trailing slash. 146b0088928SVladimir Kotal# 147b0088928SVladimir Kotalfunction print_upload_header 148b0088928SVladimir Kotal{ 149b0088928SVladimir Kotal typeset -r prefix=$1 150b0088928SVladimir Kotal typeset display_target 151b0088928SVladimir Kotal 152b0088928SVladimir Kotal if [[ -z $tflag ]]; then 153b0088928SVladimir Kotal display_target=${prefix}${remote_target} 154b0088928SVladimir Kotal else 155b0088928SVladimir Kotal display_target=${remote_target} 156b0088928SVladimir Kotal fi 157b0088928SVladimir Kotal 158b0088928SVladimir Kotal if [[ ${display_target} != */ ]]; then 159b0088928SVladimir Kotal display_target=${display_target}/ 160b0088928SVladimir Kotal fi 161b0088928SVladimir Kotal 162b0088928SVladimir Kotal print " Upload to: ${display_target}\n" \ 163b0088928SVladimir Kotal " Uploading: \c" 164b0088928SVladimir Kotal} 165b0088928SVladimir Kotal 166b0088928SVladimir Kotal# 16702d26c39SVladimir Kotal# Upload the webrev via rsync. Return 0 on success, 1 on error. 168b0088928SVladimir Kotal# 169ba44d8a2SVladimir Kotalfunction rsync_upload 17002d26c39SVladimir Kotal{ 171b0088928SVladimir Kotal if (( $# != 2 )); then 172b0088928SVladimir Kotal print "\nERROR: rsync_upload: wrong usage ($#)" 173b0088928SVladimir Kotal exit 1 17402d26c39SVladimir Kotal fi 17502d26c39SVladimir Kotal 176b0088928SVladimir Kotal typeset -r dst=$1 177b0088928SVladimir Kotal integer -r print_err_msg=$2 17802d26c39SVladimir Kotal 179b0088928SVladimir Kotal print_upload_header ${rsync_prefix} 180b0088928SVladimir Kotal print "rsync ... \c" 181b0088928SVladimir Kotal typeset -r err_msg=$( $MKTEMP /tmp/rsync_err.XXX ) 182b0088928SVladimir Kotal if [[ -z $err_msg ]]; then 183b0088928SVladimir Kotal print "\nERROR: rsync_upload: cannot create temporary file" 184b0088928SVladimir Kotal return 1 185b0088928SVladimir Kotal fi 186b0088928SVladimir Kotal # 187b0088928SVladimir Kotal # The source directory must end with a slash in order to copy just 188b0088928SVladimir Kotal # directory contents, not the whole directory. 189b0088928SVladimir Kotal # 190b0088928SVladimir Kotal typeset src_dir=$WDIR 191b0088928SVladimir Kotal if [[ ${src_dir} != */ ]]; then 192b0088928SVladimir Kotal src_dir=${src_dir}/ 193b0088928SVladimir Kotal fi 194b0088928SVladimir Kotal $RSYNC -r -q ${src_dir} $dst 2>$err_msg 19502d26c39SVladimir Kotal if (( $? != 0 )); then 196b0088928SVladimir Kotal if (( ${print_err_msg} > 0 )); then 197b0088928SVladimir Kotal print "Failed.\nERROR: rsync failed" 198b0088928SVladimir Kotal print "src dir: '${src_dir}'\ndst dir: '$dst'" 199b0088928SVladimir Kotal print "error messages:" 200b0088928SVladimir Kotal $SED 's/^/> /' $err_msg 201b0088928SVladimir Kotal rm -f $err_msg 202b0088928SVladimir Kotal fi 20302d26c39SVladimir Kotal return 1 20402d26c39SVladimir Kotal fi 20502d26c39SVladimir Kotal 206b0088928SVladimir Kotal rm -f $err_msg 20702d26c39SVladimir Kotal print "Done." 20802d26c39SVladimir Kotal return 0 20902d26c39SVladimir Kotal} 21002d26c39SVladimir Kotal 211b0088928SVladimir Kotal# 212b0088928SVladimir Kotal# Create directories on remote host using SFTP. Return 0 on success, 213b0088928SVladimir Kotal# 1 on failure. 214b0088928SVladimir Kotal# 215b0088928SVladimir Kotalfunction remote_mkdirs 216b0088928SVladimir Kotal{ 217b0088928SVladimir Kotal typeset -r dir_spec=$1 218b0088928SVladimir Kotal 219b0088928SVladimir Kotal # 220b0088928SVladimir Kotal # If the supplied path is absolute we assume all directories are 221b0088928SVladimir Kotal # created, otherwise try to create all directories in the path 222b0088928SVladimir Kotal # except the last one which will be created by scp. 223b0088928SVladimir Kotal # 224b0088928SVladimir Kotal if [[ "${dir_spec}" == */* && "${dir_spec}" != /* ]]; then 225b0088928SVladimir Kotal print "mkdirs \c" 226b0088928SVladimir Kotal # 227b0088928SVladimir Kotal # Remove the last directory from directory specification. 228b0088928SVladimir Kotal # 229b0088928SVladimir Kotal typeset -r dirs_mk=${dir_spec%/*} 230b0088928SVladimir Kotal typeset -r batch_file_mkdir=$( $MKTEMP /tmp/webrev_mkdir.XXX ) 231b0088928SVladimir Kotal if [[ -z $batch_file_mkdir ]]; then 232b0088928SVladimir Kotal print "\nERROR: remote_mkdirs:" \ 233b0088928SVladimir Kotal "cannot create temporary file for batch file" 234b0088928SVladimir Kotal return 1 235b0088928SVladimir Kotal fi 236b0088928SVladimir Kotal OLDIFS=$IFS 237b0088928SVladimir Kotal IFS=/ 238b0088928SVladimir Kotal typeset dir 239b0088928SVladimir Kotal for dir in ${dirs_mk}; do 240b0088928SVladimir Kotal # 241b0088928SVladimir Kotal # Use the '-' prefix to ignore mkdir errors in order 242b0088928SVladimir Kotal # to avoid an error in case the directory already 243b0088928SVladimir Kotal # exists. We check the directory with chdir to be sure 244b0088928SVladimir Kotal # there is one. 245b0088928SVladimir Kotal # 246b0088928SVladimir Kotal print -- "-mkdir ${dir}" >> ${batch_file_mkdir} 247b0088928SVladimir Kotal print "chdir ${dir}" >> ${batch_file_mkdir} 248b0088928SVladimir Kotal done 249b0088928SVladimir Kotal IFS=$OLDIFS 250b0088928SVladimir Kotal typeset -r sftp_err_msg=$( $MKTEMP /tmp/webrev_scp_err.XXX ) 251b0088928SVladimir Kotal if [[ -z ${sftp_err_msg} ]]; then 252b0088928SVladimir Kotal print "\nERROR: remote_mkdirs:" \ 253b0088928SVladimir Kotal "cannot create temporary file for error messages" 254b0088928SVladimir Kotal return 1 255b0088928SVladimir Kotal fi 256b0088928SVladimir Kotal $SFTP -b ${batch_file_mkdir} ${host_spec} 2>${sftp_err_msg} 1>&2 257b0088928SVladimir Kotal if (( $? != 0 )); then 258b0088928SVladimir Kotal print "\nERROR: failed to create remote directories" 259b0088928SVladimir Kotal print "error messages:" 260b0088928SVladimir Kotal $SED 's/^/> /' ${sftp_err_msg} 261b0088928SVladimir Kotal rm -f ${sftp_err_msg} ${batch_file_mkdir} 262b0088928SVladimir Kotal return 1 263b0088928SVladimir Kotal fi 264b0088928SVladimir Kotal rm -f ${sftp_err_msg} ${batch_file_mkdir} 265b0088928SVladimir Kotal fi 266b0088928SVladimir Kotal 267b0088928SVladimir Kotal return 0 268b0088928SVladimir Kotal} 269b0088928SVladimir Kotal 270b0088928SVladimir Kotal# 27102d26c39SVladimir Kotal# Upload the webrev via SSH. Return 0 on success, 1 on error. 272b0088928SVladimir Kotal# 273ba44d8a2SVladimir Kotalfunction ssh_upload 27402d26c39SVladimir Kotal{ 27502d26c39SVladimir Kotal if (( $# != 1 )); then 276b0088928SVladimir Kotal print "\nERROR: ssh_upload: wrong number of arguments" 277b0088928SVladimir Kotal exit 1 27802d26c39SVladimir Kotal fi 27902d26c39SVladimir Kotal 28002d26c39SVladimir Kotal typeset dst=$1 28102d26c39SVladimir Kotal typeset -r host_spec=${dst%%:*} 282ba44d8a2SVladimir Kotal typeset -r dir_spec=${dst#*:} 28302d26c39SVladimir Kotal 284b0088928SVladimir Kotal # 285b0088928SVladimir Kotal # Display the upload information before calling delete_webrev 286b0088928SVladimir Kotal # because it will also print its progress. 287b0088928SVladimir Kotal # 288b0088928SVladimir Kotal print_upload_header ${ssh_prefix} 289b0088928SVladimir Kotal 290b0088928SVladimir Kotal # 291b0088928SVladimir Kotal # If the deletion was explicitly requested there is no need 292b0088928SVladimir Kotal # to perform it again. 293b0088928SVladimir Kotal # 294ba44d8a2SVladimir Kotal if [[ -z $Dflag ]]; then 295b0088928SVladimir Kotal # 296b0088928SVladimir Kotal # We do not care about return value because this might be 297b0088928SVladimir Kotal # the first time this directory is uploaded. 298b0088928SVladimir Kotal # 299ba44d8a2SVladimir Kotal delete_webrev 0 30002d26c39SVladimir Kotal fi 30102d26c39SVladimir Kotal 302b0088928SVladimir Kotal # 303b0088928SVladimir Kotal # Create remote directories. Any error reporting will be done 304b0088928SVladimir Kotal # in remote_mkdirs function. 305b0088928SVladimir Kotal # 306b0088928SVladimir Kotal remote_mkdirs ${dir_spec} 30702d26c39SVladimir Kotal if (( $? != 0 )); then 30802d26c39SVladimir Kotal return 1 30902d26c39SVladimir Kotal fi 31002d26c39SVladimir Kotal 311b0088928SVladimir Kotal print "upload ... \c" 312b0088928SVladimir Kotal typeset -r scp_err_msg=$( $MKTEMP /tmp/scp_err.XXX ) 313b0088928SVladimir Kotal if [[ -z ${scp_err_msg} ]]; then 314b0088928SVladimir Kotal print "\nERROR: ssh_upload:" \ 315b0088928SVladimir Kotal "cannot create temporary file for error messages" 316b0088928SVladimir Kotal return 1 317b0088928SVladimir Kotal fi 31802d26c39SVladimir Kotal $SCP -q -C -B -o PreferredAuthentications=publickey -r \ 319b0088928SVladimir Kotal $WDIR $dst 2>${scp_err_msg} 32002d26c39SVladimir Kotal if (( $? != 0 )); then 321b0088928SVladimir Kotal print "Failed.\nERROR: scp failed" 322b0088928SVladimir Kotal print "src dir: '$WDIR'\ndst dir: '$dst'" 323b0088928SVladimir Kotal print "error messages:" 324b0088928SVladimir Kotal $SED 's/^/> /' ${scp_err_msg} 325b0088928SVladimir Kotal rm -f ${scp_err_msg} 32602d26c39SVladimir Kotal return 1 32702d26c39SVladimir Kotal fi 32802d26c39SVladimir Kotal 329b0088928SVladimir Kotal rm -f ${scp_err_msg} 33002d26c39SVladimir Kotal print "Done." 33102d26c39SVladimir Kotal return 0 33202d26c39SVladimir Kotal} 33302d26c39SVladimir Kotal 33402d26c39SVladimir Kotal# 335ba44d8a2SVladimir Kotal# Delete webrev at remote site. Return 0 on success, 1 or exit code from sftp 336b0088928SVladimir Kotal# on failure. If first argument is 1 then perform the check of sftp return 337b0088928SVladimir Kotal# value otherwise ignore it. If second argument is present it means this run 338b0088928SVladimir Kotal# only performs deletion. 339ba44d8a2SVladimir Kotal# 340ba44d8a2SVladimir Kotalfunction delete_webrev 341ba44d8a2SVladimir Kotal{ 342b0088928SVladimir Kotal if (( $# < 1 )); then 343b0088928SVladimir Kotal print "delete_webrev: wrong number of arguments" 344b0088928SVladimir Kotal exit 1 345ba44d8a2SVladimir Kotal fi 346ba44d8a2SVladimir Kotal 347b0088928SVladimir Kotal integer -r check=$1 348b0088928SVladimir Kotal integer delete_only=0 349b0088928SVladimir Kotal if (( $# == 2 )); then 350b0088928SVladimir Kotal delete_only=1 351b0088928SVladimir Kotal fi 352b0088928SVladimir Kotal 353b0088928SVladimir Kotal # 354ba44d8a2SVladimir Kotal # Strip the transport specification part of remote target first. 355b0088928SVladimir Kotal # 356ba44d8a2SVladimir Kotal typeset -r stripped_target=${remote_target##*://} 357ba44d8a2SVladimir Kotal typeset -r host_spec=${stripped_target%%:*} 358ba44d8a2SVladimir Kotal typeset -r dir_spec=${stripped_target#*:} 359ba44d8a2SVladimir Kotal typeset dir_rm 360ba44d8a2SVladimir Kotal 361b0088928SVladimir Kotal # 362ba44d8a2SVladimir Kotal # Do not accept an absolute path. 363b0088928SVladimir Kotal # 364ba44d8a2SVladimir Kotal if [[ ${dir_spec} == /* ]]; then 365ba44d8a2SVladimir Kotal return 1 366ba44d8a2SVladimir Kotal fi 367ba44d8a2SVladimir Kotal 368b0088928SVladimir Kotal # 369ba44d8a2SVladimir Kotal # Strip the ending slash. 370b0088928SVladimir Kotal # 371ba44d8a2SVladimir Kotal if [[ ${dir_spec} == */ ]]; then 372ba44d8a2SVladimir Kotal dir_rm=${dir_spec%%/} 373ba44d8a2SVladimir Kotal else 374ba44d8a2SVladimir Kotal dir_rm=${dir_spec} 375ba44d8a2SVladimir Kotal fi 376ba44d8a2SVladimir Kotal 377b0088928SVladimir Kotal if (( ${delete_only} > 0 )); then 378b0088928SVladimir Kotal print " Removing: \c" 379b0088928SVladimir Kotal else 380b0088928SVladimir Kotal print "rmdir \c" 381b0088928SVladimir Kotal fi 382ba44d8a2SVladimir Kotal if [[ -z "$dir_rm" ]]; then 383b0088928SVladimir Kotal print "\nERROR: empty directory for removal" 384ba44d8a2SVladimir Kotal return 1 385ba44d8a2SVladimir Kotal fi 386ba44d8a2SVladimir Kotal 387b0088928SVladimir Kotal # 388ba44d8a2SVladimir Kotal # Prepare batch file. 389b0088928SVladimir Kotal # 390ba44d8a2SVladimir Kotal typeset -r batch_file_rm=$( $MKTEMP /tmp/webrev_remove.XXX ) 391ba44d8a2SVladimir Kotal if [[ -z $batch_file_rm ]]; then 392b0088928SVladimir Kotal print "\nERROR: delete_webrev: cannot create temporary file" 393ba44d8a2SVladimir Kotal return 1 394ba44d8a2SVladimir Kotal fi 395ba44d8a2SVladimir Kotal print "rename $dir_rm $TRASH_DIR/removed.$$" > $batch_file_rm 396ba44d8a2SVladimir Kotal 397b0088928SVladimir Kotal # 398ba44d8a2SVladimir Kotal # Perform remote deletion and remove the batch file. 399b0088928SVladimir Kotal # 400b0088928SVladimir Kotal typeset -r sftp_err_msg=$( $MKTEMP /tmp/webrev_scp_err.XXX ) 401b0088928SVladimir Kotal if [[ -z ${sftp_err_msg} ]]; then 402b0088928SVladimir Kotal print "\nERROR: delete_webrev:" \ 403b0088928SVladimir Kotal "cannot create temporary file for error messages" 404b0088928SVladimir Kotal return 1 405b0088928SVladimir Kotal fi 406b0088928SVladimir Kotal $SFTP -b $batch_file_rm $host_spec 2>${sftp_err_msg} 1>&2 407ba44d8a2SVladimir Kotal integer -r ret=$? 408ba44d8a2SVladimir Kotal rm -f $batch_file_rm 409ba44d8a2SVladimir Kotal if (( $ret != 0 && $check > 0 )); then 410b0088928SVladimir Kotal print "Failed.\nERROR: failed to remove remote directories" 411b0088928SVladimir Kotal print "error messages:" 412b0088928SVladimir Kotal $SED 's/^/> /' ${sftp_err_msg} 413b0088928SVladimir Kotal rm -f ${sftp_err_msg} 414ba44d8a2SVladimir Kotal return $ret 415ba44d8a2SVladimir Kotal fi 416b0088928SVladimir Kotal rm -f ${sftp_err_msg} 417b0088928SVladimir Kotal if (( ${delete_only} > 0 )); then 418ba44d8a2SVladimir Kotal print "Done." 419b0088928SVladimir Kotal fi 420ba44d8a2SVladimir Kotal 421ba44d8a2SVladimir Kotal return 0 422ba44d8a2SVladimir Kotal} 423ba44d8a2SVladimir Kotal 424ba44d8a2SVladimir Kotal# 42502d26c39SVladimir Kotal# Upload webrev to remote site 42602d26c39SVladimir Kotal# 427ba44d8a2SVladimir Kotalfunction upload_webrev 42802d26c39SVladimir Kotal{ 429b0088928SVladimir Kotal integer ret 43002d26c39SVladimir Kotal 43102d26c39SVladimir Kotal if [[ ! -d "$WDIR" ]]; then 432b0088928SVladimir Kotal print "\nERROR: webrev directory '$WDIR' does not exist" 43302d26c39SVladimir Kotal return 1 43402d26c39SVladimir Kotal fi 43502d26c39SVladimir Kotal 436b0088928SVladimir Kotal # 43702d26c39SVladimir Kotal # Perform a late check to make sure we do not upload closed source 43802d26c39SVladimir Kotal # to remote target when -n is used. If the user used custom remote 43902d26c39SVladimir Kotal # target he probably knows what he is doing. 440b0088928SVladimir Kotal # 44102d26c39SVladimir Kotal if [[ -n $nflag && -z $tflag ]]; then 442ba44d8a2SVladimir Kotal $FIND $WDIR -type d -name closed \ 44302d26c39SVladimir Kotal | $GREP closed >/dev/null 44402d26c39SVladimir Kotal if (( $? == 0 )); then 445b0088928SVladimir Kotal print "\nERROR: directory '$WDIR' contains" \ 446b0088928SVladimir Kotal "\"closed\" directory" 44702d26c39SVladimir Kotal return 1 44802d26c39SVladimir Kotal fi 44902d26c39SVladimir Kotal fi 45002d26c39SVladimir Kotal 451b0088928SVladimir Kotal 452b0088928SVladimir Kotal # 453b0088928SVladimir Kotal # We have the URI for remote destination now so let's start the upload. 454b0088928SVladimir Kotal # 45502d26c39SVladimir Kotal if [[ -n $tflag ]]; then 45602d26c39SVladimir Kotal if [[ "${remote_target}" == ${rsync_prefix}?* ]]; then 457b0088928SVladimir Kotal rsync_upload ${remote_target##$rsync_prefix} 1 458b0088928SVladimir Kotal ret=$? 459b0088928SVladimir Kotal return $ret 46002d26c39SVladimir Kotal elif [[ "${remote_target}" == ${ssh_prefix}?* ]]; then 46102d26c39SVladimir Kotal ssh_upload ${remote_target##$ssh_prefix} 462b0088928SVladimir Kotal ret=$? 463b0088928SVladimir Kotal return $ret 46402d26c39SVladimir Kotal fi 46502d26c39SVladimir Kotal else 466b0088928SVladimir Kotal # 467b0088928SVladimir Kotal # Try rsync first and fallback to SSH in case it fails. 468b0088928SVladimir Kotal # 469b0088928SVladimir Kotal rsync_upload ${remote_target} 0 470b0088928SVladimir Kotal ret=$? 471b0088928SVladimir Kotal if (( $ret != 0 )); then 472b0088928SVladimir Kotal print "Failed. (falling back to SSH)" 473ba44d8a2SVladimir Kotal ssh_upload ${remote_target} 474b0088928SVladimir Kotal ret=$? 47502d26c39SVladimir Kotal fi 476b0088928SVladimir Kotal return $ret 47702d26c39SVladimir Kotal fi 47802d26c39SVladimir Kotal} 47902d26c39SVladimir Kotal 480daaffb31Sdp# 481371d72daSLubomir Sedlacik# input_cmd | url_encode | output_cmd 482371d72daSLubomir Sedlacik# 483371d72daSLubomir Sedlacik# URL-encode (percent-encode) reserved characters as defined in RFC 3986. 484371d72daSLubomir Sedlacik# 485371d72daSLubomir Sedlacik# Reserved characters are: :/?#[]@!$&'()*+,;= 486371d72daSLubomir Sedlacik# 487371d72daSLubomir Sedlacik# While not a reserved character itself, percent '%' is reserved by definition 488371d72daSLubomir Sedlacik# so encode it first to avoid recursive transformation, and skip '/' which is 489371d72daSLubomir Sedlacik# a path delimiter. 490371d72daSLubomir Sedlacik# 491371d72daSLubomir Sedlacikfunction url_encode 492371d72daSLubomir Sedlacik{ 493b0088928SVladimir Kotal $SED -e "s|%|%25|g" -e "s|:|%3A|g" -e "s|\&|%26|g" \ 494371d72daSLubomir Sedlacik -e "s|?|%3F|g" -e "s|#|%23|g" -e "s|\[|%5B|g" \ 495371d72daSLubomir Sedlacik -e "s|*|%2A|g" -e "s|@|%40|g" -e "s|\!|%21|g" \ 496371d72daSLubomir Sedlacik -e "s|=|%3D|g" -e "s|;|%3B|g" -e "s|\]|%5D|g" \ 497371d72daSLubomir Sedlacik -e "s|(|%28|g" -e "s|)|%29|g" -e "s|\'|%27|g" \ 498371d72daSLubomir Sedlacik -e "s|+|%2B|g" -e "s|\,|%2C|g" -e "s|\\\$|%24|g" 499371d72daSLubomir Sedlacik} 500371d72daSLubomir Sedlacik 501371d72daSLubomir Sedlacik# 502daaffb31Sdp# input_cmd | html_quote | output_cmd 503daaffb31Sdp# or 504daaffb31Sdp# html_quote filename | output_cmd 5057c478bd9Sstevel@tonic-gate# 5067c478bd9Sstevel@tonic-gate# Make a piece of source code safe for display in an HTML <pre> block. 5077c478bd9Sstevel@tonic-gate# 5087c478bd9Sstevel@tonic-gatehtml_quote() 5097c478bd9Sstevel@tonic-gate{ 510b0088928SVladimir Kotal $SED -e "s/&/\&/g" -e "s/</\</g" -e "s/>/\>/g" "$@" | expand 5117c478bd9Sstevel@tonic-gate} 5127c478bd9Sstevel@tonic-gate 513daaffb31Sdp# 514*0fd2682eSMark J. Nelson# input_cmd | its2url | output_cmd 515daaffb31Sdp# 516*0fd2682eSMark J. Nelson# Scan for information tracking system references and insert <a> links to the 517*0fd2682eSMark J. Nelson# relevant databases. 518daaffb31Sdp# 519*0fd2682eSMark J. Nelsonits2url() 5207c478bd9Sstevel@tonic-gate{ 521*0fd2682eSMark J. Nelson $SED -f ${its_sed_script} 522daaffb31Sdp} 523daaffb31Sdp 5247c478bd9Sstevel@tonic-gate# 525daaffb31Sdp# strip_unchanged <infile> | output_cmd 5267c478bd9Sstevel@tonic-gate# 527daaffb31Sdp# Removes chunks of sdiff documents that have not changed. This makes it 528daaffb31Sdp# easier for a code reviewer to find the bits that have changed. 5297c478bd9Sstevel@tonic-gate# 530daaffb31Sdp# Deleted lines of text are replaced by a horizontal rule. Some 531daaffb31Sdp# identical lines are retained before and after the changed lines to 532daaffb31Sdp# provide some context. The number of these lines is controlled by the 533cdf0c1d5Smjnelson# variable C in the $AWK script below. 534daaffb31Sdp# 535daaffb31Sdp# The script detects changed lines as any line that has a "<span class=" 536daaffb31Sdp# string embedded (unchanged lines have no particular class and are not 537daaffb31Sdp# part of a <span>). Blank lines (without a sequence number) are also 538daaffb31Sdp# detected since they flag lines that have been inserted or deleted. 539daaffb31Sdp# 540daaffb31Sdpstrip_unchanged() 541daaffb31Sdp{ 542cdf0c1d5Smjnelson $AWK ' 543daaffb31Sdp BEGIN { C = c = 20 } 544cdf0c1d5Smjnelson NF == 0 || /<span class="/ { 545daaffb31Sdp if (c > C) { 546daaffb31Sdp c -= C 547daaffb31Sdp inx = 0 548daaffb31Sdp if (c > C) { 549cac38512Smjnelson print "\n</pre><hr></hr><pre>" 550daaffb31Sdp inx = c % C 551daaffb31Sdp c = C 552daaffb31Sdp } 553daaffb31Sdp 554daaffb31Sdp for (i = 0; i < c; i++) 555daaffb31Sdp print ln[(inx + i) % C] 556daaffb31Sdp } 557daaffb31Sdp c = 0; 558daaffb31Sdp print 559daaffb31Sdp next 560daaffb31Sdp } 561daaffb31Sdp { if (c >= C) { 562daaffb31Sdp ln[c % C] = $0 563daaffb31Sdp c++; 564daaffb31Sdp next; 565daaffb31Sdp } 566daaffb31Sdp c++; 567daaffb31Sdp print 568daaffb31Sdp } 569cac38512Smjnelson END { if (c > (C * 2)) print "\n</pre><hr></hr>" } 570daaffb31Sdp 571daaffb31Sdp ' $1 572daaffb31Sdp} 573daaffb31Sdp 574daaffb31Sdp# 575daaffb31Sdp# sdiff_to_html 576daaffb31Sdp# 577daaffb31Sdp# This function takes two files as arguments, obtains their diff, and 578daaffb31Sdp# processes the diff output to present the files as an HTML document with 579daaffb31Sdp# the files displayed side-by-side, differences shown in color. It also 580daaffb31Sdp# takes a delta comment, rendered as an HTML snippet, as the third 581daaffb31Sdp# argument. The function takes two files as arguments, then the name of 582daaffb31Sdp# file, the path, and the comment. The HTML will be delivered on stdout, 583daaffb31Sdp# e.g. 584daaffb31Sdp# 585daaffb31Sdp# $ sdiff_to_html old/usr/src/tools/scripts/webrev.sh \ 586daaffb31Sdp# new/usr/src/tools/scripts/webrev.sh \ 587daaffb31Sdp# webrev.sh usr/src/tools/scripts \ 588daaffb31Sdp# '<a href="http://monaco.sfbay.sun.com/detail.jsp?cr=1234567"> 589daaffb31Sdp# 1234567</a> my bugid' > <file>.html 590daaffb31Sdp# 591daaffb31Sdp# framed_sdiff() is then called which creates $2.frames.html 592daaffb31Sdp# in the webrev tree. 593daaffb31Sdp# 594daaffb31Sdp# FYI: This function is rather unusual in its use of awk. The initial 595daaffb31Sdp# diff run produces conventional diff output showing changed lines mixed 596daaffb31Sdp# with editing codes. The changed lines are ignored - we're interested in 597daaffb31Sdp# the editing codes, e.g. 5987c478bd9Sstevel@tonic-gate# 5997c478bd9Sstevel@tonic-gate# 8c8 6007c478bd9Sstevel@tonic-gate# 57a61 6017c478bd9Sstevel@tonic-gate# 63c66,76 6027c478bd9Sstevel@tonic-gate# 68,93d80 6037c478bd9Sstevel@tonic-gate# 106d90 6047c478bd9Sstevel@tonic-gate# 108,110d91 6057c478bd9Sstevel@tonic-gate# 606daaffb31Sdp# These editing codes are parsed by the awk script and used to generate 607daaffb31Sdp# another awk script that generates HTML, e.g the above lines would turn 608daaffb31Sdp# into something like this: 6097c478bd9Sstevel@tonic-gate# 6107c478bd9Sstevel@tonic-gate# BEGIN { printf "<pre>\n" } 6117c478bd9Sstevel@tonic-gate# function sp(n) {for (i=0;i<n;i++)printf "\n"} 612daaffb31Sdp# function wl(n) {printf "<font color=%s>%4d %s </font>\n", n, NR, $0} 6137c478bd9Sstevel@tonic-gate# NR==8 {wl("#7A7ADD");next} 6147c478bd9Sstevel@tonic-gate# NR==54 {wl("#7A7ADD");sp(3);next} 6157c478bd9Sstevel@tonic-gate# NR==56 {wl("#7A7ADD");next} 6167c478bd9Sstevel@tonic-gate# NR==57 {wl("black");printf "\n"; next} 6177c478bd9Sstevel@tonic-gate# : : 6187c478bd9Sstevel@tonic-gate# 619daaffb31Sdp# This script is then run on the original source file to generate the 620daaffb31Sdp# HTML that corresponds to the source file. 6217c478bd9Sstevel@tonic-gate# 622daaffb31Sdp# The two HTML files are then combined into a single piece of HTML that 623daaffb31Sdp# uses an HTML table construct to present the files side by side. You'll 624daaffb31Sdp# notice that the changes are color-coded: 6257c478bd9Sstevel@tonic-gate# 6267c478bd9Sstevel@tonic-gate# black - unchanged lines 6277c478bd9Sstevel@tonic-gate# blue - changed lines 6287c478bd9Sstevel@tonic-gate# bold blue - new lines 6297c478bd9Sstevel@tonic-gate# brown - deleted lines 6307c478bd9Sstevel@tonic-gate# 631daaffb31Sdp# Blank lines are inserted in each file to keep unchanged lines in sync 632daaffb31Sdp# (side-by-side). This format is familiar to users of sdiff(1) or 633daaffb31Sdp# Teamware's filemerge tool. 634daaffb31Sdp# 635daaffb31Sdpsdiff_to_html() 636daaffb31Sdp{ 6377c478bd9Sstevel@tonic-gate diff -b $1 $2 > /tmp/$$.diffs 6387c478bd9Sstevel@tonic-gate 639daaffb31Sdp TNAME=$3 640daaffb31Sdp TPATH=$4 641daaffb31Sdp COMMENT=$5 642daaffb31Sdp 6437c478bd9Sstevel@tonic-gate # 6447c478bd9Sstevel@tonic-gate # Now we have the diffs, generate the HTML for the old file. 6457c478bd9Sstevel@tonic-gate # 646cdf0c1d5Smjnelson $AWK ' 6477c478bd9Sstevel@tonic-gate BEGIN { 6487c478bd9Sstevel@tonic-gate printf "function sp(n) {for (i=0;i<n;i++)printf \"\\n\"}\n" 649daaffb31Sdp printf "function removed() " 650daaffb31Sdp printf "{printf \"<span class=\\\"removed\\\">%%4d %%s</span>\\n\", NR, $0}\n" 651daaffb31Sdp printf "function changed() " 652daaffb31Sdp printf "{printf \"<span class=\\\"changed\\\">%%4d %%s</span>\\n\", NR, $0}\n" 653daaffb31Sdp printf "function bl() {printf \"%%4d %%s\\n\", NR, $0}\n" 6547c478bd9Sstevel@tonic-gate} 6557c478bd9Sstevel@tonic-gate /^</ {next} 6567c478bd9Sstevel@tonic-gate /^>/ {next} 6577c478bd9Sstevel@tonic-gate /^---/ {next} 658daaffb31Sdp 6597c478bd9Sstevel@tonic-gate { 6607c478bd9Sstevel@tonic-gate split($1, a, /[cad]/) ; 6617c478bd9Sstevel@tonic-gate if (index($1, "a")) { 6627c478bd9Sstevel@tonic-gate if (a[1] == 0) { 6637c478bd9Sstevel@tonic-gate n = split(a[2], r, /,/); 6647c478bd9Sstevel@tonic-gate if (n == 1) 6657c478bd9Sstevel@tonic-gate printf "BEGIN\t\t{sp(1)}\n" 6667c478bd9Sstevel@tonic-gate else 6677c478bd9Sstevel@tonic-gate printf "BEGIN\t\t{sp(%d)}\n",\ 6687c478bd9Sstevel@tonic-gate (r[2] - r[1]) + 1 6697c478bd9Sstevel@tonic-gate next 6707c478bd9Sstevel@tonic-gate } 6717c478bd9Sstevel@tonic-gate 6727c478bd9Sstevel@tonic-gate printf "NR==%s\t\t{", a[1] 6737c478bd9Sstevel@tonic-gate n = split(a[2], r, /,/); 6747c478bd9Sstevel@tonic-gate s = r[1]; 6757c478bd9Sstevel@tonic-gate if (n == 1) 6767c478bd9Sstevel@tonic-gate printf "bl();printf \"\\n\"; next}\n" 6777c478bd9Sstevel@tonic-gate else { 6787c478bd9Sstevel@tonic-gate n = r[2] - r[1] 6797c478bd9Sstevel@tonic-gate printf "bl();sp(%d);next}\n",\ 6807c478bd9Sstevel@tonic-gate (r[2] - r[1]) + 1 6817c478bd9Sstevel@tonic-gate } 6827c478bd9Sstevel@tonic-gate next 6837c478bd9Sstevel@tonic-gate } 6847c478bd9Sstevel@tonic-gate if (index($1, "d")) { 6857c478bd9Sstevel@tonic-gate n = split(a[1], r, /,/); 6867c478bd9Sstevel@tonic-gate n1 = r[1] 6877c478bd9Sstevel@tonic-gate n2 = r[2] 6887c478bd9Sstevel@tonic-gate if (n == 1) 689daaffb31Sdp printf "NR==%s\t\t{removed(); next}\n" , n1 6907c478bd9Sstevel@tonic-gate else 691daaffb31Sdp printf "NR==%s,NR==%s\t{removed(); next}\n" , n1, n2 6927c478bd9Sstevel@tonic-gate next 6937c478bd9Sstevel@tonic-gate } 6947c478bd9Sstevel@tonic-gate if (index($1, "c")) { 6957c478bd9Sstevel@tonic-gate n = split(a[1], r, /,/); 6967c478bd9Sstevel@tonic-gate n1 = r[1] 6977c478bd9Sstevel@tonic-gate n2 = r[2] 6987c478bd9Sstevel@tonic-gate final = n2 6997c478bd9Sstevel@tonic-gate d1 = 0 7007c478bd9Sstevel@tonic-gate if (n == 1) 701daaffb31Sdp printf "NR==%s\t\t{changed();" , n1 7027c478bd9Sstevel@tonic-gate else { 7037c478bd9Sstevel@tonic-gate d1 = n2 - n1 704daaffb31Sdp printf "NR==%s,NR==%s\t{changed();" , n1, n2 7057c478bd9Sstevel@tonic-gate } 7067c478bd9Sstevel@tonic-gate m = split(a[2], r, /,/); 7077c478bd9Sstevel@tonic-gate n1 = r[1] 7087c478bd9Sstevel@tonic-gate n2 = r[2] 7097c478bd9Sstevel@tonic-gate if (m > 1) { 7107c478bd9Sstevel@tonic-gate d2 = n2 - n1 7117c478bd9Sstevel@tonic-gate if (d2 > d1) { 7127c478bd9Sstevel@tonic-gate if (n > 1) printf "if (NR==%d)", final 7137c478bd9Sstevel@tonic-gate printf "sp(%d);", d2 - d1 7147c478bd9Sstevel@tonic-gate } 7157c478bd9Sstevel@tonic-gate } 7167c478bd9Sstevel@tonic-gate printf "next}\n" ; 7177c478bd9Sstevel@tonic-gate 7187c478bd9Sstevel@tonic-gate next 7197c478bd9Sstevel@tonic-gate } 7207c478bd9Sstevel@tonic-gate } 7217c478bd9Sstevel@tonic-gate 722daaffb31Sdp END { printf "{printf \"%%4d %%s\\n\", NR, $0 }\n" } 723daaffb31Sdp ' /tmp/$$.diffs > /tmp/$$.file1 7247c478bd9Sstevel@tonic-gate 7257c478bd9Sstevel@tonic-gate # 7267c478bd9Sstevel@tonic-gate # Now generate the HTML for the new file 7277c478bd9Sstevel@tonic-gate # 728cdf0c1d5Smjnelson $AWK ' 7297c478bd9Sstevel@tonic-gate BEGIN { 7307c478bd9Sstevel@tonic-gate printf "function sp(n) {for (i=0;i<n;i++)printf \"\\n\"}\n" 731daaffb31Sdp printf "function new() " 732daaffb31Sdp printf "{printf \"<span class=\\\"new\\\">%%4d %%s</span>\\n\", NR, $0}\n" 733daaffb31Sdp printf "function changed() " 734daaffb31Sdp printf "{printf \"<span class=\\\"changed\\\">%%4d %%s</span>\\n\", NR, $0}\n" 735daaffb31Sdp printf "function bl() {printf \"%%4d %%s\\n\", NR, $0}\n" 7367c478bd9Sstevel@tonic-gate } 737daaffb31Sdp 7387c478bd9Sstevel@tonic-gate /^</ {next} 7397c478bd9Sstevel@tonic-gate /^>/ {next} 7407c478bd9Sstevel@tonic-gate /^---/ {next} 741daaffb31Sdp 7427c478bd9Sstevel@tonic-gate { 7437c478bd9Sstevel@tonic-gate split($1, a, /[cad]/) ; 7447c478bd9Sstevel@tonic-gate if (index($1, "d")) { 7457c478bd9Sstevel@tonic-gate if (a[2] == 0) { 7467c478bd9Sstevel@tonic-gate n = split(a[1], r, /,/); 7477c478bd9Sstevel@tonic-gate if (n == 1) 7487c478bd9Sstevel@tonic-gate printf "BEGIN\t\t{sp(1)}\n" 7497c478bd9Sstevel@tonic-gate else 7507c478bd9Sstevel@tonic-gate printf "BEGIN\t\t{sp(%d)}\n",\ 7517c478bd9Sstevel@tonic-gate (r[2] - r[1]) + 1 7527c478bd9Sstevel@tonic-gate next 7537c478bd9Sstevel@tonic-gate } 7547c478bd9Sstevel@tonic-gate 7557c478bd9Sstevel@tonic-gate printf "NR==%s\t\t{", a[2] 7567c478bd9Sstevel@tonic-gate n = split(a[1], r, /,/); 7577c478bd9Sstevel@tonic-gate s = r[1]; 7587c478bd9Sstevel@tonic-gate if (n == 1) 7597c478bd9Sstevel@tonic-gate printf "bl();printf \"\\n\"; next}\n" 7607c478bd9Sstevel@tonic-gate else { 7617c478bd9Sstevel@tonic-gate n = r[2] - r[1] 7627c478bd9Sstevel@tonic-gate printf "bl();sp(%d);next}\n",\ 7637c478bd9Sstevel@tonic-gate (r[2] - r[1]) + 1 7647c478bd9Sstevel@tonic-gate } 7657c478bd9Sstevel@tonic-gate next 7667c478bd9Sstevel@tonic-gate } 7677c478bd9Sstevel@tonic-gate if (index($1, "a")) { 7687c478bd9Sstevel@tonic-gate n = split(a[2], r, /,/); 7697c478bd9Sstevel@tonic-gate n1 = r[1] 7707c478bd9Sstevel@tonic-gate n2 = r[2] 7717c478bd9Sstevel@tonic-gate if (n == 1) 772daaffb31Sdp printf "NR==%s\t\t{new() ; next}\n" , n1 7737c478bd9Sstevel@tonic-gate else 774daaffb31Sdp printf "NR==%s,NR==%s\t{new() ; next}\n" , n1, n2 7757c478bd9Sstevel@tonic-gate next 7767c478bd9Sstevel@tonic-gate } 7777c478bd9Sstevel@tonic-gate if (index($1, "c")) { 7787c478bd9Sstevel@tonic-gate n = split(a[2], r, /,/); 7797c478bd9Sstevel@tonic-gate n1 = r[1] 7807c478bd9Sstevel@tonic-gate n2 = r[2] 7817c478bd9Sstevel@tonic-gate final = n2 7827c478bd9Sstevel@tonic-gate d2 = 0; 7837c478bd9Sstevel@tonic-gate if (n == 1) { 7847c478bd9Sstevel@tonic-gate final = n1 785daaffb31Sdp printf "NR==%s\t\t{changed();" , n1 7867c478bd9Sstevel@tonic-gate } else { 7877c478bd9Sstevel@tonic-gate d2 = n2 - n1 788daaffb31Sdp printf "NR==%s,NR==%s\t{changed();" , n1, n2 7897c478bd9Sstevel@tonic-gate } 7907c478bd9Sstevel@tonic-gate m = split(a[1], r, /,/); 7917c478bd9Sstevel@tonic-gate n1 = r[1] 7927c478bd9Sstevel@tonic-gate n2 = r[2] 7937c478bd9Sstevel@tonic-gate if (m > 1) { 7947c478bd9Sstevel@tonic-gate d1 = n2 - n1 7957c478bd9Sstevel@tonic-gate if (d1 > d2) { 7967c478bd9Sstevel@tonic-gate if (n > 1) printf "if (NR==%d)", final 7977c478bd9Sstevel@tonic-gate printf "sp(%d);", d1 - d2 7987c478bd9Sstevel@tonic-gate } 7997c478bd9Sstevel@tonic-gate } 8007c478bd9Sstevel@tonic-gate printf "next}\n" ; 8017c478bd9Sstevel@tonic-gate next 8027c478bd9Sstevel@tonic-gate } 8037c478bd9Sstevel@tonic-gate } 804daaffb31Sdp END { printf "{printf \"%%4d %%s\\n\", NR, $0 }\n" } 8057c478bd9Sstevel@tonic-gate ' /tmp/$$.diffs > /tmp/$$.file2 8067c478bd9Sstevel@tonic-gate 807daaffb31Sdp # 808cdf0c1d5Smjnelson # Post-process the HTML files by running them back through $AWK 809daaffb31Sdp # 810cdf0c1d5Smjnelson html_quote < $1 | $AWK -f /tmp/$$.file1 > /tmp/$$.file1.html 8117c478bd9Sstevel@tonic-gate 812cdf0c1d5Smjnelson html_quote < $2 | $AWK -f /tmp/$$.file2 > /tmp/$$.file2.html 8137c478bd9Sstevel@tonic-gate 814daaffb31Sdp # 815daaffb31Sdp # Now combine into a valid HTML file and side-by-side into a table 816daaffb31Sdp # 817daaffb31Sdp print "$HTML<head>$STDHEAD" 818cdf0c1d5Smjnelson print "<title>$WNAME Sdiff $TPATH/$TNAME</title>" 819daaffb31Sdp print "</head><body id=\"SUNWwebrev\">" 820daaffb31Sdp print "<a class=\"print\" href=\"javascript:print()\">Print this page</a>" 821daaffb31Sdp print "<pre>$COMMENT</pre>\n" 822daaffb31Sdp print "<table><tr valign=\"top\">" 823daaffb31Sdp print "<td><pre>" 8247c478bd9Sstevel@tonic-gate 8257c478bd9Sstevel@tonic-gate strip_unchanged /tmp/$$.file1.html 8267c478bd9Sstevel@tonic-gate 827daaffb31Sdp print "</pre></td><td><pre>" 8287c478bd9Sstevel@tonic-gate 8297c478bd9Sstevel@tonic-gate strip_unchanged /tmp/$$.file2.html 8307c478bd9Sstevel@tonic-gate 831daaffb31Sdp print "</pre></td>" 832daaffb31Sdp print "</tr></table>" 833daaffb31Sdp print "</body></html>" 8347c478bd9Sstevel@tonic-gate 835daaffb31Sdp framed_sdiff $TNAME $TPATH /tmp/$$.file1.html /tmp/$$.file2.html \ 836daaffb31Sdp "$COMMENT" 8377c478bd9Sstevel@tonic-gate} 8387c478bd9Sstevel@tonic-gate 8397c478bd9Sstevel@tonic-gate 840daaffb31Sdp# 841daaffb31Sdp# framed_sdiff <filename> <filepath> <lhsfile> <rhsfile> <comment> 842daaffb31Sdp# 843daaffb31Sdp# Expects lefthand and righthand side html files created by sdiff_to_html. 844daaffb31Sdp# We use insert_anchors() to augment those with HTML navigation anchors, 845daaffb31Sdp# and then emit the main frame. Content is placed into: 846daaffb31Sdp# 847daaffb31Sdp# $WDIR/DIR/$TNAME.lhs.html 848daaffb31Sdp# $WDIR/DIR/$TNAME.rhs.html 849daaffb31Sdp# $WDIR/DIR/$TNAME.frames.html 850daaffb31Sdp# 851daaffb31Sdp# NOTE: We rely on standard usage of $WDIR and $DIR. 852daaffb31Sdp# 8537c478bd9Sstevel@tonic-gatefunction framed_sdiff 8547c478bd9Sstevel@tonic-gate{ 8557c478bd9Sstevel@tonic-gate typeset TNAME=$1 856daaffb31Sdp typeset TPATH=$2 857daaffb31Sdp typeset lhsfile=$3 858daaffb31Sdp typeset rhsfile=$4 859daaffb31Sdp typeset comments=$5 8607c478bd9Sstevel@tonic-gate typeset RTOP 861daaffb31Sdp 8627c478bd9Sstevel@tonic-gate # Enable html files to access WDIR via a relative path. 863daaffb31Sdp RTOP=$(relative_dir $TPATH $WDIR) 864daaffb31Sdp 865daaffb31Sdp # Make the rhs/lhs files and output the frameset file. 866daaffb31Sdp print "$HTML<head>$STDHEAD" > $WDIR/$DIR/$TNAME.lhs.html 867daaffb31Sdp 868daaffb31Sdp cat >> $WDIR/$DIR/$TNAME.lhs.html <<-EOF 8698b3b7b16SMark J. Nelson <script type="text/javascript" src="${RTOP}ancnav.js"></script> 8707c478bd9Sstevel@tonic-gate </head> 871daaffb31Sdp <body id="SUNWwebrev" onkeypress="keypress(event);"> 872cac38512Smjnelson <a name="0"></a> 873cac38512Smjnelson <pre>$comments</pre><hr></hr> 874daaffb31Sdp EOF 875daaffb31Sdp 876daaffb31Sdp cp $WDIR/$DIR/$TNAME.lhs.html $WDIR/$DIR/$TNAME.rhs.html 877daaffb31Sdp 878daaffb31Sdp insert_anchors $lhsfile >> $WDIR/$DIR/$TNAME.lhs.html 879daaffb31Sdp insert_anchors $rhsfile >> $WDIR/$DIR/$TNAME.rhs.html 880daaffb31Sdp 881daaffb31Sdp close='</body></html>' 882daaffb31Sdp 883daaffb31Sdp print $close >> $WDIR/$DIR/$TNAME.lhs.html 884daaffb31Sdp print $close >> $WDIR/$DIR/$TNAME.rhs.html 885daaffb31Sdp 886daaffb31Sdp print "$FRAMEHTML<head>$STDHEAD" > $WDIR/$DIR/$TNAME.frames.html 887daaffb31Sdp print "<title>$WNAME Framed-Sdiff " \ 888daaffb31Sdp "$TPATH/$TNAME</title> </head>" >> $WDIR/$DIR/$TNAME.frames.html 889daaffb31Sdp cat >> $WDIR/$DIR/$TNAME.frames.html <<-EOF 890daaffb31Sdp <frameset rows="*,60"> 891daaffb31Sdp <frameset cols="50%,50%"> 892cac38512Smjnelson <frame src="$TNAME.lhs.html" scrolling="auto" name="lhs"></frame> 893cac38512Smjnelson <frame src="$TNAME.rhs.html" scrolling="auto" name="rhs"></frame> 894daaffb31Sdp </frameset> 8958b3b7b16SMark J. Nelson <frame src="${RTOP}ancnav.html" scrolling="no" marginwidth="0" 896cac38512Smjnelson marginheight="0" name="nav"></frame> 897daaffb31Sdp <noframes> 898daaffb31Sdp <body id="SUNWwebrev"> 899daaffb31Sdp Alas 'frames' webrev requires that your browser supports frames 9007c478bd9Sstevel@tonic-gate and has the feature enabled. 901daaffb31Sdp </body> 902daaffb31Sdp </noframes> 903daaffb31Sdp </frameset> 9047c478bd9Sstevel@tonic-gate </html> 9057c478bd9Sstevel@tonic-gate EOF 9067c478bd9Sstevel@tonic-gate} 9077c478bd9Sstevel@tonic-gate 9087c478bd9Sstevel@tonic-gate 909daaffb31Sdp# 910daaffb31Sdp# fix_postscript 911daaffb31Sdp# 912daaffb31Sdp# Merge codereview output files to a single conforming postscript file, by: 913daaffb31Sdp# - removing all extraneous headers/trailers 914daaffb31Sdp# - making the page numbers right 915daaffb31Sdp# - removing pages devoid of contents which confuse some 916daaffb31Sdp# postscript readers. 917daaffb31Sdp# 918daaffb31Sdp# From Casper. 919daaffb31Sdp# 920daaffb31Sdpfunction fix_postscript 9217c478bd9Sstevel@tonic-gate{ 922daaffb31Sdp infile=$1 9237c478bd9Sstevel@tonic-gate 924daaffb31Sdp cat > /tmp/$$.crmerge.pl << \EOF 9257c478bd9Sstevel@tonic-gate 926daaffb31Sdp print scalar(<>); # %!PS-Adobe--- 927daaffb31Sdp print "%%Orientation: Landscape\n"; 9287c478bd9Sstevel@tonic-gate 929daaffb31Sdp $pno = 0; 930daaffb31Sdp $doprint = 1; 931daaffb31Sdp 932daaffb31Sdp $page = ""; 933daaffb31Sdp 934daaffb31Sdp while (<>) { 935daaffb31Sdp next if (/^%%Pages:\s*\d+/); 936daaffb31Sdp 937daaffb31Sdp if (/^%%Page:/) { 938daaffb31Sdp if ($pno == 0 || $page =~ /\)S/) { 939daaffb31Sdp # Header or single page containing text 940daaffb31Sdp print "%%Page: ? $pno\n" if ($pno > 0); 941daaffb31Sdp print $page; 942daaffb31Sdp $pno++; 943daaffb31Sdp } else { 944daaffb31Sdp # Empty page, skip it. 9457c478bd9Sstevel@tonic-gate } 946daaffb31Sdp $page = ""; 947daaffb31Sdp $doprint = 1; 9487c478bd9Sstevel@tonic-gate next; 9497c478bd9Sstevel@tonic-gate } 9507c478bd9Sstevel@tonic-gate 951daaffb31Sdp # Skip from %%Trailer of one document to Endprolog 952daaffb31Sdp # %%Page of the next 953daaffb31Sdp $doprint = 0 if (/^%%Trailer/); 954daaffb31Sdp $page .= $_ if ($doprint); 9557c478bd9Sstevel@tonic-gate } 9567c478bd9Sstevel@tonic-gate 957daaffb31Sdp if ($page =~ /\)S/) { 958daaffb31Sdp print "%%Page: ? $pno\n"; 959daaffb31Sdp print $page; 960daaffb31Sdp } else { 961daaffb31Sdp $pno--; 962daaffb31Sdp } 963daaffb31Sdp print "%%Trailer\n%%Pages: $pno\n"; 964daaffb31SdpEOF 965daaffb31Sdp 96614983201Sdp $PERL /tmp/$$.crmerge.pl < $infile 967daaffb31Sdp} 968daaffb31Sdp 969daaffb31Sdp 970daaffb31Sdp# 971daaffb31Sdp# input_cmd | insert_anchors | output_cmd 972daaffb31Sdp# 9737c478bd9Sstevel@tonic-gate# Flag blocks of difference with sequentially numbered invisible 974daaffb31Sdp# anchors. These are used to drive the frames version of the 9757c478bd9Sstevel@tonic-gate# sdiffs output. 9767c478bd9Sstevel@tonic-gate# 9777c478bd9Sstevel@tonic-gate# NOTE: Anchor zero flags the top of the file irrespective of changes, 9787c478bd9Sstevel@tonic-gate# an additional anchor is also appended to flag the bottom. 9797c478bd9Sstevel@tonic-gate# 980daaffb31Sdp# The script detects changed lines as any line that has a "<span 981daaffb31Sdp# class=" string embedded (unchanged lines have no class set and are 982daaffb31Sdp# not part of a <span>. Blank lines (without a sequence number) 9837c478bd9Sstevel@tonic-gate# are also detected since they flag lines that have been inserted or 9847c478bd9Sstevel@tonic-gate# deleted. 9857c478bd9Sstevel@tonic-gate# 986daaffb31Sdpfunction insert_anchors 987daaffb31Sdp{ 988cdf0c1d5Smjnelson $AWK ' 9897c478bd9Sstevel@tonic-gate function ia() { 990daaffb31Sdp printf "<a name=\"%d\" id=\"anc%d\"></a>", anc, anc++; 9917c478bd9Sstevel@tonic-gate } 992daaffb31Sdp 9937c478bd9Sstevel@tonic-gate BEGIN { 994daaffb31Sdp anc=1; 9957c478bd9Sstevel@tonic-gate inblock=1; 996daaffb31Sdp printf "<pre>\n"; 9977c478bd9Sstevel@tonic-gate } 998daaffb31Sdp NF == 0 || /^<span class=/ { 9997c478bd9Sstevel@tonic-gate if (inblock == 0) { 10007c478bd9Sstevel@tonic-gate ia(); 10017c478bd9Sstevel@tonic-gate inblock=1; 10027c478bd9Sstevel@tonic-gate } 10037c478bd9Sstevel@tonic-gate print; 10047c478bd9Sstevel@tonic-gate next; 10057c478bd9Sstevel@tonic-gate } 10067c478bd9Sstevel@tonic-gate { 10077c478bd9Sstevel@tonic-gate inblock=0; 10087c478bd9Sstevel@tonic-gate print; 10097c478bd9Sstevel@tonic-gate } 10107c478bd9Sstevel@tonic-gate END { 10117c478bd9Sstevel@tonic-gate ia(); 1012daaffb31Sdp 1013daaffb31Sdp printf "<b style=\"font-size: large; color: red\">"; 1014daaffb31Sdp printf "--- EOF ---</b>" 10157c478bd9Sstevel@tonic-gate for(i=0;i<8;i++) printf "\n\n\n\n\n\n\n\n\n\n"; 1016daaffb31Sdp printf "</pre>" 1017daaffb31Sdp printf "<form name=\"eof\">"; 1018cac38512Smjnelson printf "<input name=\"value\" value=\"%d\" " \ 1019cac38512Smjnelson "type=\"hidden\"></input>", anc - 1; 1020daaffb31Sdp printf "</form>"; 10217c478bd9Sstevel@tonic-gate } 10227c478bd9Sstevel@tonic-gate ' $1 10237c478bd9Sstevel@tonic-gate} 10247c478bd9Sstevel@tonic-gate 10257c478bd9Sstevel@tonic-gate 1026daaffb31Sdp# 1027daaffb31Sdp# relative_dir 1028daaffb31Sdp# 1029daaffb31Sdp# Print a relative return path from $1 to $2. For example if 1030daaffb31Sdp# $1=/tmp/myreview/raw_files/usr/src/tools/scripts and $2=/tmp/myreview, 1031daaffb31Sdp# this function would print "../../../../". 1032daaffb31Sdp# 1033daaffb31Sdp# In the event that $1 is not in $2 a warning is printed to stderr, 1034daaffb31Sdp# and $2 is returned-- the result of this is that the resulting webrev 1035daaffb31Sdp# is not relocatable. 1036daaffb31Sdp# 1037daaffb31Sdpfunction relative_dir 10387c478bd9Sstevel@tonic-gate{ 1039daaffb31Sdp typeset cur="${1##$2?(/)}" 10408b3b7b16SMark J. Nelson 10418b3b7b16SMark J. Nelson # 10428b3b7b16SMark J. Nelson # If the first path was specified absolutely, and it does 10438b3b7b16SMark J. Nelson # not start with the second path, it's an error. 10448b3b7b16SMark J. Nelson # 1045*0fd2682eSMark J. Nelson if [[ "$cur" = "/${1#/}" ]]; then 1046daaffb31Sdp # Should never happen. 104714983201Sdp print -u2 "\nWARNING: relative_dir: \"$1\" not relative " 1048daaffb31Sdp print -u2 "to \"$2\". Check input paths. Framed webrev " 1049daaffb31Sdp print -u2 "will not be relocatable!" 1050daaffb31Sdp print $2 1051daaffb31Sdp return 1052daaffb31Sdp fi 1053daaffb31Sdp 10548b3b7b16SMark J. Nelson # 10558b3b7b16SMark J. Nelson # This is kind of ugly. The sed script will do the following: 10568b3b7b16SMark J. Nelson # 10578b3b7b16SMark J. Nelson # 1. Strip off a leading "." or "./": this is important to get 10588b3b7b16SMark J. Nelson # the correct arcnav links for files in $WDIR. 10598b3b7b16SMark J. Nelson # 2. Strip off a trailing "/": this is not strictly necessary, 10608b3b7b16SMark J. Nelson # but is kind of nice, since it doesn't end up in "//" at 10618b3b7b16SMark J. Nelson # the end of a relative path. 10628b3b7b16SMark J. Nelson # 3. Replace all remaining sequences of non-"/" with "..": the 10638b3b7b16SMark J. Nelson # assumption here is that each dirname represents another 10648b3b7b16SMark J. Nelson # level of relative separation. 10658b3b7b16SMark J. Nelson # 4. Append a trailing "/" only for non-empty paths: this way 10668b3b7b16SMark J. Nelson # the caller doesn't need to duplicate this logic, and does 10678b3b7b16SMark J. Nelson # not end up using $RTOP/file for files in $WDIR. 10688b3b7b16SMark J. Nelson # 1069*0fd2682eSMark J. Nelson print $cur | $SED -e '{ 10708b3b7b16SMark J. Nelson s:^\./*:: 10718b3b7b16SMark J. Nelson s:/$:: 10728b3b7b16SMark J. Nelson s:[^/][^/]*:..:g 1073*0fd2682eSMark J. Nelson s:^\(..*\)$:\1/: 1074*0fd2682eSMark J. Nelson }' 10757c478bd9Sstevel@tonic-gate} 10767c478bd9Sstevel@tonic-gate 1077daaffb31Sdp# 1078daaffb31Sdp# frame_nav_js 1079daaffb31Sdp# 1080daaffb31Sdp# Emit javascript for frame navigation 1081daaffb31Sdp# 1082daaffb31Sdpfunction frame_nav_js 10837c478bd9Sstevel@tonic-gate{ 10847c478bd9Sstevel@tonic-gatecat << \EOF 10857c478bd9Sstevel@tonic-gatevar myInt; 10867c478bd9Sstevel@tonic-gatevar scrolling=0; 1087daaffb31Sdpvar sfactor = 3; 10887c478bd9Sstevel@tonic-gatevar scount=10; 10897c478bd9Sstevel@tonic-gate 10907c478bd9Sstevel@tonic-gatefunction scrollByPix() { 10917c478bd9Sstevel@tonic-gate if (scount<=0) { 10927c478bd9Sstevel@tonic-gate sfactor*=1.2; 10937c478bd9Sstevel@tonic-gate scount=10; 10947c478bd9Sstevel@tonic-gate } 10957c478bd9Sstevel@tonic-gate parent.lhs.scrollBy(0,sfactor); 10967c478bd9Sstevel@tonic-gate parent.rhs.scrollBy(0,sfactor); 10977c478bd9Sstevel@tonic-gate scount--; 10987c478bd9Sstevel@tonic-gate} 10997c478bd9Sstevel@tonic-gate 1100daaffb31Sdpfunction scrollToAnc(num) { 1101daaffb31Sdp 1102daaffb31Sdp // Update the value of the anchor in the form which we use as 1103daaffb31Sdp // storage for this value. setAncValue() will take care of 1104daaffb31Sdp // correcting for overflow and underflow of the value and return 1105daaffb31Sdp // us the new value. 1106daaffb31Sdp num = setAncValue(num); 1107daaffb31Sdp 1108daaffb31Sdp // Set location and scroll back a little to expose previous 1109daaffb31Sdp // lines. 1110daaffb31Sdp // 1111daaffb31Sdp // Note that this could be improved: it is possible although 1112daaffb31Sdp // complex to compute the x and y position of an anchor, and to 1113daaffb31Sdp // scroll to that location directly. 1114daaffb31Sdp // 11157c478bd9Sstevel@tonic-gate parent.lhs.location.replace(parent.lhs.location.pathname + "#" + num); 11167c478bd9Sstevel@tonic-gate parent.rhs.location.replace(parent.rhs.location.pathname + "#" + num); 1117daaffb31Sdp 11187c478bd9Sstevel@tonic-gate parent.lhs.scrollBy(0,-30); 11197c478bd9Sstevel@tonic-gate parent.rhs.scrollBy(0,-30); 11207c478bd9Sstevel@tonic-gate} 11217c478bd9Sstevel@tonic-gate 1122daaffb31Sdpfunction getAncValue() 1123daaffb31Sdp{ 1124daaffb31Sdp return (parseInt(parent.nav.document.diff.real.value)); 1125daaffb31Sdp} 1126daaffb31Sdp 1127daaffb31Sdpfunction setAncValue(val) 1128daaffb31Sdp{ 1129daaffb31Sdp if (val <= 0) { 1130daaffb31Sdp val = 0; 1131daaffb31Sdp parent.nav.document.diff.real.value = val; 1132daaffb31Sdp parent.nav.document.diff.display.value = "BOF"; 1133daaffb31Sdp return (val); 1134daaffb31Sdp } 1135daaffb31Sdp 1136daaffb31Sdp // 1137daaffb31Sdp // The way we compute the max anchor value is to stash it 1138daaffb31Sdp // inline in the left and right hand side pages-- it's the same 1139daaffb31Sdp // on each side, so we pluck from the left. 1140daaffb31Sdp // 1141daaffb31Sdp maxval = parent.lhs.document.eof.value.value; 1142daaffb31Sdp if (val < maxval) { 1143daaffb31Sdp parent.nav.document.diff.real.value = val; 1144daaffb31Sdp parent.nav.document.diff.display.value = val.toString(); 1145daaffb31Sdp return (val); 1146daaffb31Sdp } 1147daaffb31Sdp 1148daaffb31Sdp // this must be: val >= maxval 1149daaffb31Sdp val = maxval; 1150daaffb31Sdp parent.nav.document.diff.real.value = val; 1151daaffb31Sdp parent.nav.document.diff.display.value = "EOF"; 1152daaffb31Sdp return (val); 1153daaffb31Sdp} 1154daaffb31Sdp 11557c478bd9Sstevel@tonic-gatefunction stopScroll() { 11567c478bd9Sstevel@tonic-gate if (scrolling==1) { 11577c478bd9Sstevel@tonic-gate clearInterval(myInt); 11587c478bd9Sstevel@tonic-gate scrolling=0; 11597c478bd9Sstevel@tonic-gate } 11607c478bd9Sstevel@tonic-gate} 11617c478bd9Sstevel@tonic-gate 11627c478bd9Sstevel@tonic-gatefunction startScroll() { 11637c478bd9Sstevel@tonic-gate stopScroll(); 11647c478bd9Sstevel@tonic-gate scrolling=1; 11657c478bd9Sstevel@tonic-gate myInt=setInterval("scrollByPix()",10); 11667c478bd9Sstevel@tonic-gate} 11677c478bd9Sstevel@tonic-gate 11687c478bd9Sstevel@tonic-gatefunction handlePress(b) { 1169daaffb31Sdp 11707c478bd9Sstevel@tonic-gate switch (b) { 11717c478bd9Sstevel@tonic-gate case 1 : 1172daaffb31Sdp scrollToAnc(-1); 11737c478bd9Sstevel@tonic-gate break; 11747c478bd9Sstevel@tonic-gate case 2 : 1175daaffb31Sdp scrollToAnc(getAncValue() - 1); 11767c478bd9Sstevel@tonic-gate break; 11777c478bd9Sstevel@tonic-gate case 3 : 11787c478bd9Sstevel@tonic-gate sfactor=-3; 11797c478bd9Sstevel@tonic-gate startScroll(); 11807c478bd9Sstevel@tonic-gate break; 11817c478bd9Sstevel@tonic-gate case 4 : 11827c478bd9Sstevel@tonic-gate sfactor=3; 11837c478bd9Sstevel@tonic-gate startScroll(); 11847c478bd9Sstevel@tonic-gate break; 11857c478bd9Sstevel@tonic-gate case 5 : 1186daaffb31Sdp scrollToAnc(getAncValue() + 1); 11877c478bd9Sstevel@tonic-gate break; 11887c478bd9Sstevel@tonic-gate case 6 : 1189daaffb31Sdp scrollToAnc(999999); 11907c478bd9Sstevel@tonic-gate break; 11917c478bd9Sstevel@tonic-gate } 11927c478bd9Sstevel@tonic-gate} 11937c478bd9Sstevel@tonic-gate 11947c478bd9Sstevel@tonic-gatefunction handleRelease(b) { 11957c478bd9Sstevel@tonic-gate stopScroll(); 11967c478bd9Sstevel@tonic-gate} 11977c478bd9Sstevel@tonic-gate 1198daaffb31Sdpfunction keypress(ev) { 1199daaffb31Sdp var keynum; 1200daaffb31Sdp var keychar; 1201daaffb31Sdp 1202daaffb31Sdp if (window.event) { // IE 1203daaffb31Sdp keynum = ev.keyCode; 1204daaffb31Sdp } else if (ev.which) { // non-IE 1205daaffb31Sdp keynum = ev.which; 1206daaffb31Sdp } 1207daaffb31Sdp 1208daaffb31Sdp keychar = String.fromCharCode(keynum); 1209daaffb31Sdp 1210daaffb31Sdp if (keychar == "k") { 1211daaffb31Sdp handlePress(2); 1212daaffb31Sdp return (0); 1213daaffb31Sdp } else if (keychar == "j" || keychar == " ") { 1214daaffb31Sdp handlePress(5); 1215daaffb31Sdp return (0); 1216daaffb31Sdp } 1217daaffb31Sdp return (1); 1218daaffb31Sdp} 1219daaffb31Sdp 12207c478bd9Sstevel@tonic-gatefunction ValidateDiffNum(){ 1221daaffb31Sdp val = parent.nav.document.diff.display.value; 1222daaffb31Sdp if (val == "EOF") { 1223daaffb31Sdp scrollToAnc(999999); 1224daaffb31Sdp return; 1225daaffb31Sdp } 1226daaffb31Sdp 1227daaffb31Sdp if (val == "BOF") { 1228daaffb31Sdp scrollToAnc(0); 1229daaffb31Sdp return; 1230daaffb31Sdp } 1231daaffb31Sdp 1232daaffb31Sdp i=parseInt(val); 12337c478bd9Sstevel@tonic-gate if (isNaN(i)) { 1234daaffb31Sdp parent.nav.document.diff.display.value = getAncValue(); 12357c478bd9Sstevel@tonic-gate } else { 1236daaffb31Sdp scrollToAnc(i); 12377c478bd9Sstevel@tonic-gate } 12387c478bd9Sstevel@tonic-gate return false; 12397c478bd9Sstevel@tonic-gate} 12407c478bd9Sstevel@tonic-gate 1241daaffb31SdpEOF 1242daaffb31Sdp} 1243daaffb31Sdp 1244daaffb31Sdp# 1245daaffb31Sdp# frame_navigation 1246daaffb31Sdp# 1247daaffb31Sdp# Output anchor navigation file for framed sdiffs. 1248daaffb31Sdp# 1249daaffb31Sdpfunction frame_navigation 1250daaffb31Sdp{ 1251daaffb31Sdp print "$HTML<head>$STDHEAD" 1252daaffb31Sdp 1253daaffb31Sdp cat << \EOF 1254daaffb31Sdp<title>Anchor Navigation</title> 1255daaffb31Sdp<meta http-equiv="Content-Script-Type" content="text/javascript"> 1256daaffb31Sdp<meta http-equiv="Content-Type" content="text/html"> 1257daaffb31Sdp 1258daaffb31Sdp<style type="text/css"> 1259daaffb31Sdp div.button td { padding-left: 5px; padding-right: 5px; 1260daaffb31Sdp background-color: #eee; text-align: center; 1261daaffb31Sdp border: 1px #444 outset; cursor: pointer; } 1262daaffb31Sdp div.button a { font-weight: bold; color: black } 1263daaffb31Sdp div.button td:hover { background: #ffcc99; } 1264daaffb31Sdp</style> 1265daaffb31SdpEOF 1266daaffb31Sdp 1267cac38512Smjnelson print "<script type=\"text/javascript\" src=\"ancnav.js\"></script>" 1268daaffb31Sdp 1269daaffb31Sdp cat << \EOF 12707c478bd9Sstevel@tonic-gate</head> 1271daaffb31Sdp<body id="SUNWwebrev" bgcolor="#eeeeee" onload="document.diff.real.focus();" 1272daaffb31Sdp onkeypress="keypress(event);"> 12737c478bd9Sstevel@tonic-gate <noscript lang="javascript"> 12747c478bd9Sstevel@tonic-gate <center> 1275cac38512Smjnelson <p><big>Framed Navigation controls require Javascript</big><br></br> 12767c478bd9Sstevel@tonic-gate Either this browser is incompatable or javascript is not enabled</p> 12777c478bd9Sstevel@tonic-gate </center> 12787c478bd9Sstevel@tonic-gate </noscript> 12797c478bd9Sstevel@tonic-gate <table width="100%" border="0" align="center"> 1280daaffb31Sdp <tr> 1281daaffb31Sdp <td valign="middle" width="25%">Diff navigation: 1282daaffb31Sdp Use 'j' and 'k' for next and previous diffs; or use buttons 1283daaffb31Sdp at right</td> 1284daaffb31Sdp <td align="center" valign="top" width="50%"> 12857c478bd9Sstevel@tonic-gate <div class="button"> 1286daaffb31Sdp <table border="0" align="center"> 1287daaffb31Sdp <tr> 1288daaffb31Sdp <td> 12897c478bd9Sstevel@tonic-gate <a onMouseDown="handlePress(1);return true;" 12907c478bd9Sstevel@tonic-gate onMouseUp="handleRelease(1);return true;" 12917c478bd9Sstevel@tonic-gate onMouseOut="handleRelease(1);return true;" 12927c478bd9Sstevel@tonic-gate onClick="return false;" 12937c478bd9Sstevel@tonic-gate title="Go to Beginning Of file">BOF</a></td> 1294daaffb31Sdp <td> 12957c478bd9Sstevel@tonic-gate <a onMouseDown="handlePress(3);return true;" 12967c478bd9Sstevel@tonic-gate onMouseUp="handleRelease(3);return true;" 12977c478bd9Sstevel@tonic-gate onMouseOut="handleRelease(3);return true;" 12987c478bd9Sstevel@tonic-gate title="Scroll Up: Press and Hold to accelerate" 1299daaffb31Sdp onClick="return false;">Scroll Up</a></td> 1300daaffb31Sdp <td> 13017c478bd9Sstevel@tonic-gate <a onMouseDown="handlePress(2);return true;" 13027c478bd9Sstevel@tonic-gate onMouseUp="handleRelease(2);return true;" 13037c478bd9Sstevel@tonic-gate onMouseOut="handleRelease(2);return true;" 13047c478bd9Sstevel@tonic-gate title="Go to previous Diff" 13057c478bd9Sstevel@tonic-gate onClick="return false;">Prev Diff</a> 13067c478bd9Sstevel@tonic-gate </td></tr> 1307daaffb31Sdp 13087c478bd9Sstevel@tonic-gate <tr> 1309daaffb31Sdp <td> 13107c478bd9Sstevel@tonic-gate <a onMouseDown="handlePress(6);return true;" 13117c478bd9Sstevel@tonic-gate onMouseUp="handleRelease(6);return true;" 13127c478bd9Sstevel@tonic-gate onMouseOut="handleRelease(6);return true;" 13137c478bd9Sstevel@tonic-gate onClick="return false;" 13147c478bd9Sstevel@tonic-gate title="Go to End Of File">EOF</a></td> 1315daaffb31Sdp <td> 13167c478bd9Sstevel@tonic-gate <a onMouseDown="handlePress(4);return true;" 13177c478bd9Sstevel@tonic-gate onMouseUp="handleRelease(4);return true;" 13187c478bd9Sstevel@tonic-gate onMouseOut="handleRelease(4);return true;" 13197c478bd9Sstevel@tonic-gate title="Scroll Down: Press and Hold to accelerate" 1320daaffb31Sdp onClick="return false;">Scroll Down</a></td> 1321daaffb31Sdp <td> 13227c478bd9Sstevel@tonic-gate <a onMouseDown="handlePress(5);return true;" 13237c478bd9Sstevel@tonic-gate onMouseUp="handleRelease(5);return true;" 13247c478bd9Sstevel@tonic-gate onMouseOut="handleRelease(5);return true;" 13257c478bd9Sstevel@tonic-gate title="Go to next Diff" 13267c478bd9Sstevel@tonic-gate onClick="return false;">Next Diff</a></td> 1327daaffb31Sdp </tr> 1328daaffb31Sdp </table> 1329daaffb31Sdp </div> 1330daaffb31Sdp </td> 13317c478bd9Sstevel@tonic-gate <th valign="middle" width="25%"> 1332daaffb31Sdp <form action="" name="diff" onsubmit="return ValidateDiffNum();"> 1333cac38512Smjnelson <input name="display" value="BOF" size="8" type="text"></input> 1334cac38512Smjnelson <input name="real" value="0" size="8" type="hidden"></input> 13357c478bd9Sstevel@tonic-gate </form> 13367c478bd9Sstevel@tonic-gate </th> 1337daaffb31Sdp </tr> 13387c478bd9Sstevel@tonic-gate </table> 13397c478bd9Sstevel@tonic-gate </body> 13407c478bd9Sstevel@tonic-gate</html> 13417c478bd9Sstevel@tonic-gateEOF 13427c478bd9Sstevel@tonic-gate} 13437c478bd9Sstevel@tonic-gate 13447c478bd9Sstevel@tonic-gate 1345daaffb31Sdp 1346daaffb31Sdp# 1347daaffb31Sdp# diff_to_html <filename> <filepath> { U | C } <comment> 1348daaffb31Sdp# 1349daaffb31Sdp# Processes the output of diff to produce an HTML file representing either 1350daaffb31Sdp# context or unified diffs. 1351daaffb31Sdp# 13527c478bd9Sstevel@tonic-gatediff_to_html() 13537c478bd9Sstevel@tonic-gate{ 13547c478bd9Sstevel@tonic-gate TNAME=$1 1355daaffb31Sdp TPATH=$2 1356daaffb31Sdp DIFFTYPE=$3 1357daaffb31Sdp COMMENT=$4 1358daaffb31Sdp 1359daaffb31Sdp print "$HTML<head>$STDHEAD" 1360daaffb31Sdp print "<title>$WNAME ${DIFFTYPE}diff $TPATH</title>" 1361daaffb31Sdp 1362daaffb31Sdp if [[ $DIFFTYPE == "U" ]]; then 1363daaffb31Sdp print "$UDIFFCSS" 1364daaffb31Sdp fi 1365daaffb31Sdp 1366daaffb31Sdp cat <<-EOF 1367daaffb31Sdp </head> 1368daaffb31Sdp <body id="SUNWwebrev"> 1369daaffb31Sdp <a class="print" href="javascript:print()">Print this page</a> 1370daaffb31Sdp <pre>$COMMENT</pre> 1371daaffb31Sdp <pre> 1372daaffb31Sdp EOF 13737c478bd9Sstevel@tonic-gate 1374cdf0c1d5Smjnelson html_quote | $AWK ' 1375daaffb31Sdp /^--- new/ { next } 1376daaffb31Sdp /^\+\+\+ new/ { next } 1377daaffb31Sdp /^--- old/ { next } 1378daaffb31Sdp /^\*\*\* old/ { next } 1379daaffb31Sdp /^\*\*\*\*/ { next } 13807c478bd9Sstevel@tonic-gate /^-------/ { printf "<center><h1>%s</h1></center>\n", $0; next } 1381cac38512Smjnelson /^\@\@.*\@\@$/ { printf "</pre><hr></hr><pre>\n"; 1382daaffb31Sdp printf "<span class=\"newmarker\">%s</span>\n", $0; 1383daaffb31Sdp next} 1384daaffb31Sdp 1385cac38512Smjnelson /^\*\*\*/ { printf "<hr></hr><span class=\"oldmarker\">%s</span>\n", $0; 1386daaffb31Sdp next} 1387daaffb31Sdp /^---/ { printf "<span class=\"newmarker\">%s</span>\n", $0; 1388daaffb31Sdp next} 1389daaffb31Sdp /^\+/ {printf "<span class=\"new\">%s</span>\n", $0; next} 1390daaffb31Sdp /^!/ {printf "<span class=\"changed\">%s</span>\n", $0; next} 1391daaffb31Sdp /^-/ {printf "<span class=\"removed\">%s</span>\n", $0; next} 1392daaffb31Sdp {printf "%s\n", $0; next} 13937c478bd9Sstevel@tonic-gate ' 1394daaffb31Sdp 1395daaffb31Sdp print "</pre></body></html>\n" 13967c478bd9Sstevel@tonic-gate} 13977c478bd9Sstevel@tonic-gate 13987c478bd9Sstevel@tonic-gate 1399daaffb31Sdp# 1400daaffb31Sdp# source_to_html { new | old } <filename> 1401daaffb31Sdp# 1402daaffb31Sdp# Process a plain vanilla source file to transform it into an HTML file. 1403daaffb31Sdp# 14047c478bd9Sstevel@tonic-gatesource_to_html() 14057c478bd9Sstevel@tonic-gate{ 14067c478bd9Sstevel@tonic-gate WHICH=$1 14077c478bd9Sstevel@tonic-gate TNAME=$2 14087c478bd9Sstevel@tonic-gate 1409daaffb31Sdp print "$HTML<head>$STDHEAD" 1410cdf0c1d5Smjnelson print "<title>$WNAME $WHICH $TNAME</title>" 1411daaffb31Sdp print "<body id=\"SUNWwebrev\">" 1412daaffb31Sdp print "<pre>" 1413cdf0c1d5Smjnelson html_quote | $AWK '{line += 1 ; printf "%4d %s\n", line, $0 }' 1414daaffb31Sdp print "</pre></body></html>" 14157c478bd9Sstevel@tonic-gate} 14167c478bd9Sstevel@tonic-gate 1417daaffb31Sdp# 1418cdf0c1d5Smjnelson# comments_from_teamware {text|html} parent-file child-file 1419daaffb31Sdp# 1420daaffb31Sdp# Find the first delta in the child that's not in the parent. Get the 1421daaffb31Sdp# newest delta from the parent, get all deltas from the child starting 1422daaffb31Sdp# with that delta, and then get all info starting with the second oldest 1423daaffb31Sdp# delta in that list (the first delta unique to the child). 14247c478bd9Sstevel@tonic-gate# 14257c478bd9Sstevel@tonic-gate# This code adapted from Bill Shannon's "spc" script 1426daaffb31Sdp# 1427daaffb31Sdpcomments_from_teamware() 14287c478bd9Sstevel@tonic-gate{ 1429daaffb31Sdp fmt=$1 1430daaffb31Sdp pfile=$PWS/$2 1431daaffb31Sdp cfile=$CWS/$3 14327c478bd9Sstevel@tonic-gate 1433cdf0c1d5Smjnelson if [[ ! -f $PWS/${2%/*}/SCCS/s.${2##*/} && -n $RWS ]]; then 1434cdf0c1d5Smjnelson pfile=$RWS/$2 1435cdf0c1d5Smjnelson fi 1436cdf0c1d5Smjnelson 1437daaffb31Sdp if [[ -f $pfile ]]; then 1438cdf0c1d5Smjnelson psid=$($SCCS prs -d:I: $pfile 2>/dev/null) 14397c478bd9Sstevel@tonic-gate else 14407c478bd9Sstevel@tonic-gate psid=1.1 14417c478bd9Sstevel@tonic-gate fi 14427c478bd9Sstevel@tonic-gate 1443cdf0c1d5Smjnelson set -A sids $($SCCS prs -l -r$psid -d:I: $cfile 2>/dev/null) 14447c478bd9Sstevel@tonic-gate N=${#sids[@]} 14457c478bd9Sstevel@tonic-gate 1446daaffb31Sdp nawkprg=' 1447daaffb31Sdp /^COMMENTS:/ {p=1; continue} 1448daaffb31Sdp /^D [0-9]+\.[0-9]+/ {printf "--- %s ---\n", $2; p=0; } 1449daaffb31Sdp NF == 0u { continue } 1450daaffb31Sdp {if (p==0) continue; print $0 }' 1451daaffb31Sdp 14527c478bd9Sstevel@tonic-gate if [[ $N -ge 2 ]]; then 14537c478bd9Sstevel@tonic-gate sid1=${sids[$((N-2))]} # Gets 2nd to last sid 14547c478bd9Sstevel@tonic-gate 1455daaffb31Sdp if [[ $fmt == "text" ]]; then 1456cdf0c1d5Smjnelson $SCCS prs -l -r$sid1 $cfile 2>/dev/null | \ 1457cdf0c1d5Smjnelson $AWK "$nawkprg" 1458daaffb31Sdp return 1459daaffb31Sdp fi 1460daaffb31Sdp 1461cdf0c1d5Smjnelson $SCCS prs -l -r$sid1 $cfile 2>/dev/null | \ 1462*0fd2682eSMark J. Nelson html_quote | its2url | $AWK "$nawkprg" 14637c478bd9Sstevel@tonic-gate fi 14647c478bd9Sstevel@tonic-gate} 14657c478bd9Sstevel@tonic-gate 1466daaffb31Sdp# 1467cdf0c1d5Smjnelson# comments_from_wx {text|html} filepath 1468daaffb31Sdp# 1469cdf0c1d5Smjnelson# Given the pathname of a file, find its location in a "wx" active 1470cdf0c1d5Smjnelson# file list and print the following comment. Output is either text or 1471cdf0c1d5Smjnelson# HTML; if the latter, embedded bugids (sequence of 5 or more digits) 1472cdf0c1d5Smjnelson# are turned into URLs. 1473cdf0c1d5Smjnelson# 1474cdf0c1d5Smjnelson# This is also used with Mercurial and the file list provided by hg-active. 1475daaffb31Sdp# 1476daaffb31Sdpcomments_from_wx() 14777c478bd9Sstevel@tonic-gate{ 1478daaffb31Sdp typeset fmt=$1 1479daaffb31Sdp typeset p=$2 14807c478bd9Sstevel@tonic-gate 1481cdf0c1d5Smjnelson comm=`$AWK ' 1482daaffb31Sdp $1 == "'$p'" { 14837c478bd9Sstevel@tonic-gate do getline ; while (NF > 0) 14847c478bd9Sstevel@tonic-gate getline 14857c478bd9Sstevel@tonic-gate while (NF > 0) { print ; getline } 14867c478bd9Sstevel@tonic-gate exit 1487daaffb31Sdp }' < $wxfile` 1488daaffb31Sdp 1489cdf0c1d5Smjnelson if [[ -z $comm ]]; then 1490cdf0c1d5Smjnelson comm="*** NO COMMENTS ***" 1491cdf0c1d5Smjnelson fi 1492cdf0c1d5Smjnelson 1493daaffb31Sdp if [[ $fmt == "text" ]]; then 1494cdf0c1d5Smjnelson print -- "$comm" 1495daaffb31Sdp return 1496daaffb31Sdp fi 1497daaffb31Sdp 1498*0fd2682eSMark J. Nelson print -- "$comm" | html_quote | its2url 1499cdf0c1d5Smjnelson 15007c478bd9Sstevel@tonic-gate} 15017c478bd9Sstevel@tonic-gate 15027c478bd9Sstevel@tonic-gate# 1503daaffb31Sdp# getcomments {text|html} filepath parentpath 1504daaffb31Sdp# 1505daaffb31Sdp# Fetch the comments depending on what SCM mode we're in. 1506daaffb31Sdp# 1507daaffb31Sdpgetcomments() 1508daaffb31Sdp{ 1509daaffb31Sdp typeset fmt=$1 1510daaffb31Sdp typeset p=$2 1511daaffb31Sdp typeset pp=$3 15127c478bd9Sstevel@tonic-gate 15133df69ef3SDarren Moffat if [[ -n $Nflag ]]; then 15143df69ef3SDarren Moffat return 15153df69ef3SDarren Moffat fi 1516cdf0c1d5Smjnelson # 1517cdf0c1d5Smjnelson # Mercurial support uses a file list in wx format, so this 1518cdf0c1d5Smjnelson # will be used there, too 1519cdf0c1d5Smjnelson # 1520daaffb31Sdp if [[ -n $wxfile ]]; then 1521daaffb31Sdp comments_from_wx $fmt $p 1522daaffb31Sdp else 1523daaffb31Sdp if [[ $SCM_MODE == "teamware" ]]; then 1524daaffb31Sdp comments_from_teamware $fmt $pp $p 1525daaffb31Sdp fi 1526daaffb31Sdp fi 1527daaffb31Sdp} 1528daaffb31Sdp 1529daaffb31Sdp# 1530daaffb31Sdp# printCI <total-changed> <inserted> <deleted> <modified> <unchanged> 1531daaffb31Sdp# 1532daaffb31Sdp# Print out Code Inspection figures similar to sccs-prt(1) format. 1533daaffb31Sdp# 1534daaffb31Sdpfunction printCI 1535daaffb31Sdp{ 1536daaffb31Sdp integer tot=$1 ins=$2 del=$3 mod=$4 unc=$5 1537daaffb31Sdp typeset str 1538daaffb31Sdp if (( tot == 1 )); then 1539daaffb31Sdp str="line" 1540daaffb31Sdp else 1541daaffb31Sdp str="lines" 1542daaffb31Sdp fi 1543daaffb31Sdp printf '%d %s changed: %d ins; %d del; %d mod; %d unchg\n' \ 1544daaffb31Sdp $tot $str $ins $del $mod $unc 1545daaffb31Sdp} 1546daaffb31Sdp 1547daaffb31Sdp 1548daaffb31Sdp# 1549daaffb31Sdp# difflines <oldfile> <newfile> 1550daaffb31Sdp# 1551daaffb31Sdp# Calculate and emit number of added, removed, modified and unchanged lines, 1552daaffb31Sdp# and total lines changed, the sum of added + removed + modified. 1553daaffb31Sdp# 15547c478bd9Sstevel@tonic-gatefunction difflines 15557c478bd9Sstevel@tonic-gate{ 1556daaffb31Sdp integer tot mod del ins unc err 15577c478bd9Sstevel@tonic-gate typeset filename 15587c478bd9Sstevel@tonic-gate 1559cdf0c1d5Smjnelson eval $( diff -e $1 $2 | $AWK ' 1560daaffb31Sdp # Change range of lines: N,Nc 15617c478bd9Sstevel@tonic-gate /^[0-9]*,[0-9]*c$/ { 15627c478bd9Sstevel@tonic-gate n=split(substr($1,1,length($1)-1), counts, ","); 15637c478bd9Sstevel@tonic-gate if (n != 2) { 15647c478bd9Sstevel@tonic-gate error=2 15657c478bd9Sstevel@tonic-gate exit; 15667c478bd9Sstevel@tonic-gate } 1567daaffb31Sdp # 1568daaffb31Sdp # 3,5c means lines 3 , 4 and 5 are changed, a total of 3 lines. 1569daaffb31Sdp # following would be 5 - 3 = 2! Hence +1 for correction. 1570daaffb31Sdp # 15717c478bd9Sstevel@tonic-gate r=(counts[2]-counts[1])+1; 1572daaffb31Sdp 1573daaffb31Sdp # 1574daaffb31Sdp # Now count replacement lines: each represents a change instead 1575daaffb31Sdp # of a delete, so increment c and decrement r. 1576daaffb31Sdp # 15777c478bd9Sstevel@tonic-gate while (getline != /^\.$/) { 15787c478bd9Sstevel@tonic-gate c++; 15797c478bd9Sstevel@tonic-gate r--; 15807c478bd9Sstevel@tonic-gate } 1581daaffb31Sdp # 1582daaffb31Sdp # If there were more replacement lines than original lines, 1583daaffb31Sdp # then r will be negative; in this case there are no deletions, 1584daaffb31Sdp # but there are r changes that should be counted as adds, and 1585daaffb31Sdp # since r is negative, subtract it from a and add it to c. 1586daaffb31Sdp # 15877c478bd9Sstevel@tonic-gate if (r < 0) { 15887c478bd9Sstevel@tonic-gate a-=r; 15897c478bd9Sstevel@tonic-gate c+=r; 15907c478bd9Sstevel@tonic-gate } 1591daaffb31Sdp 1592daaffb31Sdp # 1593daaffb31Sdp # If there were more original lines than replacement lines, then 1594daaffb31Sdp # r will be positive; in this case, increment d by that much. 1595daaffb31Sdp # 15967c478bd9Sstevel@tonic-gate if (r > 0) { 15977c478bd9Sstevel@tonic-gate d+=r; 15987c478bd9Sstevel@tonic-gate } 15997c478bd9Sstevel@tonic-gate next; 16007c478bd9Sstevel@tonic-gate } 16017c478bd9Sstevel@tonic-gate 1602daaffb31Sdp # Change lines: Nc 16037c478bd9Sstevel@tonic-gate /^[0-9].*c$/ { 1604daaffb31Sdp # The first line is a replacement; any more are additions. 16057c478bd9Sstevel@tonic-gate if (getline != /^\.$/) { 16067c478bd9Sstevel@tonic-gate c++; 16077c478bd9Sstevel@tonic-gate while (getline != /^\.$/) a++; 16087c478bd9Sstevel@tonic-gate } 16097c478bd9Sstevel@tonic-gate next; 16107c478bd9Sstevel@tonic-gate } 16117c478bd9Sstevel@tonic-gate 1612daaffb31Sdp # Add lines: both Na and N,Na 16137c478bd9Sstevel@tonic-gate /^[0-9].*a$/ { 16147c478bd9Sstevel@tonic-gate while (getline != /^\.$/) a++; 16157c478bd9Sstevel@tonic-gate next; 16167c478bd9Sstevel@tonic-gate } 16177c478bd9Sstevel@tonic-gate 1618daaffb31Sdp # Delete range of lines: N,Nd 16197c478bd9Sstevel@tonic-gate /^[0-9]*,[0-9]*d$/ { 16207c478bd9Sstevel@tonic-gate n=split(substr($1,1,length($1)-1), counts, ","); 16217c478bd9Sstevel@tonic-gate if (n != 2) { 16227c478bd9Sstevel@tonic-gate error=2 16237c478bd9Sstevel@tonic-gate exit; 16247c478bd9Sstevel@tonic-gate } 1625daaffb31Sdp # 1626daaffb31Sdp # 3,5d means lines 3 , 4 and 5 are deleted, a total of 3 lines. 1627daaffb31Sdp # following would be 5 - 3 = 2! Hence +1 for correction. 1628daaffb31Sdp # 16297c478bd9Sstevel@tonic-gate r=(counts[2]-counts[1])+1; 16307c478bd9Sstevel@tonic-gate d+=r; 16317c478bd9Sstevel@tonic-gate next; 16327c478bd9Sstevel@tonic-gate } 16337c478bd9Sstevel@tonic-gate 1634daaffb31Sdp # Delete line: Nd. For example 10d says line 10 is deleted. 16357c478bd9Sstevel@tonic-gate /^[0-9]*d$/ {d++; next} 16367c478bd9Sstevel@tonic-gate 1637daaffb31Sdp # Should not get here! 16387c478bd9Sstevel@tonic-gate { 16397c478bd9Sstevel@tonic-gate error=1; 16407c478bd9Sstevel@tonic-gate exit; 16417c478bd9Sstevel@tonic-gate } 16427c478bd9Sstevel@tonic-gate 1643daaffb31Sdp # Finish off - print results 16447c478bd9Sstevel@tonic-gate END { 1645daaffb31Sdp printf("tot=%d;mod=%d;del=%d;ins=%d;err=%d\n", 16467c478bd9Sstevel@tonic-gate (c+d+a), c, d, a, error); 16477c478bd9Sstevel@tonic-gate }' ) 16487c478bd9Sstevel@tonic-gate 1649cdf0c1d5Smjnelson # End of $AWK, Check to see if any trouble occurred. 16507c478bd9Sstevel@tonic-gate if (( $? > 0 || err > 0 )); then 1651daaffb31Sdp print "Unexpected Error occurred reading" \ 1652daaffb31Sdp "\`diff -e $1 $2\`: \$?=$?, err=" $err 1653daaffb31Sdp return 1654daaffb31Sdp fi 1655daaffb31Sdp 16567c478bd9Sstevel@tonic-gate # Accumulate totals 16577c478bd9Sstevel@tonic-gate (( TOTL += tot )) 1658daaffb31Sdp (( TMOD += mod )) 16597c478bd9Sstevel@tonic-gate (( TDEL += del )) 16607c478bd9Sstevel@tonic-gate (( TINS += ins )) 16617c478bd9Sstevel@tonic-gate # Calculate unchanged lines 1662cdf0c1d5Smjnelson unc=`wc -l < $1` 16637c478bd9Sstevel@tonic-gate if (( unc > 0 )); then 1664daaffb31Sdp (( unc -= del + mod )) 16657c478bd9Sstevel@tonic-gate (( TUNC += unc )) 16667c478bd9Sstevel@tonic-gate fi 16677c478bd9Sstevel@tonic-gate # print summary 1668daaffb31Sdp print "<span class=\"lineschanged\">" 1669daaffb31Sdp printCI $tot $ins $del $mod $unc 1670daaffb31Sdp print "</span>" 16717c478bd9Sstevel@tonic-gate} 16727c478bd9Sstevel@tonic-gate 1673daaffb31Sdp 16747c478bd9Sstevel@tonic-gate# 1675daaffb31Sdp# flist_from_wx 1676daaffb31Sdp# 1677daaffb31Sdp# Sets up webrev to source its information from a wx-formatted file. 1678daaffb31Sdp# Sets the global 'wxfile' variable. 1679daaffb31Sdp# 1680daaffb31Sdpfunction flist_from_wx 16817c478bd9Sstevel@tonic-gate{ 1682daaffb31Sdp typeset argfile=$1 1683daaffb31Sdp if [[ -n ${argfile%%/*} ]]; then 1684daaffb31Sdp # 1685daaffb31Sdp # If the wx file pathname is relative then make it absolute 1686daaffb31Sdp # because the webrev does a "cd" later on. 1687daaffb31Sdp # 1688daaffb31Sdp wxfile=$PWD/$argfile 16897c478bd9Sstevel@tonic-gate else 1690daaffb31Sdp wxfile=$argfile 16917c478bd9Sstevel@tonic-gate fi 16927c478bd9Sstevel@tonic-gate 1693cdf0c1d5Smjnelson $AWK '{ c = 1; print; 16947c478bd9Sstevel@tonic-gate while (getline) { 16957c478bd9Sstevel@tonic-gate if (NF == 0) { c = -c; continue } 16967c478bd9Sstevel@tonic-gate if (c > 0) print 16977c478bd9Sstevel@tonic-gate } 1698daaffb31Sdp }' $wxfile > $FLIST 16997c478bd9Sstevel@tonic-gate 1700daaffb31Sdp print " Done." 1701daaffb31Sdp} 17027c478bd9Sstevel@tonic-gate 1703daaffb31Sdp# 1704daaffb31Sdp# flist_from_teamware [ <args-to-putback-n> ] 1705daaffb31Sdp# 1706daaffb31Sdp# Generate the file list by extracting file names from a putback -n. Some 1707daaffb31Sdp# names may come from the "update/create" messages and others from the 1708daaffb31Sdp# "currently checked out" warning. Renames are detected here too. Extract 1709daaffb31Sdp# values for CODEMGR_WS and CODEMGR_PARENT from the output of the putback 1710daaffb31Sdp# -n as well, but remove them if they are already defined. 1711daaffb31Sdp# 1712daaffb31Sdpfunction flist_from_teamware 1713daaffb31Sdp{ 1714cdf0c1d5Smjnelson if [[ -n $codemgr_parent && -z $parent_webrev ]]; then 1715daaffb31Sdp if [[ ! -d $codemgr_parent/Codemgr_wsdata ]]; then 1716daaffb31Sdp print -u2 "parent $codemgr_parent doesn't look like a" \ 1717daaffb31Sdp "valid teamware workspace" 17187c478bd9Sstevel@tonic-gate exit 1 17197c478bd9Sstevel@tonic-gate fi 1720daaffb31Sdp parent_args="-p $codemgr_parent" 17217c478bd9Sstevel@tonic-gate fi 17227c478bd9Sstevel@tonic-gate 1723daaffb31Sdp print " File list from: 'putback -n $parent_args $*' ... \c" 17247c478bd9Sstevel@tonic-gate 1725daaffb31Sdp putback -n $parent_args $* 2>&1 | 1726cdf0c1d5Smjnelson $AWK ' 1727daaffb31Sdp /^update:|^create:/ {print $2} 1728daaffb31Sdp /^Parent workspace:/ {printf("CODEMGR_PARENT=%s\n",$3)} 1729daaffb31Sdp /^Child workspace:/ {printf("CODEMGR_WS=%s\n",$3)} 1730daaffb31Sdp /^The following files are currently checked out/ {p = 1; continue} 1731daaffb31Sdp NF == 0 {p=0 ; continue} 1732daaffb31Sdp /^rename/ {old=$3} 1733daaffb31Sdp $1 == "to:" {print $2, old} 1734daaffb31Sdp /^"/ {continue} 1735daaffb31Sdp p == 1 {print $1}' | 1736daaffb31Sdp sort -r -k 1,1 -u | sort > $FLIST 17377c478bd9Sstevel@tonic-gate 1738daaffb31Sdp print " Done." 1739daaffb31Sdp} 1740daaffb31Sdp 1741cdf0c1d5Smjnelson# 1742cdf0c1d5Smjnelson# Call hg-active to get the active list output in the wx active list format 1743cdf0c1d5Smjnelson# 1744cdf0c1d5Smjnelsonfunction hg_active_wxfile 1745cdf0c1d5Smjnelson{ 1746cdf0c1d5Smjnelson typeset child=$1 1747cdf0c1d5Smjnelson typeset parent=$2 1748cdf0c1d5Smjnelson 1749cdf0c1d5Smjnelson TMPFLIST=/tmp/$$.active 17509a70fc3bSMark J. Nelson $HG_ACTIVE -w $child -p $parent -o $TMPFLIST 1751cdf0c1d5Smjnelson wxfile=$TMPFLIST 1752cdf0c1d5Smjnelson} 1753cdf0c1d5Smjnelson 1754cdf0c1d5Smjnelson# 1755cdf0c1d5Smjnelson# flist_from_mercurial 1756cdf0c1d5Smjnelson# Call hg-active to get a wx-style active list, and hand it off to 1757cdf0c1d5Smjnelson# flist_from_wx 1758cdf0c1d5Smjnelson# 1759cdf0c1d5Smjnelsonfunction flist_from_mercurial 1760cdf0c1d5Smjnelson{ 1761cdf0c1d5Smjnelson typeset child=$1 1762cdf0c1d5Smjnelson typeset parent=$2 1763cdf0c1d5Smjnelson 1764cdf0c1d5Smjnelson print " File list from: hg-active -p $parent ...\c" 1765cdf0c1d5Smjnelson 1766cdf0c1d5Smjnelson if [[ ! -x $HG_ACTIVE ]]; then 1767cdf0c1d5Smjnelson print # Blank line for the \c above 1768cdf0c1d5Smjnelson print -u2 "Error: hg-active tool not found. Exiting" 1769cdf0c1d5Smjnelson exit 1 1770cdf0c1d5Smjnelson fi 1771cdf0c1d5Smjnelson hg_active_wxfile $child $parent 1772cdf0c1d5Smjnelson 1773cdf0c1d5Smjnelson # flist_from_wx prints the Done, so we don't have to. 1774cdf0c1d5Smjnelson flist_from_wx $TMPFLIST 1775cdf0c1d5Smjnelson} 1776cdf0c1d5Smjnelson 1777cdf0c1d5Smjnelson# 1778cdf0c1d5Smjnelson# flist_from_subversion 1779cdf0c1d5Smjnelson# 1780cdf0c1d5Smjnelson# Generate the file list by extracting file names from svn status. 1781cdf0c1d5Smjnelson# 1782cdf0c1d5Smjnelsonfunction flist_from_subversion 1783cdf0c1d5Smjnelson{ 1784cdf0c1d5Smjnelson CWS=$1 1785cdf0c1d5Smjnelson OLDPWD=$2 1786cdf0c1d5Smjnelson 1787cdf0c1d5Smjnelson cd $CWS 1788cdf0c1d5Smjnelson print -u2 " File list from: svn status ... \c" 1789cdf0c1d5Smjnelson svn status | $AWK '/^[ACDMR]/ { print $NF }' > $FLIST 1790cdf0c1d5Smjnelson print -u2 " Done." 1791cdf0c1d5Smjnelson cd $OLDPWD 1792cdf0c1d5Smjnelson} 1793cdf0c1d5Smjnelson 1794daaffb31Sdpfunction env_from_flist 1795daaffb31Sdp{ 1796daaffb31Sdp [[ -r $FLIST ]] || return 1797daaffb31Sdp 1798daaffb31Sdp # 1799daaffb31Sdp # Use "eval" to set env variables that are listed in the file 1800daaffb31Sdp # list. Then copy those into our local versions of those 1801daaffb31Sdp # variables if they have not been set already. 1802daaffb31Sdp # 1803b0088928SVladimir Kotal eval `$SED -e "s/#.*$//" $FLIST | $GREP = ` 18047c478bd9Sstevel@tonic-gate 1805cdf0c1d5Smjnelson if [[ -z $codemgr_ws && -n $CODEMGR_WS ]]; then 1806cdf0c1d5Smjnelson codemgr_ws=$CODEMGR_WS 1807cdf0c1d5Smjnelson export CODEMGR_WS 1808cdf0c1d5Smjnelson fi 18097c478bd9Sstevel@tonic-gate 1810daaffb31Sdp # 1811daaffb31Sdp # Check to see if CODEMGR_PARENT is set in the flist file. 1812daaffb31Sdp # 1813cdf0c1d5Smjnelson if [[ -z $codemgr_parent && -n $CODEMGR_PARENT ]]; then 1814daaffb31Sdp codemgr_parent=$CODEMGR_PARENT 1815cdf0c1d5Smjnelson export CODEMGR_PARENT 1816daaffb31Sdp fi 1817daaffb31Sdp} 1818daaffb31Sdp 181914983201Sdpfunction look_for_prog 182014983201Sdp{ 182114983201Sdp typeset path 182214983201Sdp typeset ppath 182314983201Sdp typeset progname=$1 182414983201Sdp 182514983201Sdp ppath=$PATH 182614983201Sdp ppath=$ppath:/usr/sfw/bin:/usr/bin:/usr/sbin 182714983201Sdp ppath=$ppath:/opt/teamware/bin:/opt/onbld/bin 1828cdf0c1d5Smjnelson ppath=$ppath:/opt/onbld/bin/`uname -p` 182914983201Sdp 183014983201Sdp PATH=$ppath prog=`whence $progname` 183114983201Sdp if [[ -n $prog ]]; then 183214983201Sdp print $prog 183314983201Sdp fi 183414983201Sdp} 183514983201Sdp 1836cdf0c1d5Smjnelsonfunction get_file_mode 1837cdf0c1d5Smjnelson{ 1838cdf0c1d5Smjnelson $PERL -e ' 1839cdf0c1d5Smjnelson if (@stat = stat($ARGV[0])) { 1840cdf0c1d5Smjnelson $mode = $stat[2] & 0777; 1841cdf0c1d5Smjnelson printf "%03o\n", $mode; 1842cdf0c1d5Smjnelson exit 0; 1843cdf0c1d5Smjnelson } else { 1844cdf0c1d5Smjnelson exit 1; 1845cdf0c1d5Smjnelson } 1846cdf0c1d5Smjnelson ' $1 1847cdf0c1d5Smjnelson} 1848cdf0c1d5Smjnelson 1849cdf0c1d5Smjnelsonfunction build_old_new_teamware 1850cdf0c1d5Smjnelson{ 1851cdf0c1d5Smjnelson typeset olddir="$1" 1852cdf0c1d5Smjnelson typeset newdir="$2" 1853cdf0c1d5Smjnelson 1854cdf0c1d5Smjnelson # If the child's version doesn't exist then 1855cdf0c1d5Smjnelson # get a readonly copy. 1856cdf0c1d5Smjnelson 1857cdf0c1d5Smjnelson if [[ ! -f $CWS/$DIR/$F && -f $CWS/$DIR/SCCS/s.$F ]]; then 1858cdf0c1d5Smjnelson $SCCS get -s -p $CWS/$DIR/$F > $CWS/$DIR/$F 1859cdf0c1d5Smjnelson fi 1860cdf0c1d5Smjnelson 1861cdf0c1d5Smjnelson # The following two sections propagate file permissions the 1862cdf0c1d5Smjnelson # same way SCCS does. If the file is already under version 1863cdf0c1d5Smjnelson # control, always use permissions from the SCCS/s.file. If 1864cdf0c1d5Smjnelson # the file is not under SCCS control, use permissions from the 1865cdf0c1d5Smjnelson # working copy. In all cases, the file copied to the webrev 1866cdf0c1d5Smjnelson # is set to read only, and group/other permissions are set to 1867cdf0c1d5Smjnelson # match those of the file owner. This way, even if the file 1868cdf0c1d5Smjnelson # is currently checked out, the webrev will display the final 1869cdf0c1d5Smjnelson # permissions that would result after check in. 1870cdf0c1d5Smjnelson 1871cdf0c1d5Smjnelson # 1872cdf0c1d5Smjnelson # Snag new version of file. 1873cdf0c1d5Smjnelson # 1874cdf0c1d5Smjnelson rm -f $newdir/$DIR/$F 1875cdf0c1d5Smjnelson cp $CWS/$DIR/$F $newdir/$DIR/$F 1876cdf0c1d5Smjnelson if [[ -f $CWS/$DIR/SCCS/s.$F ]]; then 1877cdf0c1d5Smjnelson chmod `get_file_mode $CWS/$DIR/SCCS/s.$F` \ 1878cdf0c1d5Smjnelson $newdir/$DIR/$F 1879cdf0c1d5Smjnelson fi 1880cdf0c1d5Smjnelson chmod u-w,go=u $newdir/$DIR/$F 1881cdf0c1d5Smjnelson 1882cdf0c1d5Smjnelson # 1883cdf0c1d5Smjnelson # Get the parent's version of the file. First see whether the 1884cdf0c1d5Smjnelson # child's version is checked out and get the parent's version 1885cdf0c1d5Smjnelson # with keywords expanded or unexpanded as appropriate. 1886cdf0c1d5Smjnelson # 1887cdf0c1d5Smjnelson if [[ -f $PWS/$PDIR/$PF && ! -f $PWS/$PDIR/SCCS/s.$PF && \ 1888cdf0c1d5Smjnelson ! -f $PWS/$PDIR/SCCS/p.$PF ]]; then 1889cdf0c1d5Smjnelson # Parent is not a real workspace, but just a raw 1890cdf0c1d5Smjnelson # directory tree - use the file that's there as 1891cdf0c1d5Smjnelson # the old file. 1892cdf0c1d5Smjnelson 1893cdf0c1d5Smjnelson rm -f $olddir/$PDIR/$PF 1894cdf0c1d5Smjnelson cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF 1895cdf0c1d5Smjnelson else 1896cdf0c1d5Smjnelson if [[ -f $PWS/$PDIR/SCCS/s.$PF ]]; then 1897cdf0c1d5Smjnelson real_parent=$PWS 1898cdf0c1d5Smjnelson else 1899cdf0c1d5Smjnelson real_parent=$RWS 1900cdf0c1d5Smjnelson fi 1901cdf0c1d5Smjnelson 1902cdf0c1d5Smjnelson rm -f $olddir/$PDIR/$PF 1903cdf0c1d5Smjnelson 1904cdf0c1d5Smjnelson if [[ -f $real_parent/$PDIR/$PF ]]; then 1905cdf0c1d5Smjnelson if [ -f $CWS/$DIR/SCCS/p.$F ]; then 1906cdf0c1d5Smjnelson $SCCS get -s -p -k $real_parent/$PDIR/$PF > \ 1907cdf0c1d5Smjnelson $olddir/$PDIR/$PF 1908cdf0c1d5Smjnelson else 1909cdf0c1d5Smjnelson $SCCS get -s -p $real_parent/$PDIR/$PF > \ 1910cdf0c1d5Smjnelson $olddir/$PDIR/$PF 1911cdf0c1d5Smjnelson fi 1912cdf0c1d5Smjnelson chmod `get_file_mode $real_parent/$PDIR/SCCS/s.$PF` \ 1913cdf0c1d5Smjnelson $olddir/$PDIR/$PF 1914cdf0c1d5Smjnelson fi 1915cdf0c1d5Smjnelson fi 1916cdf0c1d5Smjnelson if [[ -f $olddir/$PDIR/$PF ]]; then 1917cdf0c1d5Smjnelson chmod u-w,go=u $olddir/$PDIR/$PF 1918cdf0c1d5Smjnelson fi 1919cdf0c1d5Smjnelson} 1920cdf0c1d5Smjnelson 1921cdf0c1d5Smjnelsonfunction build_old_new_mercurial 1922cdf0c1d5Smjnelson{ 1923cdf0c1d5Smjnelson typeset olddir="$1" 1924cdf0c1d5Smjnelson typeset newdir="$2" 1925cdf0c1d5Smjnelson typeset old_mode= 1926cdf0c1d5Smjnelson typeset new_mode= 1927cdf0c1d5Smjnelson typeset file 1928cdf0c1d5Smjnelson 1929cdf0c1d5Smjnelson # 1930cdf0c1d5Smjnelson # Get old file mode, from the parent revision manifest entry. 1931cdf0c1d5Smjnelson # Mercurial only stores a "file is executable" flag, but the 1932cdf0c1d5Smjnelson # manifest will display an octal mode "644" or "755". 1933cdf0c1d5Smjnelson # 1934cdf0c1d5Smjnelson if [[ "$PDIR" == "." ]]; then 1935cdf0c1d5Smjnelson file="$PF" 1936cdf0c1d5Smjnelson else 1937cdf0c1d5Smjnelson file="$PDIR/$PF" 1938cdf0c1d5Smjnelson fi 1939b0088928SVladimir Kotal file=`echo $file | $SED 's#/#\\\/#g'` 1940cdf0c1d5Smjnelson # match the exact filename, and return only the permission digits 1941b0088928SVladimir Kotal old_mode=`$SED -n -e "/^\\(...\\) . ${file}$/s//\\1/p" \ 1942cdf0c1d5Smjnelson < $HG_PARENT_MANIFEST` 1943cdf0c1d5Smjnelson 1944cdf0c1d5Smjnelson # 1945cdf0c1d5Smjnelson # Get new file mode, directly from the filesystem. 1946cdf0c1d5Smjnelson # Normalize the mode to match Mercurial's behavior. 1947cdf0c1d5Smjnelson # 1948cdf0c1d5Smjnelson new_mode=`get_file_mode $CWS/$DIR/$F` 1949cdf0c1d5Smjnelson if [[ -n "$new_mode" ]]; then 1950cdf0c1d5Smjnelson if [[ "$new_mode" = *[1357]* ]]; then 1951cdf0c1d5Smjnelson new_mode=755 1952cdf0c1d5Smjnelson else 1953cdf0c1d5Smjnelson new_mode=644 1954cdf0c1d5Smjnelson fi 1955cdf0c1d5Smjnelson fi 1956cdf0c1d5Smjnelson 1957cdf0c1d5Smjnelson # 1958cdf0c1d5Smjnelson # new version of the file. 1959cdf0c1d5Smjnelson # 1960cdf0c1d5Smjnelson rm -rf $newdir/$DIR/$F 1961cdf0c1d5Smjnelson if [[ -e $CWS/$DIR/$F ]]; then 1962cdf0c1d5Smjnelson cp $CWS/$DIR/$F $newdir/$DIR/$F 1963cdf0c1d5Smjnelson if [[ -n $new_mode ]]; then 1964cdf0c1d5Smjnelson chmod $new_mode $newdir/$DIR/$F 1965cdf0c1d5Smjnelson else 1966cdf0c1d5Smjnelson # should never happen 1967cdf0c1d5Smjnelson print -u2 "ERROR: set mode of $newdir/$DIR/$F" 1968cdf0c1d5Smjnelson fi 1969cdf0c1d5Smjnelson fi 1970cdf0c1d5Smjnelson 1971cdf0c1d5Smjnelson # 1972cdf0c1d5Smjnelson # parent's version of the file 1973cdf0c1d5Smjnelson # 1974cdf0c1d5Smjnelson # Note that we get this from the last version common to both 1975cdf0c1d5Smjnelson # ourselves and the parent. References are via $CWS since we have no 1976cdf0c1d5Smjnelson # guarantee that the parent workspace is reachable via the filesystem. 1977cdf0c1d5Smjnelson # 1978cdf0c1d5Smjnelson if [[ -n $parent_webrev && -e $PWS/$PDIR/$PF ]]; then 1979cdf0c1d5Smjnelson cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF 1980cdf0c1d5Smjnelson elif [[ -n $HG_PARENT ]]; then 1981cdf0c1d5Smjnelson hg cat -R $CWS -r $HG_PARENT $CWS/$PDIR/$PF > \ 1982cdf0c1d5Smjnelson $olddir/$PDIR/$PF 2>/dev/null 1983cdf0c1d5Smjnelson 198402d26c39SVladimir Kotal if (( $? != 0 )); then 1985cdf0c1d5Smjnelson rm -f $olddir/$PDIR/$PF 1986cdf0c1d5Smjnelson else 1987cdf0c1d5Smjnelson if [[ -n $old_mode ]]; then 1988cdf0c1d5Smjnelson chmod $old_mode $olddir/$PDIR/$PF 1989cdf0c1d5Smjnelson else 1990cdf0c1d5Smjnelson # should never happen 1991cdf0c1d5Smjnelson print -u2 "ERROR: set mode of $olddir/$PDIR/$PF" 1992cdf0c1d5Smjnelson fi 1993cdf0c1d5Smjnelson fi 1994cdf0c1d5Smjnelson fi 1995cdf0c1d5Smjnelson} 1996cdf0c1d5Smjnelson 1997cdf0c1d5Smjnelsonfunction build_old_new_subversion 1998cdf0c1d5Smjnelson{ 1999cdf0c1d5Smjnelson typeset olddir="$1" 2000cdf0c1d5Smjnelson typeset newdir="$2" 2001cdf0c1d5Smjnelson 2002cdf0c1d5Smjnelson # Snag new version of file. 2003cdf0c1d5Smjnelson rm -f $newdir/$DIR/$F 2004cdf0c1d5Smjnelson [[ -e $CWS/$DIR/$F ]] && cp $CWS/$DIR/$F $newdir/$DIR/$F 2005cdf0c1d5Smjnelson 2006cdf0c1d5Smjnelson if [[ -n $PWS && -e $PWS/$PDIR/$PF ]]; then 2007cdf0c1d5Smjnelson cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF 2008cdf0c1d5Smjnelson else 2009cdf0c1d5Smjnelson # Get the parent's version of the file. 2010cdf0c1d5Smjnelson svn status $CWS/$DIR/$F | read stat file 2011cdf0c1d5Smjnelson if [[ $stat != "A" ]]; then 2012cdf0c1d5Smjnelson svn cat -r BASE $CWS/$DIR/$F > $olddir/$PDIR/$PF 2013cdf0c1d5Smjnelson fi 2014cdf0c1d5Smjnelson fi 2015cdf0c1d5Smjnelson} 2016cdf0c1d5Smjnelson 2017cdf0c1d5Smjnelsonfunction build_old_new_unknown 2018cdf0c1d5Smjnelson{ 2019cdf0c1d5Smjnelson typeset olddir="$1" 2020cdf0c1d5Smjnelson typeset newdir="$2" 2021cdf0c1d5Smjnelson 2022cdf0c1d5Smjnelson # 2023cdf0c1d5Smjnelson # Snag new version of file. 2024cdf0c1d5Smjnelson # 2025cdf0c1d5Smjnelson rm -f $newdir/$DIR/$F 2026cdf0c1d5Smjnelson [[ -e $CWS/$DIR/$F ]] && cp $CWS/$DIR/$F $newdir/$DIR/$F 2027cdf0c1d5Smjnelson 2028cdf0c1d5Smjnelson # 2029cdf0c1d5Smjnelson # Snag the parent's version of the file. 2030cdf0c1d5Smjnelson # 2031cdf0c1d5Smjnelson if [[ -f $PWS/$PDIR/$PF ]]; then 2032cdf0c1d5Smjnelson rm -f $olddir/$PDIR/$PF 2033cdf0c1d5Smjnelson cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF 2034cdf0c1d5Smjnelson fi 2035cdf0c1d5Smjnelson} 2036cdf0c1d5Smjnelson 2037cdf0c1d5Smjnelsonfunction build_old_new 2038cdf0c1d5Smjnelson{ 2039cdf0c1d5Smjnelson typeset WDIR=$1 2040cdf0c1d5Smjnelson typeset PWS=$2 2041cdf0c1d5Smjnelson typeset PDIR=$3 2042cdf0c1d5Smjnelson typeset PF=$4 2043cdf0c1d5Smjnelson typeset CWS=$5 2044cdf0c1d5Smjnelson typeset DIR=$6 2045cdf0c1d5Smjnelson typeset F=$7 2046cdf0c1d5Smjnelson 2047cdf0c1d5Smjnelson typeset olddir="$WDIR/raw_files/old" 2048cdf0c1d5Smjnelson typeset newdir="$WDIR/raw_files/new" 2049cdf0c1d5Smjnelson 2050cdf0c1d5Smjnelson mkdir -p $olddir/$PDIR 2051cdf0c1d5Smjnelson mkdir -p $newdir/$DIR 2052cdf0c1d5Smjnelson 2053cdf0c1d5Smjnelson if [[ $SCM_MODE == "teamware" ]]; then 2054cdf0c1d5Smjnelson build_old_new_teamware "$olddir" "$newdir" 2055cdf0c1d5Smjnelson elif [[ $SCM_MODE == "mercurial" ]]; then 2056cdf0c1d5Smjnelson build_old_new_mercurial "$olddir" "$newdir" 2057cdf0c1d5Smjnelson elif [[ $SCM_MODE == "subversion" ]]; then 2058cdf0c1d5Smjnelson build_old_new_subversion "$olddir" "$newdir" 2059cdf0c1d5Smjnelson elif [[ $SCM_MODE == "unknown" ]]; then 2060cdf0c1d5Smjnelson build_old_new_unknown "$olddir" "$newdir" 2061cdf0c1d5Smjnelson fi 2062cdf0c1d5Smjnelson 2063cdf0c1d5Smjnelson if [[ ! -f $olddir/$PDIR/$PF && ! -f $newdir/$DIR/$F ]]; then 2064cdf0c1d5Smjnelson print "*** Error: file not in parent or child" 2065cdf0c1d5Smjnelson return 1 2066cdf0c1d5Smjnelson fi 2067cdf0c1d5Smjnelson return 0 2068cdf0c1d5Smjnelson} 2069cdf0c1d5Smjnelson 2070cdf0c1d5Smjnelson 2071daaffb31Sdp# 2072daaffb31Sdp# Usage message. 2073daaffb31Sdp# 2074daaffb31Sdpfunction usage 2075daaffb31Sdp{ 2076daaffb31Sdp print 'Usage:\twebrev [common-options] 2077daaffb31Sdp webrev [common-options] ( <file> | - ) 2078daaffb31Sdp webrev [common-options] -w <wx file> 2079daaffb31Sdp 2080daaffb31SdpOptions: 2081*0fd2682eSMark J. Nelson -C <filename>: Use <filename> for the information tracking configuration. 2082ba44d8a2SVladimir Kotal -D: delete remote webrev 2083daaffb31Sdp -i <filename>: Include <filename> in the index.html file. 2084*0fd2682eSMark J. Nelson -I <filename>: Use <filename> for the information tracking registry. 2085ba44d8a2SVladimir Kotal -n: do not generate the webrev (useful with -U) 2086ba44d8a2SVladimir Kotal -O: Print bugids/arc cases suitable for OpenSolaris. 2087daaffb31Sdp -o <outdir>: Output webrev to specified directory. 2088daaffb31Sdp -p <compare-against>: Use specified parent wkspc or basis for comparison 208902d26c39SVladimir Kotal -t <remote_target>: Specify remote destination for webrev upload 209002d26c39SVladimir Kotal -U: upload the webrev to remote destination 2091daaffb31Sdp -w <wxfile>: Use specified wx active file. 2092daaffb31Sdp 2093daaffb31SdpEnvironment: 2094daaffb31Sdp WDIR: Control the output directory. 2095ba44d8a2SVladimir Kotal WEBREV_TRASH_DIR: Set directory for webrev delete. 2096daaffb31Sdp 2097cdf0c1d5SmjnelsonSCM Specific Options: 2098cdf0c1d5Smjnelson TeamWare: webrev [common-options] -l [arguments to 'putback'] 2099cdf0c1d5Smjnelson 2100daaffb31SdpSCM Environment: 2101cdf0c1d5Smjnelson CODEMGR_WS: Workspace location. 2102cdf0c1d5Smjnelson CODEMGR_PARENT: Parent workspace location. 2103daaffb31Sdp' 2104daaffb31Sdp 2105daaffb31Sdp exit 2 2106daaffb31Sdp} 2107daaffb31Sdp 2108daaffb31Sdp# 2109daaffb31Sdp# 2110daaffb31Sdp# Main program starts here 2111daaffb31Sdp# 2112daaffb31Sdp# 2113daaffb31Sdp 2114daaffb31Sdptrap "rm -f /tmp/$$.* ; exit" 0 1 2 3 15 2115daaffb31Sdp 2116daaffb31Sdpset +o noclobber 2117daaffb31Sdp 2118cdf0c1d5SmjnelsonPATH=$(dirname $(whence $0)):$PATH 2119cdf0c1d5Smjnelson 212014983201Sdp[[ -z $WDIFF ]] && WDIFF=`look_for_prog wdiff` 212114983201Sdp[[ -z $WX ]] && WX=`look_for_prog wx` 2122cdf0c1d5Smjnelson[[ -z $HG_ACTIVE ]] && HG_ACTIVE=`look_for_prog hg-active` 2123cdf0c1d5Smjnelson[[ -z $WHICH_SCM ]] && WHICH_SCM=`look_for_prog which_scm` 212414983201Sdp[[ -z $CODEREVIEW ]] && CODEREVIEW=`look_for_prog codereview` 212514983201Sdp[[ -z $PS2PDF ]] && PS2PDF=`look_for_prog ps2pdf` 212614983201Sdp[[ -z $PERL ]] && PERL=`look_for_prog perl` 212702d26c39SVladimir Kotal[[ -z $RSYNC ]] && RSYNC=`look_for_prog rsync` 2128cdf0c1d5Smjnelson[[ -z $SCCS ]] && SCCS=`look_for_prog sccs` 2129cdf0c1d5Smjnelson[[ -z $AWK ]] && AWK=`look_for_prog nawk` 2130cdf0c1d5Smjnelson[[ -z $AWK ]] && AWK=`look_for_prog gawk` 2131cdf0c1d5Smjnelson[[ -z $AWK ]] && AWK=`look_for_prog awk` 213202d26c39SVladimir Kotal[[ -z $SCP ]] && SCP=`look_for_prog scp` 2133b0088928SVladimir Kotal[[ -z $SED ]] && SED=`look_for_prog sed` 213402d26c39SVladimir Kotal[[ -z $SFTP ]] && SFTP=`look_for_prog sftp` 213502d26c39SVladimir Kotal[[ -z $MKTEMP ]] && MKTEMP=`look_for_prog mktemp` 213602d26c39SVladimir Kotal[[ -z $GREP ]] && GREP=`look_for_prog grep` 2137ba44d8a2SVladimir Kotal[[ -z $FIND ]] && FIND=`look_for_prog find` 2138cdf0c1d5Smjnelson 2139ba44d8a2SVladimir Kotal# set name of trash directory for remote webrev deletion 2140ba44d8a2SVladimir KotalTRASH_DIR=".trash" 2141ba44d8a2SVladimir Kotal[[ -n $WEBREV_TRASH_DIR ]] && TRASH_DIR=$WEBREV_TRASH_DIR 214214983201Sdp 214314983201Sdpif [[ ! -x $PERL ]]; then 214414983201Sdp print -u2 "Error: No perl interpreter found. Exiting." 214514983201Sdp exit 1 2146daaffb31Sdpfi 214714983201Sdp 2148cdf0c1d5Smjnelsonif [[ ! -x $WHICH_SCM ]]; then 2149cdf0c1d5Smjnelson print -u2 "Error: Could not find which_scm. Exiting." 2150cdf0c1d5Smjnelson exit 1 2151cdf0c1d5Smjnelsonfi 2152cdf0c1d5Smjnelson 215314983201Sdp# 215414983201Sdp# These aren't fatal, but we want to note them to the user. 215514983201Sdp# We don't warn on the absence of 'wx' until later when we've 215614983201Sdp# determined that we actually need to try to invoke it. 215714983201Sdp# 215814983201Sdp[[ ! -x $CODEREVIEW ]] && print -u2 "WARNING: codereview(1) not found." 215914983201Sdp[[ ! -x $PS2PDF ]] && print -u2 "WARNING: ps2pdf(1) not found." 216014983201Sdp[[ ! -x $WDIFF ]] && print -u2 "WARNING: wdiff not found." 2161daaffb31Sdp 2162daaffb31Sdp# Declare global total counters. 2163daaffb31Sdpinteger TOTL TINS TDEL TMOD TUNC 2164daaffb31Sdp 2165ba44d8a2SVladimir Kotal# default remote host for upload/delete 2166ba44d8a2SVladimir Kotaltypeset -r DEFAULT_REMOTE_HOST="cr.opensolaris.org" 2167b0088928SVladimir Kotal# prefixes for upload targets 2168b0088928SVladimir Kotaltypeset -r rsync_prefix="rsync://" 2169b0088928SVladimir Kotaltypeset -r ssh_prefix="ssh://" 2170ba44d8a2SVladimir Kotal 2171*0fd2682eSMark J. NelsonCflag= 2172ba44d8a2SVladimir KotalDflag= 217314983201Sdpflist_mode= 217414983201Sdpflist_file= 2175daaffb31Sdpiflag= 2176*0fd2682eSMark J. NelsonIflag= 217702d26c39SVladimir Kotallflag= 217802d26c39SVladimir KotalNflag= 217902d26c39SVladimir Kotalnflag= 218002d26c39SVladimir KotalOflag= 2181daaffb31Sdpoflag= 2182daaffb31Sdppflag= 218302d26c39SVladimir Kotaltflag= 218402d26c39SVladimir Kotaluflag= 218502d26c39SVladimir KotalUflag= 2186daaffb31Sdpwflag= 218702d26c39SVladimir Kotalremote_target= 2188ba44d8a2SVladimir Kotal 2189ba44d8a2SVladimir Kotal# 2190ba44d8a2SVladimir Kotal# NOTE: when adding/removing options it is necessary to sync the list 2191ba44d8a2SVladimir Kotal# with usr/src/tools/onbld/hgext/cdm.py 2192ba44d8a2SVladimir Kotal# 2193*0fd2682eSMark J. Nelsonwhile getopts "C:tDi:I:lnNo:Op::Uw" opt 2194daaffb31Sdpdo 2195daaffb31Sdp case $opt in 2196*0fd2682eSMark J. Nelson C) Cflag=1 2197*0fd2682eSMark J. Nelson ITSCONF=$OPTARG;; 2198*0fd2682eSMark J. Nelson 2199ba44d8a2SVladimir Kotal D) Dflag=1;; 2200ba44d8a2SVladimir Kotal 2201daaffb31Sdp i) iflag=1 2202daaffb31Sdp INCLUDE_FILE=$OPTARG;; 2203daaffb31Sdp 2204*0fd2682eSMark J. Nelson I) Iflag=1 2205*0fd2682eSMark J. Nelson ITSREG=$OPTARG;; 2206*0fd2682eSMark J. Nelson 2207daaffb31Sdp # 2208daaffb31Sdp # If -l has been specified, we need to abort further options 2209daaffb31Sdp # processing, because subsequent arguments are going to be 2210daaffb31Sdp # arguments to 'putback -n'. 2211daaffb31Sdp # 2212daaffb31Sdp l) lflag=1 2213daaffb31Sdp break;; 2214daaffb31Sdp 221502d26c39SVladimir Kotal N) Nflag=1;; 221602d26c39SVladimir Kotal 221702d26c39SVladimir Kotal n) nflag=1;; 2218daaffb31Sdp 2219daaffb31Sdp O) Oflag=1;; 2220daaffb31Sdp 222102d26c39SVladimir Kotal o) oflag=1 222202d26c39SVladimir Kotal WDIR=$OPTARG;; 222302d26c39SVladimir Kotal 222402d26c39SVladimir Kotal p) pflag=1 222502d26c39SVladimir Kotal codemgr_parent=$OPTARG;; 222602d26c39SVladimir Kotal 222702d26c39SVladimir Kotal t) tflag=1 222802d26c39SVladimir Kotal remote_target=$OPTARG;; 222902d26c39SVladimir Kotal 223002d26c39SVladimir Kotal U) Uflag=1;; 223102d26c39SVladimir Kotal 223202d26c39SVladimir Kotal w) wflag=1;; 22333df69ef3SDarren Moffat 2234daaffb31Sdp ?) usage;; 2235daaffb31Sdp esac 2236daaffb31Sdpdone 2237daaffb31Sdp 2238daaffb31SdpFLIST=/tmp/$$.flist 2239daaffb31Sdp 2240daaffb31Sdpif [[ -n $wflag && -n $lflag ]]; then 2241daaffb31Sdp usage 2242daaffb31Sdpfi 2243daaffb31Sdp 224402d26c39SVladimir Kotal# more sanity checking 224502d26c39SVladimir Kotalif [[ -n $nflag && -z $Uflag ]]; then 2246ba44d8a2SVladimir Kotal print "it does not make sense to skip webrev generation" \ 2247ba44d8a2SVladimir Kotal "without -U" 224802d26c39SVladimir Kotal exit 1 224902d26c39SVladimir Kotalfi 225002d26c39SVladimir Kotal 2251ba44d8a2SVladimir Kotalif [[ -n $tflag && -z $Uflag && -z $Dflag ]]; then 2252ba44d8a2SVladimir Kotal echo "remote target has to be used only for upload or delete" 225302d26c39SVladimir Kotal exit 1 225402d26c39SVladimir Kotalfi 225502d26c39SVladimir Kotal 2256daaffb31Sdp# 2257*0fd2682eSMark J. Nelson# If the command line options indicate no webrev generation, either 2258*0fd2682eSMark J. Nelson# explicitly (-n) or implicitly (-D but not -U), then there's a whole 2259*0fd2682eSMark J. Nelson# ton of logic we can skip. 2260*0fd2682eSMark J. Nelson# 2261*0fd2682eSMark J. Nelson# Instead of increasing indentation, we intentionally leave this loop 2262*0fd2682eSMark J. Nelson# body open here, and exit via break from multiple points within. 2263*0fd2682eSMark J. Nelson# Search for DO_EVERYTHING below to find the break points and closure. 2264*0fd2682eSMark J. Nelson# 2265*0fd2682eSMark J. Nelsonfor do_everything in 1; do 2266*0fd2682eSMark J. Nelson 2267*0fd2682eSMark J. Nelson# DO_EVERYTHING: break point 2268*0fd2682eSMark J. Nelsonif [[ -n $nflag || ( -z $Uflag && -n $Dflag ) ]]; then 2269*0fd2682eSMark J. Nelson break 2270*0fd2682eSMark J. Nelsonfi 2271*0fd2682eSMark J. Nelson 2272*0fd2682eSMark J. Nelson# 2273daaffb31Sdp# If this manually set as the parent, and it appears to be an earlier webrev, 2274daaffb31Sdp# then note that fact and set the parent to the raw_files/new subdirectory. 2275daaffb31Sdp# 2276daaffb31Sdpif [[ -n $pflag && -d $codemgr_parent/raw_files/new ]]; then 2277daaffb31Sdp parent_webrev="$codemgr_parent" 2278daaffb31Sdp codemgr_parent="$codemgr_parent/raw_files/new" 2279daaffb31Sdpfi 2280daaffb31Sdp 2281daaffb31Sdpif [[ -z $wflag && -z $lflag ]]; then 2282daaffb31Sdp shift $(($OPTIND - 1)) 2283daaffb31Sdp 2284daaffb31Sdp if [[ $1 == "-" ]]; then 2285daaffb31Sdp cat > $FLIST 228614983201Sdp flist_mode="stdin" 228714983201Sdp flist_done=1 228814983201Sdp shift 2289daaffb31Sdp elif [[ -n $1 ]]; then 229014983201Sdp if [[ ! -r $1 ]]; then 2291daaffb31Sdp print -u2 "$1: no such file or not readable" 2292daaffb31Sdp usage 2293daaffb31Sdp fi 2294daaffb31Sdp cat $1 > $FLIST 229514983201Sdp flist_mode="file" 229614983201Sdp flist_file=$1 229714983201Sdp flist_done=1 229814983201Sdp shift 2299daaffb31Sdp else 230014983201Sdp flist_mode="auto" 2301daaffb31Sdp fi 2302daaffb31Sdpfi 2303daaffb31Sdp 2304daaffb31Sdp# 2305daaffb31Sdp# Before we go on to further consider -l and -w, work out which SCM we think 2306daaffb31Sdp# is in use. 2307daaffb31Sdp# 2308cdf0c1d5Smjnelson$WHICH_SCM | read SCM_MODE junk || exit 1 2309cdf0c1d5Smjnelsoncase "$SCM_MODE" in 2310cdf0c1d5Smjnelsonteamware|mercurial|subversion) 2311cdf0c1d5Smjnelson ;; 2312cdf0c1d5Smjnelsonunknown) 2313cdf0c1d5Smjnelson if [[ $flist_mode == "auto" ]]; then 2314cdf0c1d5Smjnelson print -u2 "Unable to determine SCM in use and file list not specified" 2315cdf0c1d5Smjnelson print -u2 "See which_scm(1) for SCM detection information." 23167c478bd9Sstevel@tonic-gate exit 1 23177c478bd9Sstevel@tonic-gate fi 2318cdf0c1d5Smjnelson ;; 2319cdf0c1d5Smjnelson*) 2320cdf0c1d5Smjnelson if [[ $flist_mode == "auto" ]]; then 2321cdf0c1d5Smjnelson print -u2 "Unsupported SCM in use ($SCM_MODE) and file list not specified" 2322cdf0c1d5Smjnelson exit 1 2323cdf0c1d5Smjnelson fi 2324cdf0c1d5Smjnelson ;; 2325cdf0c1d5Smjnelsonesac 23267c478bd9Sstevel@tonic-gate 2327daaffb31Sdpprint -u2 " SCM detected: $SCM_MODE" 2328daaffb31Sdp 2329daaffb31Sdpif [[ -n $lflag ]]; then 2330daaffb31Sdp # 2331daaffb31Sdp # If the -l flag is given instead of the name of a file list, 2332daaffb31Sdp # then generate the file list by extracting file names from a 2333daaffb31Sdp # putback -n. 2334daaffb31Sdp # 2335daaffb31Sdp shift $(($OPTIND - 1)) 2336cdf0c1d5Smjnelson if [[ $SCM_MODE == "teamware" ]]; then 2337daaffb31Sdp flist_from_teamware "$*" 2338cdf0c1d5Smjnelson else 2339cdf0c1d5Smjnelson print -u2 -- "Error: -l option only applies to TeamWare" 2340cdf0c1d5Smjnelson exit 1 2341cdf0c1d5Smjnelson fi 2342daaffb31Sdp flist_done=1 2343daaffb31Sdp shift $# 2344daaffb31Sdpelif [[ -n $wflag ]]; then 2345daaffb31Sdp # 2346daaffb31Sdp # If the -w is given then assume the file list is in Bonwick's "wx" 2347daaffb31Sdp # command format, i.e. pathname lines alternating with SCCS comment 2348daaffb31Sdp # lines with blank lines as separators. Use the SCCS comments later 2349daaffb31Sdp # in building the index.html file. 2350daaffb31Sdp # 2351daaffb31Sdp shift $(($OPTIND - 1)) 2352daaffb31Sdp wxfile=$1 2353daaffb31Sdp if [[ -z $wxfile && -n $CODEMGR_WS ]]; then 2354daaffb31Sdp if [[ -r $CODEMGR_WS/wx/active ]]; then 2355daaffb31Sdp wxfile=$CODEMGR_WS/wx/active 2356daaffb31Sdp fi 2357daaffb31Sdp fi 2358daaffb31Sdp 2359daaffb31Sdp [[ -z $wxfile ]] && print -u2 "wx file not specified, and could not " \ 2360daaffb31Sdp "be auto-detected (check \$CODEMGR_WS)" && exit 1 2361daaffb31Sdp 2362cdf0c1d5Smjnelson if [[ ! -r $wxfile ]]; then 2363cdf0c1d5Smjnelson print -u2 "$wxfile: no such file or not readable" 2364cdf0c1d5Smjnelson usage 2365cdf0c1d5Smjnelson fi 2366cdf0c1d5Smjnelson 2367daaffb31Sdp print -u2 " File list from: wx 'active' file '$wxfile' ... \c" 2368daaffb31Sdp flist_from_wx $wxfile 2369daaffb31Sdp flist_done=1 2370daaffb31Sdp if [[ -n "$*" ]]; then 2371daaffb31Sdp shift 2372daaffb31Sdp fi 237314983201Sdpelif [[ $flist_mode == "stdin" ]]; then 237414983201Sdp print -u2 " File list from: standard input" 237514983201Sdpelif [[ $flist_mode == "file" ]]; then 237614983201Sdp print -u2 " File list from: $flist_file" 2377daaffb31Sdpfi 2378daaffb31Sdp 2379daaffb31Sdpif [[ $# -gt 0 ]]; then 238014983201Sdp print -u2 "WARNING: unused arguments: $*" 2381daaffb31Sdpfi 2382daaffb31Sdp 2383daaffb31Sdpif [[ $SCM_MODE == "teamware" ]]; then 2384daaffb31Sdp # 2385daaffb31Sdp # Parent (internally $codemgr_parent) and workspace ($codemgr_ws) can 2386daaffb31Sdp # be set in a number of ways, in decreasing precedence: 2387daaffb31Sdp # 2388daaffb31Sdp # 1) on the command line (only for the parent) 2389daaffb31Sdp # 2) in the user environment 2390daaffb31Sdp # 3) in the flist 2391daaffb31Sdp # 4) automatically based on the workspace (only for the parent) 2392daaffb31Sdp # 2393daaffb31Sdp 2394daaffb31Sdp # 2395daaffb31Sdp # Here is case (2): the user environment 2396daaffb31Sdp # 2397daaffb31Sdp [[ -z $codemgr_ws && -n $CODEMGR_WS ]] && codemgr_ws=$CODEMGR_WS 2398daaffb31Sdp if [[ -n $codemgr_ws && ! -d $codemgr_ws ]]; then 2399daaffb31Sdp print -u2 "$codemgr_ws: no such workspace" 24007c478bd9Sstevel@tonic-gate exit 1 24017c478bd9Sstevel@tonic-gate fi 24027c478bd9Sstevel@tonic-gate 2403daaffb31Sdp [[ -z $codemgr_parent && -n $CODEMGR_PARENT ]] && \ 2404daaffb31Sdp codemgr_parent=$CODEMGR_PARENT 2405daaffb31Sdp if [[ -n $codemgr_parent && ! -d $codemgr_parent ]]; then 2406daaffb31Sdp print -u2 "$codemgr_parent: no such directory" 24077c478bd9Sstevel@tonic-gate exit 1 24087c478bd9Sstevel@tonic-gate fi 24097c478bd9Sstevel@tonic-gate 2410daaffb31Sdp # 2411daaffb31Sdp # If we're in auto-detect mode and we haven't already gotten the file 2412daaffb31Sdp # list, then see if we can get it by probing for wx. 2413daaffb31Sdp # 241414983201Sdp if [[ -z $flist_done && $flist_mode == "auto" && -n $codemgr_ws ]]; then 241514983201Sdp if [[ ! -x $WX ]]; then 241614983201Sdp print -u2 "WARNING: wx not found!" 2417daaffb31Sdp fi 24187c478bd9Sstevel@tonic-gate 2419daaffb31Sdp # 2420daaffb31Sdp # We need to use wx list -w so that we get renamed files, etc. 2421daaffb31Sdp # but only if a wx active file exists-- otherwise wx will 2422daaffb31Sdp # hang asking us to initialize our wx information. 2423daaffb31Sdp # 242414983201Sdp if [[ -x $WX && -f $codemgr_ws/wx/active ]]; then 2425daaffb31Sdp print -u2 " File list from: 'wx list -w' ... \c" 2426daaffb31Sdp $WX list -w > $FLIST 2427daaffb31Sdp $WX comments > /tmp/$$.wx_comments 2428daaffb31Sdp wxfile=/tmp/$$.wx_comments 2429daaffb31Sdp print -u2 "done" 2430daaffb31Sdp flist_done=1 2431daaffb31Sdp fi 2432daaffb31Sdp fi 2433daaffb31Sdp 2434daaffb31Sdp # 2435daaffb31Sdp # If by hook or by crook we've gotten a file list by now (perhaps 2436daaffb31Sdp # from the command line), eval it to extract environment variables from 2437daaffb31Sdp # it: This is step (3). 2438daaffb31Sdp # 2439daaffb31Sdp env_from_flist 2440daaffb31Sdp 2441daaffb31Sdp # 2442daaffb31Sdp # Continuing step (3): If we still have no file list, we'll try to get 2443daaffb31Sdp # it from teamware. 2444daaffb31Sdp # 2445daaffb31Sdp if [[ -z $flist_done ]]; then 2446daaffb31Sdp flist_from_teamware 2447daaffb31Sdp env_from_flist 2448daaffb31Sdp fi 2449daaffb31Sdp 2450daaffb31Sdp # 2451daaffb31Sdp # (4) If we still don't have a value for codemgr_parent, get it 2452daaffb31Sdp # from workspace. 2453daaffb31Sdp # 2454cdf0c1d5Smjnelson [[ -z $codemgr_ws ]] && codemgr_ws=`workspace name` 2455daaffb31Sdp [[ -z $codemgr_parent ]] && codemgr_parent=`workspace parent` 2456daaffb31Sdp if [[ ! -d $codemgr_parent ]]; then 2457daaffb31Sdp print -u2 "$CODEMGR_PARENT: no such parent workspace" 2458daaffb31Sdp exit 1 2459daaffb31Sdp fi 2460daaffb31Sdp 2461daaffb31Sdp # 2462cdf0c1d5Smjnelson # Observe true directory name of CODEMGR_WS, as used later in 2463cdf0c1d5Smjnelson # webrev title. 2464cdf0c1d5Smjnelson # 2465cdf0c1d5Smjnelson codemgr_ws=$(cd $codemgr_ws;print $PWD) 2466cdf0c1d5Smjnelson 2467cdf0c1d5Smjnelson # 2468daaffb31Sdp # Reset CODEMGR_WS to make sure teamware commands are happy. 2469daaffb31Sdp # 2470daaffb31Sdp CODEMGR_WS=$codemgr_ws 2471daaffb31Sdp CWS=$codemgr_ws 2472daaffb31Sdp PWS=$codemgr_parent 2473cdf0c1d5Smjnelson 2474cdf0c1d5Smjnelson [[ -n $parent_webrev ]] && RWS=$(workspace parent $CWS) 2475cdf0c1d5Smjnelson 2476cdf0c1d5Smjnelsonelif [[ $SCM_MODE == "mercurial" ]]; then 2477cdf0c1d5Smjnelson [[ -z $codemgr_ws && -n $CODEMGR_WS ]] && \ 2478cdf0c1d5Smjnelson codemgr_ws=`hg root -R $CODEMGR_WS 2>/dev/null` 2479cdf0c1d5Smjnelson 2480cdf0c1d5Smjnelson [[ -z $codemgr_ws ]] && codemgr_ws=`hg root 2>/dev/null` 2481cdf0c1d5Smjnelson 2482cdf0c1d5Smjnelson # 2483cdf0c1d5Smjnelson # Parent can either be specified with -p 2484cdf0c1d5Smjnelson # Specified with CODEMGR_PARENT in the environment 2485cdf0c1d5Smjnelson # or taken from hg's default path. 2486cdf0c1d5Smjnelson # 2487cdf0c1d5Smjnelson 2488cdf0c1d5Smjnelson if [[ -z $codemgr_parent && -n $CODEMGR_PARENT ]]; then 2489cdf0c1d5Smjnelson codemgr_parent=$CODEMGR_PARENT 2490cdf0c1d5Smjnelson fi 2491cdf0c1d5Smjnelson 2492cdf0c1d5Smjnelson if [[ -z $codemgr_parent ]]; then 2493cdf0c1d5Smjnelson codemgr_parent=`hg path -R $codemgr_ws default 2>/dev/null` 2494cdf0c1d5Smjnelson fi 2495cdf0c1d5Smjnelson 2496cdf0c1d5Smjnelson CWS_REV=`hg parent -R $codemgr_ws --template '{node|short}' 2>/dev/null` 2497cdf0c1d5Smjnelson CWS=$codemgr_ws 2498cdf0c1d5Smjnelson PWS=$codemgr_parent 2499cdf0c1d5Smjnelson 2500cdf0c1d5Smjnelson # 2501cdf0c1d5Smjnelson # If the parent is a webrev, we want to do some things against 2502cdf0c1d5Smjnelson # the natural workspace parent (file list, comments, etc) 2503cdf0c1d5Smjnelson # 2504cdf0c1d5Smjnelson if [[ -n $parent_webrev ]]; then 2505cdf0c1d5Smjnelson real_parent=$(hg path -R $codemgr_ws default 2>/dev/null) 2506cdf0c1d5Smjnelson else 2507cdf0c1d5Smjnelson real_parent=$PWS 2508cdf0c1d5Smjnelson fi 2509cdf0c1d5Smjnelson 2510cdf0c1d5Smjnelson # 2511cdf0c1d5Smjnelson # If hg-active exists, then we run it. In the case of no explicit 2512cdf0c1d5Smjnelson # flist given, we'll use it for our comments. In the case of an 2513cdf0c1d5Smjnelson # explicit flist given we'll try to use it for comments for any 2514cdf0c1d5Smjnelson # files mentioned in the flist. 2515cdf0c1d5Smjnelson # 2516cdf0c1d5Smjnelson if [[ -z $flist_done ]]; then 2517cdf0c1d5Smjnelson flist_from_mercurial $CWS $real_parent 2518cdf0c1d5Smjnelson flist_done=1 2519cdf0c1d5Smjnelson fi 2520cdf0c1d5Smjnelson 2521cdf0c1d5Smjnelson # 2522cdf0c1d5Smjnelson # If we have a file list now, pull out any variables set 2523cdf0c1d5Smjnelson # therein. We do this now (rather than when we possibly use 2524cdf0c1d5Smjnelson # hg-active to find comments) to avoid stomping specifications 2525cdf0c1d5Smjnelson # in the user-specified flist. 2526cdf0c1d5Smjnelson # 2527cdf0c1d5Smjnelson if [[ -n $flist_done ]]; then 2528cdf0c1d5Smjnelson env_from_flist 2529cdf0c1d5Smjnelson fi 2530cdf0c1d5Smjnelson 2531cdf0c1d5Smjnelson # 2532cdf0c1d5Smjnelson # Only call hg-active if we don't have a wx formatted file already 2533cdf0c1d5Smjnelson # 2534cdf0c1d5Smjnelson if [[ -x $HG_ACTIVE && -z $wxfile ]]; then 2535cdf0c1d5Smjnelson print " Comments from: hg-active -p $real_parent ...\c" 2536cdf0c1d5Smjnelson hg_active_wxfile $CWS $real_parent 2537cdf0c1d5Smjnelson print " Done." 2538cdf0c1d5Smjnelson fi 2539cdf0c1d5Smjnelson 2540cdf0c1d5Smjnelson # 2541cdf0c1d5Smjnelson # At this point we must have a wx flist either from hg-active, 2542cdf0c1d5Smjnelson # or in general. Use it to try and find our parent revision, 2543cdf0c1d5Smjnelson # if we don't have one. 2544cdf0c1d5Smjnelson # 2545cdf0c1d5Smjnelson if [[ -z $HG_PARENT ]]; then 2546b0088928SVladimir Kotal eval `$SED -e "s/#.*$//" $wxfile | $GREP HG_PARENT=` 2547cdf0c1d5Smjnelson fi 2548cdf0c1d5Smjnelson 2549cdf0c1d5Smjnelson # 2550cdf0c1d5Smjnelson # If we still don't have a parent, we must have been given a 2551cdf0c1d5Smjnelson # wx-style active list with no HG_PARENT specification, run 2552cdf0c1d5Smjnelson # hg-active and pull an HG_PARENT out of it, ignore the rest. 2553cdf0c1d5Smjnelson # 2554cdf0c1d5Smjnelson if [[ -z $HG_PARENT && -x $HG_ACTIVE ]]; then 2555cdf0c1d5Smjnelson $HG_ACTIVE -w $codemgr_ws -p $real_parent | \ 2556b0088928SVladimir Kotal eval `$SED -e "s/#.*$//" | $GREP HG_PARENT=` 2557cdf0c1d5Smjnelson elif [[ -z $HG_PARENT ]]; then 2558cdf0c1d5Smjnelson print -u2 "Error: Cannot discover parent revision" 2559cdf0c1d5Smjnelson exit 1 2560cdf0c1d5Smjnelson fi 2561cdf0c1d5Smjnelsonelif [[ $SCM_MODE == "subversion" ]]; then 2562cdf0c1d5Smjnelson if [[ -n $CODEMGR_WS && -d $CODEMGR_WS/.svn ]]; then 2563cdf0c1d5Smjnelson CWS=$CODEMGR_WS 2564cdf0c1d5Smjnelson else 2565cdf0c1d5Smjnelson svn info | while read line; do 2566cdf0c1d5Smjnelson if [[ $line == "URL: "* ]]; then 2567cdf0c1d5Smjnelson url=${line#URL: } 2568cdf0c1d5Smjnelson elif [[ $line == "Repository Root: "* ]]; then 2569cdf0c1d5Smjnelson repo=${line#Repository Root: } 2570cdf0c1d5Smjnelson fi 2571cdf0c1d5Smjnelson done 2572cdf0c1d5Smjnelson 2573cdf0c1d5Smjnelson rel=${url#$repo} 2574cdf0c1d5Smjnelson CWS=${PWD%$rel} 2575cdf0c1d5Smjnelson fi 2576cdf0c1d5Smjnelson 2577cdf0c1d5Smjnelson # 2578cdf0c1d5Smjnelson # We only will have a real parent workspace in the case one 2579cdf0c1d5Smjnelson # was specified (be it an older webrev, or another checkout). 2580cdf0c1d5Smjnelson # 2581cdf0c1d5Smjnelson [[ -n $codemgr_parent ]] && PWS=$codemgr_parent 2582cdf0c1d5Smjnelson 2583cdf0c1d5Smjnelson if [[ -z $flist_done && $flist_mode == "auto" ]]; then 2584cdf0c1d5Smjnelson flist_from_subversion $CWS $OLDPWD 2585cdf0c1d5Smjnelson fi 2586cdf0c1d5Smjnelsonelse 2587cdf0c1d5Smjnelson if [[ $SCM_MODE == "unknown" ]]; then 2588cdf0c1d5Smjnelson print -u2 " Unknown type of SCM in use" 2589cdf0c1d5Smjnelson else 2590cdf0c1d5Smjnelson print -u2 " Unsupported SCM in use: $SCM_MODE" 2591cdf0c1d5Smjnelson fi 2592cdf0c1d5Smjnelson 2593cdf0c1d5Smjnelson env_from_flist 2594cdf0c1d5Smjnelson 2595cdf0c1d5Smjnelson if [[ -z $CODEMGR_WS ]]; then 2596cdf0c1d5Smjnelson print -u2 "SCM not detected/supported and CODEMGR_WS not specified" 2597cdf0c1d5Smjnelson exit 1 2598cdf0c1d5Smjnelson fi 2599cdf0c1d5Smjnelson 2600cdf0c1d5Smjnelson if [[ -z $CODEMGR_PARENT ]]; then 2601cdf0c1d5Smjnelson print -u2 "SCM not detected/supported and CODEMGR_PARENT not specified" 2602cdf0c1d5Smjnelson exit 1 2603cdf0c1d5Smjnelson fi 2604cdf0c1d5Smjnelson 2605cdf0c1d5Smjnelson CWS=$CODEMGR_WS 2606cdf0c1d5Smjnelson PWS=$CODEMGR_PARENT 2607daaffb31Sdpfi 2608daaffb31Sdp 2609daaffb31Sdp# 2610daaffb31Sdp# If the user didn't specify a -i option, check to see if there is a 2611daaffb31Sdp# webrev-info file in the workspace directory. 2612daaffb31Sdp# 2613daaffb31Sdpif [[ -z $iflag && -r "$CWS/webrev-info" ]]; then 2614daaffb31Sdp iflag=1 2615daaffb31Sdp INCLUDE_FILE="$CWS/webrev-info" 2616daaffb31Sdpfi 2617daaffb31Sdp 2618daaffb31Sdpif [[ -n $iflag ]]; then 2619daaffb31Sdp if [[ ! -r $INCLUDE_FILE ]]; then 2620daaffb31Sdp print -u2 "include file '$INCLUDE_FILE' does not exist or is" \ 2621daaffb31Sdp "not readable." 2622daaffb31Sdp exit 1 2623daaffb31Sdp else 2624daaffb31Sdp # 2625daaffb31Sdp # $INCLUDE_FILE may be a relative path, and the script alters 2626daaffb31Sdp # PWD, so we just stash a copy in /tmp. 2627daaffb31Sdp # 2628daaffb31Sdp cp $INCLUDE_FILE /tmp/$$.include 2629daaffb31Sdp fi 2630daaffb31Sdpfi 2631daaffb31Sdp 2632*0fd2682eSMark J. Nelson# DO_EVERYTHING: break point 2633*0fd2682eSMark J. Nelsonif [[ -n $Nflag ]]; then 2634*0fd2682eSMark J. Nelson break 2635*0fd2682eSMark J. Nelsonfi 2636*0fd2682eSMark J. Nelson 2637*0fd2682eSMark J. Nelsontypeset -A itsinfo 2638*0fd2682eSMark J. Nelsontypeset -r its_sed_script=/tmp/$$.its_sed 2639*0fd2682eSMark J. Nelsonvalid_prefixes= 2640*0fd2682eSMark J. Nelsonif [[ -z $nflag ]]; then 2641*0fd2682eSMark J. Nelson DEFREGFILE="$(dirname $(whence $0))/../etc/its.reg" 2642*0fd2682eSMark J. Nelson if [[ -n $Iflag ]]; then 2643*0fd2682eSMark J. Nelson REGFILE=$ITSREG 2644*0fd2682eSMark J. Nelson elif [[ -r $HOME/.its.reg ]]; then 2645*0fd2682eSMark J. Nelson REGFILE=$HOME/.its.reg 2646*0fd2682eSMark J. Nelson else 2647*0fd2682eSMark J. Nelson REGFILE=$DEFREGFILE 2648*0fd2682eSMark J. Nelson fi 2649*0fd2682eSMark J. Nelson if [[ ! -r $REGFILE ]]; then 2650*0fd2682eSMark J. Nelson print "ERROR: Unable to read database registry file $REGFILE" 2651*0fd2682eSMark J. Nelson exit 1 2652*0fd2682eSMark J. Nelson elif [[ $REGFILE != $DEFREGFILE ]]; then 2653*0fd2682eSMark J. Nelson print " its.reg from: $REGFILE" 2654*0fd2682eSMark J. Nelson fi 2655*0fd2682eSMark J. Nelson 2656*0fd2682eSMark J. Nelson $SED -e '/^#/d' -e '/^[ ]*$/d' $REGFILE | while read LINE; do 2657*0fd2682eSMark J. Nelson 2658*0fd2682eSMark J. Nelson name=${LINE%%=*} 2659*0fd2682eSMark J. Nelson value="${LINE#*=}" 2660*0fd2682eSMark J. Nelson 2661*0fd2682eSMark J. Nelson if [[ $name == PREFIX ]]; then 2662*0fd2682eSMark J. Nelson p=${value} 2663*0fd2682eSMark J. Nelson valid_prefixes="${p} ${valid_prefixes}" 2664*0fd2682eSMark J. Nelson else 2665*0fd2682eSMark J. Nelson itsinfo["${p}_${name}"]="${value}" 2666*0fd2682eSMark J. Nelson fi 2667*0fd2682eSMark J. Nelson done 2668*0fd2682eSMark J. Nelson 2669*0fd2682eSMark J. Nelson 2670*0fd2682eSMark J. Nelson DEFCONFFILE="$(dirname $(whence $0))/../etc/its.conf" 2671*0fd2682eSMark J. Nelson CONFFILES=$DEFCONFFILE 2672*0fd2682eSMark J. Nelson if [[ -r $HOME/.its.conf ]]; then 2673*0fd2682eSMark J. Nelson CONFFILES="${CONFFILES} $HOME/.its.conf" 2674*0fd2682eSMark J. Nelson fi 2675*0fd2682eSMark J. Nelson if [[ -n $Cflag ]]; then 2676*0fd2682eSMark J. Nelson CONFFILES="${CONFFILES} ${ITSCONF}" 2677*0fd2682eSMark J. Nelson fi 2678*0fd2682eSMark J. Nelson its_domain= 2679*0fd2682eSMark J. Nelson its_priority= 2680*0fd2682eSMark J. Nelson for cf in ${CONFFILES}; do 2681*0fd2682eSMark J. Nelson if [[ ! -r $cf ]]; then 2682*0fd2682eSMark J. Nelson print "ERROR: Unable to read database configuration file $cf" 2683*0fd2682eSMark J. Nelson exit 1 2684*0fd2682eSMark J. Nelson elif [[ $cf != $DEFCONFFILE ]]; then 2685*0fd2682eSMark J. Nelson print " its.conf: reading $cf" 2686*0fd2682eSMark J. Nelson fi 2687*0fd2682eSMark J. Nelson $SED -e '/^#/d' -e '/^[ ]*$/d' $cf | while read LINE; do 2688*0fd2682eSMark J. Nelson eval "${LINE}" 2689*0fd2682eSMark J. Nelson done 2690*0fd2682eSMark J. Nelson done 2691*0fd2682eSMark J. Nelson 2692*0fd2682eSMark J. Nelson # 2693*0fd2682eSMark J. Nelson # If an information tracking system is explicitly identified by prefix, 2694*0fd2682eSMark J. Nelson # we want to disregard the specified priorities and resolve it accordingly. 2695*0fd2682eSMark J. Nelson # 2696*0fd2682eSMark J. Nelson # To that end, we'll build a sed script to do each valid prefix in turn. 2697*0fd2682eSMark J. Nelson # 2698*0fd2682eSMark J. Nelson for p in ${valid_prefixes}; do 2699*0fd2682eSMark J. Nelson # 2700*0fd2682eSMark J. Nelson # When an informational URL was provided, translate it to a 2701*0fd2682eSMark J. Nelson # hyperlink. When omitted, simply use the prefix text. 2702*0fd2682eSMark J. Nelson # 2703*0fd2682eSMark J. Nelson if [[ -z ${itsinfo["${p}_INFO"]} ]]; then 2704*0fd2682eSMark J. Nelson itsinfo["${p}_INFO"]=${p} 2705*0fd2682eSMark J. Nelson else 2706*0fd2682eSMark J. Nelson itsinfo["${p}_INFO"]="<a href=\\\"${itsinfo["${p}_INFO"]}\\\">${p}</a>" 2707*0fd2682eSMark J. Nelson fi 2708*0fd2682eSMark J. Nelson 2709*0fd2682eSMark J. Nelson # 2710*0fd2682eSMark J. Nelson # Assume that, for this invocation of webrev, all references 2711*0fd2682eSMark J. Nelson # to this information tracking system should resolve through 2712*0fd2682eSMark J. Nelson # the same URL. 2713*0fd2682eSMark J. Nelson # 2714*0fd2682eSMark J. Nelson # If the caller specified -O, then always use EXTERNAL_URL. 2715*0fd2682eSMark J. Nelson # 2716*0fd2682eSMark J. Nelson # Otherwise, look in the list of domains for a matching 2717*0fd2682eSMark J. Nelson # INTERNAL_URL. 2718*0fd2682eSMark J. Nelson # 2719*0fd2682eSMark J. Nelson [[ -z $Oflag ]] && for d in ${its_domain}; do 2720*0fd2682eSMark J. Nelson if [[ -n ${itsinfo["${p}_INTERNAL_URL_${d}"]} ]]; then 2721*0fd2682eSMark J. Nelson itsinfo["${p}_URL"]="${itsinfo[${p}_INTERNAL_URL_${d}]}" 2722*0fd2682eSMark J. Nelson break 2723*0fd2682eSMark J. Nelson fi 2724*0fd2682eSMark J. Nelson done 2725*0fd2682eSMark J. Nelson if [[ -z ${itsinfo["${p}_URL"]} ]]; then 2726*0fd2682eSMark J. Nelson itsinfo["${p}_URL"]="${itsinfo[${p}_EXTERNAL_URL]}" 2727*0fd2682eSMark J. Nelson fi 2728*0fd2682eSMark J. Nelson 2729*0fd2682eSMark J. Nelson # 2730*0fd2682eSMark J. Nelson # Turn the destination URL into a hyperlink 2731*0fd2682eSMark J. Nelson # 2732*0fd2682eSMark J. Nelson itsinfo["${p}_URL"]="<a href=\\\"${itsinfo[${p}_URL]}\\\">&</a>" 2733*0fd2682eSMark J. Nelson 2734*0fd2682eSMark J. Nelson print "/^${p}[ ]/ { 2735*0fd2682eSMark J. Nelson s;${itsinfo[${p}_REGEX]};${itsinfo[${p}_URL]};g 2736*0fd2682eSMark J. Nelson s;^${p};${itsinfo[${p}_INFO]}; 2737*0fd2682eSMark J. Nelson }" >> ${its_sed_script} 2738*0fd2682eSMark J. Nelson done 2739*0fd2682eSMark J. Nelson 2740*0fd2682eSMark J. Nelson # 2741*0fd2682eSMark J. Nelson # The previous loop took care of explicit specification. Now use 2742*0fd2682eSMark J. Nelson # the configured priorities to attempt implicit translations. 2743*0fd2682eSMark J. Nelson # 2744*0fd2682eSMark J. Nelson for p in ${its_priority}; do 2745*0fd2682eSMark J. Nelson print "/^${itsinfo[${p}_REGEX]}[ ]/ { 2746*0fd2682eSMark J. Nelson s;${itsinfo[${p}_REGEX]};${itsinfo[${p}_URL]};g 2747*0fd2682eSMark J. Nelson }" >> ${its_sed_script} 2748*0fd2682eSMark J. Nelson done 2749*0fd2682eSMark J. Nelsonfi 2750*0fd2682eSMark J. Nelson 2751*0fd2682eSMark J. Nelson# 2752*0fd2682eSMark J. Nelson# Search for DO_EVERYTHING above for matching "for" statement 2753*0fd2682eSMark J. Nelson# and explanation of this terminator. 2754*0fd2682eSMark J. Nelson# 2755*0fd2682eSMark J. Nelsondone 2756*0fd2682eSMark J. Nelson 2757daaffb31Sdp# 2758daaffb31Sdp# Output directory. 2759daaffb31Sdp# 2760daaffb31SdpWDIR=${WDIR:-$CWS/webrev} 2761daaffb31Sdp 2762daaffb31Sdp# 276302d26c39SVladimir Kotal# Name of the webrev, derived from the workspace name or output directory; 276402d26c39SVladimir Kotal# in the future this could potentially be an option. 2765daaffb31Sdp# 276602d26c39SVladimir Kotalif [[ -n $oflag ]]; then 276702d26c39SVladimir Kotal WNAME=${WDIR##*/} 276802d26c39SVladimir Kotalelse 2769daaffb31Sdp WNAME=${CWS##*/} 277002d26c39SVladimir Kotalfi 277102d26c39SVladimir Kotal 2772ba44d8a2SVladimir Kotal# Make sure remote target is well formed for remote upload/delete. 2773ba44d8a2SVladimir Kotalif [[ -n $Dflag || -n $Uflag ]]; then 2774b0088928SVladimir Kotal # 2775ba44d8a2SVladimir Kotal # If remote target is not specified, build it from scratch using 2776ba44d8a2SVladimir Kotal # the default values. 2777b0088928SVladimir Kotal # 2778ba44d8a2SVladimir Kotal if [[ -z $tflag ]]; then 2779ba44d8a2SVladimir Kotal remote_target=${DEFAULT_REMOTE_HOST}:${WNAME} 2780ba44d8a2SVladimir Kotal else 2781b0088928SVladimir Kotal # 2782b0088928SVladimir Kotal # Check upload target prefix first. 2783b0088928SVladimir Kotal # 2784b0088928SVladimir Kotal if [[ "${remote_target}" != ${rsync_prefix}* && 2785b0088928SVladimir Kotal "${remote_target}" != ${ssh_prefix}* ]]; then 2786b0088928SVladimir Kotal print "ERROR: invalid prefix of upload URI" \ 2787b0088928SVladimir Kotal "($remote_target)" 2788b0088928SVladimir Kotal exit 1 2789b0088928SVladimir Kotal fi 2790b0088928SVladimir Kotal # 2791ba44d8a2SVladimir Kotal # If destination specification is not in the form of 2792ba44d8a2SVladimir Kotal # host_spec:remote_dir then assume it is just remote hostname 2793ba44d8a2SVladimir Kotal # and append a colon and destination directory formed from 2794ba44d8a2SVladimir Kotal # local webrev directory name. 2795b0088928SVladimir Kotal # 2796b0088928SVladimir Kotal typeset target_no_prefix=${remote_target##*://} 2797b0088928SVladimir Kotal if [[ ${target_no_prefix} == *:* ]]; then 2798ba44d8a2SVladimir Kotal if [[ "${remote_target}" == *: ]]; then 2799b0088928SVladimir Kotal remote_target=${remote_target}${WNAME} 2800ba44d8a2SVladimir Kotal fi 2801b0088928SVladimir Kotal else 2802b0088928SVladimir Kotal if [[ ${target_no_prefix} == */* ]]; then 2803b0088928SVladimir Kotal print "ERROR: badly formed upload URI" \ 2804b0088928SVladimir Kotal "($remote_target)" 2805b0088928SVladimir Kotal exit 1 2806b0088928SVladimir Kotal else 2807b0088928SVladimir Kotal remote_target=${remote_target}:${WNAME} 2808ba44d8a2SVladimir Kotal fi 2809ba44d8a2SVladimir Kotal fi 2810ba44d8a2SVladimir Kotal fi 2811ba44d8a2SVladimir Kotal 2812b0088928SVladimir Kotal # 2813b0088928SVladimir Kotal # Strip trailing slash. Each upload method will deal with directory 2814b0088928SVladimir Kotal # specification separately. 2815b0088928SVladimir Kotal # 2816b0088928SVladimir Kotal remote_target=${remote_target%/} 2817b0088928SVladimir Kotalfi 2818b0088928SVladimir Kotal 2819b0088928SVladimir Kotal# 2820ba44d8a2SVladimir Kotal# Option -D by itself (option -U not present) implies no webrev generation. 2821b0088928SVladimir Kotal# 2822ba44d8a2SVladimir Kotalif [[ -z $Uflag && -n $Dflag ]]; then 2823b0088928SVladimir Kotal delete_webrev 1 1 2824ba44d8a2SVladimir Kotal exit $? 2825ba44d8a2SVladimir Kotalfi 2826ba44d8a2SVladimir Kotal 2827b0088928SVladimir Kotal# 2828ba44d8a2SVladimir Kotal# Do not generate the webrev, just upload it or delete it. 2829b0088928SVladimir Kotal# 2830ba44d8a2SVladimir Kotalif [[ -n $nflag ]]; then 2831ba44d8a2SVladimir Kotal if [[ -n $Dflag ]]; then 2832b0088928SVladimir Kotal delete_webrev 1 1 2833ba44d8a2SVladimir Kotal (( $? == 0 )) || exit $? 2834ba44d8a2SVladimir Kotal fi 2835ba44d8a2SVladimir Kotal if [[ -n $Uflag ]]; then 283602d26c39SVladimir Kotal upload_webrev 283702d26c39SVladimir Kotal exit $? 283802d26c39SVladimir Kotal fi 2839ba44d8a2SVladimir Kotalfi 2840daaffb31Sdp 2841e0e0293aSjmcpif [ "${WDIR%%/*}" ]; then 28427c478bd9Sstevel@tonic-gate WDIR=$PWD/$WDIR 28437c478bd9Sstevel@tonic-gatefi 2844daaffb31Sdp 2845daaffb31Sdpif [[ ! -d $WDIR ]]; then 2846daaffb31Sdp mkdir -p $WDIR 2847ba44d8a2SVladimir Kotal (( $? != 0 )) && exit 1 28487c478bd9Sstevel@tonic-gatefi 28497c478bd9Sstevel@tonic-gate 2850daaffb31Sdp# 2851daaffb31Sdp# Summarize what we're going to do. 2852daaffb31Sdp# 2853cdf0c1d5Smjnelsonif [[ -n $CWS_REV ]]; then 2854cdf0c1d5Smjnelson print " Workspace: $CWS (at $CWS_REV)" 2855cdf0c1d5Smjnelsonelse 2856daaffb31Sdp print " Workspace: $CWS" 2857cdf0c1d5Smjnelsonfi 2858daaffb31Sdpif [[ -n $parent_webrev ]]; then 2859daaffb31Sdp print "Compare against: webrev at $parent_webrev" 2860daaffb31Sdpelse 2861cdf0c1d5Smjnelson if [[ -n $HG_PARENT ]]; then 2862cdf0c1d5Smjnelson hg_parent_short=`echo $HG_PARENT \ 2863b0088928SVladimir Kotal | $SED -e 's/\([0-9a-f]\{12\}\).*/\1/'` 2864cdf0c1d5Smjnelson print "Compare against: $PWS (at $hg_parent_short)" 2865cdf0c1d5Smjnelson else 2866daaffb31Sdp print "Compare against: $PWS" 2867daaffb31Sdp fi 2868cdf0c1d5Smjnelsonfi 2869daaffb31Sdp 2870daaffb31Sdp[[ -n $INCLUDE_FILE ]] && print " Including: $INCLUDE_FILE" 2871daaffb31Sdpprint " Output to: $WDIR" 2872daaffb31Sdp 2873daaffb31Sdp# 28747c478bd9Sstevel@tonic-gate# Save the file list in the webrev dir 2875daaffb31Sdp# 2876daaffb31Sdp[[ ! $FLIST -ef $WDIR/file.list ]] && cp $FLIST $WDIR/file.list 28777c478bd9Sstevel@tonic-gate 2878daaffb31Sdprm -f $WDIR/$WNAME.patch 2879daaffb31Sdprm -f $WDIR/$WNAME.ps 2880daaffb31Sdprm -f $WDIR/$WNAME.pdf 28817c478bd9Sstevel@tonic-gate 2882daaffb31Sdptouch $WDIR/$WNAME.patch 28837c478bd9Sstevel@tonic-gate 2884daaffb31Sdpprint " Output Files:" 2885daaffb31Sdp 2886daaffb31Sdp# 2887daaffb31Sdp# Clean up the file list: Remove comments, blank lines and env variables. 2888daaffb31Sdp# 2889b0088928SVladimir Kotal$SED -e "s/#.*$//" -e "/=/d" -e "/^[ ]*$/d" $FLIST > /tmp/$$.flist.clean 2890daaffb31SdpFLIST=/tmp/$$.flist.clean 2891daaffb31Sdp 2892daaffb31Sdp# 2893cdf0c1d5Smjnelson# For Mercurial, create a cache of manifest entries. 2894cdf0c1d5Smjnelson# 2895cdf0c1d5Smjnelsonif [[ $SCM_MODE == "mercurial" ]]; then 2896cdf0c1d5Smjnelson # 2897cdf0c1d5Smjnelson # Transform the FLIST into a temporary sed script that matches 2898cdf0c1d5Smjnelson # relevant entries in the Mercurial manifest as follows: 2899cdf0c1d5Smjnelson # 1) The script will be used against the parent revision manifest, 2900cdf0c1d5Smjnelson # so for FLIST lines that have two filenames (a renamed file) 2901cdf0c1d5Smjnelson # keep only the old name. 2902cdf0c1d5Smjnelson # 2) Escape all forward slashes the filename. 2903cdf0c1d5Smjnelson # 3) Change the filename into another sed command that matches 2904cdf0c1d5Smjnelson # that file in "hg manifest -v" output: start of line, three 2905cdf0c1d5Smjnelson # octal digits for file permissions, space, a file type flag 2906cdf0c1d5Smjnelson # character, space, the filename, end of line. 2907cdf0c1d5Smjnelson # 2908cdf0c1d5Smjnelson SEDFILE=/tmp/$$.manifest.sed 2909b0088928SVladimir Kotal $SED ' 2910cdf0c1d5Smjnelson s#^[^ ]* ## 2911cdf0c1d5Smjnelson s#/#\\\/#g 2912cdf0c1d5Smjnelson s#^.*$#/^... . &$/p# 2913cdf0c1d5Smjnelson ' < $FLIST > $SEDFILE 2914cdf0c1d5Smjnelson 2915cdf0c1d5Smjnelson # 2916cdf0c1d5Smjnelson # Apply the generated script to the output of "hg manifest -v" 2917cdf0c1d5Smjnelson # to get the relevant subset for this webrev. 2918cdf0c1d5Smjnelson # 2919cdf0c1d5Smjnelson HG_PARENT_MANIFEST=/tmp/$$.manifest 2920cdf0c1d5Smjnelson hg -R $CWS manifest -v -r $HG_PARENT | 2921b0088928SVladimir Kotal $SED -n -f $SEDFILE > $HG_PARENT_MANIFEST 2922cdf0c1d5Smjnelsonfi 2923cdf0c1d5Smjnelson 2924cdf0c1d5Smjnelson# 2925daaffb31Sdp# First pass through the files: generate the per-file webrev HTML-files. 2926daaffb31Sdp# 2927daaffb31Sdpcat $FLIST | while read LINE 29287c478bd9Sstevel@tonic-gatedo 29297c478bd9Sstevel@tonic-gate set - $LINE 29307c478bd9Sstevel@tonic-gate P=$1 29317c478bd9Sstevel@tonic-gate 2932daaffb31Sdp # 2933daaffb31Sdp # Normally, each line in the file list is just a pathname of a 2934daaffb31Sdp # file that has been modified or created in the child. A file 2935daaffb31Sdp # that is renamed in the child workspace has two names on the 2936daaffb31Sdp # line: new name followed by the old name. 2937daaffb31Sdp # 2938daaffb31Sdp oldname="" 2939daaffb31Sdp oldpath="" 2940daaffb31Sdp rename= 2941daaffb31Sdp if [[ $# -eq 2 ]]; then 29427c478bd9Sstevel@tonic-gate PP=$2 # old filename 2943daaffb31Sdp oldname=" (was $PP)" 2944daaffb31Sdp oldpath="$PP" 2945daaffb31Sdp rename=1 29467c478bd9Sstevel@tonic-gate PDIR=${PP%/*} 2947daaffb31Sdp if [[ $PDIR == $PP ]]; then 29487c478bd9Sstevel@tonic-gate PDIR="." # File at root of workspace 29497c478bd9Sstevel@tonic-gate fi 29507c478bd9Sstevel@tonic-gate 29517c478bd9Sstevel@tonic-gate PF=${PP##*/} 29527c478bd9Sstevel@tonic-gate 29537c478bd9Sstevel@tonic-gate DIR=${P%/*} 2954daaffb31Sdp if [[ $DIR == $P ]]; then 29557c478bd9Sstevel@tonic-gate DIR="." # File at root of workspace 29567c478bd9Sstevel@tonic-gate fi 29577c478bd9Sstevel@tonic-gate 29587c478bd9Sstevel@tonic-gate F=${P##*/} 2959daaffb31Sdp 29607c478bd9Sstevel@tonic-gate else 29617c478bd9Sstevel@tonic-gate DIR=${P%/*} 2962daaffb31Sdp if [[ "$DIR" == "$P" ]]; then 29637c478bd9Sstevel@tonic-gate DIR="." # File at root of workspace 29647c478bd9Sstevel@tonic-gate fi 29657c478bd9Sstevel@tonic-gate 29667c478bd9Sstevel@tonic-gate F=${P##*/} 29677c478bd9Sstevel@tonic-gate 29687c478bd9Sstevel@tonic-gate PP=$P 29697c478bd9Sstevel@tonic-gate PDIR=$DIR 29707c478bd9Sstevel@tonic-gate PF=$F 29717c478bd9Sstevel@tonic-gate fi 29727c478bd9Sstevel@tonic-gate 2973daaffb31Sdp COMM=`getcomments html $P $PP` 29747c478bd9Sstevel@tonic-gate 2975daaffb31Sdp print "\t$P$oldname\n\t\t\c" 29767c478bd9Sstevel@tonic-gate 29777c478bd9Sstevel@tonic-gate # Make the webrev mirror directory if necessary 29787c478bd9Sstevel@tonic-gate mkdir -p $WDIR/$DIR 29797c478bd9Sstevel@tonic-gate 2980daaffb31Sdp # 2981daaffb31Sdp # If we're in OpenSolaris mode, we enforce a minor policy: 2982daaffb31Sdp # help to make sure the reviewer doesn't accidentally publish 2983e0e0293aSjmcp # source which is in usr/closed/* or deleted_files/usr/closed/* 2984daaffb31Sdp # 2985e0e0293aSjmcp if [[ -n "$Oflag" ]]; then 2986daaffb31Sdp pclosed=${P##usr/closed/} 2987e0e0293aSjmcp pdeleted=${P##deleted_files/usr/closed/} 2988e0e0293aSjmcp if [[ "$pclosed" != "$P" || "$pdeleted" != "$P" ]]; then 2989daaffb31Sdp print "*** Omitting closed source for OpenSolaris" \ 2990daaffb31Sdp "mode review" 2991daaffb31Sdp continue 2992daaffb31Sdp fi 2993daaffb31Sdp fi 2994daaffb31Sdp 2995daaffb31Sdp # 2996cdf0c1d5Smjnelson # We stash old and new files into parallel directories in $WDIR 2997daaffb31Sdp # and do our diffs there. This makes it possible to generate 2998daaffb31Sdp # clean looking diffs which don't have absolute paths present. 2999daaffb31Sdp # 3000daaffb31Sdp 3001cdf0c1d5Smjnelson build_old_new "$WDIR" "$PWS" "$PDIR" "$PF" "$CWS" "$DIR" "$F" || \ 30027c478bd9Sstevel@tonic-gate continue 30037c478bd9Sstevel@tonic-gate 3004cdf0c1d5Smjnelson # 3005cdf0c1d5Smjnelson # Keep the old PWD around, so we can safely switch back after 3006cdf0c1d5Smjnelson # diff generation, such that build_old_new runs in a 3007cdf0c1d5Smjnelson # consistent environment. 3008cdf0c1d5Smjnelson # 3009cdf0c1d5Smjnelson OWD=$PWD 3010daaffb31Sdp cd $WDIR/raw_files 3011daaffb31Sdp ofile=old/$PDIR/$PF 3012daaffb31Sdp nfile=new/$DIR/$F 30137c478bd9Sstevel@tonic-gate 3014daaffb31Sdp mv_but_nodiff= 3015daaffb31Sdp cmp $ofile $nfile > /dev/null 2>&1 3016daaffb31Sdp if [[ $? == 0 && $rename == 1 ]]; then 3017daaffb31Sdp mv_but_nodiff=1 3018daaffb31Sdp fi 3019daaffb31Sdp 3020daaffb31Sdp # 3021daaffb31Sdp # If we have old and new versions of the file then run the appropriate 3022daaffb31Sdp # diffs. This is complicated by a couple of factors: 3023daaffb31Sdp # 3024daaffb31Sdp # - renames must be handled specially: we emit a 'remove' 3025daaffb31Sdp # diff and an 'add' diff 3026daaffb31Sdp # - new files and deleted files must be handled specially 3027daaffb31Sdp # - Solaris patch(1m) can't cope with file creation 3028daaffb31Sdp # (and hence renames) as of this writing. 3029daaffb31Sdp # - To make matters worse, gnu patch doesn't interpret the 3030daaffb31Sdp # output of Solaris diff properly when it comes to 3031daaffb31Sdp # adds and deletes. We need to do some "cleansing" 3032daaffb31Sdp # transformations: 3033daaffb31Sdp # [to add a file] @@ -1,0 +X,Y @@ --> @@ -0,0 +X,Y @@ 3034daaffb31Sdp # [to del a file] @@ -X,Y +1,0 @@ --> @@ -X,Y +0,0 @@ 3035daaffb31Sdp # 3036b0088928SVladimir Kotal cleanse_rmfile="$SED 's/^\(@@ [0-9+,-]*\) [0-9+,-]* @@$/\1 +0,0 @@/'" 3037b0088928SVladimir Kotal cleanse_newfile="$SED 's/^@@ [0-9+,-]* \([0-9+,-]* @@\)$/@@ -0,0 \1/'" 3038daaffb31Sdp 3039daaffb31Sdp rm -f $WDIR/$DIR/$F.patch 3040daaffb31Sdp if [[ -z $rename ]]; then 3041e0e0293aSjmcp if [ ! -f "$ofile" ]; then 3042daaffb31Sdp diff -u /dev/null $nfile | sh -c "$cleanse_newfile" \ 3043daaffb31Sdp > $WDIR/$DIR/$F.patch 3044e0e0293aSjmcp elif [ ! -f "$nfile" ]; then 3045daaffb31Sdp diff -u $ofile /dev/null | sh -c "$cleanse_rmfile" \ 3046daaffb31Sdp > $WDIR/$DIR/$F.patch 3047daaffb31Sdp else 3048daaffb31Sdp diff -u $ofile $nfile > $WDIR/$DIR/$F.patch 3049daaffb31Sdp fi 3050daaffb31Sdp else 3051daaffb31Sdp diff -u $ofile /dev/null | sh -c "$cleanse_rmfile" \ 3052daaffb31Sdp > $WDIR/$DIR/$F.patch 3053daaffb31Sdp 3054daaffb31Sdp diff -u /dev/null $nfile | sh -c "$cleanse_newfile" \ 3055daaffb31Sdp >> $WDIR/$DIR/$F.patch 3056daaffb31Sdp 3057daaffb31Sdp fi 3058daaffb31Sdp 3059daaffb31Sdp # 3060daaffb31Sdp # Tack the patch we just made onto the accumulated patch for the 3061daaffb31Sdp # whole wad. 3062daaffb31Sdp # 3063daaffb31Sdp cat $WDIR/$DIR/$F.patch >> $WDIR/$WNAME.patch 3064daaffb31Sdp 3065daaffb31Sdp print " patch\c" 3066daaffb31Sdp 3067daaffb31Sdp if [[ -f $ofile && -f $nfile && -z $mv_but_nodiff ]]; then 3068daaffb31Sdp 3069daaffb31Sdp ${CDIFFCMD:-diff -bt -C 5} $ofile $nfile > $WDIR/$DIR/$F.cdiff 3070daaffb31Sdp diff_to_html $F $DIR/$F "C" "$COMM" < $WDIR/$DIR/$F.cdiff \ 3071daaffb31Sdp > $WDIR/$DIR/$F.cdiff.html 30727c478bd9Sstevel@tonic-gate print " cdiffs\c" 30737c478bd9Sstevel@tonic-gate 3074daaffb31Sdp ${UDIFFCMD:-diff -bt -U 5} $ofile $nfile > $WDIR/$DIR/$F.udiff 3075daaffb31Sdp diff_to_html $F $DIR/$F "U" "$COMM" < $WDIR/$DIR/$F.udiff \ 3076daaffb31Sdp > $WDIR/$DIR/$F.udiff.html 3077daaffb31Sdp 30787c478bd9Sstevel@tonic-gate print " udiffs\c" 30797c478bd9Sstevel@tonic-gate 30807c478bd9Sstevel@tonic-gate if [[ -x $WDIFF ]]; then 3081daaffb31Sdp $WDIFF -c "$COMM" \ 3082daaffb31Sdp -t "$WNAME Wdiff $DIR/$F" $ofile $nfile > \ 3083daaffb31Sdp $WDIR/$DIR/$F.wdiff.html 2>/dev/null 3084daaffb31Sdp if [[ $? -eq 0 ]]; then 30857c478bd9Sstevel@tonic-gate print " wdiffs\c" 3086daaffb31Sdp else 3087daaffb31Sdp print " wdiffs[fail]\c" 3088daaffb31Sdp fi 30897c478bd9Sstevel@tonic-gate fi 30907c478bd9Sstevel@tonic-gate 3091daaffb31Sdp sdiff_to_html $ofile $nfile $F $DIR "$COMM" \ 3092daaffb31Sdp > $WDIR/$DIR/$F.sdiff.html 30937c478bd9Sstevel@tonic-gate print " sdiffs\c" 30947c478bd9Sstevel@tonic-gate 30957c478bd9Sstevel@tonic-gate print " frames\c" 30967c478bd9Sstevel@tonic-gate 30977c478bd9Sstevel@tonic-gate rm -f $WDIR/$DIR/$F.cdiff $WDIR/$DIR/$F.udiff 30987c478bd9Sstevel@tonic-gate 3099daaffb31Sdp difflines $ofile $nfile > $WDIR/$DIR/$F.count 3100daaffb31Sdp 3101daaffb31Sdp elif [[ -f $ofile && -f $nfile && -n $mv_but_nodiff ]]; then 3102daaffb31Sdp # renamed file: may also have differences 3103daaffb31Sdp difflines $ofile $nfile > $WDIR/$DIR/$F.count 3104daaffb31Sdp elif [[ -f $nfile ]]; then 31057c478bd9Sstevel@tonic-gate # new file: count added lines 3106daaffb31Sdp difflines /dev/null $nfile > $WDIR/$DIR/$F.count 3107daaffb31Sdp elif [[ -f $ofile ]]; then 31087c478bd9Sstevel@tonic-gate # old file: count deleted lines 3109daaffb31Sdp difflines $ofile /dev/null > $WDIR/$DIR/$F.count 31107c478bd9Sstevel@tonic-gate fi 31117c478bd9Sstevel@tonic-gate 3112daaffb31Sdp # 3113daaffb31Sdp # Now we generate the postscript for this file. We generate diffs 3114daaffb31Sdp # only in the event that there is delta, or the file is new (it seems 3115daaffb31Sdp # tree-killing to print out the contents of deleted files). 3116daaffb31Sdp # 3117daaffb31Sdp if [[ -f $nfile ]]; then 3118daaffb31Sdp ocr=$ofile 3119daaffb31Sdp [[ ! -f $ofile ]] && ocr=/dev/null 3120daaffb31Sdp 3121daaffb31Sdp if [[ -z $mv_but_nodiff ]]; then 3122daaffb31Sdp textcomm=`getcomments text $P $PP` 312314983201Sdp if [[ -x $CODEREVIEW ]]; then 312414983201Sdp $CODEREVIEW -y "$textcomm" \ 312514983201Sdp -e $ocr $nfile \ 312614983201Sdp > /tmp/$$.psfile 2>/dev/null && 312714983201Sdp cat /tmp/$$.psfile >> $WDIR/$WNAME.ps 3128daaffb31Sdp if [[ $? -eq 0 ]]; then 3129daaffb31Sdp print " ps\c" 3130daaffb31Sdp else 3131daaffb31Sdp print " ps[fail]\c" 3132daaffb31Sdp fi 3133daaffb31Sdp fi 3134daaffb31Sdp fi 313514983201Sdp fi 3136daaffb31Sdp 3137cdf0c1d5Smjnelson if [[ -f $ofile ]]; then 3138cdf0c1d5Smjnelson source_to_html Old $PP < $ofile > $WDIR/$DIR/$F-.html 31397c478bd9Sstevel@tonic-gate print " old\c" 31407c478bd9Sstevel@tonic-gate fi 31417c478bd9Sstevel@tonic-gate 3142daaffb31Sdp if [[ -f $nfile ]]; then 3143daaffb31Sdp source_to_html New $P < $nfile > $WDIR/$DIR/$F.html 31447c478bd9Sstevel@tonic-gate print " new\c" 31457c478bd9Sstevel@tonic-gate fi 31467c478bd9Sstevel@tonic-gate 3147cdf0c1d5Smjnelson cd $OWD 3148cdf0c1d5Smjnelson 3149daaffb31Sdp print 31507c478bd9Sstevel@tonic-gatedone 31517c478bd9Sstevel@tonic-gate 3152daaffb31Sdpframe_nav_js > $WDIR/ancnav.js 31537c478bd9Sstevel@tonic-gateframe_navigation > $WDIR/ancnav.html 3154daaffb31Sdp 315514983201Sdpif [[ ! -f $WDIR/$WNAME.ps ]]; then 315614983201Sdp print " Generating PDF: Skipped: no output available" 315714983201Sdpelif [[ -x $CODEREVIEW && -x $PS2PDF ]]; then 315814983201Sdp print " Generating PDF: \c" 315914983201Sdp fix_postscript $WDIR/$WNAME.ps | $PS2PDF - > $WDIR/$WNAME.pdf 3160daaffb31Sdp print "Done." 316114983201Sdpelse 316214983201Sdp print " Generating PDF: Skipped: missing 'ps2pdf' or 'codereview'" 316314983201Sdpfi 31647c478bd9Sstevel@tonic-gate 3165e0e0293aSjmcp# If we're in OpenSolaris mode and there's a closed dir under $WDIR, 3166e0e0293aSjmcp# delete it - prevent accidental publishing of closed source 3167e0e0293aSjmcp 3168e0e0293aSjmcpif [[ -n "$Oflag" ]]; then 3169ba44d8a2SVladimir Kotal $FIND $WDIR -type d -name closed -exec /bin/rm -rf {} \; 3170e0e0293aSjmcpfi 3171e0e0293aSjmcp 31727c478bd9Sstevel@tonic-gate# Now build the index.html file that contains 31737c478bd9Sstevel@tonic-gate# links to the source files and their diffs. 31747c478bd9Sstevel@tonic-gate 31757c478bd9Sstevel@tonic-gatecd $CWS 31767c478bd9Sstevel@tonic-gate 31777c478bd9Sstevel@tonic-gate# Save total changed lines for Code Inspection. 3178daaffb31Sdpprint "$TOTL" > $WDIR/TotalChangedLines 31797c478bd9Sstevel@tonic-gate 3180daaffb31Sdpprint " index.html: \c" 31817c478bd9Sstevel@tonic-gateINDEXFILE=$WDIR/index.html 31827c478bd9Sstevel@tonic-gateexec 3<&1 # duplicate stdout to FD3. 31837c478bd9Sstevel@tonic-gateexec 1<&- # Close stdout. 31847c478bd9Sstevel@tonic-gateexec > $INDEXFILE # Open stdout to index file. 31857c478bd9Sstevel@tonic-gate 3186daaffb31Sdpprint "$HTML<head>$STDHEAD" 3187daaffb31Sdpprint "<title>$WNAME</title>" 3188daaffb31Sdpprint "</head>" 3189daaffb31Sdpprint "<body id=\"SUNWwebrev\">" 3190daaffb31Sdpprint "<div class=\"summary\">" 3191daaffb31Sdpprint "<h2>Code Review for $WNAME</h2>" 31927c478bd9Sstevel@tonic-gate 3193daaffb31Sdpprint "<table>" 31947c478bd9Sstevel@tonic-gate 3195daaffb31Sdp# 3196cdf0c1d5Smjnelson# Get the preparer's name: 3197daaffb31Sdp# 3198cdf0c1d5Smjnelson# If the SCM detected is Mercurial, and the configuration property 3199cdf0c1d5Smjnelson# ui.username is available, use that, but be careful to properly escape 3200cdf0c1d5Smjnelson# angle brackets (HTML syntax characters) in the email address. 3201cdf0c1d5Smjnelson# 3202cdf0c1d5Smjnelson# Otherwise, use the current userid in the form "John Doe (jdoe)", but 3203cdf0c1d5Smjnelson# to maintain compatibility with passwd(4), we must support '&' substitutions. 3204cdf0c1d5Smjnelson# 3205cdf0c1d5Smjnelsonpreparer= 3206cdf0c1d5Smjnelsonif [[ "$SCM_MODE" == mercurial ]]; then 3207cdf0c1d5Smjnelson preparer=`hg showconfig ui.username 2>/dev/null` 3208cdf0c1d5Smjnelson if [[ -n "$preparer" ]]; then 3209cdf0c1d5Smjnelson preparer="$(echo "$preparer" | html_quote)" 3210cdf0c1d5Smjnelson fi 3211cdf0c1d5Smjnelsonfi 3212cdf0c1d5Smjnelsonif [[ -z "$preparer" ]]; then 3213cdf0c1d5Smjnelson preparer=$( 3214cdf0c1d5Smjnelson $PERL -e ' 3215cdf0c1d5Smjnelson ($login, $pw, $uid, $gid, $quota, $cmt, $gcos) = getpwuid($<); 3216cdf0c1d5Smjnelson if ($login) { 3217cdf0c1d5Smjnelson $gcos =~ s/\&/ucfirst($login)/e; 3218cdf0c1d5Smjnelson printf "%s (%s)\n", $gcos, $login; 3219cdf0c1d5Smjnelson } else { 3220cdf0c1d5Smjnelson printf "(unknown)\n"; 3221cdf0c1d5Smjnelson } 3222cdf0c1d5Smjnelson ') 3223daaffb31Sdpfi 3224daaffb31Sdp 3225cdf0c1d5Smjnelsonprint "<tr><th>Prepared by:</th><td>$preparer on `date`</td></tr>" 3226cdf0c1d5Smjnelsonprint "<tr><th>Workspace:</th><td>$CWS" 3227cdf0c1d5Smjnelsonif [[ -n $CWS_REV ]]; then 3228cdf0c1d5Smjnelson print "(at $CWS_REV)" 3229cdf0c1d5Smjnelsonfi 3230cdf0c1d5Smjnelsonprint "</td></tr>" 3231daaffb31Sdpprint "<tr><th>Compare against:</th><td>" 3232daaffb31Sdpif [[ -n $parent_webrev ]]; then 3233daaffb31Sdp print "webrev at $parent_webrev" 3234daaffb31Sdpelse 3235daaffb31Sdp print "$PWS" 3236cdf0c1d5Smjnelson if [[ -n $hg_parent_short ]]; then 3237cdf0c1d5Smjnelson print "(at $hg_parent_short)" 3238cdf0c1d5Smjnelson fi 3239daaffb31Sdpfi 3240daaffb31Sdpprint "</td></tr>" 3241daaffb31Sdpprint "<tr><th>Summary of changes:</th><td>" 3242daaffb31SdpprintCI $TOTL $TINS $TDEL $TMOD $TUNC 3243daaffb31Sdpprint "</td></tr>" 3244daaffb31Sdp 3245daaffb31Sdpif [[ -f $WDIR/$WNAME.patch ]]; then 3246371d72daSLubomir Sedlacik wpatch_url="$(print $WNAME.patch | url_encode)" 3247daaffb31Sdp print "<tr><th>Patch of changes:</th><td>" 3248371d72daSLubomir Sedlacik print "<a href=\"$wpatch_url\">$WNAME.patch</a></td></tr>" 3249daaffb31Sdpfi 3250daaffb31Sdpif [[ -f $WDIR/$WNAME.pdf ]]; then 3251371d72daSLubomir Sedlacik wpdf_url="$(print $WNAME.pdf | url_encode)" 3252daaffb31Sdp print "<tr><th>Printable review:</th><td>" 3253371d72daSLubomir Sedlacik print "<a href=\"$wpdf_url\">$WNAME.pdf</a></td></tr>" 3254daaffb31Sdpfi 3255daaffb31Sdp 3256daaffb31Sdpif [[ -n "$iflag" ]]; then 3257daaffb31Sdp print "<tr><th>Author comments:</th><td><div>" 3258daaffb31Sdp cat /tmp/$$.include 3259daaffb31Sdp print "</div></td></tr>" 3260daaffb31Sdpfi 3261daaffb31Sdpprint "</table>" 3262daaffb31Sdpprint "</div>" 3263daaffb31Sdp 3264daaffb31Sdp# 3265daaffb31Sdp# Second pass through the files: generate the rest of the index file 3266daaffb31Sdp# 3267daaffb31Sdpcat $FLIST | while read LINE 32687c478bd9Sstevel@tonic-gatedo 32697c478bd9Sstevel@tonic-gate set - $LINE 32707c478bd9Sstevel@tonic-gate P=$1 32717c478bd9Sstevel@tonic-gate 3272daaffb31Sdp if [[ $# == 2 ]]; then 32737c478bd9Sstevel@tonic-gate PP=$2 3274cdf0c1d5Smjnelson oldname="$PP" 32757c478bd9Sstevel@tonic-gate else 32767c478bd9Sstevel@tonic-gate PP=$P 3277daaffb31Sdp oldname="" 3278daaffb31Sdp fi 3279daaffb31Sdp 3280cdf0c1d5Smjnelson mv_but_nodiff= 3281cdf0c1d5Smjnelson cmp $WDIR/raw_files/old/$PP $WDIR/raw_files/new/$P > /dev/null 2>&1 3282cdf0c1d5Smjnelson if [[ $? == 0 && -n "$oldname" ]]; then 3283cdf0c1d5Smjnelson mv_but_nodiff=1 3284cdf0c1d5Smjnelson fi 3285cdf0c1d5Smjnelson 3286daaffb31Sdp DIR=${P%/*} 3287daaffb31Sdp if [[ $DIR == $P ]]; then 3288daaffb31Sdp DIR="." # File at root of workspace 32897c478bd9Sstevel@tonic-gate fi 32907c478bd9Sstevel@tonic-gate 32917c478bd9Sstevel@tonic-gate # Avoid processing the same file twice. 32927c478bd9Sstevel@tonic-gate # It's possible for renamed files to 32937c478bd9Sstevel@tonic-gate # appear twice in the file list 32947c478bd9Sstevel@tonic-gate 32957c478bd9Sstevel@tonic-gate F=$WDIR/$P 32967c478bd9Sstevel@tonic-gate 3297daaffb31Sdp print "<p>" 32987c478bd9Sstevel@tonic-gate 32997c478bd9Sstevel@tonic-gate # If there's a diffs file, make diffs links 33007c478bd9Sstevel@tonic-gate 3301daaffb31Sdp if [[ -f $F.cdiff.html ]]; then 3302371d72daSLubomir Sedlacik cdiff_url="$(print $P.cdiff.html | url_encode)" 3303371d72daSLubomir Sedlacik udiff_url="$(print $P.udiff.html | url_encode)" 3304371d72daSLubomir Sedlacik print "<a href=\"$cdiff_url\">Cdiffs</a>" 3305371d72daSLubomir Sedlacik print "<a href=\"$udiff_url\">Udiffs</a>" 33067c478bd9Sstevel@tonic-gate 3307daaffb31Sdp if [[ -f $F.wdiff.html && -x $WDIFF ]]; then 3308371d72daSLubomir Sedlacik wdiff_url="$(print $P.wdiff.html | url_encode)" 3309371d72daSLubomir Sedlacik print "<a href=\"$wdiff_url\">Wdiffs</a>" 33107c478bd9Sstevel@tonic-gate fi 33117c478bd9Sstevel@tonic-gate 3312371d72daSLubomir Sedlacik sdiff_url="$(print $P.sdiff.html | url_encode)" 3313371d72daSLubomir Sedlacik print "<a href=\"$sdiff_url\">Sdiffs</a>" 33147c478bd9Sstevel@tonic-gate 3315371d72daSLubomir Sedlacik frames_url="$(print $P.frames.html | url_encode)" 3316371d72daSLubomir Sedlacik print "<a href=\"$frames_url\">Frames</a>" 33177c478bd9Sstevel@tonic-gate else 3318daaffb31Sdp print " ------ ------ ------" 33197c478bd9Sstevel@tonic-gate 3320daaffb31Sdp if [[ -x $WDIFF ]]; then 33217c478bd9Sstevel@tonic-gate print " ------" 33227c478bd9Sstevel@tonic-gate fi 3323daaffb31Sdp 3324daaffb31Sdp print " ------" 33257c478bd9Sstevel@tonic-gate fi 33267c478bd9Sstevel@tonic-gate 33277c478bd9Sstevel@tonic-gate # If there's an old file, make the link 33287c478bd9Sstevel@tonic-gate 3329daaffb31Sdp if [[ -f $F-.html ]]; then 3330371d72daSLubomir Sedlacik oldfile_url="$(print $P-.html | url_encode)" 3331371d72daSLubomir Sedlacik print "<a href=\"$oldfile_url\">Old</a>" 33327c478bd9Sstevel@tonic-gate else 3333daaffb31Sdp print " ---" 33347c478bd9Sstevel@tonic-gate fi 33357c478bd9Sstevel@tonic-gate 33367c478bd9Sstevel@tonic-gate # If there's an new file, make the link 33377c478bd9Sstevel@tonic-gate 3338daaffb31Sdp if [[ -f $F.html ]]; then 3339371d72daSLubomir Sedlacik newfile_url="$(print $P.html | url_encode)" 3340371d72daSLubomir Sedlacik print "<a href=\"$newfile_url\">New</a>" 33417c478bd9Sstevel@tonic-gate else 3342daaffb31Sdp print " ---" 33437c478bd9Sstevel@tonic-gate fi 33447c478bd9Sstevel@tonic-gate 3345daaffb31Sdp if [[ -f $F.patch ]]; then 3346371d72daSLubomir Sedlacik patch_url="$(print $P.patch | url_encode)" 3347371d72daSLubomir Sedlacik print "<a href=\"$patch_url\">Patch</a>" 3348daaffb31Sdp else 3349daaffb31Sdp print " -----" 3350daaffb31Sdp fi 3351daaffb31Sdp 3352daaffb31Sdp if [[ -f $WDIR/raw_files/new/$P ]]; then 3353371d72daSLubomir Sedlacik rawfiles_url="$(print raw_files/new/$P | url_encode)" 3354371d72daSLubomir Sedlacik print "<a href=\"$rawfiles_url\">Raw</a>" 3355daaffb31Sdp else 3356daaffb31Sdp print " ---" 3357daaffb31Sdp fi 3358daaffb31Sdp 3359cdf0c1d5Smjnelson print "<b>$P</b>" 3360cdf0c1d5Smjnelson 3361cdf0c1d5Smjnelson # For renamed files, clearly state whether or not they are modified 3362cdf0c1d5Smjnelson if [[ -n "$oldname" ]]; then 3363cdf0c1d5Smjnelson if [[ -n "$mv_but_nodiff" ]]; then 3364cdf0c1d5Smjnelson print "<i>(renamed only, was $oldname)</i>" 3365cdf0c1d5Smjnelson else 3366cdf0c1d5Smjnelson print "<i>(modified and renamed, was $oldname)</i>" 3367cdf0c1d5Smjnelson fi 3368cdf0c1d5Smjnelson fi 3369cdf0c1d5Smjnelson 3370cdf0c1d5Smjnelson # If there's an old file, but no new file, the file was deleted 3371cdf0c1d5Smjnelson if [[ -f $F-.html && ! -f $F.html ]]; then 3372cdf0c1d5Smjnelson print " <i>(deleted)</i>" 3373cdf0c1d5Smjnelson fi 3374daaffb31Sdp 3375daaffb31Sdp # 3376e0e0293aSjmcp # Check for usr/closed and deleted_files/usr/closed 3377daaffb31Sdp # 3378daaffb31Sdp if [ ! -z "$Oflag" ]; then 3379e0e0293aSjmcp if [[ $P == usr/closed/* || \ 3380e0e0293aSjmcp $P == deleted_files/usr/closed/* ]]; then 3381daaffb31Sdp print " <i>Closed source: omitted from" \ 3382daaffb31Sdp "this review</i>" 3383daaffb31Sdp fi 3384daaffb31Sdp fi 3385daaffb31Sdp 3386daaffb31Sdp print "</p>" 33877c478bd9Sstevel@tonic-gate # Insert delta comments 33887c478bd9Sstevel@tonic-gate 3389daaffb31Sdp print "<blockquote><pre>" 3390daaffb31Sdp getcomments html $P $PP 3391daaffb31Sdp print "</pre>" 33927c478bd9Sstevel@tonic-gate 33937c478bd9Sstevel@tonic-gate # Add additional comments comment 33947c478bd9Sstevel@tonic-gate 3395daaffb31Sdp print "<!-- Add comments to explain changes in $P here -->" 33967c478bd9Sstevel@tonic-gate 33977c478bd9Sstevel@tonic-gate # Add count of changes. 33987c478bd9Sstevel@tonic-gate 3399daaffb31Sdp if [[ -f $F.count ]]; then 34007c478bd9Sstevel@tonic-gate cat $F.count 34017c478bd9Sstevel@tonic-gate rm $F.count 34027c478bd9Sstevel@tonic-gate fi 3403cdf0c1d5Smjnelson 3404cdf0c1d5Smjnelson if [[ $SCM_MODE == "teamware" || 3405cdf0c1d5Smjnelson $SCM_MODE == "mercurial" || 3406cdf0c1d5Smjnelson $SCM_MODE == "unknown" ]]; then 3407cdf0c1d5Smjnelson 3408cdf0c1d5Smjnelson # Include warnings for important file mode situations: 3409cdf0c1d5Smjnelson # 1) New executable files 3410cdf0c1d5Smjnelson # 2) Permission changes of any kind 3411cdf0c1d5Smjnelson # 3) Existing executable files 3412cdf0c1d5Smjnelson 3413cdf0c1d5Smjnelson old_mode= 3414cdf0c1d5Smjnelson if [[ -f $WDIR/raw_files/old/$PP ]]; then 3415cdf0c1d5Smjnelson old_mode=`get_file_mode $WDIR/raw_files/old/$PP` 3416cdf0c1d5Smjnelson fi 3417cdf0c1d5Smjnelson 3418cdf0c1d5Smjnelson new_mode= 3419cdf0c1d5Smjnelson if [[ -f $WDIR/raw_files/new/$P ]]; then 3420cdf0c1d5Smjnelson new_mode=`get_file_mode $WDIR/raw_files/new/$P` 3421cdf0c1d5Smjnelson fi 3422cdf0c1d5Smjnelson 3423cdf0c1d5Smjnelson if [[ -z "$old_mode" && "$new_mode" = *[1357]* ]]; then 3424cdf0c1d5Smjnelson print "<span class=\"chmod\">" 3425cdf0c1d5Smjnelson print "<p>new executable file: mode $new_mode</p>" 3426cdf0c1d5Smjnelson print "</span>" 3427cdf0c1d5Smjnelson elif [[ -n "$old_mode" && -n "$new_mode" && 3428cdf0c1d5Smjnelson "$old_mode" != "$new_mode" ]]; then 3429cdf0c1d5Smjnelson print "<span class=\"chmod\">" 3430cdf0c1d5Smjnelson print "<p>mode change: $old_mode to $new_mode</p>" 3431cdf0c1d5Smjnelson print "</span>" 3432cdf0c1d5Smjnelson elif [[ "$new_mode" = *[1357]* ]]; then 3433cdf0c1d5Smjnelson print "<span class=\"chmod\">" 3434cdf0c1d5Smjnelson print "<p>executable file: mode $new_mode</p>" 3435cdf0c1d5Smjnelson print "</span>" 3436cdf0c1d5Smjnelson fi 3437cdf0c1d5Smjnelson fi 3438cdf0c1d5Smjnelson 3439daaffb31Sdp print "</blockquote>" 34407c478bd9Sstevel@tonic-gatedone 34417c478bd9Sstevel@tonic-gate 3442daaffb31Sdpprint 3443daaffb31Sdpprint 3444cac38512Smjnelsonprint "<hr></hr>" 3445daaffb31Sdpprint "<p style=\"font-size: small\">" 34469a70fc3bSMark J. Nelsonprint "This code review page was prepared using <b>$0</b>." 3447daaffb31Sdpprint "Webrev is maintained by the <a href=\"http://www.opensolaris.org\">" 3448daaffb31Sdpprint "OpenSolaris</a> project. The latest version may be obtained" 3449e9e2cfb2Sfr80241print "<a href=\"http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/tools/scripts/webrev.sh\">here</a>.</p>" 3450daaffb31Sdpprint "</body>" 3451daaffb31Sdpprint "</html>" 34527c478bd9Sstevel@tonic-gate 34537c478bd9Sstevel@tonic-gateexec 1<&- # Close FD 1. 34547c478bd9Sstevel@tonic-gateexec 1<&3 # dup FD 3 to restore stdout. 34557c478bd9Sstevel@tonic-gateexec 3<&- # close FD 3. 34567c478bd9Sstevel@tonic-gate 3457daaffb31Sdpprint "Done." 345802d26c39SVladimir Kotal 3459b0088928SVladimir Kotal# 3460ba44d8a2SVladimir Kotal# If remote deletion was specified and fails do not continue. 3461b0088928SVladimir Kotal# 3462ba44d8a2SVladimir Kotalif [[ -n $Dflag ]]; then 3463b0088928SVladimir Kotal delete_webrev 1 1 3464ba44d8a2SVladimir Kotal (( $? == 0 )) || exit $? 3465ba44d8a2SVladimir Kotalfi 3466ba44d8a2SVladimir Kotal 346702d26c39SVladimir Kotalif [[ -n $Uflag ]]; then 346802d26c39SVladimir Kotal upload_webrev 346902d26c39SVladimir Kotal exit $? 347002d26c39SVladimir Kotalfi 3471