148fe8920SMark J. Nelson#!/usr/bin/ksh93 -p 27c478bd9Sstevel@tonic-gate# 37c478bd9Sstevel@tonic-gate# CDDL HEADER START 47c478bd9Sstevel@tonic-gate# 57c478bd9Sstevel@tonic-gate# The contents of this file are subject to the terms of the 6daaffb31Sdp# Common Development and Distribution License (the "License"). 7daaffb31Sdp# You may not use this file except in compliance with the License. 87c478bd9Sstevel@tonic-gate# 97c478bd9Sstevel@tonic-gate# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate# or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate# See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate# and limitations under the License. 137c478bd9Sstevel@tonic-gate# 147c478bd9Sstevel@tonic-gate# When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate# If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate# fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate# information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate# 207c478bd9Sstevel@tonic-gate# CDDL HEADER END 217c478bd9Sstevel@tonic-gate# 229a70fc3bSMark J. Nelson 237c478bd9Sstevel@tonic-gate# 2478add226Sjmcp# Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. 257c478bd9Sstevel@tonic-gate# 26cdf0c1d5Smjnelson 272f54b716SRichard Lowe# Copyright 2008, 2010, Richard Lowe 282f54b716SRichard Lowe 29cdf0c1d5Smjnelson# 30daaffb31Sdp# This script takes a file list and a workspace and builds a set of html files 31daaffb31Sdp# suitable for doing a code review of source changes via a web page. 32daaffb31Sdp# Documentation is available via the manual page, webrev.1, or just 33daaffb31Sdp# type 'webrev -h'. 347c478bd9Sstevel@tonic-gate# 35daaffb31Sdp# Acknowledgements to contributors to webrev are listed in the webrev(1) 36daaffb31Sdp# man page. 377c478bd9Sstevel@tonic-gate# 38daaffb31Sdp 397c478bd9Sstevel@tonic-gateREMOVED_COLOR=brown 407c478bd9Sstevel@tonic-gateCHANGED_COLOR=blue 417c478bd9Sstevel@tonic-gateNEW_COLOR=blue 427c478bd9Sstevel@tonic-gate 43daaffb31SdpHTML='<?xml version="1.0"?> 44daaffb31Sdp<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 45daaffb31Sdp "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 46daaffb31Sdp<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">\n' 47daaffb31Sdp 48daaffb31SdpFRAMEHTML='<?xml version="1.0"?> 49daaffb31Sdp<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" 50daaffb31Sdp "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd"> 51daaffb31Sdp<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">\n' 52daaffb31Sdp 53cac38512SmjnelsonSTDHEAD='<meta http-equiv="cache-control" content="no-cache"></meta> 54cac38512Smjnelson<meta http-equiv="Pragma" content="no-cache"></meta> 55cac38512Smjnelson<meta http-equiv="Expires" content="-1"></meta> 56daaffb31Sdp<!-- 57daaffb31Sdp Note to customizers: the body of the webrev is IDed as SUNWwebrev 58daaffb31Sdp to allow easy overriding by users of webrev via the userContent.css 59daaffb31Sdp mechanism available in some browsers. 60daaffb31Sdp 61daaffb31Sdp For example, to have all "removed" information be red instead of 62daaffb31Sdp brown, set a rule in your userContent.css file like: 63daaffb31Sdp 64daaffb31Sdp body#SUNWwebrev span.removed { color: red ! important; } 65daaffb31Sdp--> 66daaffb31Sdp<style type="text/css" media="screen"> 67daaffb31Sdpbody { 68daaffb31Sdp background-color: #eeeeee; 69daaffb31Sdp} 70daaffb31Sdphr { 71daaffb31Sdp border: none 0; 72daaffb31Sdp border-top: 1px solid #aaa; 73daaffb31Sdp height: 1px; 74daaffb31Sdp} 75daaffb31Sdpdiv.summary { 76daaffb31Sdp font-size: .8em; 77daaffb31Sdp border-bottom: 1px solid #aaa; 78daaffb31Sdp padding-left: 1em; 79daaffb31Sdp padding-right: 1em; 80daaffb31Sdp} 81daaffb31Sdpdiv.summary h2 { 82daaffb31Sdp margin-bottom: 0.3em; 83daaffb31Sdp} 84daaffb31Sdpdiv.summary table th { 85daaffb31Sdp text-align: right; 86daaffb31Sdp vertical-align: top; 87daaffb31Sdp white-space: nowrap; 88daaffb31Sdp} 89daaffb31Sdpspan.lineschanged { 90daaffb31Sdp font-size: 0.7em; 91daaffb31Sdp} 92daaffb31Sdpspan.oldmarker { 93daaffb31Sdp color: red; 94daaffb31Sdp font-size: large; 95daaffb31Sdp font-weight: bold; 96daaffb31Sdp} 97daaffb31Sdpspan.newmarker { 98daaffb31Sdp color: green; 99daaffb31Sdp font-size: large; 100daaffb31Sdp font-weight: bold; 101daaffb31Sdp} 102daaffb31Sdpspan.removed { 103daaffb31Sdp color: brown; 104daaffb31Sdp} 105daaffb31Sdpspan.changed { 106daaffb31Sdp color: blue; 107daaffb31Sdp} 108daaffb31Sdpspan.new { 109daaffb31Sdp color: blue; 110daaffb31Sdp font-weight: bold; 111daaffb31Sdp} 112cdf0c1d5Smjnelsonspan.chmod { 113cdf0c1d5Smjnelson font-size: 0.7em; 114cdf0c1d5Smjnelson color: #db7800; 115cdf0c1d5Smjnelson} 116daaffb31Sdpa.print { font-size: x-small; } 117daaffb31Sdpa:hover { background-color: #ffcc99; } 118daaffb31Sdp</style> 119daaffb31Sdp 120daaffb31Sdp<style type="text/css" media="print"> 121daaffb31Sdppre { font-size: 0.8em; font-family: courier, monospace; } 122daaffb31Sdpspan.removed { color: #444; font-style: italic } 123daaffb31Sdpspan.changed { font-weight: bold; } 124daaffb31Sdpspan.new { font-weight: bold; } 125daaffb31Sdpspan.newmarker { font-size: 1.2em; font-weight: bold; } 126daaffb31Sdpspan.oldmarker { font-size: 1.2em; font-weight: bold; } 127daaffb31Sdpa.print {display: none} 128daaffb31Sdphr { border: none 0; border-top: 1px solid #aaa; height: 1px; } 129daaffb31Sdp</style> 130daaffb31Sdp' 131daaffb31Sdp 132daaffb31Sdp# 133daaffb31Sdp# UDiffs need a slightly different CSS rule for 'new' items (we don't 134daaffb31Sdp# want them to be bolded as we do in cdiffs or sdiffs). 135daaffb31Sdp# 136daaffb31SdpUDIFFCSS=' 137daaffb31Sdp<style type="text/css" media="screen"> 138daaffb31Sdpspan.new { 139daaffb31Sdp color: blue; 140daaffb31Sdp font-weight: normal; 141daaffb31Sdp} 142daaffb31Sdp</style> 143daaffb31Sdp' 144daaffb31Sdp 145b0088928SVladimir Kotal# 146b0088928SVladimir Kotal# Display remote target with prefix and trailing slash. 147b0088928SVladimir Kotal# 148b0088928SVladimir Kotalfunction print_upload_header 149b0088928SVladimir Kotal{ 150b0088928SVladimir Kotal typeset -r prefix=$1 151b0088928SVladimir Kotal typeset display_target 152b0088928SVladimir Kotal 153b0088928SVladimir Kotal if [[ -z $tflag ]]; then 154b0088928SVladimir Kotal display_target=${prefix}${remote_target} 155b0088928SVladimir Kotal else 156b0088928SVladimir Kotal display_target=${remote_target} 157b0088928SVladimir Kotal fi 158b0088928SVladimir Kotal 159b0088928SVladimir Kotal if [[ ${display_target} != */ ]]; then 160b0088928SVladimir Kotal display_target=${display_target}/ 161b0088928SVladimir Kotal fi 162b0088928SVladimir Kotal 163b0088928SVladimir Kotal print " Upload to: ${display_target}\n" \ 164b0088928SVladimir Kotal " Uploading: \c" 165b0088928SVladimir Kotal} 166b0088928SVladimir Kotal 167b0088928SVladimir Kotal# 16802d26c39SVladimir Kotal# Upload the webrev via rsync. Return 0 on success, 1 on error. 169b0088928SVladimir Kotal# 170ba44d8a2SVladimir Kotalfunction rsync_upload 17102d26c39SVladimir Kotal{ 172b0088928SVladimir Kotal if (( $# != 2 )); then 173b0088928SVladimir Kotal print "\nERROR: rsync_upload: wrong usage ($#)" 174b0088928SVladimir Kotal exit 1 17502d26c39SVladimir Kotal fi 17602d26c39SVladimir Kotal 177b0088928SVladimir Kotal typeset -r dst=$1 178b0088928SVladimir Kotal integer -r print_err_msg=$2 17902d26c39SVladimir Kotal 180b0088928SVladimir Kotal print_upload_header ${rsync_prefix} 181b0088928SVladimir Kotal print "rsync ... \c" 1828a34f8dcSVladimir Kotal typeset -r err_msg=$( $MKTEMP /tmp/rsync_err.XXXXXX ) 183b0088928SVladimir Kotal if [[ -z $err_msg ]]; then 184b0088928SVladimir Kotal print "\nERROR: rsync_upload: cannot create temporary file" 185b0088928SVladimir Kotal return 1 186b0088928SVladimir Kotal fi 187b0088928SVladimir Kotal # 188b0088928SVladimir Kotal # The source directory must end with a slash in order to copy just 189b0088928SVladimir Kotal # directory contents, not the whole directory. 190b0088928SVladimir Kotal # 191b0088928SVladimir Kotal typeset src_dir=$WDIR 192b0088928SVladimir Kotal if [[ ${src_dir} != */ ]]; then 193b0088928SVladimir Kotal src_dir=${src_dir}/ 194b0088928SVladimir Kotal fi 195b0088928SVladimir Kotal $RSYNC -r -q ${src_dir} $dst 2>$err_msg 19602d26c39SVladimir Kotal if (( $? != 0 )); then 197b0088928SVladimir Kotal if (( ${print_err_msg} > 0 )); then 198b0088928SVladimir Kotal print "Failed.\nERROR: rsync failed" 199b0088928SVladimir Kotal print "src dir: '${src_dir}'\ndst dir: '$dst'" 200b0088928SVladimir Kotal print "error messages:" 201b0088928SVladimir Kotal $SED 's/^/> /' $err_msg 202b0088928SVladimir Kotal rm -f $err_msg 203b0088928SVladimir Kotal fi 20402d26c39SVladimir Kotal return 1 20502d26c39SVladimir Kotal fi 20602d26c39SVladimir Kotal 207b0088928SVladimir Kotal rm -f $err_msg 20802d26c39SVladimir Kotal print "Done." 20902d26c39SVladimir Kotal return 0 21002d26c39SVladimir Kotal} 21102d26c39SVladimir Kotal 212b0088928SVladimir Kotal# 213b0088928SVladimir Kotal# Create directories on remote host using SFTP. Return 0 on success, 214b0088928SVladimir Kotal# 1 on failure. 215b0088928SVladimir Kotal# 216b0088928SVladimir Kotalfunction remote_mkdirs 217b0088928SVladimir Kotal{ 218b0088928SVladimir Kotal typeset -r dir_spec=$1 2199d3952abSVladimir Kotal typeset -r host_spec=$2 220b0088928SVladimir Kotal 221b0088928SVladimir Kotal # 222b0088928SVladimir Kotal # If the supplied path is absolute we assume all directories are 223b0088928SVladimir Kotal # created, otherwise try to create all directories in the path 224b0088928SVladimir Kotal # except the last one which will be created by scp. 225b0088928SVladimir Kotal # 226b0088928SVladimir Kotal if [[ "${dir_spec}" == */* && "${dir_spec}" != /* ]]; then 227b0088928SVladimir Kotal print "mkdirs \c" 228b0088928SVladimir Kotal # 229b0088928SVladimir Kotal # Remove the last directory from directory specification. 230b0088928SVladimir Kotal # 231b0088928SVladimir Kotal typeset -r dirs_mk=${dir_spec%/*} 2328a34f8dcSVladimir Kotal typeset -r batch_file_mkdir=$( $MKTEMP \ 2338a34f8dcSVladimir Kotal /tmp/webrev_mkdir.XXXXXX ) 234b0088928SVladimir Kotal if [[ -z $batch_file_mkdir ]]; then 235b0088928SVladimir Kotal print "\nERROR: remote_mkdirs:" \ 236b0088928SVladimir Kotal "cannot create temporary file for batch file" 237b0088928SVladimir Kotal return 1 238b0088928SVladimir Kotal fi 239b0088928SVladimir Kotal OLDIFS=$IFS 240b0088928SVladimir Kotal IFS=/ 241b0088928SVladimir Kotal typeset dir 242b0088928SVladimir Kotal for dir in ${dirs_mk}; do 243b0088928SVladimir Kotal # 244b0088928SVladimir Kotal # Use the '-' prefix to ignore mkdir errors in order 245b0088928SVladimir Kotal # to avoid an error in case the directory already 246b0088928SVladimir Kotal # exists. We check the directory with chdir to be sure 247b0088928SVladimir Kotal # there is one. 248b0088928SVladimir Kotal # 249b0088928SVladimir Kotal print -- "-mkdir ${dir}" >> ${batch_file_mkdir} 250b0088928SVladimir Kotal print "chdir ${dir}" >> ${batch_file_mkdir} 251b0088928SVladimir Kotal done 252b0088928SVladimir Kotal IFS=$OLDIFS 2538a34f8dcSVladimir Kotal typeset -r sftp_err_msg=$( $MKTEMP /tmp/webrev_scp_err.XXXXXX ) 254b0088928SVladimir Kotal if [[ -z ${sftp_err_msg} ]]; then 255b0088928SVladimir Kotal print "\nERROR: remote_mkdirs:" \ 256b0088928SVladimir Kotal "cannot create temporary file for error messages" 257b0088928SVladimir Kotal return 1 258b0088928SVladimir Kotal fi 259b0088928SVladimir Kotal $SFTP -b ${batch_file_mkdir} ${host_spec} 2>${sftp_err_msg} 1>&2 260b0088928SVladimir Kotal if (( $? != 0 )); then 261b0088928SVladimir Kotal print "\nERROR: failed to create remote directories" 262b0088928SVladimir Kotal print "error messages:" 263b0088928SVladimir Kotal $SED 's/^/> /' ${sftp_err_msg} 264b0088928SVladimir Kotal rm -f ${sftp_err_msg} ${batch_file_mkdir} 265b0088928SVladimir Kotal return 1 266b0088928SVladimir Kotal fi 267b0088928SVladimir Kotal rm -f ${sftp_err_msg} ${batch_file_mkdir} 268b0088928SVladimir Kotal fi 269b0088928SVladimir Kotal 270b0088928SVladimir Kotal return 0 271b0088928SVladimir Kotal} 272b0088928SVladimir Kotal 273b0088928SVladimir Kotal# 27402d26c39SVladimir Kotal# Upload the webrev via SSH. Return 0 on success, 1 on error. 275b0088928SVladimir Kotal# 276ba44d8a2SVladimir Kotalfunction ssh_upload 27702d26c39SVladimir Kotal{ 27802d26c39SVladimir Kotal if (( $# != 1 )); then 279b0088928SVladimir Kotal print "\nERROR: ssh_upload: wrong number of arguments" 280b0088928SVladimir Kotal exit 1 28102d26c39SVladimir Kotal fi 28202d26c39SVladimir Kotal 28302d26c39SVladimir Kotal typeset dst=$1 28402d26c39SVladimir Kotal typeset -r host_spec=${dst%%:*} 285ba44d8a2SVladimir Kotal typeset -r dir_spec=${dst#*:} 28602d26c39SVladimir Kotal 287b0088928SVladimir Kotal # 288b0088928SVladimir Kotal # Display the upload information before calling delete_webrev 289b0088928SVladimir Kotal # because it will also print its progress. 290b0088928SVladimir Kotal # 291b0088928SVladimir Kotal print_upload_header ${ssh_prefix} 292b0088928SVladimir Kotal 293b0088928SVladimir Kotal # 294b0088928SVladimir Kotal # If the deletion was explicitly requested there is no need 295b0088928SVladimir Kotal # to perform it again. 296b0088928SVladimir Kotal # 297ba44d8a2SVladimir Kotal if [[ -z $Dflag ]]; then 298b0088928SVladimir Kotal # 299b0088928SVladimir Kotal # We do not care about return value because this might be 300b0088928SVladimir Kotal # the first time this directory is uploaded. 301b0088928SVladimir Kotal # 302ba44d8a2SVladimir Kotal delete_webrev 0 30302d26c39SVladimir Kotal fi 30402d26c39SVladimir Kotal 305b0088928SVladimir Kotal # 306b0088928SVladimir Kotal # Create remote directories. Any error reporting will be done 307b0088928SVladimir Kotal # in remote_mkdirs function. 308b0088928SVladimir Kotal # 3099d3952abSVladimir Kotal remote_mkdirs ${dir_spec} ${host_spec} 31002d26c39SVladimir Kotal if (( $? != 0 )); then 31102d26c39SVladimir Kotal return 1 31202d26c39SVladimir Kotal fi 31302d26c39SVladimir Kotal 314b0088928SVladimir Kotal print "upload ... \c" 3158a34f8dcSVladimir Kotal typeset -r scp_err_msg=$( $MKTEMP /tmp/scp_err.XXXXXX ) 316b0088928SVladimir Kotal if [[ -z ${scp_err_msg} ]]; then 317b0088928SVladimir Kotal print "\nERROR: ssh_upload:" \ 318b0088928SVladimir Kotal "cannot create temporary file for error messages" 319b0088928SVladimir Kotal return 1 320b0088928SVladimir Kotal fi 32102d26c39SVladimir Kotal $SCP -q -C -B -o PreferredAuthentications=publickey -r \ 322b0088928SVladimir Kotal $WDIR $dst 2>${scp_err_msg} 32302d26c39SVladimir Kotal if (( $? != 0 )); then 324b0088928SVladimir Kotal print "Failed.\nERROR: scp failed" 325b0088928SVladimir Kotal print "src dir: '$WDIR'\ndst dir: '$dst'" 326b0088928SVladimir Kotal print "error messages:" 327b0088928SVladimir Kotal $SED 's/^/> /' ${scp_err_msg} 328b0088928SVladimir Kotal rm -f ${scp_err_msg} 32902d26c39SVladimir Kotal return 1 33002d26c39SVladimir Kotal fi 33102d26c39SVladimir Kotal 332b0088928SVladimir Kotal rm -f ${scp_err_msg} 33302d26c39SVladimir Kotal print "Done." 33402d26c39SVladimir Kotal return 0 33502d26c39SVladimir Kotal} 33602d26c39SVladimir Kotal 33702d26c39SVladimir Kotal# 338ba44d8a2SVladimir Kotal# Delete webrev at remote site. Return 0 on success, 1 or exit code from sftp 339b0088928SVladimir Kotal# on failure. If first argument is 1 then perform the check of sftp return 340b0088928SVladimir Kotal# value otherwise ignore it. If second argument is present it means this run 341b0088928SVladimir Kotal# only performs deletion. 342ba44d8a2SVladimir Kotal# 343ba44d8a2SVladimir Kotalfunction delete_webrev 344ba44d8a2SVladimir Kotal{ 345b0088928SVladimir Kotal if (( $# < 1 )); then 346b0088928SVladimir Kotal print "delete_webrev: wrong number of arguments" 347b0088928SVladimir Kotal exit 1 348ba44d8a2SVladimir Kotal fi 349ba44d8a2SVladimir Kotal 350b0088928SVladimir Kotal integer -r check=$1 351b0088928SVladimir Kotal integer delete_only=0 352b0088928SVladimir Kotal if (( $# == 2 )); then 353b0088928SVladimir Kotal delete_only=1 354b0088928SVladimir Kotal fi 355b0088928SVladimir Kotal 356b0088928SVladimir Kotal # 357ba44d8a2SVladimir Kotal # Strip the transport specification part of remote target first. 358b0088928SVladimir Kotal # 359ba44d8a2SVladimir Kotal typeset -r stripped_target=${remote_target##*://} 360ba44d8a2SVladimir Kotal typeset -r host_spec=${stripped_target%%:*} 361ba44d8a2SVladimir Kotal typeset -r dir_spec=${stripped_target#*:} 362ba44d8a2SVladimir Kotal typeset dir_rm 363ba44d8a2SVladimir Kotal 364b0088928SVladimir Kotal # 365ba44d8a2SVladimir Kotal # Do not accept an absolute path. 366b0088928SVladimir Kotal # 367ba44d8a2SVladimir Kotal if [[ ${dir_spec} == /* ]]; then 368ba44d8a2SVladimir Kotal return 1 369ba44d8a2SVladimir Kotal fi 370ba44d8a2SVladimir Kotal 371b0088928SVladimir Kotal # 372ba44d8a2SVladimir Kotal # Strip the ending slash. 373b0088928SVladimir Kotal # 374ba44d8a2SVladimir Kotal if [[ ${dir_spec} == */ ]]; then 375ba44d8a2SVladimir Kotal dir_rm=${dir_spec%%/} 376ba44d8a2SVladimir Kotal else 377ba44d8a2SVladimir Kotal dir_rm=${dir_spec} 378ba44d8a2SVladimir Kotal fi 379ba44d8a2SVladimir Kotal 380b0088928SVladimir Kotal if (( ${delete_only} > 0 )); then 381b0088928SVladimir Kotal print " Removing: \c" 382b0088928SVladimir Kotal else 383b0088928SVladimir Kotal print "rmdir \c" 384b0088928SVladimir Kotal fi 385ba44d8a2SVladimir Kotal if [[ -z "$dir_rm" ]]; then 386b0088928SVladimir Kotal print "\nERROR: empty directory for removal" 387ba44d8a2SVladimir Kotal return 1 388ba44d8a2SVladimir Kotal fi 389ba44d8a2SVladimir Kotal 390b0088928SVladimir Kotal # 391ba44d8a2SVladimir Kotal # Prepare batch file. 392b0088928SVladimir Kotal # 3938a34f8dcSVladimir Kotal typeset -r batch_file_rm=$( $MKTEMP /tmp/webrev_remove.XXXXXX ) 394ba44d8a2SVladimir Kotal if [[ -z $batch_file_rm ]]; then 395b0088928SVladimir Kotal print "\nERROR: delete_webrev: cannot create temporary file" 396ba44d8a2SVladimir Kotal return 1 397ba44d8a2SVladimir Kotal fi 398ba44d8a2SVladimir Kotal print "rename $dir_rm $TRASH_DIR/removed.$$" > $batch_file_rm 399ba44d8a2SVladimir Kotal 400b0088928SVladimir Kotal # 401ba44d8a2SVladimir Kotal # Perform remote deletion and remove the batch file. 402b0088928SVladimir Kotal # 4038a34f8dcSVladimir Kotal typeset -r sftp_err_msg=$( $MKTEMP /tmp/webrev_scp_err.XXXXXX ) 404b0088928SVladimir Kotal if [[ -z ${sftp_err_msg} ]]; then 405b0088928SVladimir Kotal print "\nERROR: delete_webrev:" \ 406b0088928SVladimir Kotal "cannot create temporary file for error messages" 407b0088928SVladimir Kotal return 1 408b0088928SVladimir Kotal fi 409b0088928SVladimir Kotal $SFTP -b $batch_file_rm $host_spec 2>${sftp_err_msg} 1>&2 410ba44d8a2SVladimir Kotal integer -r ret=$? 411ba44d8a2SVladimir Kotal rm -f $batch_file_rm 412ba44d8a2SVladimir Kotal if (( $ret != 0 && $check > 0 )); then 413b0088928SVladimir Kotal print "Failed.\nERROR: failed to remove remote directories" 414b0088928SVladimir Kotal print "error messages:" 415b0088928SVladimir Kotal $SED 's/^/> /' ${sftp_err_msg} 416b0088928SVladimir Kotal rm -f ${sftp_err_msg} 417ba44d8a2SVladimir Kotal return $ret 418ba44d8a2SVladimir Kotal fi 419b0088928SVladimir Kotal rm -f ${sftp_err_msg} 420b0088928SVladimir Kotal if (( ${delete_only} > 0 )); then 421ba44d8a2SVladimir Kotal print "Done." 422b0088928SVladimir Kotal fi 423ba44d8a2SVladimir Kotal 424ba44d8a2SVladimir Kotal return 0 425ba44d8a2SVladimir Kotal} 426ba44d8a2SVladimir Kotal 427ba44d8a2SVladimir Kotal# 42802d26c39SVladimir Kotal# Upload webrev to remote site 42902d26c39SVladimir Kotal# 430ba44d8a2SVladimir Kotalfunction upload_webrev 43102d26c39SVladimir Kotal{ 432b0088928SVladimir Kotal integer ret 43302d26c39SVladimir Kotal 43402d26c39SVladimir Kotal if [[ ! -d "$WDIR" ]]; then 435b0088928SVladimir Kotal print "\nERROR: webrev directory '$WDIR' does not exist" 43602d26c39SVladimir Kotal return 1 43702d26c39SVladimir Kotal fi 43802d26c39SVladimir Kotal 439b0088928SVladimir Kotal # 44002d26c39SVladimir Kotal # Perform a late check to make sure we do not upload closed source 44102d26c39SVladimir Kotal # to remote target when -n is used. If the user used custom remote 44202d26c39SVladimir Kotal # target he probably knows what he is doing. 443b0088928SVladimir Kotal # 44402d26c39SVladimir Kotal if [[ -n $nflag && -z $tflag ]]; then 445ba44d8a2SVladimir Kotal $FIND $WDIR -type d -name closed \ 44602d26c39SVladimir Kotal | $GREP closed >/dev/null 44702d26c39SVladimir Kotal if (( $? == 0 )); then 448b0088928SVladimir Kotal print "\nERROR: directory '$WDIR' contains" \ 449b0088928SVladimir Kotal "\"closed\" directory" 45002d26c39SVladimir Kotal return 1 45102d26c39SVladimir Kotal fi 45202d26c39SVladimir Kotal fi 45302d26c39SVladimir Kotal 454b0088928SVladimir Kotal 455b0088928SVladimir Kotal # 456b0088928SVladimir Kotal # We have the URI for remote destination now so let's start the upload. 457b0088928SVladimir Kotal # 45802d26c39SVladimir Kotal if [[ -n $tflag ]]; then 45902d26c39SVladimir Kotal if [[ "${remote_target}" == ${rsync_prefix}?* ]]; then 460b0088928SVladimir Kotal rsync_upload ${remote_target##$rsync_prefix} 1 461b0088928SVladimir Kotal ret=$? 462b0088928SVladimir Kotal return $ret 46302d26c39SVladimir Kotal elif [[ "${remote_target}" == ${ssh_prefix}?* ]]; then 46402d26c39SVladimir Kotal ssh_upload ${remote_target##$ssh_prefix} 465b0088928SVladimir Kotal ret=$? 466b0088928SVladimir Kotal return $ret 46702d26c39SVladimir Kotal fi 46802d26c39SVladimir Kotal else 469b0088928SVladimir Kotal # 470b0088928SVladimir Kotal # Try rsync first and fallback to SSH in case it fails. 471b0088928SVladimir Kotal # 472b0088928SVladimir Kotal rsync_upload ${remote_target} 0 473b0088928SVladimir Kotal ret=$? 474b0088928SVladimir Kotal if (( $ret != 0 )); then 475b0088928SVladimir Kotal print "Failed. (falling back to SSH)" 476ba44d8a2SVladimir Kotal ssh_upload ${remote_target} 477b0088928SVladimir Kotal ret=$? 47802d26c39SVladimir Kotal fi 479b0088928SVladimir Kotal return $ret 48002d26c39SVladimir Kotal fi 48102d26c39SVladimir Kotal} 48202d26c39SVladimir Kotal 483daaffb31Sdp# 484371d72daSLubomir Sedlacik# input_cmd | url_encode | output_cmd 485371d72daSLubomir Sedlacik# 486371d72daSLubomir Sedlacik# URL-encode (percent-encode) reserved characters as defined in RFC 3986. 487371d72daSLubomir Sedlacik# 488371d72daSLubomir Sedlacik# Reserved characters are: :/?#[]@!$&'()*+,;= 489371d72daSLubomir Sedlacik# 490371d72daSLubomir Sedlacik# While not a reserved character itself, percent '%' is reserved by definition 491371d72daSLubomir Sedlacik# so encode it first to avoid recursive transformation, and skip '/' which is 492371d72daSLubomir Sedlacik# a path delimiter. 493371d72daSLubomir Sedlacik# 49425cc4e45SVladimir Kotal# The quotation character is deliberately not escaped in order to make 49525cc4e45SVladimir Kotal# the substitution work with GNU sed. 49625cc4e45SVladimir Kotal# 497371d72daSLubomir Sedlacikfunction url_encode 498371d72daSLubomir Sedlacik{ 499b0088928SVladimir Kotal $SED -e "s|%|%25|g" -e "s|:|%3A|g" -e "s|\&|%26|g" \ 500371d72daSLubomir Sedlacik -e "s|?|%3F|g" -e "s|#|%23|g" -e "s|\[|%5B|g" \ 501371d72daSLubomir Sedlacik -e "s|*|%2A|g" -e "s|@|%40|g" -e "s|\!|%21|g" \ 502371d72daSLubomir Sedlacik -e "s|=|%3D|g" -e "s|;|%3B|g" -e "s|\]|%5D|g" \ 50325cc4e45SVladimir Kotal -e "s|(|%28|g" -e "s|)|%29|g" -e "s|'|%27|g" \ 504371d72daSLubomir Sedlacik -e "s|+|%2B|g" -e "s|\,|%2C|g" -e "s|\\\$|%24|g" 505371d72daSLubomir Sedlacik} 506371d72daSLubomir Sedlacik 507371d72daSLubomir Sedlacik# 508daaffb31Sdp# input_cmd | html_quote | output_cmd 509daaffb31Sdp# or 510daaffb31Sdp# html_quote filename | output_cmd 5117c478bd9Sstevel@tonic-gate# 5127c478bd9Sstevel@tonic-gate# Make a piece of source code safe for display in an HTML <pre> block. 5137c478bd9Sstevel@tonic-gate# 5147c478bd9Sstevel@tonic-gatehtml_quote() 5157c478bd9Sstevel@tonic-gate{ 516b0088928SVladimir Kotal $SED -e "s/&/\&/g" -e "s/</\</g" -e "s/>/\>/g" "$@" | expand 5177c478bd9Sstevel@tonic-gate} 5187c478bd9Sstevel@tonic-gate 519daaffb31Sdp# 520*8bcea973SRichard Lowe# Trim a digest-style revision to a conventionally readable yet useful length 521*8bcea973SRichard Lowe# 522*8bcea973SRichard Lowetrim_digest() 523*8bcea973SRichard Lowe{ 524*8bcea973SRichard Lowe typeset digest=$1 525*8bcea973SRichard Lowe 526*8bcea973SRichard Lowe echo $digest | $SED -e 's/\([0-9a-f]\{12\}\).*/\1/' 527*8bcea973SRichard Lowe} 528*8bcea973SRichard Lowe 529*8bcea973SRichard Lowe# 5300fd2682eSMark J. Nelson# input_cmd | its2url | output_cmd 531daaffb31Sdp# 5320fd2682eSMark J. Nelson# Scan for information tracking system references and insert <a> links to the 5330fd2682eSMark J. Nelson# relevant databases. 534daaffb31Sdp# 5350fd2682eSMark J. Nelsonits2url() 5367c478bd9Sstevel@tonic-gate{ 5370fd2682eSMark J. Nelson $SED -f ${its_sed_script} 538daaffb31Sdp} 539daaffb31Sdp 5407c478bd9Sstevel@tonic-gate# 541daaffb31Sdp# strip_unchanged <infile> | output_cmd 5427c478bd9Sstevel@tonic-gate# 543daaffb31Sdp# Removes chunks of sdiff documents that have not changed. This makes it 544daaffb31Sdp# easier for a code reviewer to find the bits that have changed. 5457c478bd9Sstevel@tonic-gate# 546daaffb31Sdp# Deleted lines of text are replaced by a horizontal rule. Some 547daaffb31Sdp# identical lines are retained before and after the changed lines to 548daaffb31Sdp# provide some context. The number of these lines is controlled by the 549cdf0c1d5Smjnelson# variable C in the $AWK script below. 550daaffb31Sdp# 551daaffb31Sdp# The script detects changed lines as any line that has a "<span class=" 552daaffb31Sdp# string embedded (unchanged lines have no particular class and are not 553daaffb31Sdp# part of a <span>). Blank lines (without a sequence number) are also 554daaffb31Sdp# detected since they flag lines that have been inserted or deleted. 555daaffb31Sdp# 556daaffb31Sdpstrip_unchanged() 557daaffb31Sdp{ 558cdf0c1d5Smjnelson $AWK ' 559daaffb31Sdp BEGIN { C = c = 20 } 560cdf0c1d5Smjnelson NF == 0 || /<span class="/ { 561daaffb31Sdp if (c > C) { 562daaffb31Sdp c -= C 563daaffb31Sdp inx = 0 564daaffb31Sdp if (c > C) { 565cac38512Smjnelson print "\n</pre><hr></hr><pre>" 566daaffb31Sdp inx = c % C 567daaffb31Sdp c = C 568daaffb31Sdp } 569daaffb31Sdp 570daaffb31Sdp for (i = 0; i < c; i++) 571daaffb31Sdp print ln[(inx + i) % C] 572daaffb31Sdp } 573daaffb31Sdp c = 0; 574daaffb31Sdp print 575daaffb31Sdp next 576daaffb31Sdp } 577daaffb31Sdp { if (c >= C) { 578daaffb31Sdp ln[c % C] = $0 579daaffb31Sdp c++; 580daaffb31Sdp next; 581daaffb31Sdp } 582daaffb31Sdp c++; 583daaffb31Sdp print 584daaffb31Sdp } 585cac38512Smjnelson END { if (c > (C * 2)) print "\n</pre><hr></hr>" } 586daaffb31Sdp 587daaffb31Sdp ' $1 588daaffb31Sdp} 589daaffb31Sdp 590daaffb31Sdp# 591daaffb31Sdp# sdiff_to_html 592daaffb31Sdp# 593daaffb31Sdp# This function takes two files as arguments, obtains their diff, and 594daaffb31Sdp# processes the diff output to present the files as an HTML document with 595daaffb31Sdp# the files displayed side-by-side, differences shown in color. It also 596daaffb31Sdp# takes a delta comment, rendered as an HTML snippet, as the third 597daaffb31Sdp# argument. The function takes two files as arguments, then the name of 598daaffb31Sdp# file, the path, and the comment. The HTML will be delivered on stdout, 599daaffb31Sdp# e.g. 600daaffb31Sdp# 601daaffb31Sdp# $ sdiff_to_html old/usr/src/tools/scripts/webrev.sh \ 602daaffb31Sdp# new/usr/src/tools/scripts/webrev.sh \ 603daaffb31Sdp# webrev.sh usr/src/tools/scripts \ 604daaffb31Sdp# '<a href="http://monaco.sfbay.sun.com/detail.jsp?cr=1234567"> 605daaffb31Sdp# 1234567</a> my bugid' > <file>.html 606daaffb31Sdp# 607daaffb31Sdp# framed_sdiff() is then called which creates $2.frames.html 608daaffb31Sdp# in the webrev tree. 609daaffb31Sdp# 610daaffb31Sdp# FYI: This function is rather unusual in its use of awk. The initial 611daaffb31Sdp# diff run produces conventional diff output showing changed lines mixed 612daaffb31Sdp# with editing codes. The changed lines are ignored - we're interested in 613daaffb31Sdp# the editing codes, e.g. 6147c478bd9Sstevel@tonic-gate# 6157c478bd9Sstevel@tonic-gate# 8c8 6167c478bd9Sstevel@tonic-gate# 57a61 6177c478bd9Sstevel@tonic-gate# 63c66,76 6187c478bd9Sstevel@tonic-gate# 68,93d80 6197c478bd9Sstevel@tonic-gate# 106d90 6207c478bd9Sstevel@tonic-gate# 108,110d91 6217c478bd9Sstevel@tonic-gate# 622daaffb31Sdp# These editing codes are parsed by the awk script and used to generate 623daaffb31Sdp# another awk script that generates HTML, e.g the above lines would turn 624daaffb31Sdp# into something like this: 6257c478bd9Sstevel@tonic-gate# 6267c478bd9Sstevel@tonic-gate# BEGIN { printf "<pre>\n" } 6277c478bd9Sstevel@tonic-gate# function sp(n) {for (i=0;i<n;i++)printf "\n"} 628daaffb31Sdp# function wl(n) {printf "<font color=%s>%4d %s </font>\n", n, NR, $0} 6297c478bd9Sstevel@tonic-gate# NR==8 {wl("#7A7ADD");next} 6307c478bd9Sstevel@tonic-gate# NR==54 {wl("#7A7ADD");sp(3);next} 6317c478bd9Sstevel@tonic-gate# NR==56 {wl("#7A7ADD");next} 6327c478bd9Sstevel@tonic-gate# NR==57 {wl("black");printf "\n"; next} 6337c478bd9Sstevel@tonic-gate# : : 6347c478bd9Sstevel@tonic-gate# 635daaffb31Sdp# This script is then run on the original source file to generate the 636daaffb31Sdp# HTML that corresponds to the source file. 6377c478bd9Sstevel@tonic-gate# 638daaffb31Sdp# The two HTML files are then combined into a single piece of HTML that 639daaffb31Sdp# uses an HTML table construct to present the files side by side. You'll 640daaffb31Sdp# notice that the changes are color-coded: 6417c478bd9Sstevel@tonic-gate# 6427c478bd9Sstevel@tonic-gate# black - unchanged lines 6437c478bd9Sstevel@tonic-gate# blue - changed lines 6447c478bd9Sstevel@tonic-gate# bold blue - new lines 6457c478bd9Sstevel@tonic-gate# brown - deleted lines 6467c478bd9Sstevel@tonic-gate# 647daaffb31Sdp# Blank lines are inserted in each file to keep unchanged lines in sync 648daaffb31Sdp# (side-by-side). This format is familiar to users of sdiff(1) or 649daaffb31Sdp# Teamware's filemerge tool. 650daaffb31Sdp# 651daaffb31Sdpsdiff_to_html() 652daaffb31Sdp{ 6537c478bd9Sstevel@tonic-gate diff -b $1 $2 > /tmp/$$.diffs 6547c478bd9Sstevel@tonic-gate 655daaffb31Sdp TNAME=$3 656daaffb31Sdp TPATH=$4 657daaffb31Sdp COMMENT=$5 658daaffb31Sdp 6597c478bd9Sstevel@tonic-gate # 6607c478bd9Sstevel@tonic-gate # Now we have the diffs, generate the HTML for the old file. 6617c478bd9Sstevel@tonic-gate # 662cdf0c1d5Smjnelson $AWK ' 6637c478bd9Sstevel@tonic-gate BEGIN { 6647c478bd9Sstevel@tonic-gate printf "function sp(n) {for (i=0;i<n;i++)printf \"\\n\"}\n" 665daaffb31Sdp printf "function removed() " 666daaffb31Sdp printf "{printf \"<span class=\\\"removed\\\">%%4d %%s</span>\\n\", NR, $0}\n" 667daaffb31Sdp printf "function changed() " 668daaffb31Sdp printf "{printf \"<span class=\\\"changed\\\">%%4d %%s</span>\\n\", NR, $0}\n" 669daaffb31Sdp printf "function bl() {printf \"%%4d %%s\\n\", NR, $0}\n" 6707c478bd9Sstevel@tonic-gate} 6717c478bd9Sstevel@tonic-gate /^</ {next} 6727c478bd9Sstevel@tonic-gate /^>/ {next} 6737c478bd9Sstevel@tonic-gate /^---/ {next} 674daaffb31Sdp 6757c478bd9Sstevel@tonic-gate { 6767c478bd9Sstevel@tonic-gate split($1, a, /[cad]/) ; 6777c478bd9Sstevel@tonic-gate if (index($1, "a")) { 6787c478bd9Sstevel@tonic-gate if (a[1] == 0) { 6797c478bd9Sstevel@tonic-gate n = split(a[2], r, /,/); 6807c478bd9Sstevel@tonic-gate if (n == 1) 6817c478bd9Sstevel@tonic-gate printf "BEGIN\t\t{sp(1)}\n" 6827c478bd9Sstevel@tonic-gate else 6837c478bd9Sstevel@tonic-gate printf "BEGIN\t\t{sp(%d)}\n",\ 6847c478bd9Sstevel@tonic-gate (r[2] - r[1]) + 1 6857c478bd9Sstevel@tonic-gate next 6867c478bd9Sstevel@tonic-gate } 6877c478bd9Sstevel@tonic-gate 6887c478bd9Sstevel@tonic-gate printf "NR==%s\t\t{", a[1] 6897c478bd9Sstevel@tonic-gate n = split(a[2], r, /,/); 6907c478bd9Sstevel@tonic-gate s = r[1]; 6917c478bd9Sstevel@tonic-gate if (n == 1) 6927c478bd9Sstevel@tonic-gate printf "bl();printf \"\\n\"; next}\n" 6937c478bd9Sstevel@tonic-gate else { 6947c478bd9Sstevel@tonic-gate n = r[2] - r[1] 6957c478bd9Sstevel@tonic-gate printf "bl();sp(%d);next}\n",\ 6967c478bd9Sstevel@tonic-gate (r[2] - r[1]) + 1 6977c478bd9Sstevel@tonic-gate } 6987c478bd9Sstevel@tonic-gate next 6997c478bd9Sstevel@tonic-gate } 7007c478bd9Sstevel@tonic-gate if (index($1, "d")) { 7017c478bd9Sstevel@tonic-gate n = split(a[1], r, /,/); 7027c478bd9Sstevel@tonic-gate n1 = r[1] 7037c478bd9Sstevel@tonic-gate n2 = r[2] 7047c478bd9Sstevel@tonic-gate if (n == 1) 705daaffb31Sdp printf "NR==%s\t\t{removed(); next}\n" , n1 7067c478bd9Sstevel@tonic-gate else 707daaffb31Sdp printf "NR==%s,NR==%s\t{removed(); next}\n" , n1, n2 7087c478bd9Sstevel@tonic-gate next 7097c478bd9Sstevel@tonic-gate } 7107c478bd9Sstevel@tonic-gate if (index($1, "c")) { 7117c478bd9Sstevel@tonic-gate n = split(a[1], r, /,/); 7127c478bd9Sstevel@tonic-gate n1 = r[1] 7137c478bd9Sstevel@tonic-gate n2 = r[2] 7147c478bd9Sstevel@tonic-gate final = n2 7157c478bd9Sstevel@tonic-gate d1 = 0 7167c478bd9Sstevel@tonic-gate if (n == 1) 717daaffb31Sdp printf "NR==%s\t\t{changed();" , n1 7187c478bd9Sstevel@tonic-gate else { 7197c478bd9Sstevel@tonic-gate d1 = n2 - n1 720daaffb31Sdp printf "NR==%s,NR==%s\t{changed();" , n1, n2 7217c478bd9Sstevel@tonic-gate } 7227c478bd9Sstevel@tonic-gate m = split(a[2], r, /,/); 7237c478bd9Sstevel@tonic-gate n1 = r[1] 7247c478bd9Sstevel@tonic-gate n2 = r[2] 7257c478bd9Sstevel@tonic-gate if (m > 1) { 7267c478bd9Sstevel@tonic-gate d2 = n2 - n1 7277c478bd9Sstevel@tonic-gate if (d2 > d1) { 7287c478bd9Sstevel@tonic-gate if (n > 1) printf "if (NR==%d)", final 7297c478bd9Sstevel@tonic-gate printf "sp(%d);", d2 - d1 7307c478bd9Sstevel@tonic-gate } 7317c478bd9Sstevel@tonic-gate } 7327c478bd9Sstevel@tonic-gate printf "next}\n" ; 7337c478bd9Sstevel@tonic-gate 7347c478bd9Sstevel@tonic-gate next 7357c478bd9Sstevel@tonic-gate } 7367c478bd9Sstevel@tonic-gate } 7377c478bd9Sstevel@tonic-gate 738daaffb31Sdp END { printf "{printf \"%%4d %%s\\n\", NR, $0 }\n" } 739daaffb31Sdp ' /tmp/$$.diffs > /tmp/$$.file1 7407c478bd9Sstevel@tonic-gate 7417c478bd9Sstevel@tonic-gate # 7427c478bd9Sstevel@tonic-gate # Now generate the HTML for the new file 7437c478bd9Sstevel@tonic-gate # 744cdf0c1d5Smjnelson $AWK ' 7457c478bd9Sstevel@tonic-gate BEGIN { 7467c478bd9Sstevel@tonic-gate printf "function sp(n) {for (i=0;i<n;i++)printf \"\\n\"}\n" 747daaffb31Sdp printf "function new() " 748daaffb31Sdp printf "{printf \"<span class=\\\"new\\\">%%4d %%s</span>\\n\", NR, $0}\n" 749daaffb31Sdp printf "function changed() " 750daaffb31Sdp printf "{printf \"<span class=\\\"changed\\\">%%4d %%s</span>\\n\", NR, $0}\n" 751daaffb31Sdp printf "function bl() {printf \"%%4d %%s\\n\", NR, $0}\n" 7527c478bd9Sstevel@tonic-gate } 753daaffb31Sdp 7547c478bd9Sstevel@tonic-gate /^</ {next} 7557c478bd9Sstevel@tonic-gate /^>/ {next} 7567c478bd9Sstevel@tonic-gate /^---/ {next} 757daaffb31Sdp 7587c478bd9Sstevel@tonic-gate { 7597c478bd9Sstevel@tonic-gate split($1, a, /[cad]/) ; 7607c478bd9Sstevel@tonic-gate if (index($1, "d")) { 7617c478bd9Sstevel@tonic-gate if (a[2] == 0) { 7627c478bd9Sstevel@tonic-gate n = split(a[1], r, /,/); 7637c478bd9Sstevel@tonic-gate if (n == 1) 7647c478bd9Sstevel@tonic-gate printf "BEGIN\t\t{sp(1)}\n" 7657c478bd9Sstevel@tonic-gate else 7667c478bd9Sstevel@tonic-gate printf "BEGIN\t\t{sp(%d)}\n",\ 7677c478bd9Sstevel@tonic-gate (r[2] - r[1]) + 1 7687c478bd9Sstevel@tonic-gate next 7697c478bd9Sstevel@tonic-gate } 7707c478bd9Sstevel@tonic-gate 7717c478bd9Sstevel@tonic-gate printf "NR==%s\t\t{", a[2] 7727c478bd9Sstevel@tonic-gate n = split(a[1], r, /,/); 7737c478bd9Sstevel@tonic-gate s = r[1]; 7747c478bd9Sstevel@tonic-gate if (n == 1) 7757c478bd9Sstevel@tonic-gate printf "bl();printf \"\\n\"; next}\n" 7767c478bd9Sstevel@tonic-gate else { 7777c478bd9Sstevel@tonic-gate n = r[2] - r[1] 7787c478bd9Sstevel@tonic-gate printf "bl();sp(%d);next}\n",\ 7797c478bd9Sstevel@tonic-gate (r[2] - r[1]) + 1 7807c478bd9Sstevel@tonic-gate } 7817c478bd9Sstevel@tonic-gate next 7827c478bd9Sstevel@tonic-gate } 7837c478bd9Sstevel@tonic-gate if (index($1, "a")) { 7847c478bd9Sstevel@tonic-gate n = split(a[2], r, /,/); 7857c478bd9Sstevel@tonic-gate n1 = r[1] 7867c478bd9Sstevel@tonic-gate n2 = r[2] 7877c478bd9Sstevel@tonic-gate if (n == 1) 788daaffb31Sdp printf "NR==%s\t\t{new() ; next}\n" , n1 7897c478bd9Sstevel@tonic-gate else 790daaffb31Sdp printf "NR==%s,NR==%s\t{new() ; next}\n" , n1, n2 7917c478bd9Sstevel@tonic-gate next 7927c478bd9Sstevel@tonic-gate } 7937c478bd9Sstevel@tonic-gate if (index($1, "c")) { 7947c478bd9Sstevel@tonic-gate n = split(a[2], r, /,/); 7957c478bd9Sstevel@tonic-gate n1 = r[1] 7967c478bd9Sstevel@tonic-gate n2 = r[2] 7977c478bd9Sstevel@tonic-gate final = n2 7987c478bd9Sstevel@tonic-gate d2 = 0; 7997c478bd9Sstevel@tonic-gate if (n == 1) { 8007c478bd9Sstevel@tonic-gate final = n1 801daaffb31Sdp printf "NR==%s\t\t{changed();" , n1 8027c478bd9Sstevel@tonic-gate } else { 8037c478bd9Sstevel@tonic-gate d2 = n2 - n1 804daaffb31Sdp printf "NR==%s,NR==%s\t{changed();" , n1, n2 8057c478bd9Sstevel@tonic-gate } 8067c478bd9Sstevel@tonic-gate m = split(a[1], r, /,/); 8077c478bd9Sstevel@tonic-gate n1 = r[1] 8087c478bd9Sstevel@tonic-gate n2 = r[2] 8097c478bd9Sstevel@tonic-gate if (m > 1) { 8107c478bd9Sstevel@tonic-gate d1 = n2 - n1 8117c478bd9Sstevel@tonic-gate if (d1 > d2) { 8127c478bd9Sstevel@tonic-gate if (n > 1) printf "if (NR==%d)", final 8137c478bd9Sstevel@tonic-gate printf "sp(%d);", d1 - d2 8147c478bd9Sstevel@tonic-gate } 8157c478bd9Sstevel@tonic-gate } 8167c478bd9Sstevel@tonic-gate printf "next}\n" ; 8177c478bd9Sstevel@tonic-gate next 8187c478bd9Sstevel@tonic-gate } 8197c478bd9Sstevel@tonic-gate } 820daaffb31Sdp END { printf "{printf \"%%4d %%s\\n\", NR, $0 }\n" } 8217c478bd9Sstevel@tonic-gate ' /tmp/$$.diffs > /tmp/$$.file2 8227c478bd9Sstevel@tonic-gate 823daaffb31Sdp # 824cdf0c1d5Smjnelson # Post-process the HTML files by running them back through $AWK 825daaffb31Sdp # 826cdf0c1d5Smjnelson html_quote < $1 | $AWK -f /tmp/$$.file1 > /tmp/$$.file1.html 8277c478bd9Sstevel@tonic-gate 828cdf0c1d5Smjnelson html_quote < $2 | $AWK -f /tmp/$$.file2 > /tmp/$$.file2.html 8297c478bd9Sstevel@tonic-gate 830daaffb31Sdp # 831daaffb31Sdp # Now combine into a valid HTML file and side-by-side into a table 832daaffb31Sdp # 833daaffb31Sdp print "$HTML<head>$STDHEAD" 834cdf0c1d5Smjnelson print "<title>$WNAME Sdiff $TPATH/$TNAME</title>" 835daaffb31Sdp print "</head><body id=\"SUNWwebrev\">" 836daaffb31Sdp print "<a class=\"print\" href=\"javascript:print()\">Print this page</a>" 837daaffb31Sdp print "<pre>$COMMENT</pre>\n" 838daaffb31Sdp print "<table><tr valign=\"top\">" 839daaffb31Sdp print "<td><pre>" 8407c478bd9Sstevel@tonic-gate 8417c478bd9Sstevel@tonic-gate strip_unchanged /tmp/$$.file1.html 8427c478bd9Sstevel@tonic-gate 843daaffb31Sdp print "</pre></td><td><pre>" 8447c478bd9Sstevel@tonic-gate 8457c478bd9Sstevel@tonic-gate strip_unchanged /tmp/$$.file2.html 8467c478bd9Sstevel@tonic-gate 847daaffb31Sdp print "</pre></td>" 848daaffb31Sdp print "</tr></table>" 849daaffb31Sdp print "</body></html>" 8507c478bd9Sstevel@tonic-gate 851daaffb31Sdp framed_sdiff $TNAME $TPATH /tmp/$$.file1.html /tmp/$$.file2.html \ 852daaffb31Sdp "$COMMENT" 8537c478bd9Sstevel@tonic-gate} 8547c478bd9Sstevel@tonic-gate 8557c478bd9Sstevel@tonic-gate 856daaffb31Sdp# 857daaffb31Sdp# framed_sdiff <filename> <filepath> <lhsfile> <rhsfile> <comment> 858daaffb31Sdp# 859daaffb31Sdp# Expects lefthand and righthand side html files created by sdiff_to_html. 860daaffb31Sdp# We use insert_anchors() to augment those with HTML navigation anchors, 861daaffb31Sdp# and then emit the main frame. Content is placed into: 862daaffb31Sdp# 863daaffb31Sdp# $WDIR/DIR/$TNAME.lhs.html 864daaffb31Sdp# $WDIR/DIR/$TNAME.rhs.html 865daaffb31Sdp# $WDIR/DIR/$TNAME.frames.html 866daaffb31Sdp# 867daaffb31Sdp# NOTE: We rely on standard usage of $WDIR and $DIR. 868daaffb31Sdp# 8697c478bd9Sstevel@tonic-gatefunction framed_sdiff 8707c478bd9Sstevel@tonic-gate{ 8717c478bd9Sstevel@tonic-gate typeset TNAME=$1 872daaffb31Sdp typeset TPATH=$2 873daaffb31Sdp typeset lhsfile=$3 874daaffb31Sdp typeset rhsfile=$4 875daaffb31Sdp typeset comments=$5 8767c478bd9Sstevel@tonic-gate typeset RTOP 877daaffb31Sdp 8787c478bd9Sstevel@tonic-gate # Enable html files to access WDIR via a relative path. 879daaffb31Sdp RTOP=$(relative_dir $TPATH $WDIR) 880daaffb31Sdp 881daaffb31Sdp # Make the rhs/lhs files and output the frameset file. 882daaffb31Sdp print "$HTML<head>$STDHEAD" > $WDIR/$DIR/$TNAME.lhs.html 883daaffb31Sdp 884daaffb31Sdp cat >> $WDIR/$DIR/$TNAME.lhs.html <<-EOF 8858b3b7b16SMark J. Nelson <script type="text/javascript" src="${RTOP}ancnav.js"></script> 8867c478bd9Sstevel@tonic-gate </head> 887daaffb31Sdp <body id="SUNWwebrev" onkeypress="keypress(event);"> 888cac38512Smjnelson <a name="0"></a> 889cac38512Smjnelson <pre>$comments</pre><hr></hr> 890daaffb31Sdp EOF 891daaffb31Sdp 892daaffb31Sdp cp $WDIR/$DIR/$TNAME.lhs.html $WDIR/$DIR/$TNAME.rhs.html 893daaffb31Sdp 894daaffb31Sdp insert_anchors $lhsfile >> $WDIR/$DIR/$TNAME.lhs.html 895daaffb31Sdp insert_anchors $rhsfile >> $WDIR/$DIR/$TNAME.rhs.html 896daaffb31Sdp 897daaffb31Sdp close='</body></html>' 898daaffb31Sdp 899daaffb31Sdp print $close >> $WDIR/$DIR/$TNAME.lhs.html 900daaffb31Sdp print $close >> $WDIR/$DIR/$TNAME.rhs.html 901daaffb31Sdp 902daaffb31Sdp print "$FRAMEHTML<head>$STDHEAD" > $WDIR/$DIR/$TNAME.frames.html 903daaffb31Sdp print "<title>$WNAME Framed-Sdiff " \ 904daaffb31Sdp "$TPATH/$TNAME</title> </head>" >> $WDIR/$DIR/$TNAME.frames.html 905daaffb31Sdp cat >> $WDIR/$DIR/$TNAME.frames.html <<-EOF 906daaffb31Sdp <frameset rows="*,60"> 907daaffb31Sdp <frameset cols="50%,50%"> 908cac38512Smjnelson <frame src="$TNAME.lhs.html" scrolling="auto" name="lhs"></frame> 909cac38512Smjnelson <frame src="$TNAME.rhs.html" scrolling="auto" name="rhs"></frame> 910daaffb31Sdp </frameset> 9118b3b7b16SMark J. Nelson <frame src="${RTOP}ancnav.html" scrolling="no" marginwidth="0" 912cac38512Smjnelson marginheight="0" name="nav"></frame> 913daaffb31Sdp <noframes> 914daaffb31Sdp <body id="SUNWwebrev"> 915daaffb31Sdp Alas 'frames' webrev requires that your browser supports frames 9167c478bd9Sstevel@tonic-gate and has the feature enabled. 917daaffb31Sdp </body> 918daaffb31Sdp </noframes> 919daaffb31Sdp </frameset> 9207c478bd9Sstevel@tonic-gate </html> 9217c478bd9Sstevel@tonic-gate EOF 9227c478bd9Sstevel@tonic-gate} 9237c478bd9Sstevel@tonic-gate 9247c478bd9Sstevel@tonic-gate 925daaffb31Sdp# 926daaffb31Sdp# fix_postscript 927daaffb31Sdp# 928daaffb31Sdp# Merge codereview output files to a single conforming postscript file, by: 929daaffb31Sdp# - removing all extraneous headers/trailers 930daaffb31Sdp# - making the page numbers right 931daaffb31Sdp# - removing pages devoid of contents which confuse some 932daaffb31Sdp# postscript readers. 933daaffb31Sdp# 934daaffb31Sdp# From Casper. 935daaffb31Sdp# 936daaffb31Sdpfunction fix_postscript 9377c478bd9Sstevel@tonic-gate{ 938daaffb31Sdp infile=$1 9397c478bd9Sstevel@tonic-gate 940daaffb31Sdp cat > /tmp/$$.crmerge.pl << \EOF 9417c478bd9Sstevel@tonic-gate 942daaffb31Sdp print scalar(<>); # %!PS-Adobe--- 943daaffb31Sdp print "%%Orientation: Landscape\n"; 9447c478bd9Sstevel@tonic-gate 945daaffb31Sdp $pno = 0; 946daaffb31Sdp $doprint = 1; 947daaffb31Sdp 948daaffb31Sdp $page = ""; 949daaffb31Sdp 950daaffb31Sdp while (<>) { 951daaffb31Sdp next if (/^%%Pages:\s*\d+/); 952daaffb31Sdp 953daaffb31Sdp if (/^%%Page:/) { 954daaffb31Sdp if ($pno == 0 || $page =~ /\)S/) { 955daaffb31Sdp # Header or single page containing text 956daaffb31Sdp print "%%Page: ? $pno\n" if ($pno > 0); 957daaffb31Sdp print $page; 958daaffb31Sdp $pno++; 959daaffb31Sdp } else { 960daaffb31Sdp # Empty page, skip it. 9617c478bd9Sstevel@tonic-gate } 962daaffb31Sdp $page = ""; 963daaffb31Sdp $doprint = 1; 9647c478bd9Sstevel@tonic-gate next; 9657c478bd9Sstevel@tonic-gate } 9667c478bd9Sstevel@tonic-gate 967daaffb31Sdp # Skip from %%Trailer of one document to Endprolog 968daaffb31Sdp # %%Page of the next 969daaffb31Sdp $doprint = 0 if (/^%%Trailer/); 970daaffb31Sdp $page .= $_ if ($doprint); 9717c478bd9Sstevel@tonic-gate } 9727c478bd9Sstevel@tonic-gate 973daaffb31Sdp if ($page =~ /\)S/) { 974daaffb31Sdp print "%%Page: ? $pno\n"; 975daaffb31Sdp print $page; 976daaffb31Sdp } else { 977daaffb31Sdp $pno--; 978daaffb31Sdp } 979daaffb31Sdp print "%%Trailer\n%%Pages: $pno\n"; 980daaffb31SdpEOF 981daaffb31Sdp 98214983201Sdp $PERL /tmp/$$.crmerge.pl < $infile 983daaffb31Sdp} 984daaffb31Sdp 985daaffb31Sdp 986daaffb31Sdp# 987daaffb31Sdp# input_cmd | insert_anchors | output_cmd 988daaffb31Sdp# 9897c478bd9Sstevel@tonic-gate# Flag blocks of difference with sequentially numbered invisible 990daaffb31Sdp# anchors. These are used to drive the frames version of the 9917c478bd9Sstevel@tonic-gate# sdiffs output. 9927c478bd9Sstevel@tonic-gate# 9937c478bd9Sstevel@tonic-gate# NOTE: Anchor zero flags the top of the file irrespective of changes, 9947c478bd9Sstevel@tonic-gate# an additional anchor is also appended to flag the bottom. 9957c478bd9Sstevel@tonic-gate# 996daaffb31Sdp# The script detects changed lines as any line that has a "<span 997daaffb31Sdp# class=" string embedded (unchanged lines have no class set and are 998daaffb31Sdp# not part of a <span>. Blank lines (without a sequence number) 9997c478bd9Sstevel@tonic-gate# are also detected since they flag lines that have been inserted or 10007c478bd9Sstevel@tonic-gate# deleted. 10017c478bd9Sstevel@tonic-gate# 1002daaffb31Sdpfunction insert_anchors 1003daaffb31Sdp{ 1004cdf0c1d5Smjnelson $AWK ' 10057c478bd9Sstevel@tonic-gate function ia() { 1006daaffb31Sdp printf "<a name=\"%d\" id=\"anc%d\"></a>", anc, anc++; 10077c478bd9Sstevel@tonic-gate } 1008daaffb31Sdp 10097c478bd9Sstevel@tonic-gate BEGIN { 1010daaffb31Sdp anc=1; 10117c478bd9Sstevel@tonic-gate inblock=1; 1012daaffb31Sdp printf "<pre>\n"; 10137c478bd9Sstevel@tonic-gate } 1014daaffb31Sdp NF == 0 || /^<span class=/ { 10157c478bd9Sstevel@tonic-gate if (inblock == 0) { 10167c478bd9Sstevel@tonic-gate ia(); 10177c478bd9Sstevel@tonic-gate inblock=1; 10187c478bd9Sstevel@tonic-gate } 10197c478bd9Sstevel@tonic-gate print; 10207c478bd9Sstevel@tonic-gate next; 10217c478bd9Sstevel@tonic-gate } 10227c478bd9Sstevel@tonic-gate { 10237c478bd9Sstevel@tonic-gate inblock=0; 10247c478bd9Sstevel@tonic-gate print; 10257c478bd9Sstevel@tonic-gate } 10267c478bd9Sstevel@tonic-gate END { 10277c478bd9Sstevel@tonic-gate ia(); 1028daaffb31Sdp 1029daaffb31Sdp printf "<b style=\"font-size: large; color: red\">"; 1030daaffb31Sdp printf "--- EOF ---</b>" 10317c478bd9Sstevel@tonic-gate for(i=0;i<8;i++) printf "\n\n\n\n\n\n\n\n\n\n"; 1032daaffb31Sdp printf "</pre>" 1033daaffb31Sdp printf "<form name=\"eof\">"; 1034cac38512Smjnelson printf "<input name=\"value\" value=\"%d\" " \ 1035cac38512Smjnelson "type=\"hidden\"></input>", anc - 1; 1036daaffb31Sdp printf "</form>"; 10377c478bd9Sstevel@tonic-gate } 10387c478bd9Sstevel@tonic-gate ' $1 10397c478bd9Sstevel@tonic-gate} 10407c478bd9Sstevel@tonic-gate 10417c478bd9Sstevel@tonic-gate 1042daaffb31Sdp# 1043daaffb31Sdp# relative_dir 1044daaffb31Sdp# 1045daaffb31Sdp# Print a relative return path from $1 to $2. For example if 1046daaffb31Sdp# $1=/tmp/myreview/raw_files/usr/src/tools/scripts and $2=/tmp/myreview, 1047daaffb31Sdp# this function would print "../../../../". 1048daaffb31Sdp# 1049daaffb31Sdp# In the event that $1 is not in $2 a warning is printed to stderr, 1050daaffb31Sdp# and $2 is returned-- the result of this is that the resulting webrev 1051daaffb31Sdp# is not relocatable. 1052daaffb31Sdp# 1053daaffb31Sdpfunction relative_dir 10547c478bd9Sstevel@tonic-gate{ 1055daaffb31Sdp typeset cur="${1##$2?(/)}" 10568b3b7b16SMark J. Nelson 10578b3b7b16SMark J. Nelson # 10588b3b7b16SMark J. Nelson # If the first path was specified absolutely, and it does 10598b3b7b16SMark J. Nelson # not start with the second path, it's an error. 10608b3b7b16SMark J. Nelson # 10610fd2682eSMark J. Nelson if [[ "$cur" = "/${1#/}" ]]; then 1062daaffb31Sdp # Should never happen. 106314983201Sdp print -u2 "\nWARNING: relative_dir: \"$1\" not relative " 1064daaffb31Sdp print -u2 "to \"$2\". Check input paths. Framed webrev " 1065daaffb31Sdp print -u2 "will not be relocatable!" 1066daaffb31Sdp print $2 1067daaffb31Sdp return 1068daaffb31Sdp fi 1069daaffb31Sdp 10708b3b7b16SMark J. Nelson # 10718b3b7b16SMark J. Nelson # This is kind of ugly. The sed script will do the following: 10728b3b7b16SMark J. Nelson # 10738b3b7b16SMark J. Nelson # 1. Strip off a leading "." or "./": this is important to get 10748b3b7b16SMark J. Nelson # the correct arcnav links for files in $WDIR. 10758b3b7b16SMark J. Nelson # 2. Strip off a trailing "/": this is not strictly necessary, 10768b3b7b16SMark J. Nelson # but is kind of nice, since it doesn't end up in "//" at 10778b3b7b16SMark J. Nelson # the end of a relative path. 10788b3b7b16SMark J. Nelson # 3. Replace all remaining sequences of non-"/" with "..": the 10798b3b7b16SMark J. Nelson # assumption here is that each dirname represents another 10808b3b7b16SMark J. Nelson # level of relative separation. 10818b3b7b16SMark J. Nelson # 4. Append a trailing "/" only for non-empty paths: this way 10828b3b7b16SMark J. Nelson # the caller doesn't need to duplicate this logic, and does 10838b3b7b16SMark J. Nelson # not end up using $RTOP/file for files in $WDIR. 10848b3b7b16SMark J. Nelson # 10850fd2682eSMark J. Nelson print $cur | $SED -e '{ 10868b3b7b16SMark J. Nelson s:^\./*:: 10878b3b7b16SMark J. Nelson s:/$:: 10888b3b7b16SMark J. Nelson s:[^/][^/]*:..:g 10890fd2682eSMark J. Nelson s:^\(..*\)$:\1/: 10900fd2682eSMark J. Nelson }' 10917c478bd9Sstevel@tonic-gate} 10927c478bd9Sstevel@tonic-gate 1093daaffb31Sdp# 1094daaffb31Sdp# frame_nav_js 1095daaffb31Sdp# 1096daaffb31Sdp# Emit javascript for frame navigation 1097daaffb31Sdp# 1098daaffb31Sdpfunction frame_nav_js 10997c478bd9Sstevel@tonic-gate{ 11007c478bd9Sstevel@tonic-gatecat << \EOF 11017c478bd9Sstevel@tonic-gatevar myInt; 11027c478bd9Sstevel@tonic-gatevar scrolling=0; 1103daaffb31Sdpvar sfactor = 3; 11047c478bd9Sstevel@tonic-gatevar scount=10; 11057c478bd9Sstevel@tonic-gate 11067c478bd9Sstevel@tonic-gatefunction scrollByPix() { 11077c478bd9Sstevel@tonic-gate if (scount<=0) { 11087c478bd9Sstevel@tonic-gate sfactor*=1.2; 11097c478bd9Sstevel@tonic-gate scount=10; 11107c478bd9Sstevel@tonic-gate } 11117c478bd9Sstevel@tonic-gate parent.lhs.scrollBy(0,sfactor); 11127c478bd9Sstevel@tonic-gate parent.rhs.scrollBy(0,sfactor); 11137c478bd9Sstevel@tonic-gate scount--; 11147c478bd9Sstevel@tonic-gate} 11157c478bd9Sstevel@tonic-gate 1116daaffb31Sdpfunction scrollToAnc(num) { 1117daaffb31Sdp 1118daaffb31Sdp // Update the value of the anchor in the form which we use as 1119daaffb31Sdp // storage for this value. setAncValue() will take care of 1120daaffb31Sdp // correcting for overflow and underflow of the value and return 1121daaffb31Sdp // us the new value. 1122daaffb31Sdp num = setAncValue(num); 1123daaffb31Sdp 1124daaffb31Sdp // Set location and scroll back a little to expose previous 1125daaffb31Sdp // lines. 1126daaffb31Sdp // 1127daaffb31Sdp // Note that this could be improved: it is possible although 1128daaffb31Sdp // complex to compute the x and y position of an anchor, and to 1129daaffb31Sdp // scroll to that location directly. 1130daaffb31Sdp // 11317c478bd9Sstevel@tonic-gate parent.lhs.location.replace(parent.lhs.location.pathname + "#" + num); 11327c478bd9Sstevel@tonic-gate parent.rhs.location.replace(parent.rhs.location.pathname + "#" + num); 1133daaffb31Sdp 11347c478bd9Sstevel@tonic-gate parent.lhs.scrollBy(0,-30); 11357c478bd9Sstevel@tonic-gate parent.rhs.scrollBy(0,-30); 11367c478bd9Sstevel@tonic-gate} 11377c478bd9Sstevel@tonic-gate 1138daaffb31Sdpfunction getAncValue() 1139daaffb31Sdp{ 1140daaffb31Sdp return (parseInt(parent.nav.document.diff.real.value)); 1141daaffb31Sdp} 1142daaffb31Sdp 1143daaffb31Sdpfunction setAncValue(val) 1144daaffb31Sdp{ 1145daaffb31Sdp if (val <= 0) { 1146daaffb31Sdp val = 0; 1147daaffb31Sdp parent.nav.document.diff.real.value = val; 1148daaffb31Sdp parent.nav.document.diff.display.value = "BOF"; 1149daaffb31Sdp return (val); 1150daaffb31Sdp } 1151daaffb31Sdp 1152daaffb31Sdp // 1153daaffb31Sdp // The way we compute the max anchor value is to stash it 1154daaffb31Sdp // inline in the left and right hand side pages-- it's the same 1155daaffb31Sdp // on each side, so we pluck from the left. 1156daaffb31Sdp // 1157daaffb31Sdp maxval = parent.lhs.document.eof.value.value; 1158daaffb31Sdp if (val < maxval) { 1159daaffb31Sdp parent.nav.document.diff.real.value = val; 1160daaffb31Sdp parent.nav.document.diff.display.value = val.toString(); 1161daaffb31Sdp return (val); 1162daaffb31Sdp } 1163daaffb31Sdp 1164daaffb31Sdp // this must be: val >= maxval 1165daaffb31Sdp val = maxval; 1166daaffb31Sdp parent.nav.document.diff.real.value = val; 1167daaffb31Sdp parent.nav.document.diff.display.value = "EOF"; 1168daaffb31Sdp return (val); 1169daaffb31Sdp} 1170daaffb31Sdp 11717c478bd9Sstevel@tonic-gatefunction stopScroll() { 11727c478bd9Sstevel@tonic-gate if (scrolling==1) { 11737c478bd9Sstevel@tonic-gate clearInterval(myInt); 11747c478bd9Sstevel@tonic-gate scrolling=0; 11757c478bd9Sstevel@tonic-gate } 11767c478bd9Sstevel@tonic-gate} 11777c478bd9Sstevel@tonic-gate 11787c478bd9Sstevel@tonic-gatefunction startScroll() { 11797c478bd9Sstevel@tonic-gate stopScroll(); 11807c478bd9Sstevel@tonic-gate scrolling=1; 11817c478bd9Sstevel@tonic-gate myInt=setInterval("scrollByPix()",10); 11827c478bd9Sstevel@tonic-gate} 11837c478bd9Sstevel@tonic-gate 11847c478bd9Sstevel@tonic-gatefunction handlePress(b) { 1185daaffb31Sdp 11867c478bd9Sstevel@tonic-gate switch (b) { 11877c478bd9Sstevel@tonic-gate case 1 : 1188daaffb31Sdp scrollToAnc(-1); 11897c478bd9Sstevel@tonic-gate break; 11907c478bd9Sstevel@tonic-gate case 2 : 1191daaffb31Sdp scrollToAnc(getAncValue() - 1); 11927c478bd9Sstevel@tonic-gate break; 11937c478bd9Sstevel@tonic-gate case 3 : 11947c478bd9Sstevel@tonic-gate sfactor=-3; 11957c478bd9Sstevel@tonic-gate startScroll(); 11967c478bd9Sstevel@tonic-gate break; 11977c478bd9Sstevel@tonic-gate case 4 : 11987c478bd9Sstevel@tonic-gate sfactor=3; 11997c478bd9Sstevel@tonic-gate startScroll(); 12007c478bd9Sstevel@tonic-gate break; 12017c478bd9Sstevel@tonic-gate case 5 : 1202daaffb31Sdp scrollToAnc(getAncValue() + 1); 12037c478bd9Sstevel@tonic-gate break; 12047c478bd9Sstevel@tonic-gate case 6 : 1205daaffb31Sdp scrollToAnc(999999); 12067c478bd9Sstevel@tonic-gate break; 12077c478bd9Sstevel@tonic-gate } 12087c478bd9Sstevel@tonic-gate} 12097c478bd9Sstevel@tonic-gate 12107c478bd9Sstevel@tonic-gatefunction handleRelease(b) { 12117c478bd9Sstevel@tonic-gate stopScroll(); 12127c478bd9Sstevel@tonic-gate} 12137c478bd9Sstevel@tonic-gate 1214daaffb31Sdpfunction keypress(ev) { 1215daaffb31Sdp var keynum; 1216daaffb31Sdp var keychar; 1217daaffb31Sdp 1218daaffb31Sdp if (window.event) { // IE 1219daaffb31Sdp keynum = ev.keyCode; 1220daaffb31Sdp } else if (ev.which) { // non-IE 1221daaffb31Sdp keynum = ev.which; 1222daaffb31Sdp } 1223daaffb31Sdp 1224daaffb31Sdp keychar = String.fromCharCode(keynum); 1225daaffb31Sdp 1226daaffb31Sdp if (keychar == "k") { 1227daaffb31Sdp handlePress(2); 1228daaffb31Sdp return (0); 1229daaffb31Sdp } else if (keychar == "j" || keychar == " ") { 1230daaffb31Sdp handlePress(5); 1231daaffb31Sdp return (0); 1232daaffb31Sdp } 1233daaffb31Sdp return (1); 1234daaffb31Sdp} 1235daaffb31Sdp 12367c478bd9Sstevel@tonic-gatefunction ValidateDiffNum(){ 1237daaffb31Sdp val = parent.nav.document.diff.display.value; 1238daaffb31Sdp if (val == "EOF") { 1239daaffb31Sdp scrollToAnc(999999); 1240daaffb31Sdp return; 1241daaffb31Sdp } 1242daaffb31Sdp 1243daaffb31Sdp if (val == "BOF") { 1244daaffb31Sdp scrollToAnc(0); 1245daaffb31Sdp return; 1246daaffb31Sdp } 1247daaffb31Sdp 1248daaffb31Sdp i=parseInt(val); 12497c478bd9Sstevel@tonic-gate if (isNaN(i)) { 1250daaffb31Sdp parent.nav.document.diff.display.value = getAncValue(); 12517c478bd9Sstevel@tonic-gate } else { 1252daaffb31Sdp scrollToAnc(i); 12537c478bd9Sstevel@tonic-gate } 12547c478bd9Sstevel@tonic-gate return false; 12557c478bd9Sstevel@tonic-gate} 12567c478bd9Sstevel@tonic-gate 1257daaffb31SdpEOF 1258daaffb31Sdp} 1259daaffb31Sdp 1260daaffb31Sdp# 1261daaffb31Sdp# frame_navigation 1262daaffb31Sdp# 1263daaffb31Sdp# Output anchor navigation file for framed sdiffs. 1264daaffb31Sdp# 1265daaffb31Sdpfunction frame_navigation 1266daaffb31Sdp{ 1267daaffb31Sdp print "$HTML<head>$STDHEAD" 1268daaffb31Sdp 1269daaffb31Sdp cat << \EOF 1270daaffb31Sdp<title>Anchor Navigation</title> 1271daaffb31Sdp<meta http-equiv="Content-Script-Type" content="text/javascript"> 1272daaffb31Sdp<meta http-equiv="Content-Type" content="text/html"> 1273daaffb31Sdp 1274daaffb31Sdp<style type="text/css"> 1275daaffb31Sdp div.button td { padding-left: 5px; padding-right: 5px; 1276daaffb31Sdp background-color: #eee; text-align: center; 1277daaffb31Sdp border: 1px #444 outset; cursor: pointer; } 1278daaffb31Sdp div.button a { font-weight: bold; color: black } 1279daaffb31Sdp div.button td:hover { background: #ffcc99; } 1280daaffb31Sdp</style> 1281daaffb31SdpEOF 1282daaffb31Sdp 1283cac38512Smjnelson print "<script type=\"text/javascript\" src=\"ancnav.js\"></script>" 1284daaffb31Sdp 1285daaffb31Sdp cat << \EOF 12867c478bd9Sstevel@tonic-gate</head> 1287daaffb31Sdp<body id="SUNWwebrev" bgcolor="#eeeeee" onload="document.diff.real.focus();" 1288daaffb31Sdp onkeypress="keypress(event);"> 12897c478bd9Sstevel@tonic-gate <noscript lang="javascript"> 12907c478bd9Sstevel@tonic-gate <center> 1291cac38512Smjnelson <p><big>Framed Navigation controls require Javascript</big><br></br> 12927c478bd9Sstevel@tonic-gate Either this browser is incompatable or javascript is not enabled</p> 12937c478bd9Sstevel@tonic-gate </center> 12947c478bd9Sstevel@tonic-gate </noscript> 12957c478bd9Sstevel@tonic-gate <table width="100%" border="0" align="center"> 1296daaffb31Sdp <tr> 1297daaffb31Sdp <td valign="middle" width="25%">Diff navigation: 1298daaffb31Sdp Use 'j' and 'k' for next and previous diffs; or use buttons 1299daaffb31Sdp at right</td> 1300daaffb31Sdp <td align="center" valign="top" width="50%"> 13017c478bd9Sstevel@tonic-gate <div class="button"> 1302daaffb31Sdp <table border="0" align="center"> 1303daaffb31Sdp <tr> 1304daaffb31Sdp <td> 13057c478bd9Sstevel@tonic-gate <a onMouseDown="handlePress(1);return true;" 13067c478bd9Sstevel@tonic-gate onMouseUp="handleRelease(1);return true;" 13077c478bd9Sstevel@tonic-gate onMouseOut="handleRelease(1);return true;" 13087c478bd9Sstevel@tonic-gate onClick="return false;" 13097c478bd9Sstevel@tonic-gate title="Go to Beginning Of file">BOF</a></td> 1310daaffb31Sdp <td> 13117c478bd9Sstevel@tonic-gate <a onMouseDown="handlePress(3);return true;" 13127c478bd9Sstevel@tonic-gate onMouseUp="handleRelease(3);return true;" 13137c478bd9Sstevel@tonic-gate onMouseOut="handleRelease(3);return true;" 13147c478bd9Sstevel@tonic-gate title="Scroll Up: Press and Hold to accelerate" 1315daaffb31Sdp onClick="return false;">Scroll Up</a></td> 1316daaffb31Sdp <td> 13177c478bd9Sstevel@tonic-gate <a onMouseDown="handlePress(2);return true;" 13187c478bd9Sstevel@tonic-gate onMouseUp="handleRelease(2);return true;" 13197c478bd9Sstevel@tonic-gate onMouseOut="handleRelease(2);return true;" 13207c478bd9Sstevel@tonic-gate title="Go to previous Diff" 13217c478bd9Sstevel@tonic-gate onClick="return false;">Prev Diff</a> 13227c478bd9Sstevel@tonic-gate </td></tr> 1323daaffb31Sdp 13247c478bd9Sstevel@tonic-gate <tr> 1325daaffb31Sdp <td> 13267c478bd9Sstevel@tonic-gate <a onMouseDown="handlePress(6);return true;" 13277c478bd9Sstevel@tonic-gate onMouseUp="handleRelease(6);return true;" 13287c478bd9Sstevel@tonic-gate onMouseOut="handleRelease(6);return true;" 13297c478bd9Sstevel@tonic-gate onClick="return false;" 13307c478bd9Sstevel@tonic-gate title="Go to End Of File">EOF</a></td> 1331daaffb31Sdp <td> 13327c478bd9Sstevel@tonic-gate <a onMouseDown="handlePress(4);return true;" 13337c478bd9Sstevel@tonic-gate onMouseUp="handleRelease(4);return true;" 13347c478bd9Sstevel@tonic-gate onMouseOut="handleRelease(4);return true;" 13357c478bd9Sstevel@tonic-gate title="Scroll Down: Press and Hold to accelerate" 1336daaffb31Sdp onClick="return false;">Scroll Down</a></td> 1337daaffb31Sdp <td> 13387c478bd9Sstevel@tonic-gate <a onMouseDown="handlePress(5);return true;" 13397c478bd9Sstevel@tonic-gate onMouseUp="handleRelease(5);return true;" 13407c478bd9Sstevel@tonic-gate onMouseOut="handleRelease(5);return true;" 13417c478bd9Sstevel@tonic-gate title="Go to next Diff" 13427c478bd9Sstevel@tonic-gate onClick="return false;">Next Diff</a></td> 1343daaffb31Sdp </tr> 1344daaffb31Sdp </table> 1345daaffb31Sdp </div> 1346daaffb31Sdp </td> 13477c478bd9Sstevel@tonic-gate <th valign="middle" width="25%"> 1348daaffb31Sdp <form action="" name="diff" onsubmit="return ValidateDiffNum();"> 1349cac38512Smjnelson <input name="display" value="BOF" size="8" type="text"></input> 1350cac38512Smjnelson <input name="real" value="0" size="8" type="hidden"></input> 13517c478bd9Sstevel@tonic-gate </form> 13527c478bd9Sstevel@tonic-gate </th> 1353daaffb31Sdp </tr> 13547c478bd9Sstevel@tonic-gate </table> 13557c478bd9Sstevel@tonic-gate </body> 13567c478bd9Sstevel@tonic-gate</html> 13577c478bd9Sstevel@tonic-gateEOF 13587c478bd9Sstevel@tonic-gate} 13597c478bd9Sstevel@tonic-gate 13607c478bd9Sstevel@tonic-gate 1361daaffb31Sdp 1362daaffb31Sdp# 1363daaffb31Sdp# diff_to_html <filename> <filepath> { U | C } <comment> 1364daaffb31Sdp# 1365daaffb31Sdp# Processes the output of diff to produce an HTML file representing either 1366daaffb31Sdp# context or unified diffs. 1367daaffb31Sdp# 13687c478bd9Sstevel@tonic-gatediff_to_html() 13697c478bd9Sstevel@tonic-gate{ 13707c478bd9Sstevel@tonic-gate TNAME=$1 1371daaffb31Sdp TPATH=$2 1372daaffb31Sdp DIFFTYPE=$3 1373daaffb31Sdp COMMENT=$4 1374daaffb31Sdp 1375daaffb31Sdp print "$HTML<head>$STDHEAD" 1376daaffb31Sdp print "<title>$WNAME ${DIFFTYPE}diff $TPATH</title>" 1377daaffb31Sdp 1378daaffb31Sdp if [[ $DIFFTYPE == "U" ]]; then 1379daaffb31Sdp print "$UDIFFCSS" 1380daaffb31Sdp fi 1381daaffb31Sdp 1382daaffb31Sdp cat <<-EOF 1383daaffb31Sdp </head> 1384daaffb31Sdp <body id="SUNWwebrev"> 1385daaffb31Sdp <a class="print" href="javascript:print()">Print this page</a> 1386daaffb31Sdp <pre>$COMMENT</pre> 1387daaffb31Sdp <pre> 1388daaffb31Sdp EOF 13897c478bd9Sstevel@tonic-gate 1390cdf0c1d5Smjnelson html_quote | $AWK ' 1391daaffb31Sdp /^--- new/ { next } 1392daaffb31Sdp /^\+\+\+ new/ { next } 1393daaffb31Sdp /^--- old/ { next } 1394daaffb31Sdp /^\*\*\* old/ { next } 1395daaffb31Sdp /^\*\*\*\*/ { next } 13967c478bd9Sstevel@tonic-gate /^-------/ { printf "<center><h1>%s</h1></center>\n", $0; next } 1397cac38512Smjnelson /^\@\@.*\@\@$/ { printf "</pre><hr></hr><pre>\n"; 1398daaffb31Sdp printf "<span class=\"newmarker\">%s</span>\n", $0; 1399daaffb31Sdp next} 1400daaffb31Sdp 1401cac38512Smjnelson /^\*\*\*/ { printf "<hr></hr><span class=\"oldmarker\">%s</span>\n", $0; 1402daaffb31Sdp next} 1403daaffb31Sdp /^---/ { printf "<span class=\"newmarker\">%s</span>\n", $0; 1404daaffb31Sdp next} 1405daaffb31Sdp /^\+/ {printf "<span class=\"new\">%s</span>\n", $0; next} 1406daaffb31Sdp /^!/ {printf "<span class=\"changed\">%s</span>\n", $0; next} 1407daaffb31Sdp /^-/ {printf "<span class=\"removed\">%s</span>\n", $0; next} 1408daaffb31Sdp {printf "%s\n", $0; next} 14097c478bd9Sstevel@tonic-gate ' 1410daaffb31Sdp 1411daaffb31Sdp print "</pre></body></html>\n" 14127c478bd9Sstevel@tonic-gate} 14137c478bd9Sstevel@tonic-gate 14147c478bd9Sstevel@tonic-gate 1415daaffb31Sdp# 1416daaffb31Sdp# source_to_html { new | old } <filename> 1417daaffb31Sdp# 1418daaffb31Sdp# Process a plain vanilla source file to transform it into an HTML file. 1419daaffb31Sdp# 14207c478bd9Sstevel@tonic-gatesource_to_html() 14217c478bd9Sstevel@tonic-gate{ 14227c478bd9Sstevel@tonic-gate WHICH=$1 14237c478bd9Sstevel@tonic-gate TNAME=$2 14247c478bd9Sstevel@tonic-gate 1425daaffb31Sdp print "$HTML<head>$STDHEAD" 1426cdf0c1d5Smjnelson print "<title>$WNAME $WHICH $TNAME</title>" 1427daaffb31Sdp print "<body id=\"SUNWwebrev\">" 1428daaffb31Sdp print "<pre>" 1429cdf0c1d5Smjnelson html_quote | $AWK '{line += 1 ; printf "%4d %s\n", line, $0 }' 1430daaffb31Sdp print "</pre></body></html>" 14317c478bd9Sstevel@tonic-gate} 14327c478bd9Sstevel@tonic-gate 1433daaffb31Sdp# 1434cdf0c1d5Smjnelson# comments_from_teamware {text|html} parent-file child-file 1435daaffb31Sdp# 1436daaffb31Sdp# Find the first delta in the child that's not in the parent. Get the 1437daaffb31Sdp# newest delta from the parent, get all deltas from the child starting 1438daaffb31Sdp# with that delta, and then get all info starting with the second oldest 1439daaffb31Sdp# delta in that list (the first delta unique to the child). 14407c478bd9Sstevel@tonic-gate# 14417c478bd9Sstevel@tonic-gate# This code adapted from Bill Shannon's "spc" script 1442daaffb31Sdp# 1443daaffb31Sdpcomments_from_teamware() 14447c478bd9Sstevel@tonic-gate{ 1445daaffb31Sdp fmt=$1 1446daaffb31Sdp pfile=$PWS/$2 1447daaffb31Sdp cfile=$CWS/$3 14487c478bd9Sstevel@tonic-gate 1449cdf0c1d5Smjnelson if [[ ! -f $PWS/${2%/*}/SCCS/s.${2##*/} && -n $RWS ]]; then 1450cdf0c1d5Smjnelson pfile=$RWS/$2 1451cdf0c1d5Smjnelson fi 1452cdf0c1d5Smjnelson 1453daaffb31Sdp if [[ -f $pfile ]]; then 1454cdf0c1d5Smjnelson psid=$($SCCS prs -d:I: $pfile 2>/dev/null) 14557c478bd9Sstevel@tonic-gate else 14567c478bd9Sstevel@tonic-gate psid=1.1 14577c478bd9Sstevel@tonic-gate fi 14587c478bd9Sstevel@tonic-gate 1459cdf0c1d5Smjnelson set -A sids $($SCCS prs -l -r$psid -d:I: $cfile 2>/dev/null) 14607c478bd9Sstevel@tonic-gate N=${#sids[@]} 14617c478bd9Sstevel@tonic-gate 1462daaffb31Sdp nawkprg=' 1463daaffb31Sdp /^COMMENTS:/ {p=1; continue} 1464daaffb31Sdp /^D [0-9]+\.[0-9]+/ {printf "--- %s ---\n", $2; p=0; } 1465daaffb31Sdp NF == 0u { continue } 1466daaffb31Sdp {if (p==0) continue; print $0 }' 1467daaffb31Sdp 14687c478bd9Sstevel@tonic-gate if [[ $N -ge 2 ]]; then 14697c478bd9Sstevel@tonic-gate sid1=${sids[$((N-2))]} # Gets 2nd to last sid 14707c478bd9Sstevel@tonic-gate 1471daaffb31Sdp if [[ $fmt == "text" ]]; then 1472cdf0c1d5Smjnelson $SCCS prs -l -r$sid1 $cfile 2>/dev/null | \ 1473cdf0c1d5Smjnelson $AWK "$nawkprg" 1474daaffb31Sdp return 1475daaffb31Sdp fi 1476daaffb31Sdp 1477cdf0c1d5Smjnelson $SCCS prs -l -r$sid1 $cfile 2>/dev/null | \ 14780fd2682eSMark J. Nelson html_quote | its2url | $AWK "$nawkprg" 14797c478bd9Sstevel@tonic-gate fi 14807c478bd9Sstevel@tonic-gate} 14817c478bd9Sstevel@tonic-gate 1482daaffb31Sdp# 1483cdf0c1d5Smjnelson# comments_from_wx {text|html} filepath 1484daaffb31Sdp# 1485cdf0c1d5Smjnelson# Given the pathname of a file, find its location in a "wx" active 1486cdf0c1d5Smjnelson# file list and print the following comment. Output is either text or 1487cdf0c1d5Smjnelson# HTML; if the latter, embedded bugids (sequence of 5 or more digits) 1488cdf0c1d5Smjnelson# are turned into URLs. 1489cdf0c1d5Smjnelson# 1490cdf0c1d5Smjnelson# This is also used with Mercurial and the file list provided by hg-active. 1491daaffb31Sdp# 1492daaffb31Sdpcomments_from_wx() 14937c478bd9Sstevel@tonic-gate{ 1494daaffb31Sdp typeset fmt=$1 1495daaffb31Sdp typeset p=$2 14967c478bd9Sstevel@tonic-gate 1497cdf0c1d5Smjnelson comm=`$AWK ' 1498daaffb31Sdp $1 == "'$p'" { 14997c478bd9Sstevel@tonic-gate do getline ; while (NF > 0) 15007c478bd9Sstevel@tonic-gate getline 15017c478bd9Sstevel@tonic-gate while (NF > 0) { print ; getline } 15027c478bd9Sstevel@tonic-gate exit 1503daaffb31Sdp }' < $wxfile` 1504daaffb31Sdp 1505cdf0c1d5Smjnelson if [[ -z $comm ]]; then 1506cdf0c1d5Smjnelson comm="*** NO COMMENTS ***" 1507cdf0c1d5Smjnelson fi 1508cdf0c1d5Smjnelson 1509daaffb31Sdp if [[ $fmt == "text" ]]; then 1510cdf0c1d5Smjnelson print -- "$comm" 1511daaffb31Sdp return 1512daaffb31Sdp fi 1513daaffb31Sdp 15140fd2682eSMark J. Nelson print -- "$comm" | html_quote | its2url 1515cdf0c1d5Smjnelson 15167c478bd9Sstevel@tonic-gate} 15177c478bd9Sstevel@tonic-gate 15187c478bd9Sstevel@tonic-gate# 1519daaffb31Sdp# getcomments {text|html} filepath parentpath 1520daaffb31Sdp# 1521daaffb31Sdp# Fetch the comments depending on what SCM mode we're in. 1522daaffb31Sdp# 1523daaffb31Sdpgetcomments() 1524daaffb31Sdp{ 1525daaffb31Sdp typeset fmt=$1 1526daaffb31Sdp typeset p=$2 1527daaffb31Sdp typeset pp=$3 15287c478bd9Sstevel@tonic-gate 15293df69ef3SDarren Moffat if [[ -n $Nflag ]]; then 15303df69ef3SDarren Moffat return 15313df69ef3SDarren Moffat fi 1532cdf0c1d5Smjnelson # 1533cdf0c1d5Smjnelson # Mercurial support uses a file list in wx format, so this 1534cdf0c1d5Smjnelson # will be used there, too 1535cdf0c1d5Smjnelson # 1536daaffb31Sdp if [[ -n $wxfile ]]; then 1537daaffb31Sdp comments_from_wx $fmt $p 1538daaffb31Sdp else 1539daaffb31Sdp if [[ $SCM_MODE == "teamware" ]]; then 1540daaffb31Sdp comments_from_teamware $fmt $pp $p 1541daaffb31Sdp fi 1542daaffb31Sdp fi 1543daaffb31Sdp} 1544daaffb31Sdp 1545daaffb31Sdp# 1546daaffb31Sdp# printCI <total-changed> <inserted> <deleted> <modified> <unchanged> 1547daaffb31Sdp# 1548daaffb31Sdp# Print out Code Inspection figures similar to sccs-prt(1) format. 1549daaffb31Sdp# 1550daaffb31Sdpfunction printCI 1551daaffb31Sdp{ 1552daaffb31Sdp integer tot=$1 ins=$2 del=$3 mod=$4 unc=$5 1553daaffb31Sdp typeset str 1554daaffb31Sdp if (( tot == 1 )); then 1555daaffb31Sdp str="line" 1556daaffb31Sdp else 1557daaffb31Sdp str="lines" 1558daaffb31Sdp fi 1559daaffb31Sdp printf '%d %s changed: %d ins; %d del; %d mod; %d unchg\n' \ 1560daaffb31Sdp $tot $str $ins $del $mod $unc 1561daaffb31Sdp} 1562daaffb31Sdp 1563daaffb31Sdp 1564daaffb31Sdp# 1565daaffb31Sdp# difflines <oldfile> <newfile> 1566daaffb31Sdp# 1567daaffb31Sdp# Calculate and emit number of added, removed, modified and unchanged lines, 1568daaffb31Sdp# and total lines changed, the sum of added + removed + modified. 1569daaffb31Sdp# 15707c478bd9Sstevel@tonic-gatefunction difflines 15717c478bd9Sstevel@tonic-gate{ 1572daaffb31Sdp integer tot mod del ins unc err 15737c478bd9Sstevel@tonic-gate typeset filename 15747c478bd9Sstevel@tonic-gate 1575cdf0c1d5Smjnelson eval $( diff -e $1 $2 | $AWK ' 1576daaffb31Sdp # Change range of lines: N,Nc 15777c478bd9Sstevel@tonic-gate /^[0-9]*,[0-9]*c$/ { 15787c478bd9Sstevel@tonic-gate n=split(substr($1,1,length($1)-1), counts, ","); 15797c478bd9Sstevel@tonic-gate if (n != 2) { 15807c478bd9Sstevel@tonic-gate error=2 15817c478bd9Sstevel@tonic-gate exit; 15827c478bd9Sstevel@tonic-gate } 1583daaffb31Sdp # 1584daaffb31Sdp # 3,5c means lines 3 , 4 and 5 are changed, a total of 3 lines. 1585daaffb31Sdp # following would be 5 - 3 = 2! Hence +1 for correction. 1586daaffb31Sdp # 15877c478bd9Sstevel@tonic-gate r=(counts[2]-counts[1])+1; 1588daaffb31Sdp 1589daaffb31Sdp # 1590daaffb31Sdp # Now count replacement lines: each represents a change instead 1591daaffb31Sdp # of a delete, so increment c and decrement r. 1592daaffb31Sdp # 15937c478bd9Sstevel@tonic-gate while (getline != /^\.$/) { 15947c478bd9Sstevel@tonic-gate c++; 15957c478bd9Sstevel@tonic-gate r--; 15967c478bd9Sstevel@tonic-gate } 1597daaffb31Sdp # 1598daaffb31Sdp # If there were more replacement lines than original lines, 1599daaffb31Sdp # then r will be negative; in this case there are no deletions, 1600daaffb31Sdp # but there are r changes that should be counted as adds, and 1601daaffb31Sdp # since r is negative, subtract it from a and add it to c. 1602daaffb31Sdp # 16037c478bd9Sstevel@tonic-gate if (r < 0) { 16047c478bd9Sstevel@tonic-gate a-=r; 16057c478bd9Sstevel@tonic-gate c+=r; 16067c478bd9Sstevel@tonic-gate } 1607daaffb31Sdp 1608daaffb31Sdp # 1609daaffb31Sdp # If there were more original lines than replacement lines, then 1610daaffb31Sdp # r will be positive; in this case, increment d by that much. 1611daaffb31Sdp # 16127c478bd9Sstevel@tonic-gate if (r > 0) { 16137c478bd9Sstevel@tonic-gate d+=r; 16147c478bd9Sstevel@tonic-gate } 16157c478bd9Sstevel@tonic-gate next; 16167c478bd9Sstevel@tonic-gate } 16177c478bd9Sstevel@tonic-gate 1618daaffb31Sdp # Change lines: Nc 16197c478bd9Sstevel@tonic-gate /^[0-9].*c$/ { 1620daaffb31Sdp # The first line is a replacement; any more are additions. 16217c478bd9Sstevel@tonic-gate if (getline != /^\.$/) { 16227c478bd9Sstevel@tonic-gate c++; 16237c478bd9Sstevel@tonic-gate while (getline != /^\.$/) a++; 16247c478bd9Sstevel@tonic-gate } 16257c478bd9Sstevel@tonic-gate next; 16267c478bd9Sstevel@tonic-gate } 16277c478bd9Sstevel@tonic-gate 1628daaffb31Sdp # Add lines: both Na and N,Na 16297c478bd9Sstevel@tonic-gate /^[0-9].*a$/ { 16307c478bd9Sstevel@tonic-gate while (getline != /^\.$/) a++; 16317c478bd9Sstevel@tonic-gate next; 16327c478bd9Sstevel@tonic-gate } 16337c478bd9Sstevel@tonic-gate 1634daaffb31Sdp # Delete range of lines: N,Nd 16357c478bd9Sstevel@tonic-gate /^[0-9]*,[0-9]*d$/ { 16367c478bd9Sstevel@tonic-gate n=split(substr($1,1,length($1)-1), counts, ","); 16377c478bd9Sstevel@tonic-gate if (n != 2) { 16387c478bd9Sstevel@tonic-gate error=2 16397c478bd9Sstevel@tonic-gate exit; 16407c478bd9Sstevel@tonic-gate } 1641daaffb31Sdp # 1642daaffb31Sdp # 3,5d means lines 3 , 4 and 5 are deleted, a total of 3 lines. 1643daaffb31Sdp # following would be 5 - 3 = 2! Hence +1 for correction. 1644daaffb31Sdp # 16457c478bd9Sstevel@tonic-gate r=(counts[2]-counts[1])+1; 16467c478bd9Sstevel@tonic-gate d+=r; 16477c478bd9Sstevel@tonic-gate next; 16487c478bd9Sstevel@tonic-gate } 16497c478bd9Sstevel@tonic-gate 1650daaffb31Sdp # Delete line: Nd. For example 10d says line 10 is deleted. 16517c478bd9Sstevel@tonic-gate /^[0-9]*d$/ {d++; next} 16527c478bd9Sstevel@tonic-gate 1653daaffb31Sdp # Should not get here! 16547c478bd9Sstevel@tonic-gate { 16557c478bd9Sstevel@tonic-gate error=1; 16567c478bd9Sstevel@tonic-gate exit; 16577c478bd9Sstevel@tonic-gate } 16587c478bd9Sstevel@tonic-gate 1659daaffb31Sdp # Finish off - print results 16607c478bd9Sstevel@tonic-gate END { 1661daaffb31Sdp printf("tot=%d;mod=%d;del=%d;ins=%d;err=%d\n", 16627c478bd9Sstevel@tonic-gate (c+d+a), c, d, a, error); 16637c478bd9Sstevel@tonic-gate }' ) 16647c478bd9Sstevel@tonic-gate 1665cdf0c1d5Smjnelson # End of $AWK, Check to see if any trouble occurred. 16667c478bd9Sstevel@tonic-gate if (( $? > 0 || err > 0 )); then 1667daaffb31Sdp print "Unexpected Error occurred reading" \ 1668daaffb31Sdp "\`diff -e $1 $2\`: \$?=$?, err=" $err 1669daaffb31Sdp return 1670daaffb31Sdp fi 1671daaffb31Sdp 16727c478bd9Sstevel@tonic-gate # Accumulate totals 16737c478bd9Sstevel@tonic-gate (( TOTL += tot )) 1674daaffb31Sdp (( TMOD += mod )) 16757c478bd9Sstevel@tonic-gate (( TDEL += del )) 16767c478bd9Sstevel@tonic-gate (( TINS += ins )) 16777c478bd9Sstevel@tonic-gate # Calculate unchanged lines 1678cdf0c1d5Smjnelson unc=`wc -l < $1` 16797c478bd9Sstevel@tonic-gate if (( unc > 0 )); then 1680daaffb31Sdp (( unc -= del + mod )) 16817c478bd9Sstevel@tonic-gate (( TUNC += unc )) 16827c478bd9Sstevel@tonic-gate fi 16837c478bd9Sstevel@tonic-gate # print summary 1684daaffb31Sdp print "<span class=\"lineschanged\">" 1685daaffb31Sdp printCI $tot $ins $del $mod $unc 1686daaffb31Sdp print "</span>" 16877c478bd9Sstevel@tonic-gate} 16887c478bd9Sstevel@tonic-gate 1689daaffb31Sdp 16907c478bd9Sstevel@tonic-gate# 1691daaffb31Sdp# flist_from_wx 1692daaffb31Sdp# 1693daaffb31Sdp# Sets up webrev to source its information from a wx-formatted file. 1694daaffb31Sdp# Sets the global 'wxfile' variable. 1695daaffb31Sdp# 1696daaffb31Sdpfunction flist_from_wx 16977c478bd9Sstevel@tonic-gate{ 1698daaffb31Sdp typeset argfile=$1 1699daaffb31Sdp if [[ -n ${argfile%%/*} ]]; then 1700daaffb31Sdp # 1701daaffb31Sdp # If the wx file pathname is relative then make it absolute 1702daaffb31Sdp # because the webrev does a "cd" later on. 1703daaffb31Sdp # 1704daaffb31Sdp wxfile=$PWD/$argfile 17057c478bd9Sstevel@tonic-gate else 1706daaffb31Sdp wxfile=$argfile 17077c478bd9Sstevel@tonic-gate fi 17087c478bd9Sstevel@tonic-gate 1709cdf0c1d5Smjnelson $AWK '{ c = 1; print; 17107c478bd9Sstevel@tonic-gate while (getline) { 17117c478bd9Sstevel@tonic-gate if (NF == 0) { c = -c; continue } 17127c478bd9Sstevel@tonic-gate if (c > 0) print 17137c478bd9Sstevel@tonic-gate } 1714daaffb31Sdp }' $wxfile > $FLIST 17157c478bd9Sstevel@tonic-gate 1716daaffb31Sdp print " Done." 1717daaffb31Sdp} 17187c478bd9Sstevel@tonic-gate 1719daaffb31Sdp# 1720daaffb31Sdp# flist_from_teamware [ <args-to-putback-n> ] 1721daaffb31Sdp# 1722daaffb31Sdp# Generate the file list by extracting file names from a putback -n. Some 1723daaffb31Sdp# names may come from the "update/create" messages and others from the 1724daaffb31Sdp# "currently checked out" warning. Renames are detected here too. Extract 1725daaffb31Sdp# values for CODEMGR_WS and CODEMGR_PARENT from the output of the putback 1726daaffb31Sdp# -n as well, but remove them if they are already defined. 1727daaffb31Sdp# 1728daaffb31Sdpfunction flist_from_teamware 1729daaffb31Sdp{ 1730cdf0c1d5Smjnelson if [[ -n $codemgr_parent && -z $parent_webrev ]]; then 1731daaffb31Sdp if [[ ! -d $codemgr_parent/Codemgr_wsdata ]]; then 1732daaffb31Sdp print -u2 "parent $codemgr_parent doesn't look like a" \ 1733daaffb31Sdp "valid teamware workspace" 17347c478bd9Sstevel@tonic-gate exit 1 17357c478bd9Sstevel@tonic-gate fi 1736daaffb31Sdp parent_args="-p $codemgr_parent" 17377c478bd9Sstevel@tonic-gate fi 17387c478bd9Sstevel@tonic-gate 1739daaffb31Sdp print " File list from: 'putback -n $parent_args $*' ... \c" 17407c478bd9Sstevel@tonic-gate 1741daaffb31Sdp putback -n $parent_args $* 2>&1 | 1742cdf0c1d5Smjnelson $AWK ' 1743daaffb31Sdp /^update:|^create:/ {print $2} 1744daaffb31Sdp /^Parent workspace:/ {printf("CODEMGR_PARENT=%s\n",$3)} 1745daaffb31Sdp /^Child workspace:/ {printf("CODEMGR_WS=%s\n",$3)} 1746daaffb31Sdp /^The following files are currently checked out/ {p = 1; continue} 1747daaffb31Sdp NF == 0 {p=0 ; continue} 1748daaffb31Sdp /^rename/ {old=$3} 1749daaffb31Sdp $1 == "to:" {print $2, old} 1750daaffb31Sdp /^"/ {continue} 1751daaffb31Sdp p == 1 {print $1}' | 1752daaffb31Sdp sort -r -k 1,1 -u | sort > $FLIST 17537c478bd9Sstevel@tonic-gate 1754daaffb31Sdp print " Done." 1755daaffb31Sdp} 1756daaffb31Sdp 1757cdf0c1d5Smjnelson# 1758cdf0c1d5Smjnelson# Call hg-active to get the active list output in the wx active list format 1759cdf0c1d5Smjnelson# 1760cdf0c1d5Smjnelsonfunction hg_active_wxfile 1761cdf0c1d5Smjnelson{ 1762cdf0c1d5Smjnelson typeset child=$1 1763cdf0c1d5Smjnelson typeset parent=$2 1764cdf0c1d5Smjnelson 1765cdf0c1d5Smjnelson TMPFLIST=/tmp/$$.active 17669a70fc3bSMark J. Nelson $HG_ACTIVE -w $child -p $parent -o $TMPFLIST 1767cdf0c1d5Smjnelson wxfile=$TMPFLIST 1768cdf0c1d5Smjnelson} 1769cdf0c1d5Smjnelson 1770cdf0c1d5Smjnelson# 1771cdf0c1d5Smjnelson# flist_from_mercurial 1772cdf0c1d5Smjnelson# Call hg-active to get a wx-style active list, and hand it off to 1773cdf0c1d5Smjnelson# flist_from_wx 1774cdf0c1d5Smjnelson# 1775cdf0c1d5Smjnelsonfunction flist_from_mercurial 1776cdf0c1d5Smjnelson{ 1777cdf0c1d5Smjnelson typeset child=$1 1778cdf0c1d5Smjnelson typeset parent=$2 1779cdf0c1d5Smjnelson 1780cdf0c1d5Smjnelson print " File list from: hg-active -p $parent ...\c" 1781cdf0c1d5Smjnelson if [[ ! -x $HG_ACTIVE ]]; then 1782cdf0c1d5Smjnelson print # Blank line for the \c above 1783cdf0c1d5Smjnelson print -u2 "Error: hg-active tool not found. Exiting" 1784cdf0c1d5Smjnelson exit 1 1785cdf0c1d5Smjnelson fi 1786cdf0c1d5Smjnelson hg_active_wxfile $child $parent 1787cdf0c1d5Smjnelson 1788cdf0c1d5Smjnelson # flist_from_wx prints the Done, so we don't have to. 1789cdf0c1d5Smjnelson flist_from_wx $TMPFLIST 1790cdf0c1d5Smjnelson} 1791cdf0c1d5Smjnelson 1792cdf0c1d5Smjnelson# 1793*8bcea973SRichard Lowe# Transform a specified 'git log' output format into a wx-like active list. 1794*8bcea973SRichard Lowe# 1795*8bcea973SRichard Lowefunction git_wxfile 1796*8bcea973SRichard Lowe{ 1797*8bcea973SRichard Lowe typeset child="$1" 1798*8bcea973SRichard Lowe typeset parent="$2" 1799*8bcea973SRichard Lowe 1800*8bcea973SRichard Lowe TMPFLIST=/tmp/$$.active 1801*8bcea973SRichard Lowe $PERL -e 'my (%files, %realfiles, $msg); 1802*8bcea973SRichard Lowe my $branch = $ARGV[0]; 1803*8bcea973SRichard Lowe 1804*8bcea973SRichard Lowe open(F, "git diff -M --name-status $branch |"); 1805*8bcea973SRichard Lowe while (<F>) { 1806*8bcea973SRichard Lowe chomp; 1807*8bcea973SRichard Lowe if (/^R(\d+)\s+([^ ]+)\s+([^ ]+)/) { # rename 1808*8bcea973SRichard Lowe if ($1 >= 75) { # Probably worth treating as a rename 1809*8bcea973SRichard Lowe $realfiles{$3} = $2 1810*8bcea973SRichard Lowe } else { 1811*8bcea973SRichard Lowe $realfiles{$3} = $3; 1812*8bcea973SRichard Lowe $realfiles{$2} = $2; 1813*8bcea973SRichard Lowe } 1814*8bcea973SRichard Lowe } else { 1815*8bcea973SRichard Lowe my $f = (split /\s+/, $_)[1]; 1816*8bcea973SRichard Lowe $realfiles{$f} = $f; 1817*8bcea973SRichard Lowe } 1818*8bcea973SRichard Lowe } 1819*8bcea973SRichard Lowe close(F); 1820*8bcea973SRichard Lowe 1821*8bcea973SRichard Lowe my $state = 1; # 0|comments, 1|files 1822*8bcea973SRichard Lowe open(F, "git whatchanged --pretty=format:%B $branch.. |"); 1823*8bcea973SRichard Lowe while (<F>) { 1824*8bcea973SRichard Lowe chomp; 1825*8bcea973SRichard Lowe if (/^:[0-9]{6}/) { 1826*8bcea973SRichard Lowe my $fname = (split /\t/, $_)[1]; 1827*8bcea973SRichard Lowe next if !defined($realfiles{$fname}); # No real change 1828*8bcea973SRichard Lowe $state = 1; 1829*8bcea973SRichard Lowe $files{$fname} = $msg; 1830*8bcea973SRichard Lowe } else { 1831*8bcea973SRichard Lowe if ($state == 1) { 1832*8bcea973SRichard Lowe $state = 0; 1833*8bcea973SRichard Lowe $msg = /^\n/ ? "" : "\n"; 1834*8bcea973SRichard Lowe } 1835*8bcea973SRichard Lowe $msg .= "$_\n" if ($_); 1836*8bcea973SRichard Lowe } 1837*8bcea973SRichard Lowe } 1838*8bcea973SRichard Lowe close(F); 1839*8bcea973SRichard Lowe 1840*8bcea973SRichard Lowe for (sort keys %files) { 1841*8bcea973SRichard Lowe if ($realfiles{$_} ne $_) { 1842*8bcea973SRichard Lowe print "$_ $realfiles{$_}\n$files{$_}\n"; 1843*8bcea973SRichard Lowe } else { 1844*8bcea973SRichard Lowe print "$_\n$files{$_}\n" 1845*8bcea973SRichard Lowe } 1846*8bcea973SRichard Lowe }' ${parent} > $TMPFLIST 1847*8bcea973SRichard Lowe 1848*8bcea973SRichard Lowe wxfile=$TMPFLIST 1849*8bcea973SRichard Lowe} 1850*8bcea973SRichard Lowe 1851*8bcea973SRichard Lowe# 1852*8bcea973SRichard Lowe# flist_from_git 1853*8bcea973SRichard Lowe# Build a wx-style active list, and hand it off to flist_from_wx 1854*8bcea973SRichard Lowe# 1855*8bcea973SRichard Lowefunction flist_from_git 1856*8bcea973SRichard Lowe{ 1857*8bcea973SRichard Lowe typeset child=$1 1858*8bcea973SRichard Lowe typeset parent=$2 1859*8bcea973SRichard Lowe 1860*8bcea973SRichard Lowe print " File list from: git ...\c" 1861*8bcea973SRichard Lowe git_wxfile "$child" "$parent"; 1862*8bcea973SRichard Lowe 1863*8bcea973SRichard Lowe # flist_from_wx prints the Done, so we don't have to. 1864*8bcea973SRichard Lowe flist_from_wx $TMPFLIST 1865*8bcea973SRichard Lowe} 1866*8bcea973SRichard Lowe 1867*8bcea973SRichard Lowe# 1868cdf0c1d5Smjnelson# flist_from_subversion 1869cdf0c1d5Smjnelson# 1870cdf0c1d5Smjnelson# Generate the file list by extracting file names from svn status. 1871cdf0c1d5Smjnelson# 1872cdf0c1d5Smjnelsonfunction flist_from_subversion 1873cdf0c1d5Smjnelson{ 1874cdf0c1d5Smjnelson CWS=$1 1875cdf0c1d5Smjnelson OLDPWD=$2 1876cdf0c1d5Smjnelson 1877cdf0c1d5Smjnelson cd $CWS 1878cdf0c1d5Smjnelson print -u2 " File list from: svn status ... \c" 1879cdf0c1d5Smjnelson svn status | $AWK '/^[ACDMR]/ { print $NF }' > $FLIST 1880cdf0c1d5Smjnelson print -u2 " Done." 1881cdf0c1d5Smjnelson cd $OLDPWD 1882cdf0c1d5Smjnelson} 1883cdf0c1d5Smjnelson 1884daaffb31Sdpfunction env_from_flist 1885daaffb31Sdp{ 1886daaffb31Sdp [[ -r $FLIST ]] || return 1887daaffb31Sdp 1888daaffb31Sdp # 1889daaffb31Sdp # Use "eval" to set env variables that are listed in the file 1890daaffb31Sdp # list. Then copy those into our local versions of those 1891daaffb31Sdp # variables if they have not been set already. 1892daaffb31Sdp # 1893b0088928SVladimir Kotal eval `$SED -e "s/#.*$//" $FLIST | $GREP = ` 18947c478bd9Sstevel@tonic-gate 1895cdf0c1d5Smjnelson if [[ -z $codemgr_ws && -n $CODEMGR_WS ]]; then 1896cdf0c1d5Smjnelson codemgr_ws=$CODEMGR_WS 1897cdf0c1d5Smjnelson export CODEMGR_WS 1898cdf0c1d5Smjnelson fi 18997c478bd9Sstevel@tonic-gate 1900daaffb31Sdp # 1901daaffb31Sdp # Check to see if CODEMGR_PARENT is set in the flist file. 1902daaffb31Sdp # 1903cdf0c1d5Smjnelson if [[ -z $codemgr_parent && -n $CODEMGR_PARENT ]]; then 1904daaffb31Sdp codemgr_parent=$CODEMGR_PARENT 1905cdf0c1d5Smjnelson export CODEMGR_PARENT 1906daaffb31Sdp fi 1907daaffb31Sdp} 1908daaffb31Sdp 190914983201Sdpfunction look_for_prog 191014983201Sdp{ 191114983201Sdp typeset path 191214983201Sdp typeset ppath 191314983201Sdp typeset progname=$1 191414983201Sdp 191514983201Sdp ppath=$PATH 191614983201Sdp ppath=$ppath:/usr/sfw/bin:/usr/bin:/usr/sbin 191714983201Sdp ppath=$ppath:/opt/teamware/bin:/opt/onbld/bin 1918cdf0c1d5Smjnelson ppath=$ppath:/opt/onbld/bin/`uname -p` 191914983201Sdp 192014983201Sdp PATH=$ppath prog=`whence $progname` 192114983201Sdp if [[ -n $prog ]]; then 192214983201Sdp print $prog 192314983201Sdp fi 192414983201Sdp} 192514983201Sdp 1926cdf0c1d5Smjnelsonfunction get_file_mode 1927cdf0c1d5Smjnelson{ 1928cdf0c1d5Smjnelson $PERL -e ' 1929cdf0c1d5Smjnelson if (@stat = stat($ARGV[0])) { 1930cdf0c1d5Smjnelson $mode = $stat[2] & 0777; 1931cdf0c1d5Smjnelson printf "%03o\n", $mode; 1932cdf0c1d5Smjnelson exit 0; 1933cdf0c1d5Smjnelson } else { 1934cdf0c1d5Smjnelson exit 1; 1935cdf0c1d5Smjnelson } 1936cdf0c1d5Smjnelson ' $1 1937cdf0c1d5Smjnelson} 1938cdf0c1d5Smjnelson 1939cdf0c1d5Smjnelsonfunction build_old_new_teamware 1940cdf0c1d5Smjnelson{ 1941cdf0c1d5Smjnelson typeset olddir="$1" 1942cdf0c1d5Smjnelson typeset newdir="$2" 1943cdf0c1d5Smjnelson 1944cdf0c1d5Smjnelson # If the child's version doesn't exist then 1945cdf0c1d5Smjnelson # get a readonly copy. 1946cdf0c1d5Smjnelson 1947cdf0c1d5Smjnelson if [[ ! -f $CWS/$DIR/$F && -f $CWS/$DIR/SCCS/s.$F ]]; then 1948cdf0c1d5Smjnelson $SCCS get -s -p $CWS/$DIR/$F > $CWS/$DIR/$F 1949cdf0c1d5Smjnelson fi 1950cdf0c1d5Smjnelson 1951cdf0c1d5Smjnelson # The following two sections propagate file permissions the 1952cdf0c1d5Smjnelson # same way SCCS does. If the file is already under version 1953cdf0c1d5Smjnelson # control, always use permissions from the SCCS/s.file. If 1954cdf0c1d5Smjnelson # the file is not under SCCS control, use permissions from the 1955cdf0c1d5Smjnelson # working copy. In all cases, the file copied to the webrev 1956cdf0c1d5Smjnelson # is set to read only, and group/other permissions are set to 1957cdf0c1d5Smjnelson # match those of the file owner. This way, even if the file 1958cdf0c1d5Smjnelson # is currently checked out, the webrev will display the final 1959cdf0c1d5Smjnelson # permissions that would result after check in. 1960cdf0c1d5Smjnelson 1961cdf0c1d5Smjnelson # 1962cdf0c1d5Smjnelson # Snag new version of file. 1963cdf0c1d5Smjnelson # 1964cdf0c1d5Smjnelson rm -f $newdir/$DIR/$F 1965cdf0c1d5Smjnelson cp $CWS/$DIR/$F $newdir/$DIR/$F 1966cdf0c1d5Smjnelson if [[ -f $CWS/$DIR/SCCS/s.$F ]]; then 1967cdf0c1d5Smjnelson chmod `get_file_mode $CWS/$DIR/SCCS/s.$F` \ 1968cdf0c1d5Smjnelson $newdir/$DIR/$F 1969cdf0c1d5Smjnelson fi 1970cdf0c1d5Smjnelson chmod u-w,go=u $newdir/$DIR/$F 1971cdf0c1d5Smjnelson 1972cdf0c1d5Smjnelson # 1973cdf0c1d5Smjnelson # Get the parent's version of the file. First see whether the 1974cdf0c1d5Smjnelson # child's version is checked out and get the parent's version 1975cdf0c1d5Smjnelson # with keywords expanded or unexpanded as appropriate. 1976cdf0c1d5Smjnelson # 1977cdf0c1d5Smjnelson if [[ -f $PWS/$PDIR/$PF && ! -f $PWS/$PDIR/SCCS/s.$PF && \ 1978cdf0c1d5Smjnelson ! -f $PWS/$PDIR/SCCS/p.$PF ]]; then 1979cdf0c1d5Smjnelson # Parent is not a real workspace, but just a raw 1980cdf0c1d5Smjnelson # directory tree - use the file that's there as 1981cdf0c1d5Smjnelson # the old file. 1982cdf0c1d5Smjnelson 1983cdf0c1d5Smjnelson rm -f $olddir/$PDIR/$PF 1984cdf0c1d5Smjnelson cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF 1985cdf0c1d5Smjnelson else 1986cdf0c1d5Smjnelson if [[ -f $PWS/$PDIR/SCCS/s.$PF ]]; then 1987cdf0c1d5Smjnelson real_parent=$PWS 1988cdf0c1d5Smjnelson else 1989cdf0c1d5Smjnelson real_parent=$RWS 1990cdf0c1d5Smjnelson fi 1991cdf0c1d5Smjnelson 1992cdf0c1d5Smjnelson rm -f $olddir/$PDIR/$PF 1993cdf0c1d5Smjnelson 1994cdf0c1d5Smjnelson if [[ -f $real_parent/$PDIR/$PF ]]; then 1995cdf0c1d5Smjnelson if [ -f $CWS/$DIR/SCCS/p.$F ]; then 1996cdf0c1d5Smjnelson $SCCS get -s -p -k $real_parent/$PDIR/$PF > \ 1997cdf0c1d5Smjnelson $olddir/$PDIR/$PF 1998cdf0c1d5Smjnelson else 1999cdf0c1d5Smjnelson $SCCS get -s -p $real_parent/$PDIR/$PF > \ 2000cdf0c1d5Smjnelson $olddir/$PDIR/$PF 2001cdf0c1d5Smjnelson fi 2002cdf0c1d5Smjnelson chmod `get_file_mode $real_parent/$PDIR/SCCS/s.$PF` \ 2003cdf0c1d5Smjnelson $olddir/$PDIR/$PF 2004cdf0c1d5Smjnelson fi 2005cdf0c1d5Smjnelson fi 2006cdf0c1d5Smjnelson if [[ -f $olddir/$PDIR/$PF ]]; then 2007cdf0c1d5Smjnelson chmod u-w,go=u $olddir/$PDIR/$PF 2008cdf0c1d5Smjnelson fi 2009cdf0c1d5Smjnelson} 2010cdf0c1d5Smjnelson 2011cdf0c1d5Smjnelsonfunction build_old_new_mercurial 2012cdf0c1d5Smjnelson{ 2013cdf0c1d5Smjnelson typeset olddir="$1" 2014cdf0c1d5Smjnelson typeset newdir="$2" 2015cdf0c1d5Smjnelson typeset old_mode= 2016cdf0c1d5Smjnelson typeset new_mode= 2017cdf0c1d5Smjnelson typeset file 2018cdf0c1d5Smjnelson 2019cdf0c1d5Smjnelson # 2020cdf0c1d5Smjnelson # Get old file mode, from the parent revision manifest entry. 2021cdf0c1d5Smjnelson # Mercurial only stores a "file is executable" flag, but the 2022cdf0c1d5Smjnelson # manifest will display an octal mode "644" or "755". 2023cdf0c1d5Smjnelson # 2024cdf0c1d5Smjnelson if [[ "$PDIR" == "." ]]; then 2025cdf0c1d5Smjnelson file="$PF" 2026cdf0c1d5Smjnelson else 2027cdf0c1d5Smjnelson file="$PDIR/$PF" 2028cdf0c1d5Smjnelson fi 2029b0088928SVladimir Kotal file=`echo $file | $SED 's#/#\\\/#g'` 2030cdf0c1d5Smjnelson # match the exact filename, and return only the permission digits 2031b0088928SVladimir Kotal old_mode=`$SED -n -e "/^\\(...\\) . ${file}$/s//\\1/p" \ 2032cdf0c1d5Smjnelson < $HG_PARENT_MANIFEST` 2033cdf0c1d5Smjnelson 2034cdf0c1d5Smjnelson # 2035cdf0c1d5Smjnelson # Get new file mode, directly from the filesystem. 2036cdf0c1d5Smjnelson # Normalize the mode to match Mercurial's behavior. 2037cdf0c1d5Smjnelson # 2038cdf0c1d5Smjnelson new_mode=`get_file_mode $CWS/$DIR/$F` 2039cdf0c1d5Smjnelson if [[ -n "$new_mode" ]]; then 2040cdf0c1d5Smjnelson if [[ "$new_mode" = *[1357]* ]]; then 2041cdf0c1d5Smjnelson new_mode=755 2042cdf0c1d5Smjnelson else 2043cdf0c1d5Smjnelson new_mode=644 2044cdf0c1d5Smjnelson fi 2045cdf0c1d5Smjnelson fi 2046cdf0c1d5Smjnelson 2047cdf0c1d5Smjnelson # 2048cdf0c1d5Smjnelson # new version of the file. 2049cdf0c1d5Smjnelson # 2050cdf0c1d5Smjnelson rm -rf $newdir/$DIR/$F 2051cdf0c1d5Smjnelson if [[ -e $CWS/$DIR/$F ]]; then 2052cdf0c1d5Smjnelson cp $CWS/$DIR/$F $newdir/$DIR/$F 2053cdf0c1d5Smjnelson if [[ -n $new_mode ]]; then 2054cdf0c1d5Smjnelson chmod $new_mode $newdir/$DIR/$F 2055cdf0c1d5Smjnelson else 2056cdf0c1d5Smjnelson # should never happen 2057cdf0c1d5Smjnelson print -u2 "ERROR: set mode of $newdir/$DIR/$F" 2058cdf0c1d5Smjnelson fi 2059cdf0c1d5Smjnelson fi 2060cdf0c1d5Smjnelson 2061cdf0c1d5Smjnelson # 2062cdf0c1d5Smjnelson # parent's version of the file 2063cdf0c1d5Smjnelson # 2064cdf0c1d5Smjnelson # Note that we get this from the last version common to both 2065cdf0c1d5Smjnelson # ourselves and the parent. References are via $CWS since we have no 2066cdf0c1d5Smjnelson # guarantee that the parent workspace is reachable via the filesystem. 2067cdf0c1d5Smjnelson # 2068cdf0c1d5Smjnelson if [[ -n $parent_webrev && -e $PWS/$PDIR/$PF ]]; then 2069cdf0c1d5Smjnelson cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF 2070cdf0c1d5Smjnelson elif [[ -n $HG_PARENT ]]; then 2071cdf0c1d5Smjnelson hg cat -R $CWS -r $HG_PARENT $CWS/$PDIR/$PF > \ 2072cdf0c1d5Smjnelson $olddir/$PDIR/$PF 2>/dev/null 2073cdf0c1d5Smjnelson 207402d26c39SVladimir Kotal if (( $? != 0 )); then 2075cdf0c1d5Smjnelson rm -f $olddir/$PDIR/$PF 2076cdf0c1d5Smjnelson else 2077cdf0c1d5Smjnelson if [[ -n $old_mode ]]; then 2078cdf0c1d5Smjnelson chmod $old_mode $olddir/$PDIR/$PF 2079cdf0c1d5Smjnelson else 2080cdf0c1d5Smjnelson # should never happen 2081cdf0c1d5Smjnelson print -u2 "ERROR: set mode of $olddir/$PDIR/$PF" 2082cdf0c1d5Smjnelson fi 2083cdf0c1d5Smjnelson fi 2084cdf0c1d5Smjnelson fi 2085cdf0c1d5Smjnelson} 2086cdf0c1d5Smjnelson 2087*8bcea973SRichard Lowefunction build_old_new_git 2088*8bcea973SRichard Lowe{ 2089*8bcea973SRichard Lowe typeset olddir="$1" 2090*8bcea973SRichard Lowe typeset newdir="$2" 2091*8bcea973SRichard Lowe typeset o_mode= 2092*8bcea973SRichard Lowe typeset n_mode= 2093*8bcea973SRichard Lowe typeset o_object= 2094*8bcea973SRichard Lowe typeset n_object= 2095*8bcea973SRichard Lowe typeset OWD=$PWD 2096*8bcea973SRichard Lowe typeset file 2097*8bcea973SRichard Lowe typeset type 2098*8bcea973SRichard Lowe 2099*8bcea973SRichard Lowe cd $CWS 2100*8bcea973SRichard Lowe 2101*8bcea973SRichard Lowe # 2102*8bcea973SRichard Lowe # Get old file and its mode from the git object tree 2103*8bcea973SRichard Lowe # 2104*8bcea973SRichard Lowe if [[ "$PDIR" == "." ]]; then 2105*8bcea973SRichard Lowe file="$PF" 2106*8bcea973SRichard Lowe else 2107*8bcea973SRichard Lowe file="$PDIR/$PF" 2108*8bcea973SRichard Lowe fi 2109*8bcea973SRichard Lowe 2110*8bcea973SRichard Lowe if [[ -n $parent_webrev && -e $PWS/$PDIR/$PF ]]; then 2111*8bcea973SRichard Lowe cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF 2112*8bcea973SRichard Lowe else 2113*8bcea973SRichard Lowe $GIT ls-tree $GIT_PARENT $file | read o_mode type o_object junk 2114*8bcea973SRichard Lowe $GIT cat-file $type $o_object > $olddir/$file 2>/dev/null 2115*8bcea973SRichard Lowe 2116*8bcea973SRichard Lowe if (( $? != 0 )); then 2117*8bcea973SRichard Lowe rm -f $olddir/$file 2118*8bcea973SRichard Lowe elif [[ -n $o_mode ]]; then 2119*8bcea973SRichard Lowe # Strip the first 3 digits, to get a regular octal mode 2120*8bcea973SRichard Lowe o_mode=${o_mode/???/} 2121*8bcea973SRichard Lowe chmod $o_mode $olddir/$file 2122*8bcea973SRichard Lowe else 2123*8bcea973SRichard Lowe # should never happen 2124*8bcea973SRichard Lowe print -u2 "ERROR: set mode of $olddir/$file" 2125*8bcea973SRichard Lowe fi 2126*8bcea973SRichard Lowe fi 2127*8bcea973SRichard Lowe 2128*8bcea973SRichard Lowe # 2129*8bcea973SRichard Lowe # new version of the file. 2130*8bcea973SRichard Lowe # 2131*8bcea973SRichard Lowe if [[ "$DIR" == "." ]]; then 2132*8bcea973SRichard Lowe file="$F" 2133*8bcea973SRichard Lowe else 2134*8bcea973SRichard Lowe file="$DIR/$F" 2135*8bcea973SRichard Lowe fi 2136*8bcea973SRichard Lowe rm -rf $newdir/$file 2137*8bcea973SRichard Lowe 2138*8bcea973SRichard Lowe if [[ -e $CWS/$DIR/$F ]]; then 2139*8bcea973SRichard Lowe cp $CWS/$DIR/$F $newdir/$DIR/$F 2140*8bcea973SRichard Lowe chmod $(get_file_mode $CWS/$DIR/$F) $newdir/$DIR/$F 2141*8bcea973SRichard Lowe fi 2142*8bcea973SRichard Lowe cd $OWD 2143*8bcea973SRichard Lowe} 2144*8bcea973SRichard Lowe 2145cdf0c1d5Smjnelsonfunction build_old_new_subversion 2146cdf0c1d5Smjnelson{ 2147cdf0c1d5Smjnelson typeset olddir="$1" 2148cdf0c1d5Smjnelson typeset newdir="$2" 2149cdf0c1d5Smjnelson 2150cdf0c1d5Smjnelson # Snag new version of file. 2151cdf0c1d5Smjnelson rm -f $newdir/$DIR/$F 2152cdf0c1d5Smjnelson [[ -e $CWS/$DIR/$F ]] && cp $CWS/$DIR/$F $newdir/$DIR/$F 2153cdf0c1d5Smjnelson 2154cdf0c1d5Smjnelson if [[ -n $PWS && -e $PWS/$PDIR/$PF ]]; then 2155cdf0c1d5Smjnelson cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF 2156cdf0c1d5Smjnelson else 2157cdf0c1d5Smjnelson # Get the parent's version of the file. 2158cdf0c1d5Smjnelson svn status $CWS/$DIR/$F | read stat file 2159cdf0c1d5Smjnelson if [[ $stat != "A" ]]; then 2160cdf0c1d5Smjnelson svn cat -r BASE $CWS/$DIR/$F > $olddir/$PDIR/$PF 2161cdf0c1d5Smjnelson fi 2162cdf0c1d5Smjnelson fi 2163cdf0c1d5Smjnelson} 2164cdf0c1d5Smjnelson 2165cdf0c1d5Smjnelsonfunction build_old_new_unknown 2166cdf0c1d5Smjnelson{ 2167cdf0c1d5Smjnelson typeset olddir="$1" 2168cdf0c1d5Smjnelson typeset newdir="$2" 2169cdf0c1d5Smjnelson 2170cdf0c1d5Smjnelson # 2171cdf0c1d5Smjnelson # Snag new version of file. 2172cdf0c1d5Smjnelson # 2173cdf0c1d5Smjnelson rm -f $newdir/$DIR/$F 2174cdf0c1d5Smjnelson [[ -e $CWS/$DIR/$F ]] && cp $CWS/$DIR/$F $newdir/$DIR/$F 2175cdf0c1d5Smjnelson 2176cdf0c1d5Smjnelson # 2177cdf0c1d5Smjnelson # Snag the parent's version of the file. 2178cdf0c1d5Smjnelson # 2179cdf0c1d5Smjnelson if [[ -f $PWS/$PDIR/$PF ]]; then 2180cdf0c1d5Smjnelson rm -f $olddir/$PDIR/$PF 2181cdf0c1d5Smjnelson cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF 2182cdf0c1d5Smjnelson fi 2183cdf0c1d5Smjnelson} 2184cdf0c1d5Smjnelson 2185cdf0c1d5Smjnelsonfunction build_old_new 2186cdf0c1d5Smjnelson{ 2187cdf0c1d5Smjnelson typeset WDIR=$1 2188cdf0c1d5Smjnelson typeset PWS=$2 2189cdf0c1d5Smjnelson typeset PDIR=$3 2190cdf0c1d5Smjnelson typeset PF=$4 2191cdf0c1d5Smjnelson typeset CWS=$5 2192cdf0c1d5Smjnelson typeset DIR=$6 2193cdf0c1d5Smjnelson typeset F=$7 2194cdf0c1d5Smjnelson 2195cdf0c1d5Smjnelson typeset olddir="$WDIR/raw_files/old" 2196cdf0c1d5Smjnelson typeset newdir="$WDIR/raw_files/new" 2197cdf0c1d5Smjnelson 2198cdf0c1d5Smjnelson mkdir -p $olddir/$PDIR 2199cdf0c1d5Smjnelson mkdir -p $newdir/$DIR 2200cdf0c1d5Smjnelson 2201cdf0c1d5Smjnelson if [[ $SCM_MODE == "teamware" ]]; then 2202cdf0c1d5Smjnelson build_old_new_teamware "$olddir" "$newdir" 2203cdf0c1d5Smjnelson elif [[ $SCM_MODE == "mercurial" ]]; then 2204cdf0c1d5Smjnelson build_old_new_mercurial "$olddir" "$newdir" 2205*8bcea973SRichard Lowe elif [[ $SCM_MODE == "git" ]]; then 2206*8bcea973SRichard Lowe build_old_new_git "$olddir" "$newdir" 2207cdf0c1d5Smjnelson elif [[ $SCM_MODE == "subversion" ]]; then 2208cdf0c1d5Smjnelson build_old_new_subversion "$olddir" "$newdir" 2209cdf0c1d5Smjnelson elif [[ $SCM_MODE == "unknown" ]]; then 2210cdf0c1d5Smjnelson build_old_new_unknown "$olddir" "$newdir" 2211cdf0c1d5Smjnelson fi 2212cdf0c1d5Smjnelson 2213cdf0c1d5Smjnelson if [[ ! -f $olddir/$PDIR/$PF && ! -f $newdir/$DIR/$F ]]; then 2214cdf0c1d5Smjnelson print "*** Error: file not in parent or child" 2215cdf0c1d5Smjnelson return 1 2216cdf0c1d5Smjnelson fi 2217cdf0c1d5Smjnelson return 0 2218cdf0c1d5Smjnelson} 2219cdf0c1d5Smjnelson 2220cdf0c1d5Smjnelson 2221daaffb31Sdp# 2222daaffb31Sdp# Usage message. 2223daaffb31Sdp# 2224daaffb31Sdpfunction usage 2225daaffb31Sdp{ 2226daaffb31Sdp print 'Usage:\twebrev [common-options] 2227daaffb31Sdp webrev [common-options] ( <file> | - ) 2228daaffb31Sdp webrev [common-options] -w <wx file> 2229daaffb31Sdp 2230daaffb31SdpOptions: 22310fd2682eSMark J. Nelson -C <filename>: Use <filename> for the information tracking configuration. 2232ba44d8a2SVladimir Kotal -D: delete remote webrev 2233daaffb31Sdp -i <filename>: Include <filename> in the index.html file. 22340fd2682eSMark J. Nelson -I <filename>: Use <filename> for the information tracking registry. 2235ba44d8a2SVladimir Kotal -n: do not generate the webrev (useful with -U) 2236ba44d8a2SVladimir Kotal -O: Print bugids/arc cases suitable for OpenSolaris. 2237daaffb31Sdp -o <outdir>: Output webrev to specified directory. 2238daaffb31Sdp -p <compare-against>: Use specified parent wkspc or basis for comparison 223902d26c39SVladimir Kotal -t <remote_target>: Specify remote destination for webrev upload 224002d26c39SVladimir Kotal -U: upload the webrev to remote destination 2241daaffb31Sdp -w <wxfile>: Use specified wx active file. 2242daaffb31Sdp 2243daaffb31SdpEnvironment: 2244daaffb31Sdp WDIR: Control the output directory. 2245ba44d8a2SVladimir Kotal WEBREV_TRASH_DIR: Set directory for webrev delete. 2246daaffb31Sdp 2247cdf0c1d5SmjnelsonSCM Specific Options: 2248cdf0c1d5Smjnelson TeamWare: webrev [common-options] -l [arguments to 'putback'] 2249cdf0c1d5Smjnelson 2250daaffb31SdpSCM Environment: 2251cdf0c1d5Smjnelson CODEMGR_WS: Workspace location. 2252cdf0c1d5Smjnelson CODEMGR_PARENT: Parent workspace location. 2253daaffb31Sdp' 2254daaffb31Sdp 2255daaffb31Sdp exit 2 2256daaffb31Sdp} 2257daaffb31Sdp 2258daaffb31Sdp# 2259daaffb31Sdp# 2260daaffb31Sdp# Main program starts here 2261daaffb31Sdp# 2262daaffb31Sdp# 2263daaffb31Sdp 2264daaffb31Sdptrap "rm -f /tmp/$$.* ; exit" 0 1 2 3 15 2265daaffb31Sdp 2266daaffb31Sdpset +o noclobber 2267daaffb31Sdp 2268*8bcea973SRichard LowePATH=$(/bin/dirname "$(whence $0)"):$PATH 2269cdf0c1d5Smjnelson 227014983201Sdp[[ -z $WDIFF ]] && WDIFF=`look_for_prog wdiff` 227114983201Sdp[[ -z $WX ]] && WX=`look_for_prog wx` 2272cdf0c1d5Smjnelson[[ -z $HG_ACTIVE ]] && HG_ACTIVE=`look_for_prog hg-active` 2273*8bcea973SRichard Lowe[[ -z $GIT ]] && GIT=`look_for_prog git` 2274cdf0c1d5Smjnelson[[ -z $WHICH_SCM ]] && WHICH_SCM=`look_for_prog which_scm` 227514983201Sdp[[ -z $CODEREVIEW ]] && CODEREVIEW=`look_for_prog codereview` 227614983201Sdp[[ -z $PS2PDF ]] && PS2PDF=`look_for_prog ps2pdf` 227714983201Sdp[[ -z $PERL ]] && PERL=`look_for_prog perl` 227802d26c39SVladimir Kotal[[ -z $RSYNC ]] && RSYNC=`look_for_prog rsync` 2279cdf0c1d5Smjnelson[[ -z $SCCS ]] && SCCS=`look_for_prog sccs` 2280cdf0c1d5Smjnelson[[ -z $AWK ]] && AWK=`look_for_prog nawk` 2281cdf0c1d5Smjnelson[[ -z $AWK ]] && AWK=`look_for_prog gawk` 2282cdf0c1d5Smjnelson[[ -z $AWK ]] && AWK=`look_for_prog awk` 228302d26c39SVladimir Kotal[[ -z $SCP ]] && SCP=`look_for_prog scp` 2284b0088928SVladimir Kotal[[ -z $SED ]] && SED=`look_for_prog sed` 228502d26c39SVladimir Kotal[[ -z $SFTP ]] && SFTP=`look_for_prog sftp` 2286e6ccc173SEdward Pilatowicz[[ -z $SORT ]] && SORT=`look_for_prog sort` 228702d26c39SVladimir Kotal[[ -z $MKTEMP ]] && MKTEMP=`look_for_prog mktemp` 228802d26c39SVladimir Kotal[[ -z $GREP ]] && GREP=`look_for_prog grep` 2289ba44d8a2SVladimir Kotal[[ -z $FIND ]] && FIND=`look_for_prog find` 2290cdf0c1d5Smjnelson 2291ba44d8a2SVladimir Kotal# set name of trash directory for remote webrev deletion 2292ba44d8a2SVladimir KotalTRASH_DIR=".trash" 2293ba44d8a2SVladimir Kotal[[ -n $WEBREV_TRASH_DIR ]] && TRASH_DIR=$WEBREV_TRASH_DIR 229414983201Sdp 229514983201Sdpif [[ ! -x $PERL ]]; then 229614983201Sdp print -u2 "Error: No perl interpreter found. Exiting." 229714983201Sdp exit 1 2298daaffb31Sdpfi 229914983201Sdp 2300cdf0c1d5Smjnelsonif [[ ! -x $WHICH_SCM ]]; then 2301cdf0c1d5Smjnelson print -u2 "Error: Could not find which_scm. Exiting." 2302cdf0c1d5Smjnelson exit 1 2303cdf0c1d5Smjnelsonfi 2304cdf0c1d5Smjnelson 230514983201Sdp# 230614983201Sdp# These aren't fatal, but we want to note them to the user. 230714983201Sdp# We don't warn on the absence of 'wx' until later when we've 230814983201Sdp# determined that we actually need to try to invoke it. 230914983201Sdp# 231014983201Sdp[[ ! -x $CODEREVIEW ]] && print -u2 "WARNING: codereview(1) not found." 231114983201Sdp[[ ! -x $PS2PDF ]] && print -u2 "WARNING: ps2pdf(1) not found." 231214983201Sdp[[ ! -x $WDIFF ]] && print -u2 "WARNING: wdiff not found." 2313daaffb31Sdp 2314daaffb31Sdp# Declare global total counters. 2315daaffb31Sdpinteger TOTL TINS TDEL TMOD TUNC 2316daaffb31Sdp 2317ba44d8a2SVladimir Kotal# default remote host for upload/delete 2318ba44d8a2SVladimir Kotaltypeset -r DEFAULT_REMOTE_HOST="cr.opensolaris.org" 2319b0088928SVladimir Kotal# prefixes for upload targets 2320b0088928SVladimir Kotaltypeset -r rsync_prefix="rsync://" 2321b0088928SVladimir Kotaltypeset -r ssh_prefix="ssh://" 2322ba44d8a2SVladimir Kotal 23230fd2682eSMark J. NelsonCflag= 2324ba44d8a2SVladimir KotalDflag= 232514983201Sdpflist_mode= 232614983201Sdpflist_file= 2327daaffb31Sdpiflag= 23280fd2682eSMark J. NelsonIflag= 232902d26c39SVladimir Kotallflag= 233002d26c39SVladimir KotalNflag= 233102d26c39SVladimir Kotalnflag= 233202d26c39SVladimir KotalOflag= 2333daaffb31Sdpoflag= 2334daaffb31Sdppflag= 233502d26c39SVladimir Kotaltflag= 233602d26c39SVladimir Kotaluflag= 233702d26c39SVladimir KotalUflag= 2338daaffb31Sdpwflag= 233902d26c39SVladimir Kotalremote_target= 2340ba44d8a2SVladimir Kotal 2341ba44d8a2SVladimir Kotal# 2342ba44d8a2SVladimir Kotal# NOTE: when adding/removing options it is necessary to sync the list 2343ba44d8a2SVladimir Kotal# with usr/src/tools/onbld/hgext/cdm.py 2344ba44d8a2SVladimir Kotal# 234525cc4e45SVladimir Kotalwhile getopts "C:Di:I:lnNo:Op:t:Uw" opt 2346daaffb31Sdpdo 2347daaffb31Sdp case $opt in 23480fd2682eSMark J. Nelson C) Cflag=1 23490fd2682eSMark J. Nelson ITSCONF=$OPTARG;; 23500fd2682eSMark J. Nelson 2351ba44d8a2SVladimir Kotal D) Dflag=1;; 2352ba44d8a2SVladimir Kotal 2353daaffb31Sdp i) iflag=1 2354daaffb31Sdp INCLUDE_FILE=$OPTARG;; 2355daaffb31Sdp 23560fd2682eSMark J. Nelson I) Iflag=1 23570fd2682eSMark J. Nelson ITSREG=$OPTARG;; 23580fd2682eSMark J. Nelson 2359daaffb31Sdp # 2360daaffb31Sdp # If -l has been specified, we need to abort further options 2361daaffb31Sdp # processing, because subsequent arguments are going to be 2362daaffb31Sdp # arguments to 'putback -n'. 2363daaffb31Sdp # 2364daaffb31Sdp l) lflag=1 2365daaffb31Sdp break;; 2366daaffb31Sdp 236702d26c39SVladimir Kotal N) Nflag=1;; 236802d26c39SVladimir Kotal 236902d26c39SVladimir Kotal n) nflag=1;; 2370daaffb31Sdp 2371daaffb31Sdp O) Oflag=1;; 2372daaffb31Sdp 237302d26c39SVladimir Kotal o) oflag=1 23749d3952abSVladimir Kotal # Strip the trailing slash to correctly form remote target. 23759d3952abSVladimir Kotal WDIR=${OPTARG%/};; 237602d26c39SVladimir Kotal 237702d26c39SVladimir Kotal p) pflag=1 237802d26c39SVladimir Kotal codemgr_parent=$OPTARG;; 237902d26c39SVladimir Kotal 238002d26c39SVladimir Kotal t) tflag=1 238102d26c39SVladimir Kotal remote_target=$OPTARG;; 238202d26c39SVladimir Kotal 238302d26c39SVladimir Kotal U) Uflag=1;; 238402d26c39SVladimir Kotal 238502d26c39SVladimir Kotal w) wflag=1;; 23863df69ef3SDarren Moffat 2387daaffb31Sdp ?) usage;; 2388daaffb31Sdp esac 2389daaffb31Sdpdone 2390daaffb31Sdp 2391daaffb31SdpFLIST=/tmp/$$.flist 2392daaffb31Sdp 2393daaffb31Sdpif [[ -n $wflag && -n $lflag ]]; then 2394daaffb31Sdp usage 2395daaffb31Sdpfi 2396daaffb31Sdp 239702d26c39SVladimir Kotal# more sanity checking 239802d26c39SVladimir Kotalif [[ -n $nflag && -z $Uflag ]]; then 2399ba44d8a2SVladimir Kotal print "it does not make sense to skip webrev generation" \ 2400ba44d8a2SVladimir Kotal "without -U" 240102d26c39SVladimir Kotal exit 1 240202d26c39SVladimir Kotalfi 240302d26c39SVladimir Kotal 2404ba44d8a2SVladimir Kotalif [[ -n $tflag && -z $Uflag && -z $Dflag ]]; then 2405ba44d8a2SVladimir Kotal echo "remote target has to be used only for upload or delete" 240602d26c39SVladimir Kotal exit 1 240702d26c39SVladimir Kotalfi 240802d26c39SVladimir Kotal 2409daaffb31Sdp# 24102d9224a3SMark J. Nelson# For the invocation "webrev -n -U" with no other options, webrev will assume 24112d9224a3SMark J. Nelson# that the webrev exists in ${CWS}/webrev, but will upload it using the name 24122d9224a3SMark J. Nelson# $(basename ${CWS}). So we need to get CWS set before we skip any remaining 24132d9224a3SMark J. Nelson# logic. 24142d9224a3SMark J. Nelson# 24152d9224a3SMark J. Nelson$WHICH_SCM | read SCM_MODE junk || exit 1 24162d9224a3SMark J. Nelsonif [[ $SCM_MODE == "teamware" ]]; then 24172d9224a3SMark J. Nelson # 24182d9224a3SMark J. Nelson # Teamware priorities: 24192d9224a3SMark J. Nelson # 1. CODEMGR_WS from the environment 24202d9224a3SMark J. Nelson # 2. workspace name 24212d9224a3SMark J. Nelson # 24222d9224a3SMark J. Nelson [[ -z $codemgr_ws && -n $CODEMGR_WS ]] && codemgr_ws=$CODEMGR_WS 24232d9224a3SMark J. Nelson if [[ -n $codemgr_ws && ! -d $codemgr_ws ]]; then 24242d9224a3SMark J. Nelson print -u2 "$codemgr_ws: no such workspace" 24252d9224a3SMark J. Nelson exit 1 24262d9224a3SMark J. Nelson fi 24272d9224a3SMark J. Nelson [[ -z $codemgr_ws ]] && codemgr_ws=$(workspace name) 24282d9224a3SMark J. Nelson codemgr_ws=$(cd $codemgr_ws;print $PWD) 24292d9224a3SMark J. Nelson CODEMGR_WS=$codemgr_ws 24302d9224a3SMark J. Nelson CWS=$codemgr_ws 24312d9224a3SMark J. Nelsonelif [[ $SCM_MODE == "mercurial" ]]; then 24322d9224a3SMark J. Nelson # 24332d9224a3SMark J. Nelson # Mercurial priorities: 24342d9224a3SMark J. Nelson # 1. hg root from CODEMGR_WS environment variable 243578add226Sjmcp # 1a. hg root from CODEMGR_WS/usr/closed if we're somewhere under 243678add226Sjmcp # usr/closed when we run webrev 24372d9224a3SMark J. Nelson # 2. hg root from directory of invocation 24382d9224a3SMark J. Nelson # 243978add226Sjmcp if [[ ${PWD} =~ "usr/closed" ]]; then 244078add226Sjmcp testparent=${CODEMGR_WS}/usr/closed 244178add226Sjmcp # If we're in OpenSolaris mode, we enforce a minor policy: 244278add226Sjmcp # help to make sure the reviewer doesn't accidentally publish 244378add226Sjmcp # source which is under usr/closed 244478add226Sjmcp if [[ -n "$Oflag" ]]; then 244578add226Sjmcp print -u2 "OpenSolaris output not permitted with" \ 244678add226Sjmcp "usr/closed changes" 244778add226Sjmcp exit 1 244878add226Sjmcp fi 244978add226Sjmcp else 245078add226Sjmcp testparent=${CODEMGR_WS} 245178add226Sjmcp fi 245278add226Sjmcp [[ -z $codemgr_ws && -n $testparent ]] && \ 245378add226Sjmcp codemgr_ws=$(hg root -R $testparent 2>/dev/null) 24542d9224a3SMark J. Nelson [[ -z $codemgr_ws ]] && codemgr_ws=$(hg root 2>/dev/null) 24552d9224a3SMark J. Nelson CWS=$codemgr_ws 2456*8bcea973SRichard Loweelif [[ $SCM_MODE == "git" ]]; then 2457*8bcea973SRichard Lowe # 2458*8bcea973SRichard Lowe # Git priorities: 2459*8bcea973SRichard Lowe # 1. git rev-parse --git-dir from CODEMGR_WS environment variable 2460*8bcea973SRichard Lowe # 2. git rev-parse --git-dir from directory of invocation 2461*8bcea973SRichard Lowe # 2462*8bcea973SRichard Lowe [[ -z $codemgr_ws && -n $CODEMGR_WS ]] && \ 2463*8bcea973SRichard Lowe codemgr_ws=$($GIT --git-dir=$CODEMGR_WS/.git rev-parse --git-dir \ 2464*8bcea973SRichard Lowe 2>/dev/null) 2465*8bcea973SRichard Lowe [[ -z $codemgr_ws ]] && \ 2466*8bcea973SRichard Lowe codemgr_ws=$($GIT rev-parse --git-dir 2>/dev/null) 2467*8bcea973SRichard Lowe 2468*8bcea973SRichard Lowe if [[ "$codemgr_ws" == ".git" ]]; then 2469*8bcea973SRichard Lowe codemgr_ws="${PWD}/${codemgr_ws}" 2470*8bcea973SRichard Lowe fi 2471*8bcea973SRichard Lowe 2472*8bcea973SRichard Lowe codemgr_ws=$(dirname $codemgr_ws) # Lose the '/.git' 2473*8bcea973SRichard Lowe CWS="$codemgr_ws" 24742d9224a3SMark J. Nelsonelif [[ $SCM_MODE == "subversion" ]]; then 24752d9224a3SMark J. Nelson # 24762d9224a3SMark J. Nelson # Subversion priorities: 24772d9224a3SMark J. Nelson # 1. CODEMGR_WS from environment 24782d9224a3SMark J. Nelson # 2. Relative path from current directory to SVN repository root 24792d9224a3SMark J. Nelson # 24802d9224a3SMark J. Nelson if [[ -n $CODEMGR_WS && -d $CODEMGR_WS/.svn ]]; then 24812d9224a3SMark J. Nelson CWS=$CODEMGR_WS 24822d9224a3SMark J. Nelson else 24832d9224a3SMark J. Nelson svn info | while read line; do 24842d9224a3SMark J. Nelson if [[ $line == "URL: "* ]]; then 24852d9224a3SMark J. Nelson url=${line#URL: } 24862d9224a3SMark J. Nelson elif [[ $line == "Repository Root: "* ]]; then 24872d9224a3SMark J. Nelson repo=${line#Repository Root: } 24882d9224a3SMark J. Nelson fi 24892d9224a3SMark J. Nelson done 24902d9224a3SMark J. Nelson 24912d9224a3SMark J. Nelson rel=${url#$repo} 24922d9224a3SMark J. Nelson CWS=${PWD%$rel} 24932d9224a3SMark J. Nelson fi 24942d9224a3SMark J. Nelsonfi 24952d9224a3SMark J. Nelson 24962d9224a3SMark J. Nelson# 24972d9224a3SMark J. Nelson# If no SCM has been determined, take either the environment setting 24982d9224a3SMark J. Nelson# setting for CODEMGR_WS, or the current directory if that wasn't set. 24992d9224a3SMark J. Nelson# 25002d9224a3SMark J. Nelsonif [[ -z ${CWS} ]]; then 25012d9224a3SMark J. Nelson CWS=${CODEMGR_WS:-.} 25022d9224a3SMark J. Nelsonfi 25032d9224a3SMark J. Nelson 25042d9224a3SMark J. Nelson# 25050fd2682eSMark J. Nelson# If the command line options indicate no webrev generation, either 25060fd2682eSMark J. Nelson# explicitly (-n) or implicitly (-D but not -U), then there's a whole 25070fd2682eSMark J. Nelson# ton of logic we can skip. 25080fd2682eSMark J. Nelson# 25090fd2682eSMark J. Nelson# Instead of increasing indentation, we intentionally leave this loop 25100fd2682eSMark J. Nelson# body open here, and exit via break from multiple points within. 25110fd2682eSMark J. Nelson# Search for DO_EVERYTHING below to find the break points and closure. 25120fd2682eSMark J. Nelson# 25130fd2682eSMark J. Nelsonfor do_everything in 1; do 25140fd2682eSMark J. Nelson 25150fd2682eSMark J. Nelson# DO_EVERYTHING: break point 25160fd2682eSMark J. Nelsonif [[ -n $nflag || ( -z $Uflag && -n $Dflag ) ]]; then 25170fd2682eSMark J. Nelson break 25180fd2682eSMark J. Nelsonfi 25190fd2682eSMark J. Nelson 25200fd2682eSMark J. Nelson# 2521daaffb31Sdp# If this manually set as the parent, and it appears to be an earlier webrev, 2522daaffb31Sdp# then note that fact and set the parent to the raw_files/new subdirectory. 2523daaffb31Sdp# 2524daaffb31Sdpif [[ -n $pflag && -d $codemgr_parent/raw_files/new ]]; then 2525*8bcea973SRichard Lowe parent_webrev=$(readlink -f "$codemgr_parent") 2526*8bcea973SRichard Lowe codemgr_parent=$(readlink -f "$codemgr_parent/raw_files/new") 2527daaffb31Sdpfi 2528daaffb31Sdp 2529daaffb31Sdpif [[ -z $wflag && -z $lflag ]]; then 2530daaffb31Sdp shift $(($OPTIND - 1)) 2531daaffb31Sdp 2532daaffb31Sdp if [[ $1 == "-" ]]; then 2533daaffb31Sdp cat > $FLIST 253414983201Sdp flist_mode="stdin" 253514983201Sdp flist_done=1 253614983201Sdp shift 2537daaffb31Sdp elif [[ -n $1 ]]; then 253814983201Sdp if [[ ! -r $1 ]]; then 2539daaffb31Sdp print -u2 "$1: no such file or not readable" 2540daaffb31Sdp usage 2541daaffb31Sdp fi 2542daaffb31Sdp cat $1 > $FLIST 254314983201Sdp flist_mode="file" 254414983201Sdp flist_file=$1 254514983201Sdp flist_done=1 254614983201Sdp shift 2547daaffb31Sdp else 254814983201Sdp flist_mode="auto" 2549daaffb31Sdp fi 2550daaffb31Sdpfi 2551daaffb31Sdp 2552daaffb31Sdp# 2553daaffb31Sdp# Before we go on to further consider -l and -w, work out which SCM we think 2554daaffb31Sdp# is in use. 2555daaffb31Sdp# 2556cdf0c1d5Smjnelsoncase "$SCM_MODE" in 2557*8bcea973SRichard Loweteamware|mercurial|git|subversion) 2558cdf0c1d5Smjnelson ;; 2559cdf0c1d5Smjnelsonunknown) 2560cdf0c1d5Smjnelson if [[ $flist_mode == "auto" ]]; then 2561cdf0c1d5Smjnelson print -u2 "Unable to determine SCM in use and file list not specified" 2562cdf0c1d5Smjnelson print -u2 "See which_scm(1) for SCM detection information." 25637c478bd9Sstevel@tonic-gate exit 1 25647c478bd9Sstevel@tonic-gate fi 2565cdf0c1d5Smjnelson ;; 2566cdf0c1d5Smjnelson*) 2567cdf0c1d5Smjnelson if [[ $flist_mode == "auto" ]]; then 2568cdf0c1d5Smjnelson print -u2 "Unsupported SCM in use ($SCM_MODE) and file list not specified" 2569cdf0c1d5Smjnelson exit 1 2570cdf0c1d5Smjnelson fi 2571cdf0c1d5Smjnelson ;; 2572cdf0c1d5Smjnelsonesac 25737c478bd9Sstevel@tonic-gate 2574daaffb31Sdpprint -u2 " SCM detected: $SCM_MODE" 2575daaffb31Sdp 2576daaffb31Sdpif [[ -n $lflag ]]; then 2577daaffb31Sdp # 2578daaffb31Sdp # If the -l flag is given instead of the name of a file list, 2579daaffb31Sdp # then generate the file list by extracting file names from a 2580daaffb31Sdp # putback -n. 2581daaffb31Sdp # 2582daaffb31Sdp shift $(($OPTIND - 1)) 2583cdf0c1d5Smjnelson if [[ $SCM_MODE == "teamware" ]]; then 2584daaffb31Sdp flist_from_teamware "$*" 2585cdf0c1d5Smjnelson else 2586cdf0c1d5Smjnelson print -u2 -- "Error: -l option only applies to TeamWare" 2587cdf0c1d5Smjnelson exit 1 2588cdf0c1d5Smjnelson fi 2589daaffb31Sdp flist_done=1 2590daaffb31Sdp shift $# 2591daaffb31Sdpelif [[ -n $wflag ]]; then 2592daaffb31Sdp # 2593daaffb31Sdp # If the -w is given then assume the file list is in Bonwick's "wx" 2594daaffb31Sdp # command format, i.e. pathname lines alternating with SCCS comment 2595daaffb31Sdp # lines with blank lines as separators. Use the SCCS comments later 2596daaffb31Sdp # in building the index.html file. 2597daaffb31Sdp # 2598daaffb31Sdp shift $(($OPTIND - 1)) 2599daaffb31Sdp wxfile=$1 2600daaffb31Sdp if [[ -z $wxfile && -n $CODEMGR_WS ]]; then 2601daaffb31Sdp if [[ -r $CODEMGR_WS/wx/active ]]; then 2602daaffb31Sdp wxfile=$CODEMGR_WS/wx/active 2603daaffb31Sdp fi 2604daaffb31Sdp fi 2605daaffb31Sdp 2606daaffb31Sdp [[ -z $wxfile ]] && print -u2 "wx file not specified, and could not " \ 2607daaffb31Sdp "be auto-detected (check \$CODEMGR_WS)" && exit 1 2608daaffb31Sdp 2609cdf0c1d5Smjnelson if [[ ! -r $wxfile ]]; then 2610cdf0c1d5Smjnelson print -u2 "$wxfile: no such file or not readable" 2611cdf0c1d5Smjnelson usage 2612cdf0c1d5Smjnelson fi 2613cdf0c1d5Smjnelson 2614daaffb31Sdp print -u2 " File list from: wx 'active' file '$wxfile' ... \c" 2615daaffb31Sdp flist_from_wx $wxfile 2616daaffb31Sdp flist_done=1 2617daaffb31Sdp if [[ -n "$*" ]]; then 2618daaffb31Sdp shift 2619daaffb31Sdp fi 262014983201Sdpelif [[ $flist_mode == "stdin" ]]; then 262114983201Sdp print -u2 " File list from: standard input" 262214983201Sdpelif [[ $flist_mode == "file" ]]; then 262314983201Sdp print -u2 " File list from: $flist_file" 2624daaffb31Sdpfi 2625daaffb31Sdp 2626daaffb31Sdpif [[ $# -gt 0 ]]; then 262714983201Sdp print -u2 "WARNING: unused arguments: $*" 2628daaffb31Sdpfi 2629daaffb31Sdp 26302d9224a3SMark J. Nelson# 26312d9224a3SMark J. Nelson# Before we entered the DO_EVERYTHING loop, we should have already set CWS 26322d9224a3SMark J. Nelson# and CODEMGR_WS as needed. Here, we set the parent workspace. 26332d9224a3SMark J. Nelson# 26342d9224a3SMark J. Nelson 2635daaffb31Sdpif [[ $SCM_MODE == "teamware" ]]; then 26362d9224a3SMark J. Nelson 2637daaffb31Sdp # 26382d9224a3SMark J. Nelson # Teamware priorities: 2639daaffb31Sdp # 26402d9224a3SMark J. Nelson # 1) via -p command line option 2641daaffb31Sdp # 2) in the user environment 2642daaffb31Sdp # 3) in the flist 26432d9224a3SMark J. Nelson # 4) automatically based on the workspace 2644daaffb31Sdp # 2645daaffb31Sdp 2646daaffb31Sdp # 26472d9224a3SMark J. Nelson # For 1, codemgr_parent will already be set. Here's 2: 2648daaffb31Sdp # 2649daaffb31Sdp [[ -z $codemgr_parent && -n $CODEMGR_PARENT ]] && \ 2650daaffb31Sdp codemgr_parent=$CODEMGR_PARENT 2651daaffb31Sdp if [[ -n $codemgr_parent && ! -d $codemgr_parent ]]; then 2652daaffb31Sdp print -u2 "$codemgr_parent: no such directory" 26537c478bd9Sstevel@tonic-gate exit 1 26547c478bd9Sstevel@tonic-gate fi 26557c478bd9Sstevel@tonic-gate 2656daaffb31Sdp # 2657daaffb31Sdp # If we're in auto-detect mode and we haven't already gotten the file 2658daaffb31Sdp # list, then see if we can get it by probing for wx. 2659daaffb31Sdp # 266014983201Sdp if [[ -z $flist_done && $flist_mode == "auto" && -n $codemgr_ws ]]; then 266114983201Sdp if [[ ! -x $WX ]]; then 266214983201Sdp print -u2 "WARNING: wx not found!" 2663daaffb31Sdp fi 26647c478bd9Sstevel@tonic-gate 2665daaffb31Sdp # 2666daaffb31Sdp # We need to use wx list -w so that we get renamed files, etc. 2667daaffb31Sdp # but only if a wx active file exists-- otherwise wx will 2668daaffb31Sdp # hang asking us to initialize our wx information. 2669daaffb31Sdp # 267014983201Sdp if [[ -x $WX && -f $codemgr_ws/wx/active ]]; then 2671daaffb31Sdp print -u2 " File list from: 'wx list -w' ... \c" 2672daaffb31Sdp $WX list -w > $FLIST 2673daaffb31Sdp $WX comments > /tmp/$$.wx_comments 2674daaffb31Sdp wxfile=/tmp/$$.wx_comments 2675daaffb31Sdp print -u2 "done" 2676daaffb31Sdp flist_done=1 2677daaffb31Sdp fi 2678daaffb31Sdp fi 2679daaffb31Sdp 2680daaffb31Sdp # 2681daaffb31Sdp # If by hook or by crook we've gotten a file list by now (perhaps 2682daaffb31Sdp # from the command line), eval it to extract environment variables from 26832d9224a3SMark J. Nelson # it: This is method 3 for finding the parent. 2684daaffb31Sdp # 2685daaffb31Sdp if [[ -z $flist_done ]]; then 2686daaffb31Sdp flist_from_teamware 2687daaffb31Sdp fi 26882d9224a3SMark J. Nelson env_from_flist 2689daaffb31Sdp 2690daaffb31Sdp # 2691daaffb31Sdp # (4) If we still don't have a value for codemgr_parent, get it 2692daaffb31Sdp # from workspace. 2693daaffb31Sdp # 2694daaffb31Sdp [[ -z $codemgr_parent ]] && codemgr_parent=`workspace parent` 2695daaffb31Sdp if [[ ! -d $codemgr_parent ]]; then 2696daaffb31Sdp print -u2 "$CODEMGR_PARENT: no such parent workspace" 2697daaffb31Sdp exit 1 2698daaffb31Sdp fi 2699daaffb31Sdp 2700daaffb31Sdp PWS=$codemgr_parent 2701cdf0c1d5Smjnelson 2702cdf0c1d5Smjnelson [[ -n $parent_webrev ]] && RWS=$(workspace parent $CWS) 2703cdf0c1d5Smjnelson 2704cdf0c1d5Smjnelsonelif [[ $SCM_MODE == "mercurial" ]]; then 2705cdf0c1d5Smjnelson # 2706cdf0c1d5Smjnelson # Parent can either be specified with -p 2707cdf0c1d5Smjnelson # Specified with CODEMGR_PARENT in the environment 2708cdf0c1d5Smjnelson # or taken from hg's default path. 2709cdf0c1d5Smjnelson # 2710cdf0c1d5Smjnelson 2711cdf0c1d5Smjnelson if [[ -z $codemgr_parent && -n $CODEMGR_PARENT ]]; then 2712cdf0c1d5Smjnelson codemgr_parent=$CODEMGR_PARENT 2713cdf0c1d5Smjnelson fi 2714cdf0c1d5Smjnelson 2715cdf0c1d5Smjnelson if [[ -z $codemgr_parent ]]; then 2716cdf0c1d5Smjnelson codemgr_parent=`hg path -R $codemgr_ws default 2>/dev/null` 2717cdf0c1d5Smjnelson fi 2718cdf0c1d5Smjnelson 2719cdf0c1d5Smjnelson PWS=$codemgr_parent 2720cdf0c1d5Smjnelson 2721cdf0c1d5Smjnelson # 2722cdf0c1d5Smjnelson # If the parent is a webrev, we want to do some things against 2723cdf0c1d5Smjnelson # the natural workspace parent (file list, comments, etc) 2724cdf0c1d5Smjnelson # 2725cdf0c1d5Smjnelson if [[ -n $parent_webrev ]]; then 2726cdf0c1d5Smjnelson real_parent=$(hg path -R $codemgr_ws default 2>/dev/null) 2727cdf0c1d5Smjnelson else 2728cdf0c1d5Smjnelson real_parent=$PWS 2729cdf0c1d5Smjnelson fi 2730cdf0c1d5Smjnelson 2731cdf0c1d5Smjnelson # 2732cdf0c1d5Smjnelson # If hg-active exists, then we run it. In the case of no explicit 2733cdf0c1d5Smjnelson # flist given, we'll use it for our comments. In the case of an 2734cdf0c1d5Smjnelson # explicit flist given we'll try to use it for comments for any 2735cdf0c1d5Smjnelson # files mentioned in the flist. 2736cdf0c1d5Smjnelson # 2737cdf0c1d5Smjnelson if [[ -z $flist_done ]]; then 2738cdf0c1d5Smjnelson flist_from_mercurial $CWS $real_parent 2739cdf0c1d5Smjnelson flist_done=1 2740cdf0c1d5Smjnelson fi 2741cdf0c1d5Smjnelson 2742cdf0c1d5Smjnelson # 2743cdf0c1d5Smjnelson # If we have a file list now, pull out any variables set 2744cdf0c1d5Smjnelson # therein. We do this now (rather than when we possibly use 2745cdf0c1d5Smjnelson # hg-active to find comments) to avoid stomping specifications 2746cdf0c1d5Smjnelson # in the user-specified flist. 2747cdf0c1d5Smjnelson # 2748cdf0c1d5Smjnelson if [[ -n $flist_done ]]; then 2749cdf0c1d5Smjnelson env_from_flist 2750cdf0c1d5Smjnelson fi 2751cdf0c1d5Smjnelson 2752cdf0c1d5Smjnelson # 2753cdf0c1d5Smjnelson # Only call hg-active if we don't have a wx formatted file already 2754cdf0c1d5Smjnelson # 2755cdf0c1d5Smjnelson if [[ -x $HG_ACTIVE && -z $wxfile ]]; then 2756cdf0c1d5Smjnelson print " Comments from: hg-active -p $real_parent ...\c" 2757cdf0c1d5Smjnelson hg_active_wxfile $CWS $real_parent 2758cdf0c1d5Smjnelson print " Done." 2759cdf0c1d5Smjnelson fi 2760cdf0c1d5Smjnelson 2761cdf0c1d5Smjnelson # 2762cdf0c1d5Smjnelson # At this point we must have a wx flist either from hg-active, 2763cdf0c1d5Smjnelson # or in general. Use it to try and find our parent revision, 2764cdf0c1d5Smjnelson # if we don't have one. 2765cdf0c1d5Smjnelson # 2766cdf0c1d5Smjnelson if [[ -z $HG_PARENT ]]; then 2767b0088928SVladimir Kotal eval `$SED -e "s/#.*$//" $wxfile | $GREP HG_PARENT=` 2768cdf0c1d5Smjnelson fi 2769cdf0c1d5Smjnelson 2770cdf0c1d5Smjnelson # 2771cdf0c1d5Smjnelson # If we still don't have a parent, we must have been given a 2772cdf0c1d5Smjnelson # wx-style active list with no HG_PARENT specification, run 2773cdf0c1d5Smjnelson # hg-active and pull an HG_PARENT out of it, ignore the rest. 2774cdf0c1d5Smjnelson # 2775cdf0c1d5Smjnelson if [[ -z $HG_PARENT && -x $HG_ACTIVE ]]; then 2776cdf0c1d5Smjnelson $HG_ACTIVE -w $codemgr_ws -p $real_parent | \ 2777b0088928SVladimir Kotal eval `$SED -e "s/#.*$//" | $GREP HG_PARENT=` 2778cdf0c1d5Smjnelson elif [[ -z $HG_PARENT ]]; then 2779cdf0c1d5Smjnelson print -u2 "Error: Cannot discover parent revision" 2780cdf0c1d5Smjnelson exit 1 2781cdf0c1d5Smjnelson fi 2782*8bcea973SRichard Lowe 2783*8bcea973SRichard Lowe pnode=$(trim_digest $HG_PARENT) 2784*8bcea973SRichard Lowe PRETTY_PWS="${PWS} (at ${pnode})" 2785*8bcea973SRichard Lowe cnode=$(hg parent -R $codemgr_ws --template '{node|short}' \ 2786*8bcea973SRichard Lowe 2>/dev/null) 2787*8bcea973SRichard Lowe PRETTY_CWS="${CWS} (at ${cnode})"} 2788*8bcea973SRichard Loweelif [[ $SCM_MODE == "git" ]]; then 2789*8bcea973SRichard Lowe # 2790*8bcea973SRichard Lowe # Parent can either be specified with -p, or specified with 2791*8bcea973SRichard Lowe # CODEMGR_PARENT in the environment. 2792*8bcea973SRichard Lowe # 2793*8bcea973SRichard Lowe 2794*8bcea973SRichard Lowe if [[ -z $codemgr_parent && -n $CODEMGR_PARENT ]]; then 2795*8bcea973SRichard Lowe codemgr_parent=$CODEMGR_PARENT 2796*8bcea973SRichard Lowe fi 2797*8bcea973SRichard Lowe 2798*8bcea973SRichard Lowe # Try to figure out the parent based on the branch the current 2799*8bcea973SRichard Lowe # branch is tracking, if we fail, use origin/master 2800*8bcea973SRichard Lowe this_branch=$($GIT branch | nawk '$1 == "*" { print $2 }') 2801*8bcea973SRichard Lowe par_branch="origin/master" 2802*8bcea973SRichard Lowe 2803*8bcea973SRichard Lowe # If we're not on a branch there's nothing we can do 2804*8bcea973SRichard Lowe if [[ $this_branch != "(no branch)" ]]; then 2805*8bcea973SRichard Lowe $GIT for-each-ref \ 2806*8bcea973SRichard Lowe --format='%(refname:short) %(upstream:short)' refs/heads/ | \ 2807*8bcea973SRichard Lowe while read local remote; do \ 2808*8bcea973SRichard Lowe [[ "$local" == "$this_branch" ]] && par_branch="$remote"; \ 2809*8bcea973SRichard Lowe done 2810*8bcea973SRichard Lowe fi 2811*8bcea973SRichard Lowe 2812*8bcea973SRichard Lowe if [[ -z $codemgr_parent ]]; then 2813*8bcea973SRichard Lowe codemgr_parent=$par_branch 2814*8bcea973SRichard Lowe fi 2815*8bcea973SRichard Lowe PWS=$codemgr_parent 2816*8bcea973SRichard Lowe 2817*8bcea973SRichard Lowe # 2818*8bcea973SRichard Lowe # If the parent is a webrev, we want to do some things against 2819*8bcea973SRichard Lowe # the natural workspace parent (file list, comments, etc) 2820*8bcea973SRichard Lowe # 2821*8bcea973SRichard Lowe if [[ -n $parent_webrev ]]; then 2822*8bcea973SRichard Lowe real_parent=$par_branch 2823*8bcea973SRichard Lowe else 2824*8bcea973SRichard Lowe real_parent=$PWS 2825*8bcea973SRichard Lowe fi 2826*8bcea973SRichard Lowe 2827*8bcea973SRichard Lowe if [[ -z $flist_done ]]; then 2828*8bcea973SRichard Lowe flist_from_git "$CWS" "$real_parent" 2829*8bcea973SRichard Lowe flist_done=1 2830*8bcea973SRichard Lowe fi 2831*8bcea973SRichard Lowe 2832*8bcea973SRichard Lowe # 2833*8bcea973SRichard Lowe # If we have a file list now, pull out any variables set 2834*8bcea973SRichard Lowe # therein. 2835*8bcea973SRichard Lowe # 2836*8bcea973SRichard Lowe if [[ -n $flist_done ]]; then 2837*8bcea973SRichard Lowe env_from_flist 2838*8bcea973SRichard Lowe fi 2839*8bcea973SRichard Lowe 2840*8bcea973SRichard Lowe # 2841*8bcea973SRichard Lowe # If we don't have a wx-format file list, build one we can pull change 2842*8bcea973SRichard Lowe # comments from. 2843*8bcea973SRichard Lowe # 2844*8bcea973SRichard Lowe if [[ -z $wxfile ]]; then 2845*8bcea973SRichard Lowe print " Comments from: git...\c" 2846*8bcea973SRichard Lowe git_wxfile "$CWS" "$real_parent" 2847*8bcea973SRichard Lowe print " Done." 2848*8bcea973SRichard Lowe fi 2849*8bcea973SRichard Lowe 2850*8bcea973SRichard Lowe if [[ -z $GIT_PARENT ]]; then 2851*8bcea973SRichard Lowe GIT_PARENT=$($GIT merge-base "$real_parent" HEAD) 2852*8bcea973SRichard Lowe fi 2853*8bcea973SRichard Lowe if [[ -z $GIT_PARENT ]]; then 2854*8bcea973SRichard Lowe print -u2 "Error: Cannot discover parent revision" 2855*8bcea973SRichard Lowe exit 1 2856*8bcea973SRichard Lowe fi 2857*8bcea973SRichard Lowe 2858*8bcea973SRichard Lowe pnode=$(trim_digest $GIT_PARENT) 2859*8bcea973SRichard Lowe 2860*8bcea973SRichard Lowe if [[ $real_parent == */* ]]; then 2861*8bcea973SRichard Lowe origin=$(echo $real_parent | cut -d/ -f1) 2862*8bcea973SRichard Lowe origin=$($GIT remote -v | \ 2863*8bcea973SRichard Lowe $AWK '$1 == "'$origin'" { print $2; exit }') 2864*8bcea973SRichard Lowe PRETTY_PWS="${PWS} (${origin} at ${pnode})" 2865*8bcea973SRichard Lowe else 2866*8bcea973SRichard Lowe PRETTY_PWS="${PWS} (at ${pnode})" 2867*8bcea973SRichard Lowe fi 2868*8bcea973SRichard Lowe 2869*8bcea973SRichard Lowe cnode=$($GIT --git-dir=${codemgr_ws}/.git rev-parse --short=12 HEAD \ 2870*8bcea973SRichard Lowe 2>/dev/null) 2871*8bcea973SRichard Lowe PRETTY_CWS="${CWS} (at ${cnode})" 2872cdf0c1d5Smjnelsonelif [[ $SCM_MODE == "subversion" ]]; then 2873cdf0c1d5Smjnelson 2874cdf0c1d5Smjnelson # 2875cdf0c1d5Smjnelson # We only will have a real parent workspace in the case one 2876cdf0c1d5Smjnelson # was specified (be it an older webrev, or another checkout). 2877cdf0c1d5Smjnelson # 2878cdf0c1d5Smjnelson [[ -n $codemgr_parent ]] && PWS=$codemgr_parent 2879cdf0c1d5Smjnelson 2880cdf0c1d5Smjnelson if [[ -z $flist_done && $flist_mode == "auto" ]]; then 2881cdf0c1d5Smjnelson flist_from_subversion $CWS $OLDPWD 2882cdf0c1d5Smjnelson fi 2883cdf0c1d5Smjnelsonelse 2884cdf0c1d5Smjnelson if [[ $SCM_MODE == "unknown" ]]; then 2885cdf0c1d5Smjnelson print -u2 " Unknown type of SCM in use" 2886cdf0c1d5Smjnelson else 2887cdf0c1d5Smjnelson print -u2 " Unsupported SCM in use: $SCM_MODE" 2888cdf0c1d5Smjnelson fi 2889cdf0c1d5Smjnelson 2890cdf0c1d5Smjnelson env_from_flist 2891cdf0c1d5Smjnelson 2892cdf0c1d5Smjnelson if [[ -z $CODEMGR_WS ]]; then 2893cdf0c1d5Smjnelson print -u2 "SCM not detected/supported and CODEMGR_WS not specified" 2894cdf0c1d5Smjnelson exit 1 2895cdf0c1d5Smjnelson fi 2896cdf0c1d5Smjnelson 2897cdf0c1d5Smjnelson if [[ -z $CODEMGR_PARENT ]]; then 2898cdf0c1d5Smjnelson print -u2 "SCM not detected/supported and CODEMGR_PARENT not specified" 2899cdf0c1d5Smjnelson exit 1 2900cdf0c1d5Smjnelson fi 2901cdf0c1d5Smjnelson 2902cdf0c1d5Smjnelson CWS=$CODEMGR_WS 2903cdf0c1d5Smjnelson PWS=$CODEMGR_PARENT 2904daaffb31Sdpfi 2905daaffb31Sdp 2906daaffb31Sdp# 2907daaffb31Sdp# If the user didn't specify a -i option, check to see if there is a 2908daaffb31Sdp# webrev-info file in the workspace directory. 2909daaffb31Sdp# 2910daaffb31Sdpif [[ -z $iflag && -r "$CWS/webrev-info" ]]; then 2911daaffb31Sdp iflag=1 2912daaffb31Sdp INCLUDE_FILE="$CWS/webrev-info" 2913daaffb31Sdpfi 2914daaffb31Sdp 2915daaffb31Sdpif [[ -n $iflag ]]; then 2916daaffb31Sdp if [[ ! -r $INCLUDE_FILE ]]; then 2917daaffb31Sdp print -u2 "include file '$INCLUDE_FILE' does not exist or is" \ 2918daaffb31Sdp "not readable." 2919daaffb31Sdp exit 1 2920daaffb31Sdp else 2921daaffb31Sdp # 2922daaffb31Sdp # $INCLUDE_FILE may be a relative path, and the script alters 2923daaffb31Sdp # PWD, so we just stash a copy in /tmp. 2924daaffb31Sdp # 2925daaffb31Sdp cp $INCLUDE_FILE /tmp/$$.include 2926daaffb31Sdp fi 2927daaffb31Sdpfi 2928daaffb31Sdp 29290fd2682eSMark J. Nelson# DO_EVERYTHING: break point 29300fd2682eSMark J. Nelsonif [[ -n $Nflag ]]; then 29310fd2682eSMark J. Nelson break 29320fd2682eSMark J. Nelsonfi 29330fd2682eSMark J. Nelson 29340fd2682eSMark J. Nelsontypeset -A itsinfo 29350fd2682eSMark J. Nelsontypeset -r its_sed_script=/tmp/$$.its_sed 29360fd2682eSMark J. Nelsonvalid_prefixes= 29370fd2682eSMark J. Nelsonif [[ -z $nflag ]]; then 2938*8bcea973SRichard Lowe DEFREGFILE="$(/bin/dirname "$(whence $0)")/../etc/its.reg" 29390fd2682eSMark J. Nelson if [[ -n $Iflag ]]; then 29400fd2682eSMark J. Nelson REGFILE=$ITSREG 29410fd2682eSMark J. Nelson elif [[ -r $HOME/.its.reg ]]; then 29420fd2682eSMark J. Nelson REGFILE=$HOME/.its.reg 29430fd2682eSMark J. Nelson else 29440fd2682eSMark J. Nelson REGFILE=$DEFREGFILE 29450fd2682eSMark J. Nelson fi 29460fd2682eSMark J. Nelson if [[ ! -r $REGFILE ]]; then 29470fd2682eSMark J. Nelson print "ERROR: Unable to read database registry file $REGFILE" 29480fd2682eSMark J. Nelson exit 1 29490fd2682eSMark J. Nelson elif [[ $REGFILE != $DEFREGFILE ]]; then 29500fd2682eSMark J. Nelson print " its.reg from: $REGFILE" 29510fd2682eSMark J. Nelson fi 29520fd2682eSMark J. Nelson 29530fd2682eSMark J. Nelson $SED -e '/^#/d' -e '/^[ ]*$/d' $REGFILE | while read LINE; do 29540fd2682eSMark J. Nelson 29550fd2682eSMark J. Nelson name=${LINE%%=*} 29560fd2682eSMark J. Nelson value="${LINE#*=}" 29570fd2682eSMark J. Nelson 29580fd2682eSMark J. Nelson if [[ $name == PREFIX ]]; then 29590fd2682eSMark J. Nelson p=${value} 29600fd2682eSMark J. Nelson valid_prefixes="${p} ${valid_prefixes}" 29610fd2682eSMark J. Nelson else 29620fd2682eSMark J. Nelson itsinfo["${p}_${name}"]="${value}" 29630fd2682eSMark J. Nelson fi 29640fd2682eSMark J. Nelson done 29650fd2682eSMark J. Nelson 29660fd2682eSMark J. Nelson 2967*8bcea973SRichard Lowe DEFCONFFILE="$(/bin/dirname "$(whence $0)")/../etc/its.conf" 29680fd2682eSMark J. Nelson CONFFILES=$DEFCONFFILE 29690fd2682eSMark J. Nelson if [[ -r $HOME/.its.conf ]]; then 29700fd2682eSMark J. Nelson CONFFILES="${CONFFILES} $HOME/.its.conf" 29710fd2682eSMark J. Nelson fi 29720fd2682eSMark J. Nelson if [[ -n $Cflag ]]; then 29730fd2682eSMark J. Nelson CONFFILES="${CONFFILES} ${ITSCONF}" 29740fd2682eSMark J. Nelson fi 29750fd2682eSMark J. Nelson its_domain= 29760fd2682eSMark J. Nelson its_priority= 29770fd2682eSMark J. Nelson for cf in ${CONFFILES}; do 29780fd2682eSMark J. Nelson if [[ ! -r $cf ]]; then 29790fd2682eSMark J. Nelson print "ERROR: Unable to read database configuration file $cf" 29800fd2682eSMark J. Nelson exit 1 29810fd2682eSMark J. Nelson elif [[ $cf != $DEFCONFFILE ]]; then 29820fd2682eSMark J. Nelson print " its.conf: reading $cf" 29830fd2682eSMark J. Nelson fi 29840fd2682eSMark J. Nelson $SED -e '/^#/d' -e '/^[ ]*$/d' $cf | while read LINE; do 29850fd2682eSMark J. Nelson eval "${LINE}" 29860fd2682eSMark J. Nelson done 29870fd2682eSMark J. Nelson done 29880fd2682eSMark J. Nelson 29890fd2682eSMark J. Nelson # 29900fd2682eSMark J. Nelson # If an information tracking system is explicitly identified by prefix, 29910fd2682eSMark J. Nelson # we want to disregard the specified priorities and resolve it accordingly. 29920fd2682eSMark J. Nelson # 29930fd2682eSMark J. Nelson # To that end, we'll build a sed script to do each valid prefix in turn. 29940fd2682eSMark J. Nelson # 29950fd2682eSMark J. Nelson for p in ${valid_prefixes}; do 29960fd2682eSMark J. Nelson # 29970fd2682eSMark J. Nelson # When an informational URL was provided, translate it to a 29980fd2682eSMark J. Nelson # hyperlink. When omitted, simply use the prefix text. 29990fd2682eSMark J. Nelson # 30000fd2682eSMark J. Nelson if [[ -z ${itsinfo["${p}_INFO"]} ]]; then 30010fd2682eSMark J. Nelson itsinfo["${p}_INFO"]=${p} 30020fd2682eSMark J. Nelson else 30030fd2682eSMark J. Nelson itsinfo["${p}_INFO"]="<a href=\\\"${itsinfo["${p}_INFO"]}\\\">${p}</a>" 30040fd2682eSMark J. Nelson fi 30050fd2682eSMark J. Nelson 30060fd2682eSMark J. Nelson # 30070fd2682eSMark J. Nelson # Assume that, for this invocation of webrev, all references 30080fd2682eSMark J. Nelson # to this information tracking system should resolve through 30090fd2682eSMark J. Nelson # the same URL. 30100fd2682eSMark J. Nelson # 30110fd2682eSMark J. Nelson # If the caller specified -O, then always use EXTERNAL_URL. 30120fd2682eSMark J. Nelson # 30130fd2682eSMark J. Nelson # Otherwise, look in the list of domains for a matching 30140fd2682eSMark J. Nelson # INTERNAL_URL. 30150fd2682eSMark J. Nelson # 30160fd2682eSMark J. Nelson [[ -z $Oflag ]] && for d in ${its_domain}; do 30170fd2682eSMark J. Nelson if [[ -n ${itsinfo["${p}_INTERNAL_URL_${d}"]} ]]; then 30180fd2682eSMark J. Nelson itsinfo["${p}_URL"]="${itsinfo[${p}_INTERNAL_URL_${d}]}" 30190fd2682eSMark J. Nelson break 30200fd2682eSMark J. Nelson fi 30210fd2682eSMark J. Nelson done 30220fd2682eSMark J. Nelson if [[ -z ${itsinfo["${p}_URL"]} ]]; then 30230fd2682eSMark J. Nelson itsinfo["${p}_URL"]="${itsinfo[${p}_EXTERNAL_URL]}" 30240fd2682eSMark J. Nelson fi 30250fd2682eSMark J. Nelson 30260fd2682eSMark J. Nelson # 30270fd2682eSMark J. Nelson # Turn the destination URL into a hyperlink 30280fd2682eSMark J. Nelson # 30290fd2682eSMark J. Nelson itsinfo["${p}_URL"]="<a href=\\\"${itsinfo[${p}_URL]}\\\">&</a>" 30300fd2682eSMark J. Nelson 30312f54b716SRichard Lowe # The character class below contains a literal tab 30322f54b716SRichard Lowe print "/^${p}[: ]/ { 30330fd2682eSMark J. Nelson s;${itsinfo[${p}_REGEX]};${itsinfo[${p}_URL]};g 30340fd2682eSMark J. Nelson s;^${p};${itsinfo[${p}_INFO]}; 30350fd2682eSMark J. Nelson }" >> ${its_sed_script} 30360fd2682eSMark J. Nelson done 30370fd2682eSMark J. Nelson 30380fd2682eSMark J. Nelson # 30390fd2682eSMark J. Nelson # The previous loop took care of explicit specification. Now use 30400fd2682eSMark J. Nelson # the configured priorities to attempt implicit translations. 30410fd2682eSMark J. Nelson # 30420fd2682eSMark J. Nelson for p in ${its_priority}; do 30430fd2682eSMark J. Nelson print "/^${itsinfo[${p}_REGEX]}[ ]/ { 30442f54b716SRichard Lowe s;^${itsinfo[${p}_REGEX]};${itsinfo[${p}_URL]};g 30450fd2682eSMark J. Nelson }" >> ${its_sed_script} 30460fd2682eSMark J. Nelson done 30470fd2682eSMark J. Nelsonfi 30480fd2682eSMark J. Nelson 30490fd2682eSMark J. Nelson# 30500fd2682eSMark J. Nelson# Search for DO_EVERYTHING above for matching "for" statement 30510fd2682eSMark J. Nelson# and explanation of this terminator. 30520fd2682eSMark J. Nelson# 30530fd2682eSMark J. Nelsondone 30540fd2682eSMark J. Nelson 3055daaffb31Sdp# 3056daaffb31Sdp# Output directory. 3057daaffb31Sdp# 3058daaffb31SdpWDIR=${WDIR:-$CWS/webrev} 3059daaffb31Sdp 3060daaffb31Sdp# 306102d26c39SVladimir Kotal# Name of the webrev, derived from the workspace name or output directory; 306202d26c39SVladimir Kotal# in the future this could potentially be an option. 3063daaffb31Sdp# 306402d26c39SVladimir Kotalif [[ -n $oflag ]]; then 306502d26c39SVladimir Kotal WNAME=${WDIR##*/} 306602d26c39SVladimir Kotalelse 3067daaffb31Sdp WNAME=${CWS##*/} 306802d26c39SVladimir Kotalfi 306902d26c39SVladimir Kotal 3070ba44d8a2SVladimir Kotal# Make sure remote target is well formed for remote upload/delete. 3071ba44d8a2SVladimir Kotalif [[ -n $Dflag || -n $Uflag ]]; then 3072b0088928SVladimir Kotal # 3073ba44d8a2SVladimir Kotal # If remote target is not specified, build it from scratch using 3074ba44d8a2SVladimir Kotal # the default values. 3075b0088928SVladimir Kotal # 3076ba44d8a2SVladimir Kotal if [[ -z $tflag ]]; then 3077ba44d8a2SVladimir Kotal remote_target=${DEFAULT_REMOTE_HOST}:${WNAME} 3078ba44d8a2SVladimir Kotal else 3079b0088928SVladimir Kotal # 3080b0088928SVladimir Kotal # Check upload target prefix first. 3081b0088928SVladimir Kotal # 3082b0088928SVladimir Kotal if [[ "${remote_target}" != ${rsync_prefix}* && 3083b0088928SVladimir Kotal "${remote_target}" != ${ssh_prefix}* ]]; then 3084b0088928SVladimir Kotal print "ERROR: invalid prefix of upload URI" \ 3085b0088928SVladimir Kotal "($remote_target)" 3086b0088928SVladimir Kotal exit 1 3087b0088928SVladimir Kotal fi 3088b0088928SVladimir Kotal # 3089ba44d8a2SVladimir Kotal # If destination specification is not in the form of 3090ba44d8a2SVladimir Kotal # host_spec:remote_dir then assume it is just remote hostname 3091ba44d8a2SVladimir Kotal # and append a colon and destination directory formed from 3092ba44d8a2SVladimir Kotal # local webrev directory name. 3093b0088928SVladimir Kotal # 3094b0088928SVladimir Kotal typeset target_no_prefix=${remote_target##*://} 3095b0088928SVladimir Kotal if [[ ${target_no_prefix} == *:* ]]; then 3096ba44d8a2SVladimir Kotal if [[ "${remote_target}" == *: ]]; then 3097b0088928SVladimir Kotal remote_target=${remote_target}${WNAME} 3098ba44d8a2SVladimir Kotal fi 3099b0088928SVladimir Kotal else 3100b0088928SVladimir Kotal if [[ ${target_no_prefix} == */* ]]; then 3101b0088928SVladimir Kotal print "ERROR: badly formed upload URI" \ 3102b0088928SVladimir Kotal "($remote_target)" 3103b0088928SVladimir Kotal exit 1 3104b0088928SVladimir Kotal else 3105b0088928SVladimir Kotal remote_target=${remote_target}:${WNAME} 3106ba44d8a2SVladimir Kotal fi 3107ba44d8a2SVladimir Kotal fi 3108ba44d8a2SVladimir Kotal fi 3109ba44d8a2SVladimir Kotal 3110b0088928SVladimir Kotal # 3111b0088928SVladimir Kotal # Strip trailing slash. Each upload method will deal with directory 3112b0088928SVladimir Kotal # specification separately. 3113b0088928SVladimir Kotal # 3114b0088928SVladimir Kotal remote_target=${remote_target%/} 3115b0088928SVladimir Kotalfi 3116b0088928SVladimir Kotal 3117b0088928SVladimir Kotal# 3118ba44d8a2SVladimir Kotal# Option -D by itself (option -U not present) implies no webrev generation. 3119b0088928SVladimir Kotal# 3120ba44d8a2SVladimir Kotalif [[ -z $Uflag && -n $Dflag ]]; then 3121b0088928SVladimir Kotal delete_webrev 1 1 3122ba44d8a2SVladimir Kotal exit $? 3123ba44d8a2SVladimir Kotalfi 3124ba44d8a2SVladimir Kotal 3125b0088928SVladimir Kotal# 3126ba44d8a2SVladimir Kotal# Do not generate the webrev, just upload it or delete it. 3127b0088928SVladimir Kotal# 3128ba44d8a2SVladimir Kotalif [[ -n $nflag ]]; then 3129ba44d8a2SVladimir Kotal if [[ -n $Dflag ]]; then 3130b0088928SVladimir Kotal delete_webrev 1 1 3131ba44d8a2SVladimir Kotal (( $? == 0 )) || exit $? 3132ba44d8a2SVladimir Kotal fi 3133ba44d8a2SVladimir Kotal if [[ -n $Uflag ]]; then 313402d26c39SVladimir Kotal upload_webrev 313502d26c39SVladimir Kotal exit $? 313602d26c39SVladimir Kotal fi 3137ba44d8a2SVladimir Kotalfi 3138daaffb31Sdp 3139e0e0293aSjmcpif [ "${WDIR%%/*}" ]; then 31407c478bd9Sstevel@tonic-gate WDIR=$PWD/$WDIR 31417c478bd9Sstevel@tonic-gatefi 3142daaffb31Sdp 3143daaffb31Sdpif [[ ! -d $WDIR ]]; then 3144daaffb31Sdp mkdir -p $WDIR 3145ba44d8a2SVladimir Kotal (( $? != 0 )) && exit 1 31467c478bd9Sstevel@tonic-gatefi 31477c478bd9Sstevel@tonic-gate 3148daaffb31Sdp# 3149daaffb31Sdp# Summarize what we're going to do. 3150daaffb31Sdp# 3151*8bcea973SRichard Loweprint " Workspace: ${PRETTY_CWS:-$CWS}" 3152daaffb31Sdpif [[ -n $parent_webrev ]]; then 3153daaffb31Sdp print "Compare against: webrev at $parent_webrev" 3154daaffb31Sdpelse 3155*8bcea973SRichard Lowe print "Compare against: ${PRETTY_PWS:-$PWS}" 3156cdf0c1d5Smjnelsonfi 3157daaffb31Sdp 3158daaffb31Sdp[[ -n $INCLUDE_FILE ]] && print " Including: $INCLUDE_FILE" 3159daaffb31Sdpprint " Output to: $WDIR" 3160daaffb31Sdp 3161daaffb31Sdp# 31627c478bd9Sstevel@tonic-gate# Save the file list in the webrev dir 3163daaffb31Sdp# 3164daaffb31Sdp[[ ! $FLIST -ef $WDIR/file.list ]] && cp $FLIST $WDIR/file.list 31657c478bd9Sstevel@tonic-gate 3166daaffb31Sdprm -f $WDIR/$WNAME.patch 3167daaffb31Sdprm -f $WDIR/$WNAME.ps 3168daaffb31Sdprm -f $WDIR/$WNAME.pdf 31697c478bd9Sstevel@tonic-gate 3170daaffb31Sdptouch $WDIR/$WNAME.patch 31717c478bd9Sstevel@tonic-gate 3172daaffb31Sdpprint " Output Files:" 3173daaffb31Sdp 3174daaffb31Sdp# 3175daaffb31Sdp# Clean up the file list: Remove comments, blank lines and env variables. 3176daaffb31Sdp# 3177b0088928SVladimir Kotal$SED -e "s/#.*$//" -e "/=/d" -e "/^[ ]*$/d" $FLIST > /tmp/$$.flist.clean 3178daaffb31SdpFLIST=/tmp/$$.flist.clean 3179daaffb31Sdp 3180daaffb31Sdp# 3181cdf0c1d5Smjnelson# For Mercurial, create a cache of manifest entries. 3182cdf0c1d5Smjnelson# 3183cdf0c1d5Smjnelsonif [[ $SCM_MODE == "mercurial" ]]; then 3184cdf0c1d5Smjnelson # 3185cdf0c1d5Smjnelson # Transform the FLIST into a temporary sed script that matches 3186cdf0c1d5Smjnelson # relevant entries in the Mercurial manifest as follows: 3187cdf0c1d5Smjnelson # 1) The script will be used against the parent revision manifest, 3188cdf0c1d5Smjnelson # so for FLIST lines that have two filenames (a renamed file) 3189cdf0c1d5Smjnelson # keep only the old name. 3190cdf0c1d5Smjnelson # 2) Escape all forward slashes the filename. 3191cdf0c1d5Smjnelson # 3) Change the filename into another sed command that matches 3192cdf0c1d5Smjnelson # that file in "hg manifest -v" output: start of line, three 3193cdf0c1d5Smjnelson # octal digits for file permissions, space, a file type flag 3194cdf0c1d5Smjnelson # character, space, the filename, end of line. 3195e6ccc173SEdward Pilatowicz # 4) Eliminate any duplicate entries. (This can occur if a 3196e6ccc173SEdward Pilatowicz # file has been used as the source of an hg cp and it's 3197e6ccc173SEdward Pilatowicz # also been modified in the same changeset.) 3198cdf0c1d5Smjnelson # 3199cdf0c1d5Smjnelson SEDFILE=/tmp/$$.manifest.sed 3200b0088928SVladimir Kotal $SED ' 3201cdf0c1d5Smjnelson s#^[^ ]* ## 3202cdf0c1d5Smjnelson s#/#\\\/#g 3203cdf0c1d5Smjnelson s#^.*$#/^... . &$/p# 3204e6ccc173SEdward Pilatowicz ' < $FLIST | $SORT -u > $SEDFILE 3205cdf0c1d5Smjnelson 3206cdf0c1d5Smjnelson # 3207cdf0c1d5Smjnelson # Apply the generated script to the output of "hg manifest -v" 3208cdf0c1d5Smjnelson # to get the relevant subset for this webrev. 3209cdf0c1d5Smjnelson # 3210cdf0c1d5Smjnelson HG_PARENT_MANIFEST=/tmp/$$.manifest 3211cdf0c1d5Smjnelson hg -R $CWS manifest -v -r $HG_PARENT | 3212b0088928SVladimir Kotal $SED -n -f $SEDFILE > $HG_PARENT_MANIFEST 3213cdf0c1d5Smjnelsonfi 3214cdf0c1d5Smjnelson 3215cdf0c1d5Smjnelson# 3216daaffb31Sdp# First pass through the files: generate the per-file webrev HTML-files. 3217daaffb31Sdp# 3218daaffb31Sdpcat $FLIST | while read LINE 32197c478bd9Sstevel@tonic-gatedo 32207c478bd9Sstevel@tonic-gate set - $LINE 32217c478bd9Sstevel@tonic-gate P=$1 32227c478bd9Sstevel@tonic-gate 3223daaffb31Sdp # 3224daaffb31Sdp # Normally, each line in the file list is just a pathname of a 3225daaffb31Sdp # file that has been modified or created in the child. A file 3226daaffb31Sdp # that is renamed in the child workspace has two names on the 3227daaffb31Sdp # line: new name followed by the old name. 3228daaffb31Sdp # 3229daaffb31Sdp oldname="" 3230daaffb31Sdp oldpath="" 3231daaffb31Sdp rename= 3232daaffb31Sdp if [[ $# -eq 2 ]]; then 32337c478bd9Sstevel@tonic-gate PP=$2 # old filename 3234e6ccc173SEdward Pilatowicz if [[ -f $PP ]]; then 3235e6ccc173SEdward Pilatowicz oldname=" (copied from $PP)" 3236e6ccc173SEdward Pilatowicz else 3237e6ccc173SEdward Pilatowicz oldname=" (renamed from $PP)" 3238e6ccc173SEdward Pilatowicz fi 3239daaffb31Sdp oldpath="$PP" 3240daaffb31Sdp rename=1 32417c478bd9Sstevel@tonic-gate PDIR=${PP%/*} 3242daaffb31Sdp if [[ $PDIR == $PP ]]; then 32437c478bd9Sstevel@tonic-gate PDIR="." # File at root of workspace 32447c478bd9Sstevel@tonic-gate fi 32457c478bd9Sstevel@tonic-gate 32467c478bd9Sstevel@tonic-gate PF=${PP##*/} 32477c478bd9Sstevel@tonic-gate 32487c478bd9Sstevel@tonic-gate DIR=${P%/*} 3249daaffb31Sdp if [[ $DIR == $P ]]; then 32507c478bd9Sstevel@tonic-gate DIR="." # File at root of workspace 32517c478bd9Sstevel@tonic-gate fi 32527c478bd9Sstevel@tonic-gate 32537c478bd9Sstevel@tonic-gate F=${P##*/} 3254daaffb31Sdp 32557c478bd9Sstevel@tonic-gate else 32567c478bd9Sstevel@tonic-gate DIR=${P%/*} 3257daaffb31Sdp if [[ "$DIR" == "$P" ]]; then 32587c478bd9Sstevel@tonic-gate DIR="." # File at root of workspace 32597c478bd9Sstevel@tonic-gate fi 32607c478bd9Sstevel@tonic-gate 32617c478bd9Sstevel@tonic-gate F=${P##*/} 32627c478bd9Sstevel@tonic-gate 32637c478bd9Sstevel@tonic-gate PP=$P 32647c478bd9Sstevel@tonic-gate PDIR=$DIR 32657c478bd9Sstevel@tonic-gate PF=$F 32667c478bd9Sstevel@tonic-gate fi 32677c478bd9Sstevel@tonic-gate 3268daaffb31Sdp COMM=`getcomments html $P $PP` 32697c478bd9Sstevel@tonic-gate 3270daaffb31Sdp print "\t$P$oldname\n\t\t\c" 32717c478bd9Sstevel@tonic-gate 32727c478bd9Sstevel@tonic-gate # Make the webrev mirror directory if necessary 32737c478bd9Sstevel@tonic-gate mkdir -p $WDIR/$DIR 32747c478bd9Sstevel@tonic-gate 3275daaffb31Sdp # 3276cdf0c1d5Smjnelson # We stash old and new files into parallel directories in $WDIR 3277daaffb31Sdp # and do our diffs there. This makes it possible to generate 3278daaffb31Sdp # clean looking diffs which don't have absolute paths present. 3279daaffb31Sdp # 3280daaffb31Sdp 3281cdf0c1d5Smjnelson build_old_new "$WDIR" "$PWS" "$PDIR" "$PF" "$CWS" "$DIR" "$F" || \ 32827c478bd9Sstevel@tonic-gate continue 32837c478bd9Sstevel@tonic-gate 3284cdf0c1d5Smjnelson # 3285cdf0c1d5Smjnelson # Keep the old PWD around, so we can safely switch back after 3286cdf0c1d5Smjnelson # diff generation, such that build_old_new runs in a 3287cdf0c1d5Smjnelson # consistent environment. 3288cdf0c1d5Smjnelson # 3289cdf0c1d5Smjnelson OWD=$PWD 3290daaffb31Sdp cd $WDIR/raw_files 3291daaffb31Sdp ofile=old/$PDIR/$PF 3292daaffb31Sdp nfile=new/$DIR/$F 32937c478bd9Sstevel@tonic-gate 3294daaffb31Sdp mv_but_nodiff= 3295daaffb31Sdp cmp $ofile $nfile > /dev/null 2>&1 3296daaffb31Sdp if [[ $? == 0 && $rename == 1 ]]; then 3297daaffb31Sdp mv_but_nodiff=1 3298daaffb31Sdp fi 3299daaffb31Sdp 3300daaffb31Sdp # 3301daaffb31Sdp # If we have old and new versions of the file then run the appropriate 3302daaffb31Sdp # diffs. This is complicated by a couple of factors: 3303daaffb31Sdp # 3304daaffb31Sdp # - renames must be handled specially: we emit a 'remove' 3305daaffb31Sdp # diff and an 'add' diff 3306daaffb31Sdp # - new files and deleted files must be handled specially 3307daaffb31Sdp # - Solaris patch(1m) can't cope with file creation 3308daaffb31Sdp # (and hence renames) as of this writing. 3309daaffb31Sdp # - To make matters worse, gnu patch doesn't interpret the 3310daaffb31Sdp # output of Solaris diff properly when it comes to 3311daaffb31Sdp # adds and deletes. We need to do some "cleansing" 3312daaffb31Sdp # transformations: 3313daaffb31Sdp # [to add a file] @@ -1,0 +X,Y @@ --> @@ -0,0 +X,Y @@ 3314daaffb31Sdp # [to del a file] @@ -X,Y +1,0 @@ --> @@ -X,Y +0,0 @@ 3315daaffb31Sdp # 3316b0088928SVladimir Kotal cleanse_rmfile="$SED 's/^\(@@ [0-9+,-]*\) [0-9+,-]* @@$/\1 +0,0 @@/'" 3317b0088928SVladimir Kotal cleanse_newfile="$SED 's/^@@ [0-9+,-]* \([0-9+,-]* @@\)$/@@ -0,0 \1/'" 3318daaffb31Sdp 3319daaffb31Sdp rm -f $WDIR/$DIR/$F.patch 3320daaffb31Sdp if [[ -z $rename ]]; then 3321e0e0293aSjmcp if [ ! -f "$ofile" ]; then 3322daaffb31Sdp diff -u /dev/null $nfile | sh -c "$cleanse_newfile" \ 3323daaffb31Sdp > $WDIR/$DIR/$F.patch 3324e0e0293aSjmcp elif [ ! -f "$nfile" ]; then 3325daaffb31Sdp diff -u $ofile /dev/null | sh -c "$cleanse_rmfile" \ 3326daaffb31Sdp > $WDIR/$DIR/$F.patch 3327daaffb31Sdp else 3328daaffb31Sdp diff -u $ofile $nfile > $WDIR/$DIR/$F.patch 3329daaffb31Sdp fi 3330daaffb31Sdp else 3331daaffb31Sdp diff -u $ofile /dev/null | sh -c "$cleanse_rmfile" \ 3332daaffb31Sdp > $WDIR/$DIR/$F.patch 3333daaffb31Sdp 3334daaffb31Sdp diff -u /dev/null $nfile | sh -c "$cleanse_newfile" \ 3335daaffb31Sdp >> $WDIR/$DIR/$F.patch 3336daaffb31Sdp fi 3337daaffb31Sdp 3338daaffb31Sdp # 3339daaffb31Sdp # Tack the patch we just made onto the accumulated patch for the 3340daaffb31Sdp # whole wad. 3341daaffb31Sdp # 3342daaffb31Sdp cat $WDIR/$DIR/$F.patch >> $WDIR/$WNAME.patch 3343daaffb31Sdp 3344daaffb31Sdp print " patch\c" 3345daaffb31Sdp 3346daaffb31Sdp if [[ -f $ofile && -f $nfile && -z $mv_but_nodiff ]]; then 3347daaffb31Sdp 3348daaffb31Sdp ${CDIFFCMD:-diff -bt -C 5} $ofile $nfile > $WDIR/$DIR/$F.cdiff 3349daaffb31Sdp diff_to_html $F $DIR/$F "C" "$COMM" < $WDIR/$DIR/$F.cdiff \ 3350daaffb31Sdp > $WDIR/$DIR/$F.cdiff.html 33517c478bd9Sstevel@tonic-gate print " cdiffs\c" 33527c478bd9Sstevel@tonic-gate 3353daaffb31Sdp ${UDIFFCMD:-diff -bt -U 5} $ofile $nfile > $WDIR/$DIR/$F.udiff 3354daaffb31Sdp diff_to_html $F $DIR/$F "U" "$COMM" < $WDIR/$DIR/$F.udiff \ 3355daaffb31Sdp > $WDIR/$DIR/$F.udiff.html 3356daaffb31Sdp 33577c478bd9Sstevel@tonic-gate print " udiffs\c" 33587c478bd9Sstevel@tonic-gate 33597c478bd9Sstevel@tonic-gate if [[ -x $WDIFF ]]; then 3360daaffb31Sdp $WDIFF -c "$COMM" \ 3361daaffb31Sdp -t "$WNAME Wdiff $DIR/$F" $ofile $nfile > \ 3362daaffb31Sdp $WDIR/$DIR/$F.wdiff.html 2>/dev/null 3363daaffb31Sdp if [[ $? -eq 0 ]]; then 33647c478bd9Sstevel@tonic-gate print " wdiffs\c" 3365daaffb31Sdp else 3366daaffb31Sdp print " wdiffs[fail]\c" 3367daaffb31Sdp fi 33687c478bd9Sstevel@tonic-gate fi 33697c478bd9Sstevel@tonic-gate 3370daaffb31Sdp sdiff_to_html $ofile $nfile $F $DIR "$COMM" \ 3371daaffb31Sdp > $WDIR/$DIR/$F.sdiff.html 33727c478bd9Sstevel@tonic-gate print " sdiffs\c" 33737c478bd9Sstevel@tonic-gate 33747c478bd9Sstevel@tonic-gate print " frames\c" 33757c478bd9Sstevel@tonic-gate 33767c478bd9Sstevel@tonic-gate rm -f $WDIR/$DIR/$F.cdiff $WDIR/$DIR/$F.udiff 33777c478bd9Sstevel@tonic-gate 3378daaffb31Sdp difflines $ofile $nfile > $WDIR/$DIR/$F.count 3379daaffb31Sdp 3380daaffb31Sdp elif [[ -f $ofile && -f $nfile && -n $mv_but_nodiff ]]; then 3381daaffb31Sdp # renamed file: may also have differences 3382daaffb31Sdp difflines $ofile $nfile > $WDIR/$DIR/$F.count 3383daaffb31Sdp elif [[ -f $nfile ]]; then 33847c478bd9Sstevel@tonic-gate # new file: count added lines 3385daaffb31Sdp difflines /dev/null $nfile > $WDIR/$DIR/$F.count 3386daaffb31Sdp elif [[ -f $ofile ]]; then 33877c478bd9Sstevel@tonic-gate # old file: count deleted lines 3388daaffb31Sdp difflines $ofile /dev/null > $WDIR/$DIR/$F.count 33897c478bd9Sstevel@tonic-gate fi 33907c478bd9Sstevel@tonic-gate 3391daaffb31Sdp # 3392daaffb31Sdp # Now we generate the postscript for this file. We generate diffs 3393daaffb31Sdp # only in the event that there is delta, or the file is new (it seems 3394daaffb31Sdp # tree-killing to print out the contents of deleted files). 3395daaffb31Sdp # 3396daaffb31Sdp if [[ -f $nfile ]]; then 3397daaffb31Sdp ocr=$ofile 3398daaffb31Sdp [[ ! -f $ofile ]] && ocr=/dev/null 3399daaffb31Sdp 3400daaffb31Sdp if [[ -z $mv_but_nodiff ]]; then 3401daaffb31Sdp textcomm=`getcomments text $P $PP` 340214983201Sdp if [[ -x $CODEREVIEW ]]; then 340314983201Sdp $CODEREVIEW -y "$textcomm" \ 340414983201Sdp -e $ocr $nfile \ 340514983201Sdp > /tmp/$$.psfile 2>/dev/null && 340614983201Sdp cat /tmp/$$.psfile >> $WDIR/$WNAME.ps 3407daaffb31Sdp if [[ $? -eq 0 ]]; then 3408daaffb31Sdp print " ps\c" 3409daaffb31Sdp else 3410daaffb31Sdp print " ps[fail]\c" 3411daaffb31Sdp fi 3412daaffb31Sdp fi 3413daaffb31Sdp fi 341414983201Sdp fi 3415daaffb31Sdp 3416cdf0c1d5Smjnelson if [[ -f $ofile ]]; then 3417cdf0c1d5Smjnelson source_to_html Old $PP < $ofile > $WDIR/$DIR/$F-.html 34187c478bd9Sstevel@tonic-gate print " old\c" 34197c478bd9Sstevel@tonic-gate fi 34207c478bd9Sstevel@tonic-gate 3421daaffb31Sdp if [[ -f $nfile ]]; then 3422daaffb31Sdp source_to_html New $P < $nfile > $WDIR/$DIR/$F.html 34237c478bd9Sstevel@tonic-gate print " new\c" 34247c478bd9Sstevel@tonic-gate fi 34257c478bd9Sstevel@tonic-gate 3426cdf0c1d5Smjnelson cd $OWD 3427cdf0c1d5Smjnelson 3428daaffb31Sdp print 34297c478bd9Sstevel@tonic-gatedone 34307c478bd9Sstevel@tonic-gate 3431daaffb31Sdpframe_nav_js > $WDIR/ancnav.js 34327c478bd9Sstevel@tonic-gateframe_navigation > $WDIR/ancnav.html 3433daaffb31Sdp 343414983201Sdpif [[ ! -f $WDIR/$WNAME.ps ]]; then 343514983201Sdp print " Generating PDF: Skipped: no output available" 343614983201Sdpelif [[ -x $CODEREVIEW && -x $PS2PDF ]]; then 343714983201Sdp print " Generating PDF: \c" 343814983201Sdp fix_postscript $WDIR/$WNAME.ps | $PS2PDF - > $WDIR/$WNAME.pdf 3439daaffb31Sdp print "Done." 344014983201Sdpelse 344114983201Sdp print " Generating PDF: Skipped: missing 'ps2pdf' or 'codereview'" 344214983201Sdpfi 34437c478bd9Sstevel@tonic-gate 3444e0e0293aSjmcp# If we're in OpenSolaris mode and there's a closed dir under $WDIR, 3445e0e0293aSjmcp# delete it - prevent accidental publishing of closed source 3446e0e0293aSjmcp 3447e0e0293aSjmcpif [[ -n "$Oflag" ]]; then 3448ba44d8a2SVladimir Kotal $FIND $WDIR -type d -name closed -exec /bin/rm -rf {} \; 3449e0e0293aSjmcpfi 3450e0e0293aSjmcp 34517c478bd9Sstevel@tonic-gate# Now build the index.html file that contains 34527c478bd9Sstevel@tonic-gate# links to the source files and their diffs. 34537c478bd9Sstevel@tonic-gate 34547c478bd9Sstevel@tonic-gatecd $CWS 34557c478bd9Sstevel@tonic-gate 34567c478bd9Sstevel@tonic-gate# Save total changed lines for Code Inspection. 3457daaffb31Sdpprint "$TOTL" > $WDIR/TotalChangedLines 34587c478bd9Sstevel@tonic-gate 3459daaffb31Sdpprint " index.html: \c" 34607c478bd9Sstevel@tonic-gateINDEXFILE=$WDIR/index.html 34617c478bd9Sstevel@tonic-gateexec 3<&1 # duplicate stdout to FD3. 34627c478bd9Sstevel@tonic-gateexec 1<&- # Close stdout. 34637c478bd9Sstevel@tonic-gateexec > $INDEXFILE # Open stdout to index file. 34647c478bd9Sstevel@tonic-gate 3465daaffb31Sdpprint "$HTML<head>$STDHEAD" 3466daaffb31Sdpprint "<title>$WNAME</title>" 3467daaffb31Sdpprint "</head>" 3468daaffb31Sdpprint "<body id=\"SUNWwebrev\">" 3469daaffb31Sdpprint "<div class=\"summary\">" 3470daaffb31Sdpprint "<h2>Code Review for $WNAME</h2>" 34717c478bd9Sstevel@tonic-gate 3472daaffb31Sdpprint "<table>" 34737c478bd9Sstevel@tonic-gate 3474daaffb31Sdp# 3475cdf0c1d5Smjnelson# Get the preparer's name: 3476daaffb31Sdp# 3477cdf0c1d5Smjnelson# If the SCM detected is Mercurial, and the configuration property 3478cdf0c1d5Smjnelson# ui.username is available, use that, but be careful to properly escape 3479cdf0c1d5Smjnelson# angle brackets (HTML syntax characters) in the email address. 3480cdf0c1d5Smjnelson# 3481cdf0c1d5Smjnelson# Otherwise, use the current userid in the form "John Doe (jdoe)", but 3482cdf0c1d5Smjnelson# to maintain compatibility with passwd(4), we must support '&' substitutions. 3483cdf0c1d5Smjnelson# 3484cdf0c1d5Smjnelsonpreparer= 3485cdf0c1d5Smjnelsonif [[ "$SCM_MODE" == mercurial ]]; then 3486cdf0c1d5Smjnelson preparer=`hg showconfig ui.username 2>/dev/null` 3487cdf0c1d5Smjnelson if [[ -n "$preparer" ]]; then 3488cdf0c1d5Smjnelson preparer="$(echo "$preparer" | html_quote)" 3489cdf0c1d5Smjnelson fi 3490cdf0c1d5Smjnelsonfi 3491cdf0c1d5Smjnelsonif [[ -z "$preparer" ]]; then 3492cdf0c1d5Smjnelson preparer=$( 3493cdf0c1d5Smjnelson $PERL -e ' 3494cdf0c1d5Smjnelson ($login, $pw, $uid, $gid, $quota, $cmt, $gcos) = getpwuid($<); 3495cdf0c1d5Smjnelson if ($login) { 3496cdf0c1d5Smjnelson $gcos =~ s/\&/ucfirst($login)/e; 3497cdf0c1d5Smjnelson printf "%s (%s)\n", $gcos, $login; 3498cdf0c1d5Smjnelson } else { 3499cdf0c1d5Smjnelson printf "(unknown)\n"; 3500cdf0c1d5Smjnelson } 3501cdf0c1d5Smjnelson ') 3502daaffb31Sdpfi 3503daaffb31Sdp 350448bc00d6SjmcpPREPDATE=$(LC_ALL=C /usr/bin/date +%Y-%b-%d\ %R\ %z\ %Z) 350548bc00d6Sjmcpprint "<tr><th>Prepared by:</th><td>$preparer on $PREPDATE</td></tr>" 3506*8bcea973SRichard Loweprint "<tr><th>Workspace:</th><td>${PRETTY_CWS:-$CWS}" 3507cdf0c1d5Smjnelsonprint "</td></tr>" 3508daaffb31Sdpprint "<tr><th>Compare against:</th><td>" 3509daaffb31Sdpif [[ -n $parent_webrev ]]; then 3510daaffb31Sdp print "webrev at $parent_webrev" 3511daaffb31Sdpelse 3512*8bcea973SRichard Lowe print "${PRETTY_PWS:-$PWS}" 3513daaffb31Sdpfi 3514daaffb31Sdpprint "</td></tr>" 3515daaffb31Sdpprint "<tr><th>Summary of changes:</th><td>" 3516daaffb31SdpprintCI $TOTL $TINS $TDEL $TMOD $TUNC 3517daaffb31Sdpprint "</td></tr>" 3518daaffb31Sdp 3519daaffb31Sdpif [[ -f $WDIR/$WNAME.patch ]]; then 3520371d72daSLubomir Sedlacik wpatch_url="$(print $WNAME.patch | url_encode)" 3521daaffb31Sdp print "<tr><th>Patch of changes:</th><td>" 3522371d72daSLubomir Sedlacik print "<a href=\"$wpatch_url\">$WNAME.patch</a></td></tr>" 3523daaffb31Sdpfi 3524daaffb31Sdpif [[ -f $WDIR/$WNAME.pdf ]]; then 3525371d72daSLubomir Sedlacik wpdf_url="$(print $WNAME.pdf | url_encode)" 3526daaffb31Sdp print "<tr><th>Printable review:</th><td>" 3527371d72daSLubomir Sedlacik print "<a href=\"$wpdf_url\">$WNAME.pdf</a></td></tr>" 3528daaffb31Sdpfi 3529daaffb31Sdp 3530daaffb31Sdpif [[ -n "$iflag" ]]; then 3531daaffb31Sdp print "<tr><th>Author comments:</th><td><div>" 3532daaffb31Sdp cat /tmp/$$.include 3533daaffb31Sdp print "</div></td></tr>" 3534daaffb31Sdpfi 3535daaffb31Sdpprint "</table>" 3536daaffb31Sdpprint "</div>" 3537daaffb31Sdp 3538daaffb31Sdp# 3539daaffb31Sdp# Second pass through the files: generate the rest of the index file 3540daaffb31Sdp# 3541daaffb31Sdpcat $FLIST | while read LINE 35427c478bd9Sstevel@tonic-gatedo 35437c478bd9Sstevel@tonic-gate set - $LINE 35447c478bd9Sstevel@tonic-gate P=$1 35457c478bd9Sstevel@tonic-gate 3546daaffb31Sdp if [[ $# == 2 ]]; then 35477c478bd9Sstevel@tonic-gate PP=$2 3548cdf0c1d5Smjnelson oldname="$PP" 35497c478bd9Sstevel@tonic-gate else 35507c478bd9Sstevel@tonic-gate PP=$P 3551daaffb31Sdp oldname="" 3552daaffb31Sdp fi 3553daaffb31Sdp 3554cdf0c1d5Smjnelson mv_but_nodiff= 3555cdf0c1d5Smjnelson cmp $WDIR/raw_files/old/$PP $WDIR/raw_files/new/$P > /dev/null 2>&1 3556cdf0c1d5Smjnelson if [[ $? == 0 && -n "$oldname" ]]; then 3557cdf0c1d5Smjnelson mv_but_nodiff=1 3558cdf0c1d5Smjnelson fi 3559cdf0c1d5Smjnelson 3560daaffb31Sdp DIR=${P%/*} 3561daaffb31Sdp if [[ $DIR == $P ]]; then 3562daaffb31Sdp DIR="." # File at root of workspace 35637c478bd9Sstevel@tonic-gate fi 35647c478bd9Sstevel@tonic-gate 35657c478bd9Sstevel@tonic-gate # Avoid processing the same file twice. 35667c478bd9Sstevel@tonic-gate # It's possible for renamed files to 35677c478bd9Sstevel@tonic-gate # appear twice in the file list 35687c478bd9Sstevel@tonic-gate 35697c478bd9Sstevel@tonic-gate F=$WDIR/$P 35707c478bd9Sstevel@tonic-gate 3571daaffb31Sdp print "<p>" 35727c478bd9Sstevel@tonic-gate 35737c478bd9Sstevel@tonic-gate # If there's a diffs file, make diffs links 35747c478bd9Sstevel@tonic-gate 3575daaffb31Sdp if [[ -f $F.cdiff.html ]]; then 3576371d72daSLubomir Sedlacik cdiff_url="$(print $P.cdiff.html | url_encode)" 3577371d72daSLubomir Sedlacik udiff_url="$(print $P.udiff.html | url_encode)" 3578371d72daSLubomir Sedlacik print "<a href=\"$cdiff_url\">Cdiffs</a>" 3579371d72daSLubomir Sedlacik print "<a href=\"$udiff_url\">Udiffs</a>" 35807c478bd9Sstevel@tonic-gate 3581daaffb31Sdp if [[ -f $F.wdiff.html && -x $WDIFF ]]; then 3582371d72daSLubomir Sedlacik wdiff_url="$(print $P.wdiff.html | url_encode)" 3583371d72daSLubomir Sedlacik print "<a href=\"$wdiff_url\">Wdiffs</a>" 35847c478bd9Sstevel@tonic-gate fi 35857c478bd9Sstevel@tonic-gate 3586371d72daSLubomir Sedlacik sdiff_url="$(print $P.sdiff.html | url_encode)" 3587371d72daSLubomir Sedlacik print "<a href=\"$sdiff_url\">Sdiffs</a>" 35887c478bd9Sstevel@tonic-gate 3589371d72daSLubomir Sedlacik frames_url="$(print $P.frames.html | url_encode)" 3590371d72daSLubomir Sedlacik print "<a href=\"$frames_url\">Frames</a>" 35917c478bd9Sstevel@tonic-gate else 3592daaffb31Sdp print " ------ ------ ------" 35937c478bd9Sstevel@tonic-gate 3594daaffb31Sdp if [[ -x $WDIFF ]]; then 35957c478bd9Sstevel@tonic-gate print " ------" 35967c478bd9Sstevel@tonic-gate fi 3597daaffb31Sdp 3598daaffb31Sdp print " ------" 35997c478bd9Sstevel@tonic-gate fi 36007c478bd9Sstevel@tonic-gate 36017c478bd9Sstevel@tonic-gate # If there's an old file, make the link 36027c478bd9Sstevel@tonic-gate 3603daaffb31Sdp if [[ -f $F-.html ]]; then 3604371d72daSLubomir Sedlacik oldfile_url="$(print $P-.html | url_encode)" 3605371d72daSLubomir Sedlacik print "<a href=\"$oldfile_url\">Old</a>" 36067c478bd9Sstevel@tonic-gate else 3607daaffb31Sdp print " ---" 36087c478bd9Sstevel@tonic-gate fi 36097c478bd9Sstevel@tonic-gate 36107c478bd9Sstevel@tonic-gate # If there's an new file, make the link 36117c478bd9Sstevel@tonic-gate 3612daaffb31Sdp if [[ -f $F.html ]]; then 3613371d72daSLubomir Sedlacik newfile_url="$(print $P.html | url_encode)" 3614371d72daSLubomir Sedlacik print "<a href=\"$newfile_url\">New</a>" 36157c478bd9Sstevel@tonic-gate else 3616daaffb31Sdp print " ---" 36177c478bd9Sstevel@tonic-gate fi 36187c478bd9Sstevel@tonic-gate 3619daaffb31Sdp if [[ -f $F.patch ]]; then 3620371d72daSLubomir Sedlacik patch_url="$(print $P.patch | url_encode)" 3621371d72daSLubomir Sedlacik print "<a href=\"$patch_url\">Patch</a>" 3622daaffb31Sdp else 3623daaffb31Sdp print " -----" 3624daaffb31Sdp fi 3625daaffb31Sdp 3626daaffb31Sdp if [[ -f $WDIR/raw_files/new/$P ]]; then 3627371d72daSLubomir Sedlacik rawfiles_url="$(print raw_files/new/$P | url_encode)" 3628371d72daSLubomir Sedlacik print "<a href=\"$rawfiles_url\">Raw</a>" 3629daaffb31Sdp else 3630daaffb31Sdp print " ---" 3631daaffb31Sdp fi 3632daaffb31Sdp 3633cdf0c1d5Smjnelson print "<b>$P</b>" 3634cdf0c1d5Smjnelson 3635cdf0c1d5Smjnelson # For renamed files, clearly state whether or not they are modified 3636e6ccc173SEdward Pilatowicz if [[ -f "$oldname" ]]; then 3637cdf0c1d5Smjnelson if [[ -n "$mv_but_nodiff" ]]; then 3638e6ccc173SEdward Pilatowicz print "<i>(copied from $oldname)</i>" 3639cdf0c1d5Smjnelson else 3640e6ccc173SEdward Pilatowicz print "<i>(copied and modified from $oldname)</i>" 3641e6ccc173SEdward Pilatowicz fi 3642e6ccc173SEdward Pilatowicz elif [[ -n "$oldname" ]]; then 3643e6ccc173SEdward Pilatowicz if [[ -n "$mv_but_nodiff" ]]; then 3644e6ccc173SEdward Pilatowicz print "<i>(renamed from $oldname)</i>" 3645e6ccc173SEdward Pilatowicz else 3646e6ccc173SEdward Pilatowicz print "<i>(renamed and modified from $oldname)</i>" 3647cdf0c1d5Smjnelson fi 3648cdf0c1d5Smjnelson fi 3649cdf0c1d5Smjnelson 3650cdf0c1d5Smjnelson # If there's an old file, but no new file, the file was deleted 3651cdf0c1d5Smjnelson if [[ -f $F-.html && ! -f $F.html ]]; then 3652cdf0c1d5Smjnelson print " <i>(deleted)</i>" 3653cdf0c1d5Smjnelson fi 3654daaffb31Sdp 3655daaffb31Sdp # 3656e0e0293aSjmcp # Check for usr/closed and deleted_files/usr/closed 3657daaffb31Sdp # 3658daaffb31Sdp if [ ! -z "$Oflag" ]; then 3659e0e0293aSjmcp if [[ $P == usr/closed/* || \ 3660e0e0293aSjmcp $P == deleted_files/usr/closed/* ]]; then 3661daaffb31Sdp print " <i>Closed source: omitted from" \ 3662daaffb31Sdp "this review</i>" 3663daaffb31Sdp fi 3664daaffb31Sdp fi 3665daaffb31Sdp 3666daaffb31Sdp print "</p>" 36677c478bd9Sstevel@tonic-gate # Insert delta comments 36687c478bd9Sstevel@tonic-gate 3669daaffb31Sdp print "<blockquote><pre>" 3670daaffb31Sdp getcomments html $P $PP 3671daaffb31Sdp print "</pre>" 36727c478bd9Sstevel@tonic-gate 36737c478bd9Sstevel@tonic-gate # Add additional comments comment 36747c478bd9Sstevel@tonic-gate 3675daaffb31Sdp print "<!-- Add comments to explain changes in $P here -->" 36767c478bd9Sstevel@tonic-gate 36777c478bd9Sstevel@tonic-gate # Add count of changes. 36787c478bd9Sstevel@tonic-gate 3679daaffb31Sdp if [[ -f $F.count ]]; then 36807c478bd9Sstevel@tonic-gate cat $F.count 36817c478bd9Sstevel@tonic-gate rm $F.count 36827c478bd9Sstevel@tonic-gate fi 3683cdf0c1d5Smjnelson 3684cdf0c1d5Smjnelson if [[ $SCM_MODE == "teamware" || 3685cdf0c1d5Smjnelson $SCM_MODE == "mercurial" || 3686cdf0c1d5Smjnelson $SCM_MODE == "unknown" ]]; then 3687cdf0c1d5Smjnelson 3688cdf0c1d5Smjnelson # Include warnings for important file mode situations: 3689cdf0c1d5Smjnelson # 1) New executable files 3690cdf0c1d5Smjnelson # 2) Permission changes of any kind 3691cdf0c1d5Smjnelson # 3) Existing executable files 3692cdf0c1d5Smjnelson 3693cdf0c1d5Smjnelson old_mode= 3694cdf0c1d5Smjnelson if [[ -f $WDIR/raw_files/old/$PP ]]; then 3695cdf0c1d5Smjnelson old_mode=`get_file_mode $WDIR/raw_files/old/$PP` 3696cdf0c1d5Smjnelson fi 3697cdf0c1d5Smjnelson 3698cdf0c1d5Smjnelson new_mode= 3699cdf0c1d5Smjnelson if [[ -f $WDIR/raw_files/new/$P ]]; then 3700cdf0c1d5Smjnelson new_mode=`get_file_mode $WDIR/raw_files/new/$P` 3701cdf0c1d5Smjnelson fi 3702cdf0c1d5Smjnelson 3703cdf0c1d5Smjnelson if [[ -z "$old_mode" && "$new_mode" = *[1357]* ]]; then 3704cdf0c1d5Smjnelson print "<span class=\"chmod\">" 3705cdf0c1d5Smjnelson print "<p>new executable file: mode $new_mode</p>" 3706cdf0c1d5Smjnelson print "</span>" 3707cdf0c1d5Smjnelson elif [[ -n "$old_mode" && -n "$new_mode" && 3708cdf0c1d5Smjnelson "$old_mode" != "$new_mode" ]]; then 3709cdf0c1d5Smjnelson print "<span class=\"chmod\">" 3710cdf0c1d5Smjnelson print "<p>mode change: $old_mode to $new_mode</p>" 3711cdf0c1d5Smjnelson print "</span>" 3712cdf0c1d5Smjnelson elif [[ "$new_mode" = *[1357]* ]]; then 3713cdf0c1d5Smjnelson print "<span class=\"chmod\">" 3714cdf0c1d5Smjnelson print "<p>executable file: mode $new_mode</p>" 3715cdf0c1d5Smjnelson print "</span>" 3716cdf0c1d5Smjnelson fi 3717cdf0c1d5Smjnelson fi 3718cdf0c1d5Smjnelson 3719daaffb31Sdp print "</blockquote>" 37207c478bd9Sstevel@tonic-gatedone 37217c478bd9Sstevel@tonic-gate 3722daaffb31Sdpprint 3723daaffb31Sdpprint 3724cac38512Smjnelsonprint "<hr></hr>" 3725daaffb31Sdpprint "<p style=\"font-size: small\">" 37269a70fc3bSMark J. Nelsonprint "This code review page was prepared using <b>$0</b>." 372787a4464eSChris Loveprint "Webrev is maintained by the <a href=\"http://www.illumos.org\">" 372887a4464eSChris Loveprint "illumos</a> project. The latest version may be obtained" 372987a4464eSChris Loveprint "<a href=\"http://src.illumos.org/source/xref/illumos-opengrok/usr/src/tools/scripts/webrev.sh\">here</a>.</p>" 3730daaffb31Sdpprint "</body>" 3731daaffb31Sdpprint "</html>" 37327c478bd9Sstevel@tonic-gate 37337c478bd9Sstevel@tonic-gateexec 1<&- # Close FD 1. 37347c478bd9Sstevel@tonic-gateexec 1<&3 # dup FD 3 to restore stdout. 37357c478bd9Sstevel@tonic-gateexec 3<&- # close FD 3. 37367c478bd9Sstevel@tonic-gate 3737daaffb31Sdpprint "Done." 373802d26c39SVladimir Kotal 3739b0088928SVladimir Kotal# 3740ba44d8a2SVladimir Kotal# If remote deletion was specified and fails do not continue. 3741b0088928SVladimir Kotal# 3742ba44d8a2SVladimir Kotalif [[ -n $Dflag ]]; then 3743b0088928SVladimir Kotal delete_webrev 1 1 3744ba44d8a2SVladimir Kotal (( $? == 0 )) || exit $? 3745ba44d8a2SVladimir Kotalfi 3746ba44d8a2SVladimir Kotal 374702d26c39SVladimir Kotalif [[ -n $Uflag ]]; then 374802d26c39SVladimir Kotal upload_webrev 374902d26c39SVladimir Kotal exit $? 375002d26c39SVladimir Kotalfi 3751