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 28*7646c8f3SMarcel Telka# Copyright 2012 Marcel Telka <marcel@telka.sk> 292f54b716SRichard Lowe 30cdf0c1d5Smjnelson# 31daaffb31Sdp# This script takes a file list and a workspace and builds a set of html files 32daaffb31Sdp# suitable for doing a code review of source changes via a web page. 33daaffb31Sdp# Documentation is available via the manual page, webrev.1, or just 34daaffb31Sdp# type 'webrev -h'. 357c478bd9Sstevel@tonic-gate# 36daaffb31Sdp# Acknowledgements to contributors to webrev are listed in the webrev(1) 37daaffb31Sdp# man page. 387c478bd9Sstevel@tonic-gate# 39daaffb31Sdp 407c478bd9Sstevel@tonic-gateREMOVED_COLOR=brown 417c478bd9Sstevel@tonic-gateCHANGED_COLOR=blue 427c478bd9Sstevel@tonic-gateNEW_COLOR=blue 437c478bd9Sstevel@tonic-gate 44daaffb31SdpHTML='<?xml version="1.0"?> 45daaffb31Sdp<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 46daaffb31Sdp "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 47daaffb31Sdp<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">\n' 48daaffb31Sdp 49daaffb31SdpFRAMEHTML='<?xml version="1.0"?> 50daaffb31Sdp<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" 51daaffb31Sdp "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd"> 52daaffb31Sdp<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">\n' 53daaffb31Sdp 54cac38512SmjnelsonSTDHEAD='<meta http-equiv="cache-control" content="no-cache"></meta> 55cac38512Smjnelson<meta http-equiv="Pragma" content="no-cache"></meta> 56cac38512Smjnelson<meta http-equiv="Expires" content="-1"></meta> 57daaffb31Sdp<!-- 58daaffb31Sdp Note to customizers: the body of the webrev is IDed as SUNWwebrev 59daaffb31Sdp to allow easy overriding by users of webrev via the userContent.css 60daaffb31Sdp mechanism available in some browsers. 61daaffb31Sdp 62daaffb31Sdp For example, to have all "removed" information be red instead of 63daaffb31Sdp brown, set a rule in your userContent.css file like: 64daaffb31Sdp 65daaffb31Sdp body#SUNWwebrev span.removed { color: red ! important; } 66daaffb31Sdp--> 67daaffb31Sdp<style type="text/css" media="screen"> 68daaffb31Sdpbody { 69daaffb31Sdp background-color: #eeeeee; 70daaffb31Sdp} 71daaffb31Sdphr { 72daaffb31Sdp border: none 0; 73daaffb31Sdp border-top: 1px solid #aaa; 74daaffb31Sdp height: 1px; 75daaffb31Sdp} 76daaffb31Sdpdiv.summary { 77daaffb31Sdp font-size: .8em; 78daaffb31Sdp border-bottom: 1px solid #aaa; 79daaffb31Sdp padding-left: 1em; 80daaffb31Sdp padding-right: 1em; 81daaffb31Sdp} 82daaffb31Sdpdiv.summary h2 { 83daaffb31Sdp margin-bottom: 0.3em; 84daaffb31Sdp} 85daaffb31Sdpdiv.summary table th { 86daaffb31Sdp text-align: right; 87daaffb31Sdp vertical-align: top; 88daaffb31Sdp white-space: nowrap; 89daaffb31Sdp} 90daaffb31Sdpspan.lineschanged { 91daaffb31Sdp font-size: 0.7em; 92daaffb31Sdp} 93daaffb31Sdpspan.oldmarker { 94daaffb31Sdp color: red; 95daaffb31Sdp font-size: large; 96daaffb31Sdp font-weight: bold; 97daaffb31Sdp} 98daaffb31Sdpspan.newmarker { 99daaffb31Sdp color: green; 100daaffb31Sdp font-size: large; 101daaffb31Sdp font-weight: bold; 102daaffb31Sdp} 103daaffb31Sdpspan.removed { 104daaffb31Sdp color: brown; 105daaffb31Sdp} 106daaffb31Sdpspan.changed { 107daaffb31Sdp color: blue; 108daaffb31Sdp} 109daaffb31Sdpspan.new { 110daaffb31Sdp color: blue; 111daaffb31Sdp font-weight: bold; 112daaffb31Sdp} 113cdf0c1d5Smjnelsonspan.chmod { 114cdf0c1d5Smjnelson font-size: 0.7em; 115cdf0c1d5Smjnelson color: #db7800; 116cdf0c1d5Smjnelson} 117daaffb31Sdpa.print { font-size: x-small; } 118daaffb31Sdpa:hover { background-color: #ffcc99; } 119daaffb31Sdp</style> 120daaffb31Sdp 121daaffb31Sdp<style type="text/css" media="print"> 122daaffb31Sdppre { font-size: 0.8em; font-family: courier, monospace; } 123daaffb31Sdpspan.removed { color: #444; font-style: italic } 124daaffb31Sdpspan.changed { font-weight: bold; } 125daaffb31Sdpspan.new { font-weight: bold; } 126daaffb31Sdpspan.newmarker { font-size: 1.2em; font-weight: bold; } 127daaffb31Sdpspan.oldmarker { font-size: 1.2em; font-weight: bold; } 128daaffb31Sdpa.print {display: none} 129daaffb31Sdphr { border: none 0; border-top: 1px solid #aaa; height: 1px; } 130daaffb31Sdp</style> 131daaffb31Sdp' 132daaffb31Sdp 133daaffb31Sdp# 134daaffb31Sdp# UDiffs need a slightly different CSS rule for 'new' items (we don't 135daaffb31Sdp# want them to be bolded as we do in cdiffs or sdiffs). 136daaffb31Sdp# 137daaffb31SdpUDIFFCSS=' 138daaffb31Sdp<style type="text/css" media="screen"> 139daaffb31Sdpspan.new { 140daaffb31Sdp color: blue; 141daaffb31Sdp font-weight: normal; 142daaffb31Sdp} 143daaffb31Sdp</style> 144daaffb31Sdp' 145daaffb31Sdp 146b0088928SVladimir Kotal# 147b0088928SVladimir Kotal# Display remote target with prefix and trailing slash. 148b0088928SVladimir Kotal# 149b0088928SVladimir Kotalfunction print_upload_header 150b0088928SVladimir Kotal{ 151b0088928SVladimir Kotal typeset -r prefix=$1 152b0088928SVladimir Kotal typeset display_target 153b0088928SVladimir Kotal 154b0088928SVladimir Kotal if [[ -z $tflag ]]; then 155b0088928SVladimir Kotal display_target=${prefix}${remote_target} 156b0088928SVladimir Kotal else 157b0088928SVladimir Kotal display_target=${remote_target} 158b0088928SVladimir Kotal fi 159b0088928SVladimir Kotal 160b0088928SVladimir Kotal if [[ ${display_target} != */ ]]; then 161b0088928SVladimir Kotal display_target=${display_target}/ 162b0088928SVladimir Kotal fi 163b0088928SVladimir Kotal 164b0088928SVladimir Kotal print " Upload to: ${display_target}\n" \ 165b0088928SVladimir Kotal " Uploading: \c" 166b0088928SVladimir Kotal} 167b0088928SVladimir Kotal 168b0088928SVladimir Kotal# 16902d26c39SVladimir Kotal# Upload the webrev via rsync. Return 0 on success, 1 on error. 170b0088928SVladimir Kotal# 171ba44d8a2SVladimir Kotalfunction rsync_upload 17202d26c39SVladimir Kotal{ 173b0088928SVladimir Kotal if (( $# != 2 )); then 174b0088928SVladimir Kotal print "\nERROR: rsync_upload: wrong usage ($#)" 175b0088928SVladimir Kotal exit 1 17602d26c39SVladimir Kotal fi 17702d26c39SVladimir Kotal 178b0088928SVladimir Kotal typeset -r dst=$1 179b0088928SVladimir Kotal integer -r print_err_msg=$2 18002d26c39SVladimir Kotal 181b0088928SVladimir Kotal print_upload_header ${rsync_prefix} 182b0088928SVladimir Kotal print "rsync ... \c" 1838a34f8dcSVladimir Kotal typeset -r err_msg=$( $MKTEMP /tmp/rsync_err.XXXXXX ) 184b0088928SVladimir Kotal if [[ -z $err_msg ]]; then 185b0088928SVladimir Kotal print "\nERROR: rsync_upload: cannot create temporary file" 186b0088928SVladimir Kotal return 1 187b0088928SVladimir Kotal fi 188b0088928SVladimir Kotal # 189b0088928SVladimir Kotal # The source directory must end with a slash in order to copy just 190b0088928SVladimir Kotal # directory contents, not the whole directory. 191b0088928SVladimir Kotal # 192b0088928SVladimir Kotal typeset src_dir=$WDIR 193b0088928SVladimir Kotal if [[ ${src_dir} != */ ]]; then 194b0088928SVladimir Kotal src_dir=${src_dir}/ 195b0088928SVladimir Kotal fi 196b0088928SVladimir Kotal $RSYNC -r -q ${src_dir} $dst 2>$err_msg 19702d26c39SVladimir Kotal if (( $? != 0 )); then 198b0088928SVladimir Kotal if (( ${print_err_msg} > 0 )); then 199b0088928SVladimir Kotal print "Failed.\nERROR: rsync failed" 200b0088928SVladimir Kotal print "src dir: '${src_dir}'\ndst dir: '$dst'" 201b0088928SVladimir Kotal print "error messages:" 202b0088928SVladimir Kotal $SED 's/^/> /' $err_msg 203b0088928SVladimir Kotal rm -f $err_msg 204b0088928SVladimir Kotal fi 20502d26c39SVladimir Kotal return 1 20602d26c39SVladimir Kotal fi 20702d26c39SVladimir Kotal 208b0088928SVladimir Kotal rm -f $err_msg 20902d26c39SVladimir Kotal print "Done." 21002d26c39SVladimir Kotal return 0 21102d26c39SVladimir Kotal} 21202d26c39SVladimir Kotal 213b0088928SVladimir Kotal# 214b0088928SVladimir Kotal# Create directories on remote host using SFTP. Return 0 on success, 215b0088928SVladimir Kotal# 1 on failure. 216b0088928SVladimir Kotal# 217b0088928SVladimir Kotalfunction remote_mkdirs 218b0088928SVladimir Kotal{ 219b0088928SVladimir Kotal typeset -r dir_spec=$1 2209d3952abSVladimir Kotal typeset -r host_spec=$2 221b0088928SVladimir Kotal 222b0088928SVladimir Kotal # 223b0088928SVladimir Kotal # If the supplied path is absolute we assume all directories are 224b0088928SVladimir Kotal # created, otherwise try to create all directories in the path 225b0088928SVladimir Kotal # except the last one which will be created by scp. 226b0088928SVladimir Kotal # 227b0088928SVladimir Kotal if [[ "${dir_spec}" == */* && "${dir_spec}" != /* ]]; then 228b0088928SVladimir Kotal print "mkdirs \c" 229b0088928SVladimir Kotal # 230b0088928SVladimir Kotal # Remove the last directory from directory specification. 231b0088928SVladimir Kotal # 232b0088928SVladimir Kotal typeset -r dirs_mk=${dir_spec%/*} 2338a34f8dcSVladimir Kotal typeset -r batch_file_mkdir=$( $MKTEMP \ 2348a34f8dcSVladimir Kotal /tmp/webrev_mkdir.XXXXXX ) 235b0088928SVladimir Kotal if [[ -z $batch_file_mkdir ]]; then 236b0088928SVladimir Kotal print "\nERROR: remote_mkdirs:" \ 237b0088928SVladimir Kotal "cannot create temporary file for batch file" 238b0088928SVladimir Kotal return 1 239b0088928SVladimir Kotal fi 240b0088928SVladimir Kotal OLDIFS=$IFS 241b0088928SVladimir Kotal IFS=/ 242b0088928SVladimir Kotal typeset dir 243b0088928SVladimir Kotal for dir in ${dirs_mk}; do 244b0088928SVladimir Kotal # 245b0088928SVladimir Kotal # Use the '-' prefix to ignore mkdir errors in order 246b0088928SVladimir Kotal # to avoid an error in case the directory already 247b0088928SVladimir Kotal # exists. We check the directory with chdir to be sure 248b0088928SVladimir Kotal # there is one. 249b0088928SVladimir Kotal # 250b0088928SVladimir Kotal print -- "-mkdir ${dir}" >> ${batch_file_mkdir} 251b0088928SVladimir Kotal print "chdir ${dir}" >> ${batch_file_mkdir} 252b0088928SVladimir Kotal done 253b0088928SVladimir Kotal IFS=$OLDIFS 2548a34f8dcSVladimir Kotal typeset -r sftp_err_msg=$( $MKTEMP /tmp/webrev_scp_err.XXXXXX ) 255b0088928SVladimir Kotal if [[ -z ${sftp_err_msg} ]]; then 256b0088928SVladimir Kotal print "\nERROR: remote_mkdirs:" \ 257b0088928SVladimir Kotal "cannot create temporary file for error messages" 258b0088928SVladimir Kotal return 1 259b0088928SVladimir Kotal fi 260b0088928SVladimir Kotal $SFTP -b ${batch_file_mkdir} ${host_spec} 2>${sftp_err_msg} 1>&2 261b0088928SVladimir Kotal if (( $? != 0 )); then 262b0088928SVladimir Kotal print "\nERROR: failed to create remote directories" 263b0088928SVladimir Kotal print "error messages:" 264b0088928SVladimir Kotal $SED 's/^/> /' ${sftp_err_msg} 265b0088928SVladimir Kotal rm -f ${sftp_err_msg} ${batch_file_mkdir} 266b0088928SVladimir Kotal return 1 267b0088928SVladimir Kotal fi 268b0088928SVladimir Kotal rm -f ${sftp_err_msg} ${batch_file_mkdir} 269b0088928SVladimir Kotal fi 270b0088928SVladimir Kotal 271b0088928SVladimir Kotal return 0 272b0088928SVladimir Kotal} 273b0088928SVladimir Kotal 274b0088928SVladimir Kotal# 27502d26c39SVladimir Kotal# Upload the webrev via SSH. Return 0 on success, 1 on error. 276b0088928SVladimir Kotal# 277ba44d8a2SVladimir Kotalfunction ssh_upload 27802d26c39SVladimir Kotal{ 27902d26c39SVladimir Kotal if (( $# != 1 )); then 280b0088928SVladimir Kotal print "\nERROR: ssh_upload: wrong number of arguments" 281b0088928SVladimir Kotal exit 1 28202d26c39SVladimir Kotal fi 28302d26c39SVladimir Kotal 28402d26c39SVladimir Kotal typeset dst=$1 28502d26c39SVladimir Kotal typeset -r host_spec=${dst%%:*} 286ba44d8a2SVladimir Kotal typeset -r dir_spec=${dst#*:} 28702d26c39SVladimir Kotal 288b0088928SVladimir Kotal # 289b0088928SVladimir Kotal # Display the upload information before calling delete_webrev 290b0088928SVladimir Kotal # because it will also print its progress. 291b0088928SVladimir Kotal # 292b0088928SVladimir Kotal print_upload_header ${ssh_prefix} 293b0088928SVladimir Kotal 294b0088928SVladimir Kotal # 295b0088928SVladimir Kotal # If the deletion was explicitly requested there is no need 296b0088928SVladimir Kotal # to perform it again. 297b0088928SVladimir Kotal # 298ba44d8a2SVladimir Kotal if [[ -z $Dflag ]]; then 299b0088928SVladimir Kotal # 300b0088928SVladimir Kotal # We do not care about return value because this might be 301b0088928SVladimir Kotal # the first time this directory is uploaded. 302b0088928SVladimir Kotal # 303ba44d8a2SVladimir Kotal delete_webrev 0 30402d26c39SVladimir Kotal fi 30502d26c39SVladimir Kotal 306b0088928SVladimir Kotal # 307b0088928SVladimir Kotal # Create remote directories. Any error reporting will be done 308b0088928SVladimir Kotal # in remote_mkdirs function. 309b0088928SVladimir Kotal # 3109d3952abSVladimir Kotal remote_mkdirs ${dir_spec} ${host_spec} 31102d26c39SVladimir Kotal if (( $? != 0 )); then 31202d26c39SVladimir Kotal return 1 31302d26c39SVladimir Kotal fi 31402d26c39SVladimir Kotal 315b0088928SVladimir Kotal print "upload ... \c" 3168a34f8dcSVladimir Kotal typeset -r scp_err_msg=$( $MKTEMP /tmp/scp_err.XXXXXX ) 317b0088928SVladimir Kotal if [[ -z ${scp_err_msg} ]]; then 318b0088928SVladimir Kotal print "\nERROR: ssh_upload:" \ 319b0088928SVladimir Kotal "cannot create temporary file for error messages" 320b0088928SVladimir Kotal return 1 321b0088928SVladimir Kotal fi 32202d26c39SVladimir Kotal $SCP -q -C -B -o PreferredAuthentications=publickey -r \ 323b0088928SVladimir Kotal $WDIR $dst 2>${scp_err_msg} 32402d26c39SVladimir Kotal if (( $? != 0 )); then 325b0088928SVladimir Kotal print "Failed.\nERROR: scp failed" 326b0088928SVladimir Kotal print "src dir: '$WDIR'\ndst dir: '$dst'" 327b0088928SVladimir Kotal print "error messages:" 328b0088928SVladimir Kotal $SED 's/^/> /' ${scp_err_msg} 329b0088928SVladimir Kotal rm -f ${scp_err_msg} 33002d26c39SVladimir Kotal return 1 33102d26c39SVladimir Kotal fi 33202d26c39SVladimir Kotal 333b0088928SVladimir Kotal rm -f ${scp_err_msg} 33402d26c39SVladimir Kotal print "Done." 33502d26c39SVladimir Kotal return 0 33602d26c39SVladimir Kotal} 33702d26c39SVladimir Kotal 33802d26c39SVladimir Kotal# 339ba44d8a2SVladimir Kotal# Delete webrev at remote site. Return 0 on success, 1 or exit code from sftp 340b0088928SVladimir Kotal# on failure. If first argument is 1 then perform the check of sftp return 341b0088928SVladimir Kotal# value otherwise ignore it. If second argument is present it means this run 342b0088928SVladimir Kotal# only performs deletion. 343ba44d8a2SVladimir Kotal# 344ba44d8a2SVladimir Kotalfunction delete_webrev 345ba44d8a2SVladimir Kotal{ 346b0088928SVladimir Kotal if (( $# < 1 )); then 347b0088928SVladimir Kotal print "delete_webrev: wrong number of arguments" 348b0088928SVladimir Kotal exit 1 349ba44d8a2SVladimir Kotal fi 350ba44d8a2SVladimir Kotal 351b0088928SVladimir Kotal integer -r check=$1 352b0088928SVladimir Kotal integer delete_only=0 353b0088928SVladimir Kotal if (( $# == 2 )); then 354b0088928SVladimir Kotal delete_only=1 355b0088928SVladimir Kotal fi 356b0088928SVladimir Kotal 357b0088928SVladimir Kotal # 358ba44d8a2SVladimir Kotal # Strip the transport specification part of remote target first. 359b0088928SVladimir Kotal # 360ba44d8a2SVladimir Kotal typeset -r stripped_target=${remote_target##*://} 361ba44d8a2SVladimir Kotal typeset -r host_spec=${stripped_target%%:*} 362ba44d8a2SVladimir Kotal typeset -r dir_spec=${stripped_target#*:} 363ba44d8a2SVladimir Kotal typeset dir_rm 364ba44d8a2SVladimir Kotal 365b0088928SVladimir Kotal # 366ba44d8a2SVladimir Kotal # Do not accept an absolute path. 367b0088928SVladimir Kotal # 368ba44d8a2SVladimir Kotal if [[ ${dir_spec} == /* ]]; then 369ba44d8a2SVladimir Kotal return 1 370ba44d8a2SVladimir Kotal fi 371ba44d8a2SVladimir Kotal 372b0088928SVladimir Kotal # 373ba44d8a2SVladimir Kotal # Strip the ending slash. 374b0088928SVladimir Kotal # 375ba44d8a2SVladimir Kotal if [[ ${dir_spec} == */ ]]; then 376ba44d8a2SVladimir Kotal dir_rm=${dir_spec%%/} 377ba44d8a2SVladimir Kotal else 378ba44d8a2SVladimir Kotal dir_rm=${dir_spec} 379ba44d8a2SVladimir Kotal fi 380ba44d8a2SVladimir Kotal 381b0088928SVladimir Kotal if (( ${delete_only} > 0 )); then 382b0088928SVladimir Kotal print " Removing: \c" 383b0088928SVladimir Kotal else 384b0088928SVladimir Kotal print "rmdir \c" 385b0088928SVladimir Kotal fi 386ba44d8a2SVladimir Kotal if [[ -z "$dir_rm" ]]; then 387b0088928SVladimir Kotal print "\nERROR: empty directory for removal" 388ba44d8a2SVladimir Kotal return 1 389ba44d8a2SVladimir Kotal fi 390ba44d8a2SVladimir Kotal 391b0088928SVladimir Kotal # 392ba44d8a2SVladimir Kotal # Prepare batch file. 393b0088928SVladimir Kotal # 3948a34f8dcSVladimir Kotal typeset -r batch_file_rm=$( $MKTEMP /tmp/webrev_remove.XXXXXX ) 395ba44d8a2SVladimir Kotal if [[ -z $batch_file_rm ]]; then 396b0088928SVladimir Kotal print "\nERROR: delete_webrev: cannot create temporary file" 397ba44d8a2SVladimir Kotal return 1 398ba44d8a2SVladimir Kotal fi 399ba44d8a2SVladimir Kotal print "rename $dir_rm $TRASH_DIR/removed.$$" > $batch_file_rm 400ba44d8a2SVladimir Kotal 401b0088928SVladimir Kotal # 402ba44d8a2SVladimir Kotal # Perform remote deletion and remove the batch file. 403b0088928SVladimir Kotal # 4048a34f8dcSVladimir Kotal typeset -r sftp_err_msg=$( $MKTEMP /tmp/webrev_scp_err.XXXXXX ) 405b0088928SVladimir Kotal if [[ -z ${sftp_err_msg} ]]; then 406b0088928SVladimir Kotal print "\nERROR: delete_webrev:" \ 407b0088928SVladimir Kotal "cannot create temporary file for error messages" 408b0088928SVladimir Kotal return 1 409b0088928SVladimir Kotal fi 410b0088928SVladimir Kotal $SFTP -b $batch_file_rm $host_spec 2>${sftp_err_msg} 1>&2 411ba44d8a2SVladimir Kotal integer -r ret=$? 412ba44d8a2SVladimir Kotal rm -f $batch_file_rm 413ba44d8a2SVladimir Kotal if (( $ret != 0 && $check > 0 )); then 414b0088928SVladimir Kotal print "Failed.\nERROR: failed to remove remote directories" 415b0088928SVladimir Kotal print "error messages:" 416b0088928SVladimir Kotal $SED 's/^/> /' ${sftp_err_msg} 417b0088928SVladimir Kotal rm -f ${sftp_err_msg} 418ba44d8a2SVladimir Kotal return $ret 419ba44d8a2SVladimir Kotal fi 420b0088928SVladimir Kotal rm -f ${sftp_err_msg} 421b0088928SVladimir Kotal if (( ${delete_only} > 0 )); then 422ba44d8a2SVladimir Kotal print "Done." 423b0088928SVladimir Kotal fi 424ba44d8a2SVladimir Kotal 425ba44d8a2SVladimir Kotal return 0 426ba44d8a2SVladimir Kotal} 427ba44d8a2SVladimir Kotal 428ba44d8a2SVladimir Kotal# 42902d26c39SVladimir Kotal# Upload webrev to remote site 43002d26c39SVladimir Kotal# 431ba44d8a2SVladimir Kotalfunction upload_webrev 43202d26c39SVladimir Kotal{ 433b0088928SVladimir Kotal integer ret 43402d26c39SVladimir Kotal 43502d26c39SVladimir Kotal if [[ ! -d "$WDIR" ]]; then 436b0088928SVladimir Kotal print "\nERROR: webrev directory '$WDIR' does not exist" 43702d26c39SVladimir Kotal return 1 43802d26c39SVladimir Kotal fi 43902d26c39SVladimir Kotal 440b0088928SVladimir Kotal # 44102d26c39SVladimir Kotal # Perform a late check to make sure we do not upload closed source 44202d26c39SVladimir Kotal # to remote target when -n is used. If the user used custom remote 44302d26c39SVladimir Kotal # target he probably knows what he is doing. 444b0088928SVladimir Kotal # 44502d26c39SVladimir Kotal if [[ -n $nflag && -z $tflag ]]; then 446ba44d8a2SVladimir Kotal $FIND $WDIR -type d -name closed \ 44702d26c39SVladimir Kotal | $GREP closed >/dev/null 44802d26c39SVladimir Kotal if (( $? == 0 )); then 449b0088928SVladimir Kotal print "\nERROR: directory '$WDIR' contains" \ 450b0088928SVladimir Kotal "\"closed\" directory" 45102d26c39SVladimir Kotal return 1 45202d26c39SVladimir Kotal fi 45302d26c39SVladimir Kotal fi 45402d26c39SVladimir Kotal 455b0088928SVladimir Kotal 456b0088928SVladimir Kotal # 457b0088928SVladimir Kotal # We have the URI for remote destination now so let's start the upload. 458b0088928SVladimir Kotal # 45902d26c39SVladimir Kotal if [[ -n $tflag ]]; then 46002d26c39SVladimir Kotal if [[ "${remote_target}" == ${rsync_prefix}?* ]]; then 461b0088928SVladimir Kotal rsync_upload ${remote_target##$rsync_prefix} 1 462b0088928SVladimir Kotal ret=$? 463b0088928SVladimir Kotal return $ret 46402d26c39SVladimir Kotal elif [[ "${remote_target}" == ${ssh_prefix}?* ]]; then 46502d26c39SVladimir Kotal ssh_upload ${remote_target##$ssh_prefix} 466b0088928SVladimir Kotal ret=$? 467b0088928SVladimir Kotal return $ret 46802d26c39SVladimir Kotal fi 46902d26c39SVladimir Kotal else 470b0088928SVladimir Kotal # 471b0088928SVladimir Kotal # Try rsync first and fallback to SSH in case it fails. 472b0088928SVladimir Kotal # 473b0088928SVladimir Kotal rsync_upload ${remote_target} 0 474b0088928SVladimir Kotal ret=$? 475b0088928SVladimir Kotal if (( $ret != 0 )); then 476b0088928SVladimir Kotal print "Failed. (falling back to SSH)" 477ba44d8a2SVladimir Kotal ssh_upload ${remote_target} 478b0088928SVladimir Kotal ret=$? 47902d26c39SVladimir Kotal fi 480b0088928SVladimir Kotal return $ret 48102d26c39SVladimir Kotal fi 48202d26c39SVladimir Kotal} 48302d26c39SVladimir Kotal 484daaffb31Sdp# 485371d72daSLubomir Sedlacik# input_cmd | url_encode | output_cmd 486371d72daSLubomir Sedlacik# 487371d72daSLubomir Sedlacik# URL-encode (percent-encode) reserved characters as defined in RFC 3986. 488371d72daSLubomir Sedlacik# 489371d72daSLubomir Sedlacik# Reserved characters are: :/?#[]@!$&'()*+,;= 490371d72daSLubomir Sedlacik# 491371d72daSLubomir Sedlacik# While not a reserved character itself, percent '%' is reserved by definition 492371d72daSLubomir Sedlacik# so encode it first to avoid recursive transformation, and skip '/' which is 493371d72daSLubomir Sedlacik# a path delimiter. 494371d72daSLubomir Sedlacik# 49525cc4e45SVladimir Kotal# The quotation character is deliberately not escaped in order to make 49625cc4e45SVladimir Kotal# the substitution work with GNU sed. 49725cc4e45SVladimir Kotal# 498371d72daSLubomir Sedlacikfunction url_encode 499371d72daSLubomir Sedlacik{ 500b0088928SVladimir Kotal $SED -e "s|%|%25|g" -e "s|:|%3A|g" -e "s|\&|%26|g" \ 501371d72daSLubomir Sedlacik -e "s|?|%3F|g" -e "s|#|%23|g" -e "s|\[|%5B|g" \ 502371d72daSLubomir Sedlacik -e "s|*|%2A|g" -e "s|@|%40|g" -e "s|\!|%21|g" \ 503371d72daSLubomir Sedlacik -e "s|=|%3D|g" -e "s|;|%3B|g" -e "s|\]|%5D|g" \ 50425cc4e45SVladimir Kotal -e "s|(|%28|g" -e "s|)|%29|g" -e "s|'|%27|g" \ 505371d72daSLubomir Sedlacik -e "s|+|%2B|g" -e "s|\,|%2C|g" -e "s|\\\$|%24|g" 506371d72daSLubomir Sedlacik} 507371d72daSLubomir Sedlacik 508371d72daSLubomir Sedlacik# 509daaffb31Sdp# input_cmd | html_quote | output_cmd 510daaffb31Sdp# or 511daaffb31Sdp# html_quote filename | output_cmd 5127c478bd9Sstevel@tonic-gate# 5137c478bd9Sstevel@tonic-gate# Make a piece of source code safe for display in an HTML <pre> block. 5147c478bd9Sstevel@tonic-gate# 5157c478bd9Sstevel@tonic-gatehtml_quote() 5167c478bd9Sstevel@tonic-gate{ 517b0088928SVladimir Kotal $SED -e "s/&/\&/g" -e "s/</\</g" -e "s/>/\>/g" "$@" | expand 5187c478bd9Sstevel@tonic-gate} 5197c478bd9Sstevel@tonic-gate 520daaffb31Sdp# 5218bcea973SRichard Lowe# Trim a digest-style revision to a conventionally readable yet useful length 5228bcea973SRichard Lowe# 5238bcea973SRichard Lowetrim_digest() 5248bcea973SRichard Lowe{ 5258bcea973SRichard Lowe typeset digest=$1 5268bcea973SRichard Lowe 5278bcea973SRichard Lowe echo $digest | $SED -e 's/\([0-9a-f]\{12\}\).*/\1/' 5288bcea973SRichard Lowe} 5298bcea973SRichard Lowe 5308bcea973SRichard Lowe# 5310fd2682eSMark J. Nelson# input_cmd | its2url | output_cmd 532daaffb31Sdp# 5330fd2682eSMark J. Nelson# Scan for information tracking system references and insert <a> links to the 5340fd2682eSMark J. Nelson# relevant databases. 535daaffb31Sdp# 5360fd2682eSMark J. Nelsonits2url() 5377c478bd9Sstevel@tonic-gate{ 5380fd2682eSMark J. Nelson $SED -f ${its_sed_script} 539daaffb31Sdp} 540daaffb31Sdp 5417c478bd9Sstevel@tonic-gate# 542daaffb31Sdp# strip_unchanged <infile> | output_cmd 5437c478bd9Sstevel@tonic-gate# 544daaffb31Sdp# Removes chunks of sdiff documents that have not changed. This makes it 545daaffb31Sdp# easier for a code reviewer to find the bits that have changed. 5467c478bd9Sstevel@tonic-gate# 547daaffb31Sdp# Deleted lines of text are replaced by a horizontal rule. Some 548daaffb31Sdp# identical lines are retained before and after the changed lines to 549daaffb31Sdp# provide some context. The number of these lines is controlled by the 550cdf0c1d5Smjnelson# variable C in the $AWK script below. 551daaffb31Sdp# 552daaffb31Sdp# The script detects changed lines as any line that has a "<span class=" 553daaffb31Sdp# string embedded (unchanged lines have no particular class and are not 554daaffb31Sdp# part of a <span>). Blank lines (without a sequence number) are also 555daaffb31Sdp# detected since they flag lines that have been inserted or deleted. 556daaffb31Sdp# 557daaffb31Sdpstrip_unchanged() 558daaffb31Sdp{ 559cdf0c1d5Smjnelson $AWK ' 560daaffb31Sdp BEGIN { C = c = 20 } 561cdf0c1d5Smjnelson NF == 0 || /<span class="/ { 562daaffb31Sdp if (c > C) { 563daaffb31Sdp c -= C 564daaffb31Sdp inx = 0 565daaffb31Sdp if (c > C) { 566cac38512Smjnelson print "\n</pre><hr></hr><pre>" 567daaffb31Sdp inx = c % C 568daaffb31Sdp c = C 569daaffb31Sdp } 570daaffb31Sdp 571daaffb31Sdp for (i = 0; i < c; i++) 572daaffb31Sdp print ln[(inx + i) % C] 573daaffb31Sdp } 574daaffb31Sdp c = 0; 575daaffb31Sdp print 576daaffb31Sdp next 577daaffb31Sdp } 578daaffb31Sdp { if (c >= C) { 579daaffb31Sdp ln[c % C] = $0 580daaffb31Sdp c++; 581daaffb31Sdp next; 582daaffb31Sdp } 583daaffb31Sdp c++; 584daaffb31Sdp print 585daaffb31Sdp } 586cac38512Smjnelson END { if (c > (C * 2)) print "\n</pre><hr></hr>" } 587daaffb31Sdp 588daaffb31Sdp ' $1 589daaffb31Sdp} 590daaffb31Sdp 591daaffb31Sdp# 592daaffb31Sdp# sdiff_to_html 593daaffb31Sdp# 594daaffb31Sdp# This function takes two files as arguments, obtains their diff, and 595daaffb31Sdp# processes the diff output to present the files as an HTML document with 596daaffb31Sdp# the files displayed side-by-side, differences shown in color. It also 597daaffb31Sdp# takes a delta comment, rendered as an HTML snippet, as the third 598daaffb31Sdp# argument. The function takes two files as arguments, then the name of 599daaffb31Sdp# file, the path, and the comment. The HTML will be delivered on stdout, 600daaffb31Sdp# e.g. 601daaffb31Sdp# 602daaffb31Sdp# $ sdiff_to_html old/usr/src/tools/scripts/webrev.sh \ 603daaffb31Sdp# new/usr/src/tools/scripts/webrev.sh \ 604daaffb31Sdp# webrev.sh usr/src/tools/scripts \ 605daaffb31Sdp# '<a href="http://monaco.sfbay.sun.com/detail.jsp?cr=1234567"> 606daaffb31Sdp# 1234567</a> my bugid' > <file>.html 607daaffb31Sdp# 608daaffb31Sdp# framed_sdiff() is then called which creates $2.frames.html 609daaffb31Sdp# in the webrev tree. 610daaffb31Sdp# 611daaffb31Sdp# FYI: This function is rather unusual in its use of awk. The initial 612daaffb31Sdp# diff run produces conventional diff output showing changed lines mixed 613daaffb31Sdp# with editing codes. The changed lines are ignored - we're interested in 614daaffb31Sdp# the editing codes, e.g. 6157c478bd9Sstevel@tonic-gate# 6167c478bd9Sstevel@tonic-gate# 8c8 6177c478bd9Sstevel@tonic-gate# 57a61 6187c478bd9Sstevel@tonic-gate# 63c66,76 6197c478bd9Sstevel@tonic-gate# 68,93d80 6207c478bd9Sstevel@tonic-gate# 106d90 6217c478bd9Sstevel@tonic-gate# 108,110d91 6227c478bd9Sstevel@tonic-gate# 623daaffb31Sdp# These editing codes are parsed by the awk script and used to generate 624daaffb31Sdp# another awk script that generates HTML, e.g the above lines would turn 625daaffb31Sdp# into something like this: 6267c478bd9Sstevel@tonic-gate# 6277c478bd9Sstevel@tonic-gate# BEGIN { printf "<pre>\n" } 6287c478bd9Sstevel@tonic-gate# function sp(n) {for (i=0;i<n;i++)printf "\n"} 629daaffb31Sdp# function wl(n) {printf "<font color=%s>%4d %s </font>\n", n, NR, $0} 6307c478bd9Sstevel@tonic-gate# NR==8 {wl("#7A7ADD");next} 6317c478bd9Sstevel@tonic-gate# NR==54 {wl("#7A7ADD");sp(3);next} 6327c478bd9Sstevel@tonic-gate# NR==56 {wl("#7A7ADD");next} 6337c478bd9Sstevel@tonic-gate# NR==57 {wl("black");printf "\n"; next} 6347c478bd9Sstevel@tonic-gate# : : 6357c478bd9Sstevel@tonic-gate# 636daaffb31Sdp# This script is then run on the original source file to generate the 637daaffb31Sdp# HTML that corresponds to the source file. 6387c478bd9Sstevel@tonic-gate# 639daaffb31Sdp# The two HTML files are then combined into a single piece of HTML that 640daaffb31Sdp# uses an HTML table construct to present the files side by side. You'll 641daaffb31Sdp# notice that the changes are color-coded: 6427c478bd9Sstevel@tonic-gate# 6437c478bd9Sstevel@tonic-gate# black - unchanged lines 6447c478bd9Sstevel@tonic-gate# blue - changed lines 6457c478bd9Sstevel@tonic-gate# bold blue - new lines 6467c478bd9Sstevel@tonic-gate# brown - deleted lines 6477c478bd9Sstevel@tonic-gate# 648daaffb31Sdp# Blank lines are inserted in each file to keep unchanged lines in sync 649daaffb31Sdp# (side-by-side). This format is familiar to users of sdiff(1) or 650daaffb31Sdp# Teamware's filemerge tool. 651daaffb31Sdp# 652daaffb31Sdpsdiff_to_html() 653daaffb31Sdp{ 6547c478bd9Sstevel@tonic-gate diff -b $1 $2 > /tmp/$$.diffs 6557c478bd9Sstevel@tonic-gate 656daaffb31Sdp TNAME=$3 657daaffb31Sdp TPATH=$4 658daaffb31Sdp COMMENT=$5 659daaffb31Sdp 6607c478bd9Sstevel@tonic-gate # 6617c478bd9Sstevel@tonic-gate # Now we have the diffs, generate the HTML for the old file. 6627c478bd9Sstevel@tonic-gate # 663cdf0c1d5Smjnelson $AWK ' 6647c478bd9Sstevel@tonic-gate BEGIN { 6657c478bd9Sstevel@tonic-gate printf "function sp(n) {for (i=0;i<n;i++)printf \"\\n\"}\n" 666daaffb31Sdp printf "function removed() " 667daaffb31Sdp printf "{printf \"<span class=\\\"removed\\\">%%4d %%s</span>\\n\", NR, $0}\n" 668daaffb31Sdp printf "function changed() " 669daaffb31Sdp printf "{printf \"<span class=\\\"changed\\\">%%4d %%s</span>\\n\", NR, $0}\n" 670daaffb31Sdp printf "function bl() {printf \"%%4d %%s\\n\", NR, $0}\n" 6717c478bd9Sstevel@tonic-gate} 6727c478bd9Sstevel@tonic-gate /^</ {next} 6737c478bd9Sstevel@tonic-gate /^>/ {next} 6747c478bd9Sstevel@tonic-gate /^---/ {next} 675daaffb31Sdp 6767c478bd9Sstevel@tonic-gate { 6777c478bd9Sstevel@tonic-gate split($1, a, /[cad]/) ; 6787c478bd9Sstevel@tonic-gate if (index($1, "a")) { 6797c478bd9Sstevel@tonic-gate if (a[1] == 0) { 6807c478bd9Sstevel@tonic-gate n = split(a[2], r, /,/); 6817c478bd9Sstevel@tonic-gate if (n == 1) 6827c478bd9Sstevel@tonic-gate printf "BEGIN\t\t{sp(1)}\n" 6837c478bd9Sstevel@tonic-gate else 6847c478bd9Sstevel@tonic-gate printf "BEGIN\t\t{sp(%d)}\n",\ 6857c478bd9Sstevel@tonic-gate (r[2] - r[1]) + 1 6867c478bd9Sstevel@tonic-gate next 6877c478bd9Sstevel@tonic-gate } 6887c478bd9Sstevel@tonic-gate 6897c478bd9Sstevel@tonic-gate printf "NR==%s\t\t{", a[1] 6907c478bd9Sstevel@tonic-gate n = split(a[2], r, /,/); 6917c478bd9Sstevel@tonic-gate s = r[1]; 6927c478bd9Sstevel@tonic-gate if (n == 1) 6937c478bd9Sstevel@tonic-gate printf "bl();printf \"\\n\"; next}\n" 6947c478bd9Sstevel@tonic-gate else { 6957c478bd9Sstevel@tonic-gate n = r[2] - r[1] 6967c478bd9Sstevel@tonic-gate printf "bl();sp(%d);next}\n",\ 6977c478bd9Sstevel@tonic-gate (r[2] - r[1]) + 1 6987c478bd9Sstevel@tonic-gate } 6997c478bd9Sstevel@tonic-gate next 7007c478bd9Sstevel@tonic-gate } 7017c478bd9Sstevel@tonic-gate if (index($1, "d")) { 7027c478bd9Sstevel@tonic-gate n = split(a[1], r, /,/); 7037c478bd9Sstevel@tonic-gate n1 = r[1] 7047c478bd9Sstevel@tonic-gate n2 = r[2] 7057c478bd9Sstevel@tonic-gate if (n == 1) 706daaffb31Sdp printf "NR==%s\t\t{removed(); next}\n" , n1 7077c478bd9Sstevel@tonic-gate else 708daaffb31Sdp printf "NR==%s,NR==%s\t{removed(); next}\n" , n1, n2 7097c478bd9Sstevel@tonic-gate next 7107c478bd9Sstevel@tonic-gate } 7117c478bd9Sstevel@tonic-gate if (index($1, "c")) { 7127c478bd9Sstevel@tonic-gate n = split(a[1], r, /,/); 7137c478bd9Sstevel@tonic-gate n1 = r[1] 7147c478bd9Sstevel@tonic-gate n2 = r[2] 7157c478bd9Sstevel@tonic-gate final = n2 7167c478bd9Sstevel@tonic-gate d1 = 0 7177c478bd9Sstevel@tonic-gate if (n == 1) 718daaffb31Sdp printf "NR==%s\t\t{changed();" , n1 7197c478bd9Sstevel@tonic-gate else { 7207c478bd9Sstevel@tonic-gate d1 = n2 - n1 721daaffb31Sdp printf "NR==%s,NR==%s\t{changed();" , n1, n2 7227c478bd9Sstevel@tonic-gate } 7237c478bd9Sstevel@tonic-gate m = split(a[2], r, /,/); 7247c478bd9Sstevel@tonic-gate n1 = r[1] 7257c478bd9Sstevel@tonic-gate n2 = r[2] 7267c478bd9Sstevel@tonic-gate if (m > 1) { 7277c478bd9Sstevel@tonic-gate d2 = n2 - n1 7287c478bd9Sstevel@tonic-gate if (d2 > d1) { 7297c478bd9Sstevel@tonic-gate if (n > 1) printf "if (NR==%d)", final 7307c478bd9Sstevel@tonic-gate printf "sp(%d);", d2 - d1 7317c478bd9Sstevel@tonic-gate } 7327c478bd9Sstevel@tonic-gate } 7337c478bd9Sstevel@tonic-gate printf "next}\n" ; 7347c478bd9Sstevel@tonic-gate 7357c478bd9Sstevel@tonic-gate next 7367c478bd9Sstevel@tonic-gate } 7377c478bd9Sstevel@tonic-gate } 7387c478bd9Sstevel@tonic-gate 739daaffb31Sdp END { printf "{printf \"%%4d %%s\\n\", NR, $0 }\n" } 740daaffb31Sdp ' /tmp/$$.diffs > /tmp/$$.file1 7417c478bd9Sstevel@tonic-gate 7427c478bd9Sstevel@tonic-gate # 7437c478bd9Sstevel@tonic-gate # Now generate the HTML for the new file 7447c478bd9Sstevel@tonic-gate # 745cdf0c1d5Smjnelson $AWK ' 7467c478bd9Sstevel@tonic-gate BEGIN { 7477c478bd9Sstevel@tonic-gate printf "function sp(n) {for (i=0;i<n;i++)printf \"\\n\"}\n" 748daaffb31Sdp printf "function new() " 749daaffb31Sdp printf "{printf \"<span class=\\\"new\\\">%%4d %%s</span>\\n\", NR, $0}\n" 750daaffb31Sdp printf "function changed() " 751daaffb31Sdp printf "{printf \"<span class=\\\"changed\\\">%%4d %%s</span>\\n\", NR, $0}\n" 752daaffb31Sdp printf "function bl() {printf \"%%4d %%s\\n\", NR, $0}\n" 7537c478bd9Sstevel@tonic-gate } 754daaffb31Sdp 7557c478bd9Sstevel@tonic-gate /^</ {next} 7567c478bd9Sstevel@tonic-gate /^>/ {next} 7577c478bd9Sstevel@tonic-gate /^---/ {next} 758daaffb31Sdp 7597c478bd9Sstevel@tonic-gate { 7607c478bd9Sstevel@tonic-gate split($1, a, /[cad]/) ; 7617c478bd9Sstevel@tonic-gate if (index($1, "d")) { 7627c478bd9Sstevel@tonic-gate if (a[2] == 0) { 7637c478bd9Sstevel@tonic-gate n = split(a[1], r, /,/); 7647c478bd9Sstevel@tonic-gate if (n == 1) 7657c478bd9Sstevel@tonic-gate printf "BEGIN\t\t{sp(1)}\n" 7667c478bd9Sstevel@tonic-gate else 7677c478bd9Sstevel@tonic-gate printf "BEGIN\t\t{sp(%d)}\n",\ 7687c478bd9Sstevel@tonic-gate (r[2] - r[1]) + 1 7697c478bd9Sstevel@tonic-gate next 7707c478bd9Sstevel@tonic-gate } 7717c478bd9Sstevel@tonic-gate 7727c478bd9Sstevel@tonic-gate printf "NR==%s\t\t{", a[2] 7737c478bd9Sstevel@tonic-gate n = split(a[1], r, /,/); 7747c478bd9Sstevel@tonic-gate s = r[1]; 7757c478bd9Sstevel@tonic-gate if (n == 1) 7767c478bd9Sstevel@tonic-gate printf "bl();printf \"\\n\"; next}\n" 7777c478bd9Sstevel@tonic-gate else { 7787c478bd9Sstevel@tonic-gate n = r[2] - r[1] 7797c478bd9Sstevel@tonic-gate printf "bl();sp(%d);next}\n",\ 7807c478bd9Sstevel@tonic-gate (r[2] - r[1]) + 1 7817c478bd9Sstevel@tonic-gate } 7827c478bd9Sstevel@tonic-gate next 7837c478bd9Sstevel@tonic-gate } 7847c478bd9Sstevel@tonic-gate if (index($1, "a")) { 7857c478bd9Sstevel@tonic-gate n = split(a[2], r, /,/); 7867c478bd9Sstevel@tonic-gate n1 = r[1] 7877c478bd9Sstevel@tonic-gate n2 = r[2] 7887c478bd9Sstevel@tonic-gate if (n == 1) 789daaffb31Sdp printf "NR==%s\t\t{new() ; next}\n" , n1 7907c478bd9Sstevel@tonic-gate else 791daaffb31Sdp printf "NR==%s,NR==%s\t{new() ; next}\n" , n1, n2 7927c478bd9Sstevel@tonic-gate next 7937c478bd9Sstevel@tonic-gate } 7947c478bd9Sstevel@tonic-gate if (index($1, "c")) { 7957c478bd9Sstevel@tonic-gate n = split(a[2], r, /,/); 7967c478bd9Sstevel@tonic-gate n1 = r[1] 7977c478bd9Sstevel@tonic-gate n2 = r[2] 7987c478bd9Sstevel@tonic-gate final = n2 7997c478bd9Sstevel@tonic-gate d2 = 0; 8007c478bd9Sstevel@tonic-gate if (n == 1) { 8017c478bd9Sstevel@tonic-gate final = n1 802daaffb31Sdp printf "NR==%s\t\t{changed();" , n1 8037c478bd9Sstevel@tonic-gate } else { 8047c478bd9Sstevel@tonic-gate d2 = n2 - n1 805daaffb31Sdp printf "NR==%s,NR==%s\t{changed();" , n1, n2 8067c478bd9Sstevel@tonic-gate } 8077c478bd9Sstevel@tonic-gate m = split(a[1], r, /,/); 8087c478bd9Sstevel@tonic-gate n1 = r[1] 8097c478bd9Sstevel@tonic-gate n2 = r[2] 8107c478bd9Sstevel@tonic-gate if (m > 1) { 8117c478bd9Sstevel@tonic-gate d1 = n2 - n1 8127c478bd9Sstevel@tonic-gate if (d1 > d2) { 8137c478bd9Sstevel@tonic-gate if (n > 1) printf "if (NR==%d)", final 8147c478bd9Sstevel@tonic-gate printf "sp(%d);", d1 - d2 8157c478bd9Sstevel@tonic-gate } 8167c478bd9Sstevel@tonic-gate } 8177c478bd9Sstevel@tonic-gate printf "next}\n" ; 8187c478bd9Sstevel@tonic-gate next 8197c478bd9Sstevel@tonic-gate } 8207c478bd9Sstevel@tonic-gate } 821daaffb31Sdp END { printf "{printf \"%%4d %%s\\n\", NR, $0 }\n" } 8227c478bd9Sstevel@tonic-gate ' /tmp/$$.diffs > /tmp/$$.file2 8237c478bd9Sstevel@tonic-gate 824daaffb31Sdp # 825cdf0c1d5Smjnelson # Post-process the HTML files by running them back through $AWK 826daaffb31Sdp # 827cdf0c1d5Smjnelson html_quote < $1 | $AWK -f /tmp/$$.file1 > /tmp/$$.file1.html 8287c478bd9Sstevel@tonic-gate 829cdf0c1d5Smjnelson html_quote < $2 | $AWK -f /tmp/$$.file2 > /tmp/$$.file2.html 8307c478bd9Sstevel@tonic-gate 831daaffb31Sdp # 832daaffb31Sdp # Now combine into a valid HTML file and side-by-side into a table 833daaffb31Sdp # 834daaffb31Sdp print "$HTML<head>$STDHEAD" 835cdf0c1d5Smjnelson print "<title>$WNAME Sdiff $TPATH/$TNAME</title>" 836daaffb31Sdp print "</head><body id=\"SUNWwebrev\">" 837daaffb31Sdp print "<a class=\"print\" href=\"javascript:print()\">Print this page</a>" 838daaffb31Sdp print "<pre>$COMMENT</pre>\n" 839daaffb31Sdp print "<table><tr valign=\"top\">" 840daaffb31Sdp print "<td><pre>" 8417c478bd9Sstevel@tonic-gate 8427c478bd9Sstevel@tonic-gate strip_unchanged /tmp/$$.file1.html 8437c478bd9Sstevel@tonic-gate 844daaffb31Sdp print "</pre></td><td><pre>" 8457c478bd9Sstevel@tonic-gate 8467c478bd9Sstevel@tonic-gate strip_unchanged /tmp/$$.file2.html 8477c478bd9Sstevel@tonic-gate 848daaffb31Sdp print "</pre></td>" 849daaffb31Sdp print "</tr></table>" 850daaffb31Sdp print "</body></html>" 8517c478bd9Sstevel@tonic-gate 852daaffb31Sdp framed_sdiff $TNAME $TPATH /tmp/$$.file1.html /tmp/$$.file2.html \ 853daaffb31Sdp "$COMMENT" 8547c478bd9Sstevel@tonic-gate} 8557c478bd9Sstevel@tonic-gate 8567c478bd9Sstevel@tonic-gate 857daaffb31Sdp# 858daaffb31Sdp# framed_sdiff <filename> <filepath> <lhsfile> <rhsfile> <comment> 859daaffb31Sdp# 860daaffb31Sdp# Expects lefthand and righthand side html files created by sdiff_to_html. 861daaffb31Sdp# We use insert_anchors() to augment those with HTML navigation anchors, 862daaffb31Sdp# and then emit the main frame. Content is placed into: 863daaffb31Sdp# 864daaffb31Sdp# $WDIR/DIR/$TNAME.lhs.html 865daaffb31Sdp# $WDIR/DIR/$TNAME.rhs.html 866daaffb31Sdp# $WDIR/DIR/$TNAME.frames.html 867daaffb31Sdp# 868daaffb31Sdp# NOTE: We rely on standard usage of $WDIR and $DIR. 869daaffb31Sdp# 8707c478bd9Sstevel@tonic-gatefunction framed_sdiff 8717c478bd9Sstevel@tonic-gate{ 8727c478bd9Sstevel@tonic-gate typeset TNAME=$1 873daaffb31Sdp typeset TPATH=$2 874daaffb31Sdp typeset lhsfile=$3 875daaffb31Sdp typeset rhsfile=$4 876daaffb31Sdp typeset comments=$5 8777c478bd9Sstevel@tonic-gate typeset RTOP 878daaffb31Sdp 8797c478bd9Sstevel@tonic-gate # Enable html files to access WDIR via a relative path. 880daaffb31Sdp RTOP=$(relative_dir $TPATH $WDIR) 881daaffb31Sdp 882daaffb31Sdp # Make the rhs/lhs files and output the frameset file. 883daaffb31Sdp print "$HTML<head>$STDHEAD" > $WDIR/$DIR/$TNAME.lhs.html 884daaffb31Sdp 885daaffb31Sdp cat >> $WDIR/$DIR/$TNAME.lhs.html <<-EOF 8868b3b7b16SMark J. Nelson <script type="text/javascript" src="${RTOP}ancnav.js"></script> 8877c478bd9Sstevel@tonic-gate </head> 888daaffb31Sdp <body id="SUNWwebrev" onkeypress="keypress(event);"> 889cac38512Smjnelson <a name="0"></a> 890cac38512Smjnelson <pre>$comments</pre><hr></hr> 891daaffb31Sdp EOF 892daaffb31Sdp 893daaffb31Sdp cp $WDIR/$DIR/$TNAME.lhs.html $WDIR/$DIR/$TNAME.rhs.html 894daaffb31Sdp 895daaffb31Sdp insert_anchors $lhsfile >> $WDIR/$DIR/$TNAME.lhs.html 896daaffb31Sdp insert_anchors $rhsfile >> $WDIR/$DIR/$TNAME.rhs.html 897daaffb31Sdp 898daaffb31Sdp close='</body></html>' 899daaffb31Sdp 900daaffb31Sdp print $close >> $WDIR/$DIR/$TNAME.lhs.html 901daaffb31Sdp print $close >> $WDIR/$DIR/$TNAME.rhs.html 902daaffb31Sdp 903daaffb31Sdp print "$FRAMEHTML<head>$STDHEAD" > $WDIR/$DIR/$TNAME.frames.html 904daaffb31Sdp print "<title>$WNAME Framed-Sdiff " \ 905daaffb31Sdp "$TPATH/$TNAME</title> </head>" >> $WDIR/$DIR/$TNAME.frames.html 906daaffb31Sdp cat >> $WDIR/$DIR/$TNAME.frames.html <<-EOF 907daaffb31Sdp <frameset rows="*,60"> 908daaffb31Sdp <frameset cols="50%,50%"> 909cac38512Smjnelson <frame src="$TNAME.lhs.html" scrolling="auto" name="lhs"></frame> 910cac38512Smjnelson <frame src="$TNAME.rhs.html" scrolling="auto" name="rhs"></frame> 911daaffb31Sdp </frameset> 9128b3b7b16SMark J. Nelson <frame src="${RTOP}ancnav.html" scrolling="no" marginwidth="0" 913cac38512Smjnelson marginheight="0" name="nav"></frame> 914daaffb31Sdp <noframes> 915daaffb31Sdp <body id="SUNWwebrev"> 916daaffb31Sdp Alas 'frames' webrev requires that your browser supports frames 9177c478bd9Sstevel@tonic-gate and has the feature enabled. 918daaffb31Sdp </body> 919daaffb31Sdp </noframes> 920daaffb31Sdp </frameset> 9217c478bd9Sstevel@tonic-gate </html> 9227c478bd9Sstevel@tonic-gate EOF 9237c478bd9Sstevel@tonic-gate} 9247c478bd9Sstevel@tonic-gate 9257c478bd9Sstevel@tonic-gate 926daaffb31Sdp# 927daaffb31Sdp# fix_postscript 928daaffb31Sdp# 929daaffb31Sdp# Merge codereview output files to a single conforming postscript file, by: 930daaffb31Sdp# - removing all extraneous headers/trailers 931daaffb31Sdp# - making the page numbers right 932daaffb31Sdp# - removing pages devoid of contents which confuse some 933daaffb31Sdp# postscript readers. 934daaffb31Sdp# 935daaffb31Sdp# From Casper. 936daaffb31Sdp# 937daaffb31Sdpfunction fix_postscript 9387c478bd9Sstevel@tonic-gate{ 939daaffb31Sdp infile=$1 9407c478bd9Sstevel@tonic-gate 941daaffb31Sdp cat > /tmp/$$.crmerge.pl << \EOF 9427c478bd9Sstevel@tonic-gate 943daaffb31Sdp print scalar(<>); # %!PS-Adobe--- 944daaffb31Sdp print "%%Orientation: Landscape\n"; 9457c478bd9Sstevel@tonic-gate 946daaffb31Sdp $pno = 0; 947daaffb31Sdp $doprint = 1; 948daaffb31Sdp 949daaffb31Sdp $page = ""; 950daaffb31Sdp 951daaffb31Sdp while (<>) { 952daaffb31Sdp next if (/^%%Pages:\s*\d+/); 953daaffb31Sdp 954daaffb31Sdp if (/^%%Page:/) { 955daaffb31Sdp if ($pno == 0 || $page =~ /\)S/) { 956daaffb31Sdp # Header or single page containing text 957daaffb31Sdp print "%%Page: ? $pno\n" if ($pno > 0); 958daaffb31Sdp print $page; 959daaffb31Sdp $pno++; 960daaffb31Sdp } else { 961daaffb31Sdp # Empty page, skip it. 9627c478bd9Sstevel@tonic-gate } 963daaffb31Sdp $page = ""; 964daaffb31Sdp $doprint = 1; 9657c478bd9Sstevel@tonic-gate next; 9667c478bd9Sstevel@tonic-gate } 9677c478bd9Sstevel@tonic-gate 968daaffb31Sdp # Skip from %%Trailer of one document to Endprolog 969daaffb31Sdp # %%Page of the next 970daaffb31Sdp $doprint = 0 if (/^%%Trailer/); 971daaffb31Sdp $page .= $_ if ($doprint); 9727c478bd9Sstevel@tonic-gate } 9737c478bd9Sstevel@tonic-gate 974daaffb31Sdp if ($page =~ /\)S/) { 975daaffb31Sdp print "%%Page: ? $pno\n"; 976daaffb31Sdp print $page; 977daaffb31Sdp } else { 978daaffb31Sdp $pno--; 979daaffb31Sdp } 980daaffb31Sdp print "%%Trailer\n%%Pages: $pno\n"; 981daaffb31SdpEOF 982daaffb31Sdp 98314983201Sdp $PERL /tmp/$$.crmerge.pl < $infile 984daaffb31Sdp} 985daaffb31Sdp 986daaffb31Sdp 987daaffb31Sdp# 988daaffb31Sdp# input_cmd | insert_anchors | output_cmd 989daaffb31Sdp# 9907c478bd9Sstevel@tonic-gate# Flag blocks of difference with sequentially numbered invisible 991daaffb31Sdp# anchors. These are used to drive the frames version of the 9927c478bd9Sstevel@tonic-gate# sdiffs output. 9937c478bd9Sstevel@tonic-gate# 9947c478bd9Sstevel@tonic-gate# NOTE: Anchor zero flags the top of the file irrespective of changes, 9957c478bd9Sstevel@tonic-gate# an additional anchor is also appended to flag the bottom. 9967c478bd9Sstevel@tonic-gate# 997daaffb31Sdp# The script detects changed lines as any line that has a "<span 998daaffb31Sdp# class=" string embedded (unchanged lines have no class set and are 999daaffb31Sdp# not part of a <span>. Blank lines (without a sequence number) 10007c478bd9Sstevel@tonic-gate# are also detected since they flag lines that have been inserted or 10017c478bd9Sstevel@tonic-gate# deleted. 10027c478bd9Sstevel@tonic-gate# 1003daaffb31Sdpfunction insert_anchors 1004daaffb31Sdp{ 1005cdf0c1d5Smjnelson $AWK ' 10067c478bd9Sstevel@tonic-gate function ia() { 1007daaffb31Sdp printf "<a name=\"%d\" id=\"anc%d\"></a>", anc, anc++; 10087c478bd9Sstevel@tonic-gate } 1009daaffb31Sdp 10107c478bd9Sstevel@tonic-gate BEGIN { 1011daaffb31Sdp anc=1; 10127c478bd9Sstevel@tonic-gate inblock=1; 1013daaffb31Sdp printf "<pre>\n"; 10147c478bd9Sstevel@tonic-gate } 1015daaffb31Sdp NF == 0 || /^<span class=/ { 10167c478bd9Sstevel@tonic-gate if (inblock == 0) { 10177c478bd9Sstevel@tonic-gate ia(); 10187c478bd9Sstevel@tonic-gate inblock=1; 10197c478bd9Sstevel@tonic-gate } 10207c478bd9Sstevel@tonic-gate print; 10217c478bd9Sstevel@tonic-gate next; 10227c478bd9Sstevel@tonic-gate } 10237c478bd9Sstevel@tonic-gate { 10247c478bd9Sstevel@tonic-gate inblock=0; 10257c478bd9Sstevel@tonic-gate print; 10267c478bd9Sstevel@tonic-gate } 10277c478bd9Sstevel@tonic-gate END { 10287c478bd9Sstevel@tonic-gate ia(); 1029daaffb31Sdp 1030daaffb31Sdp printf "<b style=\"font-size: large; color: red\">"; 1031daaffb31Sdp printf "--- EOF ---</b>" 10327c478bd9Sstevel@tonic-gate for(i=0;i<8;i++) printf "\n\n\n\n\n\n\n\n\n\n"; 1033daaffb31Sdp printf "</pre>" 1034daaffb31Sdp printf "<form name=\"eof\">"; 1035cac38512Smjnelson printf "<input name=\"value\" value=\"%d\" " \ 1036cac38512Smjnelson "type=\"hidden\"></input>", anc - 1; 1037daaffb31Sdp printf "</form>"; 10387c478bd9Sstevel@tonic-gate } 10397c478bd9Sstevel@tonic-gate ' $1 10407c478bd9Sstevel@tonic-gate} 10417c478bd9Sstevel@tonic-gate 10427c478bd9Sstevel@tonic-gate 1043daaffb31Sdp# 1044daaffb31Sdp# relative_dir 1045daaffb31Sdp# 1046daaffb31Sdp# Print a relative return path from $1 to $2. For example if 1047daaffb31Sdp# $1=/tmp/myreview/raw_files/usr/src/tools/scripts and $2=/tmp/myreview, 1048daaffb31Sdp# this function would print "../../../../". 1049daaffb31Sdp# 1050daaffb31Sdp# In the event that $1 is not in $2 a warning is printed to stderr, 1051daaffb31Sdp# and $2 is returned-- the result of this is that the resulting webrev 1052daaffb31Sdp# is not relocatable. 1053daaffb31Sdp# 1054daaffb31Sdpfunction relative_dir 10557c478bd9Sstevel@tonic-gate{ 1056daaffb31Sdp typeset cur="${1##$2?(/)}" 10578b3b7b16SMark J. Nelson 10588b3b7b16SMark J. Nelson # 10598b3b7b16SMark J. Nelson # If the first path was specified absolutely, and it does 10608b3b7b16SMark J. Nelson # not start with the second path, it's an error. 10618b3b7b16SMark J. Nelson # 10620fd2682eSMark J. Nelson if [[ "$cur" = "/${1#/}" ]]; then 1063daaffb31Sdp # Should never happen. 106414983201Sdp print -u2 "\nWARNING: relative_dir: \"$1\" not relative " 1065daaffb31Sdp print -u2 "to \"$2\". Check input paths. Framed webrev " 1066daaffb31Sdp print -u2 "will not be relocatable!" 1067daaffb31Sdp print $2 1068daaffb31Sdp return 1069daaffb31Sdp fi 1070daaffb31Sdp 10718b3b7b16SMark J. Nelson # 10728b3b7b16SMark J. Nelson # This is kind of ugly. The sed script will do the following: 10738b3b7b16SMark J. Nelson # 10748b3b7b16SMark J. Nelson # 1. Strip off a leading "." or "./": this is important to get 10758b3b7b16SMark J. Nelson # the correct arcnav links for files in $WDIR. 10768b3b7b16SMark J. Nelson # 2. Strip off a trailing "/": this is not strictly necessary, 10778b3b7b16SMark J. Nelson # but is kind of nice, since it doesn't end up in "//" at 10788b3b7b16SMark J. Nelson # the end of a relative path. 10798b3b7b16SMark J. Nelson # 3. Replace all remaining sequences of non-"/" with "..": the 10808b3b7b16SMark J. Nelson # assumption here is that each dirname represents another 10818b3b7b16SMark J. Nelson # level of relative separation. 10828b3b7b16SMark J. Nelson # 4. Append a trailing "/" only for non-empty paths: this way 10838b3b7b16SMark J. Nelson # the caller doesn't need to duplicate this logic, and does 10848b3b7b16SMark J. Nelson # not end up using $RTOP/file for files in $WDIR. 10858b3b7b16SMark J. Nelson # 10860fd2682eSMark J. Nelson print $cur | $SED -e '{ 10878b3b7b16SMark J. Nelson s:^\./*:: 10888b3b7b16SMark J. Nelson s:/$:: 10898b3b7b16SMark J. Nelson s:[^/][^/]*:..:g 10900fd2682eSMark J. Nelson s:^\(..*\)$:\1/: 10910fd2682eSMark J. Nelson }' 10927c478bd9Sstevel@tonic-gate} 10937c478bd9Sstevel@tonic-gate 1094daaffb31Sdp# 1095daaffb31Sdp# frame_nav_js 1096daaffb31Sdp# 1097daaffb31Sdp# Emit javascript for frame navigation 1098daaffb31Sdp# 1099daaffb31Sdpfunction frame_nav_js 11007c478bd9Sstevel@tonic-gate{ 11017c478bd9Sstevel@tonic-gatecat << \EOF 11027c478bd9Sstevel@tonic-gatevar myInt; 11037c478bd9Sstevel@tonic-gatevar scrolling=0; 1104daaffb31Sdpvar sfactor = 3; 11057c478bd9Sstevel@tonic-gatevar scount=10; 11067c478bd9Sstevel@tonic-gate 11077c478bd9Sstevel@tonic-gatefunction scrollByPix() { 11087c478bd9Sstevel@tonic-gate if (scount<=0) { 11097c478bd9Sstevel@tonic-gate sfactor*=1.2; 11107c478bd9Sstevel@tonic-gate scount=10; 11117c478bd9Sstevel@tonic-gate } 11127c478bd9Sstevel@tonic-gate parent.lhs.scrollBy(0,sfactor); 11137c478bd9Sstevel@tonic-gate parent.rhs.scrollBy(0,sfactor); 11147c478bd9Sstevel@tonic-gate scount--; 11157c478bd9Sstevel@tonic-gate} 11167c478bd9Sstevel@tonic-gate 1117daaffb31Sdpfunction scrollToAnc(num) { 1118daaffb31Sdp 1119daaffb31Sdp // Update the value of the anchor in the form which we use as 1120daaffb31Sdp // storage for this value. setAncValue() will take care of 1121daaffb31Sdp // correcting for overflow and underflow of the value and return 1122daaffb31Sdp // us the new value. 1123daaffb31Sdp num = setAncValue(num); 1124daaffb31Sdp 1125daaffb31Sdp // Set location and scroll back a little to expose previous 1126daaffb31Sdp // lines. 1127daaffb31Sdp // 1128daaffb31Sdp // Note that this could be improved: it is possible although 1129daaffb31Sdp // complex to compute the x and y position of an anchor, and to 1130daaffb31Sdp // scroll to that location directly. 1131daaffb31Sdp // 11327c478bd9Sstevel@tonic-gate parent.lhs.location.replace(parent.lhs.location.pathname + "#" + num); 11337c478bd9Sstevel@tonic-gate parent.rhs.location.replace(parent.rhs.location.pathname + "#" + num); 1134daaffb31Sdp 11357c478bd9Sstevel@tonic-gate parent.lhs.scrollBy(0,-30); 11367c478bd9Sstevel@tonic-gate parent.rhs.scrollBy(0,-30); 11377c478bd9Sstevel@tonic-gate} 11387c478bd9Sstevel@tonic-gate 1139daaffb31Sdpfunction getAncValue() 1140daaffb31Sdp{ 1141daaffb31Sdp return (parseInt(parent.nav.document.diff.real.value)); 1142daaffb31Sdp} 1143daaffb31Sdp 1144daaffb31Sdpfunction setAncValue(val) 1145daaffb31Sdp{ 1146daaffb31Sdp if (val <= 0) { 1147daaffb31Sdp val = 0; 1148daaffb31Sdp parent.nav.document.diff.real.value = val; 1149daaffb31Sdp parent.nav.document.diff.display.value = "BOF"; 1150daaffb31Sdp return (val); 1151daaffb31Sdp } 1152daaffb31Sdp 1153daaffb31Sdp // 1154daaffb31Sdp // The way we compute the max anchor value is to stash it 1155daaffb31Sdp // inline in the left and right hand side pages-- it's the same 1156daaffb31Sdp // on each side, so we pluck from the left. 1157daaffb31Sdp // 1158daaffb31Sdp maxval = parent.lhs.document.eof.value.value; 1159daaffb31Sdp if (val < maxval) { 1160daaffb31Sdp parent.nav.document.diff.real.value = val; 1161daaffb31Sdp parent.nav.document.diff.display.value = val.toString(); 1162daaffb31Sdp return (val); 1163daaffb31Sdp } 1164daaffb31Sdp 1165daaffb31Sdp // this must be: val >= maxval 1166daaffb31Sdp val = maxval; 1167daaffb31Sdp parent.nav.document.diff.real.value = val; 1168daaffb31Sdp parent.nav.document.diff.display.value = "EOF"; 1169daaffb31Sdp return (val); 1170daaffb31Sdp} 1171daaffb31Sdp 11727c478bd9Sstevel@tonic-gatefunction stopScroll() { 11737c478bd9Sstevel@tonic-gate if (scrolling==1) { 11747c478bd9Sstevel@tonic-gate clearInterval(myInt); 11757c478bd9Sstevel@tonic-gate scrolling=0; 11767c478bd9Sstevel@tonic-gate } 11777c478bd9Sstevel@tonic-gate} 11787c478bd9Sstevel@tonic-gate 11797c478bd9Sstevel@tonic-gatefunction startScroll() { 11807c478bd9Sstevel@tonic-gate stopScroll(); 11817c478bd9Sstevel@tonic-gate scrolling=1; 11827c478bd9Sstevel@tonic-gate myInt=setInterval("scrollByPix()",10); 11837c478bd9Sstevel@tonic-gate} 11847c478bd9Sstevel@tonic-gate 11857c478bd9Sstevel@tonic-gatefunction handlePress(b) { 1186daaffb31Sdp 11877c478bd9Sstevel@tonic-gate switch (b) { 11887c478bd9Sstevel@tonic-gate case 1 : 1189daaffb31Sdp scrollToAnc(-1); 11907c478bd9Sstevel@tonic-gate break; 11917c478bd9Sstevel@tonic-gate case 2 : 1192daaffb31Sdp scrollToAnc(getAncValue() - 1); 11937c478bd9Sstevel@tonic-gate break; 11947c478bd9Sstevel@tonic-gate case 3 : 11957c478bd9Sstevel@tonic-gate sfactor=-3; 11967c478bd9Sstevel@tonic-gate startScroll(); 11977c478bd9Sstevel@tonic-gate break; 11987c478bd9Sstevel@tonic-gate case 4 : 11997c478bd9Sstevel@tonic-gate sfactor=3; 12007c478bd9Sstevel@tonic-gate startScroll(); 12017c478bd9Sstevel@tonic-gate break; 12027c478bd9Sstevel@tonic-gate case 5 : 1203daaffb31Sdp scrollToAnc(getAncValue() + 1); 12047c478bd9Sstevel@tonic-gate break; 12057c478bd9Sstevel@tonic-gate case 6 : 1206daaffb31Sdp scrollToAnc(999999); 12077c478bd9Sstevel@tonic-gate break; 12087c478bd9Sstevel@tonic-gate } 12097c478bd9Sstevel@tonic-gate} 12107c478bd9Sstevel@tonic-gate 12117c478bd9Sstevel@tonic-gatefunction handleRelease(b) { 12127c478bd9Sstevel@tonic-gate stopScroll(); 12137c478bd9Sstevel@tonic-gate} 12147c478bd9Sstevel@tonic-gate 1215daaffb31Sdpfunction keypress(ev) { 1216daaffb31Sdp var keynum; 1217daaffb31Sdp var keychar; 1218daaffb31Sdp 1219daaffb31Sdp if (window.event) { // IE 1220daaffb31Sdp keynum = ev.keyCode; 1221daaffb31Sdp } else if (ev.which) { // non-IE 1222daaffb31Sdp keynum = ev.which; 1223daaffb31Sdp } 1224daaffb31Sdp 1225daaffb31Sdp keychar = String.fromCharCode(keynum); 1226daaffb31Sdp 1227daaffb31Sdp if (keychar == "k") { 1228daaffb31Sdp handlePress(2); 1229daaffb31Sdp return (0); 1230daaffb31Sdp } else if (keychar == "j" || keychar == " ") { 1231daaffb31Sdp handlePress(5); 1232daaffb31Sdp return (0); 1233daaffb31Sdp } 1234daaffb31Sdp return (1); 1235daaffb31Sdp} 1236daaffb31Sdp 12377c478bd9Sstevel@tonic-gatefunction ValidateDiffNum(){ 1238daaffb31Sdp val = parent.nav.document.diff.display.value; 1239daaffb31Sdp if (val == "EOF") { 1240daaffb31Sdp scrollToAnc(999999); 1241daaffb31Sdp return; 1242daaffb31Sdp } 1243daaffb31Sdp 1244daaffb31Sdp if (val == "BOF") { 1245daaffb31Sdp scrollToAnc(0); 1246daaffb31Sdp return; 1247daaffb31Sdp } 1248daaffb31Sdp 1249daaffb31Sdp i=parseInt(val); 12507c478bd9Sstevel@tonic-gate if (isNaN(i)) { 1251daaffb31Sdp parent.nav.document.diff.display.value = getAncValue(); 12527c478bd9Sstevel@tonic-gate } else { 1253daaffb31Sdp scrollToAnc(i); 12547c478bd9Sstevel@tonic-gate } 12557c478bd9Sstevel@tonic-gate return false; 12567c478bd9Sstevel@tonic-gate} 12577c478bd9Sstevel@tonic-gate 1258daaffb31SdpEOF 1259daaffb31Sdp} 1260daaffb31Sdp 1261daaffb31Sdp# 1262daaffb31Sdp# frame_navigation 1263daaffb31Sdp# 1264daaffb31Sdp# Output anchor navigation file for framed sdiffs. 1265daaffb31Sdp# 1266daaffb31Sdpfunction frame_navigation 1267daaffb31Sdp{ 1268daaffb31Sdp print "$HTML<head>$STDHEAD" 1269daaffb31Sdp 1270daaffb31Sdp cat << \EOF 1271daaffb31Sdp<title>Anchor Navigation</title> 1272daaffb31Sdp<meta http-equiv="Content-Script-Type" content="text/javascript"> 1273daaffb31Sdp<meta http-equiv="Content-Type" content="text/html"> 1274daaffb31Sdp 1275daaffb31Sdp<style type="text/css"> 1276daaffb31Sdp div.button td { padding-left: 5px; padding-right: 5px; 1277daaffb31Sdp background-color: #eee; text-align: center; 1278daaffb31Sdp border: 1px #444 outset; cursor: pointer; } 1279daaffb31Sdp div.button a { font-weight: bold; color: black } 1280daaffb31Sdp div.button td:hover { background: #ffcc99; } 1281daaffb31Sdp</style> 1282daaffb31SdpEOF 1283daaffb31Sdp 1284cac38512Smjnelson print "<script type=\"text/javascript\" src=\"ancnav.js\"></script>" 1285daaffb31Sdp 1286daaffb31Sdp cat << \EOF 12877c478bd9Sstevel@tonic-gate</head> 1288daaffb31Sdp<body id="SUNWwebrev" bgcolor="#eeeeee" onload="document.diff.real.focus();" 1289daaffb31Sdp onkeypress="keypress(event);"> 12907c478bd9Sstevel@tonic-gate <noscript lang="javascript"> 12917c478bd9Sstevel@tonic-gate <center> 1292cac38512Smjnelson <p><big>Framed Navigation controls require Javascript</big><br></br> 12937c478bd9Sstevel@tonic-gate Either this browser is incompatable or javascript is not enabled</p> 12947c478bd9Sstevel@tonic-gate </center> 12957c478bd9Sstevel@tonic-gate </noscript> 12967c478bd9Sstevel@tonic-gate <table width="100%" border="0" align="center"> 1297daaffb31Sdp <tr> 1298daaffb31Sdp <td valign="middle" width="25%">Diff navigation: 1299daaffb31Sdp Use 'j' and 'k' for next and previous diffs; or use buttons 1300daaffb31Sdp at right</td> 1301daaffb31Sdp <td align="center" valign="top" width="50%"> 13027c478bd9Sstevel@tonic-gate <div class="button"> 1303daaffb31Sdp <table border="0" align="center"> 1304daaffb31Sdp <tr> 1305daaffb31Sdp <td> 13067c478bd9Sstevel@tonic-gate <a onMouseDown="handlePress(1);return true;" 13077c478bd9Sstevel@tonic-gate onMouseUp="handleRelease(1);return true;" 13087c478bd9Sstevel@tonic-gate onMouseOut="handleRelease(1);return true;" 13097c478bd9Sstevel@tonic-gate onClick="return false;" 13107c478bd9Sstevel@tonic-gate title="Go to Beginning Of file">BOF</a></td> 1311daaffb31Sdp <td> 13127c478bd9Sstevel@tonic-gate <a onMouseDown="handlePress(3);return true;" 13137c478bd9Sstevel@tonic-gate onMouseUp="handleRelease(3);return true;" 13147c478bd9Sstevel@tonic-gate onMouseOut="handleRelease(3);return true;" 13157c478bd9Sstevel@tonic-gate title="Scroll Up: Press and Hold to accelerate" 1316daaffb31Sdp onClick="return false;">Scroll Up</a></td> 1317daaffb31Sdp <td> 13187c478bd9Sstevel@tonic-gate <a onMouseDown="handlePress(2);return true;" 13197c478bd9Sstevel@tonic-gate onMouseUp="handleRelease(2);return true;" 13207c478bd9Sstevel@tonic-gate onMouseOut="handleRelease(2);return true;" 13217c478bd9Sstevel@tonic-gate title="Go to previous Diff" 13227c478bd9Sstevel@tonic-gate onClick="return false;">Prev Diff</a> 13237c478bd9Sstevel@tonic-gate </td></tr> 1324daaffb31Sdp 13257c478bd9Sstevel@tonic-gate <tr> 1326daaffb31Sdp <td> 13277c478bd9Sstevel@tonic-gate <a onMouseDown="handlePress(6);return true;" 13287c478bd9Sstevel@tonic-gate onMouseUp="handleRelease(6);return true;" 13297c478bd9Sstevel@tonic-gate onMouseOut="handleRelease(6);return true;" 13307c478bd9Sstevel@tonic-gate onClick="return false;" 13317c478bd9Sstevel@tonic-gate title="Go to End Of File">EOF</a></td> 1332daaffb31Sdp <td> 13337c478bd9Sstevel@tonic-gate <a onMouseDown="handlePress(4);return true;" 13347c478bd9Sstevel@tonic-gate onMouseUp="handleRelease(4);return true;" 13357c478bd9Sstevel@tonic-gate onMouseOut="handleRelease(4);return true;" 13367c478bd9Sstevel@tonic-gate title="Scroll Down: Press and Hold to accelerate" 1337daaffb31Sdp onClick="return false;">Scroll Down</a></td> 1338daaffb31Sdp <td> 13397c478bd9Sstevel@tonic-gate <a onMouseDown="handlePress(5);return true;" 13407c478bd9Sstevel@tonic-gate onMouseUp="handleRelease(5);return true;" 13417c478bd9Sstevel@tonic-gate onMouseOut="handleRelease(5);return true;" 13427c478bd9Sstevel@tonic-gate title="Go to next Diff" 13437c478bd9Sstevel@tonic-gate onClick="return false;">Next Diff</a></td> 1344daaffb31Sdp </tr> 1345daaffb31Sdp </table> 1346daaffb31Sdp </div> 1347daaffb31Sdp </td> 13487c478bd9Sstevel@tonic-gate <th valign="middle" width="25%"> 1349daaffb31Sdp <form action="" name="diff" onsubmit="return ValidateDiffNum();"> 1350cac38512Smjnelson <input name="display" value="BOF" size="8" type="text"></input> 1351cac38512Smjnelson <input name="real" value="0" size="8" type="hidden"></input> 13527c478bd9Sstevel@tonic-gate </form> 13537c478bd9Sstevel@tonic-gate </th> 1354daaffb31Sdp </tr> 13557c478bd9Sstevel@tonic-gate </table> 13567c478bd9Sstevel@tonic-gate </body> 13577c478bd9Sstevel@tonic-gate</html> 13587c478bd9Sstevel@tonic-gateEOF 13597c478bd9Sstevel@tonic-gate} 13607c478bd9Sstevel@tonic-gate 13617c478bd9Sstevel@tonic-gate 1362daaffb31Sdp 1363daaffb31Sdp# 1364daaffb31Sdp# diff_to_html <filename> <filepath> { U | C } <comment> 1365daaffb31Sdp# 1366daaffb31Sdp# Processes the output of diff to produce an HTML file representing either 1367daaffb31Sdp# context or unified diffs. 1368daaffb31Sdp# 13697c478bd9Sstevel@tonic-gatediff_to_html() 13707c478bd9Sstevel@tonic-gate{ 13717c478bd9Sstevel@tonic-gate TNAME=$1 1372daaffb31Sdp TPATH=$2 1373daaffb31Sdp DIFFTYPE=$3 1374daaffb31Sdp COMMENT=$4 1375daaffb31Sdp 1376daaffb31Sdp print "$HTML<head>$STDHEAD" 1377daaffb31Sdp print "<title>$WNAME ${DIFFTYPE}diff $TPATH</title>" 1378daaffb31Sdp 1379daaffb31Sdp if [[ $DIFFTYPE == "U" ]]; then 1380daaffb31Sdp print "$UDIFFCSS" 1381daaffb31Sdp fi 1382daaffb31Sdp 1383daaffb31Sdp cat <<-EOF 1384daaffb31Sdp </head> 1385daaffb31Sdp <body id="SUNWwebrev"> 1386daaffb31Sdp <a class="print" href="javascript:print()">Print this page</a> 1387daaffb31Sdp <pre>$COMMENT</pre> 1388daaffb31Sdp <pre> 1389daaffb31Sdp EOF 13907c478bd9Sstevel@tonic-gate 1391cdf0c1d5Smjnelson html_quote | $AWK ' 1392daaffb31Sdp /^--- new/ { next } 1393daaffb31Sdp /^\+\+\+ new/ { next } 1394daaffb31Sdp /^--- old/ { next } 1395daaffb31Sdp /^\*\*\* old/ { next } 1396daaffb31Sdp /^\*\*\*\*/ { next } 13977c478bd9Sstevel@tonic-gate /^-------/ { printf "<center><h1>%s</h1></center>\n", $0; next } 1398cac38512Smjnelson /^\@\@.*\@\@$/ { printf "</pre><hr></hr><pre>\n"; 1399daaffb31Sdp printf "<span class=\"newmarker\">%s</span>\n", $0; 1400daaffb31Sdp next} 1401daaffb31Sdp 1402cac38512Smjnelson /^\*\*\*/ { printf "<hr></hr><span class=\"oldmarker\">%s</span>\n", $0; 1403daaffb31Sdp next} 1404daaffb31Sdp /^---/ { printf "<span class=\"newmarker\">%s</span>\n", $0; 1405daaffb31Sdp next} 1406daaffb31Sdp /^\+/ {printf "<span class=\"new\">%s</span>\n", $0; next} 1407daaffb31Sdp /^!/ {printf "<span class=\"changed\">%s</span>\n", $0; next} 1408daaffb31Sdp /^-/ {printf "<span class=\"removed\">%s</span>\n", $0; next} 1409daaffb31Sdp {printf "%s\n", $0; next} 14107c478bd9Sstevel@tonic-gate ' 1411daaffb31Sdp 1412daaffb31Sdp print "</pre></body></html>\n" 14137c478bd9Sstevel@tonic-gate} 14147c478bd9Sstevel@tonic-gate 14157c478bd9Sstevel@tonic-gate 1416daaffb31Sdp# 1417daaffb31Sdp# source_to_html { new | old } <filename> 1418daaffb31Sdp# 1419daaffb31Sdp# Process a plain vanilla source file to transform it into an HTML file. 1420daaffb31Sdp# 14217c478bd9Sstevel@tonic-gatesource_to_html() 14227c478bd9Sstevel@tonic-gate{ 14237c478bd9Sstevel@tonic-gate WHICH=$1 14247c478bd9Sstevel@tonic-gate TNAME=$2 14257c478bd9Sstevel@tonic-gate 1426daaffb31Sdp print "$HTML<head>$STDHEAD" 1427cdf0c1d5Smjnelson print "<title>$WNAME $WHICH $TNAME</title>" 1428daaffb31Sdp print "<body id=\"SUNWwebrev\">" 1429daaffb31Sdp print "<pre>" 1430cdf0c1d5Smjnelson html_quote | $AWK '{line += 1 ; printf "%4d %s\n", line, $0 }' 1431daaffb31Sdp print "</pre></body></html>" 14327c478bd9Sstevel@tonic-gate} 14337c478bd9Sstevel@tonic-gate 1434daaffb31Sdp# 1435cdf0c1d5Smjnelson# comments_from_teamware {text|html} parent-file child-file 1436daaffb31Sdp# 1437daaffb31Sdp# Find the first delta in the child that's not in the parent. Get the 1438daaffb31Sdp# newest delta from the parent, get all deltas from the child starting 1439daaffb31Sdp# with that delta, and then get all info starting with the second oldest 1440daaffb31Sdp# delta in that list (the first delta unique to the child). 14417c478bd9Sstevel@tonic-gate# 14427c478bd9Sstevel@tonic-gate# This code adapted from Bill Shannon's "spc" script 1443daaffb31Sdp# 1444daaffb31Sdpcomments_from_teamware() 14457c478bd9Sstevel@tonic-gate{ 1446daaffb31Sdp fmt=$1 1447daaffb31Sdp pfile=$PWS/$2 1448daaffb31Sdp cfile=$CWS/$3 14497c478bd9Sstevel@tonic-gate 1450cdf0c1d5Smjnelson if [[ ! -f $PWS/${2%/*}/SCCS/s.${2##*/} && -n $RWS ]]; then 1451cdf0c1d5Smjnelson pfile=$RWS/$2 1452cdf0c1d5Smjnelson fi 1453cdf0c1d5Smjnelson 1454daaffb31Sdp if [[ -f $pfile ]]; then 1455cdf0c1d5Smjnelson psid=$($SCCS prs -d:I: $pfile 2>/dev/null) 14567c478bd9Sstevel@tonic-gate else 14577c478bd9Sstevel@tonic-gate psid=1.1 14587c478bd9Sstevel@tonic-gate fi 14597c478bd9Sstevel@tonic-gate 1460cdf0c1d5Smjnelson set -A sids $($SCCS prs -l -r$psid -d:I: $cfile 2>/dev/null) 14617c478bd9Sstevel@tonic-gate N=${#sids[@]} 14627c478bd9Sstevel@tonic-gate 1463daaffb31Sdp nawkprg=' 1464daaffb31Sdp /^COMMENTS:/ {p=1; continue} 1465daaffb31Sdp /^D [0-9]+\.[0-9]+/ {printf "--- %s ---\n", $2; p=0; } 1466daaffb31Sdp NF == 0u { continue } 1467daaffb31Sdp {if (p==0) continue; print $0 }' 1468daaffb31Sdp 14697c478bd9Sstevel@tonic-gate if [[ $N -ge 2 ]]; then 14707c478bd9Sstevel@tonic-gate sid1=${sids[$((N-2))]} # Gets 2nd to last sid 14717c478bd9Sstevel@tonic-gate 1472daaffb31Sdp if [[ $fmt == "text" ]]; then 1473cdf0c1d5Smjnelson $SCCS prs -l -r$sid1 $cfile 2>/dev/null | \ 1474cdf0c1d5Smjnelson $AWK "$nawkprg" 1475daaffb31Sdp return 1476daaffb31Sdp fi 1477daaffb31Sdp 1478cdf0c1d5Smjnelson $SCCS prs -l -r$sid1 $cfile 2>/dev/null | \ 14790fd2682eSMark J. Nelson html_quote | its2url | $AWK "$nawkprg" 14807c478bd9Sstevel@tonic-gate fi 14817c478bd9Sstevel@tonic-gate} 14827c478bd9Sstevel@tonic-gate 1483daaffb31Sdp# 1484cdf0c1d5Smjnelson# comments_from_wx {text|html} filepath 1485daaffb31Sdp# 1486cdf0c1d5Smjnelson# Given the pathname of a file, find its location in a "wx" active 1487cdf0c1d5Smjnelson# file list and print the following comment. Output is either text or 1488cdf0c1d5Smjnelson# HTML; if the latter, embedded bugids (sequence of 5 or more digits) 1489cdf0c1d5Smjnelson# are turned into URLs. 1490cdf0c1d5Smjnelson# 1491cdf0c1d5Smjnelson# This is also used with Mercurial and the file list provided by hg-active. 1492daaffb31Sdp# 1493daaffb31Sdpcomments_from_wx() 14947c478bd9Sstevel@tonic-gate{ 1495daaffb31Sdp typeset fmt=$1 1496daaffb31Sdp typeset p=$2 14977c478bd9Sstevel@tonic-gate 1498cdf0c1d5Smjnelson comm=`$AWK ' 1499daaffb31Sdp $1 == "'$p'" { 15007c478bd9Sstevel@tonic-gate do getline ; while (NF > 0) 15017c478bd9Sstevel@tonic-gate getline 15027c478bd9Sstevel@tonic-gate while (NF > 0) { print ; getline } 15037c478bd9Sstevel@tonic-gate exit 1504daaffb31Sdp }' < $wxfile` 1505daaffb31Sdp 1506cdf0c1d5Smjnelson if [[ -z $comm ]]; then 1507cdf0c1d5Smjnelson comm="*** NO COMMENTS ***" 1508cdf0c1d5Smjnelson fi 1509cdf0c1d5Smjnelson 1510daaffb31Sdp if [[ $fmt == "text" ]]; then 1511cdf0c1d5Smjnelson print -- "$comm" 1512daaffb31Sdp return 1513daaffb31Sdp fi 1514daaffb31Sdp 15150fd2682eSMark J. Nelson print -- "$comm" | html_quote | its2url 1516cdf0c1d5Smjnelson 15177c478bd9Sstevel@tonic-gate} 15187c478bd9Sstevel@tonic-gate 15197c478bd9Sstevel@tonic-gate# 1520daaffb31Sdp# getcomments {text|html} filepath parentpath 1521daaffb31Sdp# 1522daaffb31Sdp# Fetch the comments depending on what SCM mode we're in. 1523daaffb31Sdp# 1524daaffb31Sdpgetcomments() 1525daaffb31Sdp{ 1526daaffb31Sdp typeset fmt=$1 1527daaffb31Sdp typeset p=$2 1528daaffb31Sdp typeset pp=$3 15297c478bd9Sstevel@tonic-gate 15303df69ef3SDarren Moffat if [[ -n $Nflag ]]; then 15313df69ef3SDarren Moffat return 15323df69ef3SDarren Moffat fi 1533cdf0c1d5Smjnelson # 1534cdf0c1d5Smjnelson # Mercurial support uses a file list in wx format, so this 1535cdf0c1d5Smjnelson # will be used there, too 1536cdf0c1d5Smjnelson # 1537daaffb31Sdp if [[ -n $wxfile ]]; then 1538daaffb31Sdp comments_from_wx $fmt $p 1539daaffb31Sdp else 1540daaffb31Sdp if [[ $SCM_MODE == "teamware" ]]; then 1541daaffb31Sdp comments_from_teamware $fmt $pp $p 1542daaffb31Sdp fi 1543daaffb31Sdp fi 1544daaffb31Sdp} 1545daaffb31Sdp 1546daaffb31Sdp# 1547daaffb31Sdp# printCI <total-changed> <inserted> <deleted> <modified> <unchanged> 1548daaffb31Sdp# 1549daaffb31Sdp# Print out Code Inspection figures similar to sccs-prt(1) format. 1550daaffb31Sdp# 1551daaffb31Sdpfunction printCI 1552daaffb31Sdp{ 1553daaffb31Sdp integer tot=$1 ins=$2 del=$3 mod=$4 unc=$5 1554daaffb31Sdp typeset str 1555daaffb31Sdp if (( tot == 1 )); then 1556daaffb31Sdp str="line" 1557daaffb31Sdp else 1558daaffb31Sdp str="lines" 1559daaffb31Sdp fi 1560daaffb31Sdp printf '%d %s changed: %d ins; %d del; %d mod; %d unchg\n' \ 1561daaffb31Sdp $tot $str $ins $del $mod $unc 1562daaffb31Sdp} 1563daaffb31Sdp 1564daaffb31Sdp 1565daaffb31Sdp# 1566daaffb31Sdp# difflines <oldfile> <newfile> 1567daaffb31Sdp# 1568daaffb31Sdp# Calculate and emit number of added, removed, modified and unchanged lines, 1569daaffb31Sdp# and total lines changed, the sum of added + removed + modified. 1570daaffb31Sdp# 15717c478bd9Sstevel@tonic-gatefunction difflines 15727c478bd9Sstevel@tonic-gate{ 1573daaffb31Sdp integer tot mod del ins unc err 15747c478bd9Sstevel@tonic-gate typeset filename 15757c478bd9Sstevel@tonic-gate 1576cdf0c1d5Smjnelson eval $( diff -e $1 $2 | $AWK ' 1577daaffb31Sdp # Change range of lines: N,Nc 15787c478bd9Sstevel@tonic-gate /^[0-9]*,[0-9]*c$/ { 15797c478bd9Sstevel@tonic-gate n=split(substr($1,1,length($1)-1), counts, ","); 15807c478bd9Sstevel@tonic-gate if (n != 2) { 15817c478bd9Sstevel@tonic-gate error=2 15827c478bd9Sstevel@tonic-gate exit; 15837c478bd9Sstevel@tonic-gate } 1584daaffb31Sdp # 1585daaffb31Sdp # 3,5c means lines 3 , 4 and 5 are changed, a total of 3 lines. 1586daaffb31Sdp # following would be 5 - 3 = 2! Hence +1 for correction. 1587daaffb31Sdp # 15887c478bd9Sstevel@tonic-gate r=(counts[2]-counts[1])+1; 1589daaffb31Sdp 1590daaffb31Sdp # 1591daaffb31Sdp # Now count replacement lines: each represents a change instead 1592daaffb31Sdp # of a delete, so increment c and decrement r. 1593daaffb31Sdp # 15947c478bd9Sstevel@tonic-gate while (getline != /^\.$/) { 15957c478bd9Sstevel@tonic-gate c++; 15967c478bd9Sstevel@tonic-gate r--; 15977c478bd9Sstevel@tonic-gate } 1598daaffb31Sdp # 1599daaffb31Sdp # If there were more replacement lines than original lines, 1600daaffb31Sdp # then r will be negative; in this case there are no deletions, 1601daaffb31Sdp # but there are r changes that should be counted as adds, and 1602daaffb31Sdp # since r is negative, subtract it from a and add it to c. 1603daaffb31Sdp # 16047c478bd9Sstevel@tonic-gate if (r < 0) { 16057c478bd9Sstevel@tonic-gate a-=r; 16067c478bd9Sstevel@tonic-gate c+=r; 16077c478bd9Sstevel@tonic-gate } 1608daaffb31Sdp 1609daaffb31Sdp # 1610daaffb31Sdp # If there were more original lines than replacement lines, then 1611daaffb31Sdp # r will be positive; in this case, increment d by that much. 1612daaffb31Sdp # 16137c478bd9Sstevel@tonic-gate if (r > 0) { 16147c478bd9Sstevel@tonic-gate d+=r; 16157c478bd9Sstevel@tonic-gate } 16167c478bd9Sstevel@tonic-gate next; 16177c478bd9Sstevel@tonic-gate } 16187c478bd9Sstevel@tonic-gate 1619daaffb31Sdp # Change lines: Nc 16207c478bd9Sstevel@tonic-gate /^[0-9].*c$/ { 1621daaffb31Sdp # The first line is a replacement; any more are additions. 16227c478bd9Sstevel@tonic-gate if (getline != /^\.$/) { 16237c478bd9Sstevel@tonic-gate c++; 16247c478bd9Sstevel@tonic-gate while (getline != /^\.$/) a++; 16257c478bd9Sstevel@tonic-gate } 16267c478bd9Sstevel@tonic-gate next; 16277c478bd9Sstevel@tonic-gate } 16287c478bd9Sstevel@tonic-gate 1629daaffb31Sdp # Add lines: both Na and N,Na 16307c478bd9Sstevel@tonic-gate /^[0-9].*a$/ { 16317c478bd9Sstevel@tonic-gate while (getline != /^\.$/) a++; 16327c478bd9Sstevel@tonic-gate next; 16337c478bd9Sstevel@tonic-gate } 16347c478bd9Sstevel@tonic-gate 1635daaffb31Sdp # Delete range of lines: N,Nd 16367c478bd9Sstevel@tonic-gate /^[0-9]*,[0-9]*d$/ { 16377c478bd9Sstevel@tonic-gate n=split(substr($1,1,length($1)-1), counts, ","); 16387c478bd9Sstevel@tonic-gate if (n != 2) { 16397c478bd9Sstevel@tonic-gate error=2 16407c478bd9Sstevel@tonic-gate exit; 16417c478bd9Sstevel@tonic-gate } 1642daaffb31Sdp # 1643daaffb31Sdp # 3,5d means lines 3 , 4 and 5 are deleted, a total of 3 lines. 1644daaffb31Sdp # following would be 5 - 3 = 2! Hence +1 for correction. 1645daaffb31Sdp # 16467c478bd9Sstevel@tonic-gate r=(counts[2]-counts[1])+1; 16477c478bd9Sstevel@tonic-gate d+=r; 16487c478bd9Sstevel@tonic-gate next; 16497c478bd9Sstevel@tonic-gate } 16507c478bd9Sstevel@tonic-gate 1651daaffb31Sdp # Delete line: Nd. For example 10d says line 10 is deleted. 16527c478bd9Sstevel@tonic-gate /^[0-9]*d$/ {d++; next} 16537c478bd9Sstevel@tonic-gate 1654daaffb31Sdp # Should not get here! 16557c478bd9Sstevel@tonic-gate { 16567c478bd9Sstevel@tonic-gate error=1; 16577c478bd9Sstevel@tonic-gate exit; 16587c478bd9Sstevel@tonic-gate } 16597c478bd9Sstevel@tonic-gate 1660daaffb31Sdp # Finish off - print results 16617c478bd9Sstevel@tonic-gate END { 1662daaffb31Sdp printf("tot=%d;mod=%d;del=%d;ins=%d;err=%d\n", 16637c478bd9Sstevel@tonic-gate (c+d+a), c, d, a, error); 16647c478bd9Sstevel@tonic-gate }' ) 16657c478bd9Sstevel@tonic-gate 1666cdf0c1d5Smjnelson # End of $AWK, Check to see if any trouble occurred. 16677c478bd9Sstevel@tonic-gate if (( $? > 0 || err > 0 )); then 1668daaffb31Sdp print "Unexpected Error occurred reading" \ 1669daaffb31Sdp "\`diff -e $1 $2\`: \$?=$?, err=" $err 1670daaffb31Sdp return 1671daaffb31Sdp fi 1672daaffb31Sdp 16737c478bd9Sstevel@tonic-gate # Accumulate totals 16747c478bd9Sstevel@tonic-gate (( TOTL += tot )) 1675daaffb31Sdp (( TMOD += mod )) 16767c478bd9Sstevel@tonic-gate (( TDEL += del )) 16777c478bd9Sstevel@tonic-gate (( TINS += ins )) 16787c478bd9Sstevel@tonic-gate # Calculate unchanged lines 1679cdf0c1d5Smjnelson unc=`wc -l < $1` 16807c478bd9Sstevel@tonic-gate if (( unc > 0 )); then 1681daaffb31Sdp (( unc -= del + mod )) 16827c478bd9Sstevel@tonic-gate (( TUNC += unc )) 16837c478bd9Sstevel@tonic-gate fi 16847c478bd9Sstevel@tonic-gate # print summary 1685daaffb31Sdp print "<span class=\"lineschanged\">" 1686daaffb31Sdp printCI $tot $ins $del $mod $unc 1687daaffb31Sdp print "</span>" 16887c478bd9Sstevel@tonic-gate} 16897c478bd9Sstevel@tonic-gate 1690daaffb31Sdp 16917c478bd9Sstevel@tonic-gate# 1692daaffb31Sdp# flist_from_wx 1693daaffb31Sdp# 1694daaffb31Sdp# Sets up webrev to source its information from a wx-formatted file. 1695daaffb31Sdp# Sets the global 'wxfile' variable. 1696daaffb31Sdp# 1697daaffb31Sdpfunction flist_from_wx 16987c478bd9Sstevel@tonic-gate{ 1699daaffb31Sdp typeset argfile=$1 1700daaffb31Sdp if [[ -n ${argfile%%/*} ]]; then 1701daaffb31Sdp # 1702daaffb31Sdp # If the wx file pathname is relative then make it absolute 1703daaffb31Sdp # because the webrev does a "cd" later on. 1704daaffb31Sdp # 1705daaffb31Sdp wxfile=$PWD/$argfile 17067c478bd9Sstevel@tonic-gate else 1707daaffb31Sdp wxfile=$argfile 17087c478bd9Sstevel@tonic-gate fi 17097c478bd9Sstevel@tonic-gate 1710cdf0c1d5Smjnelson $AWK '{ c = 1; print; 17117c478bd9Sstevel@tonic-gate while (getline) { 17127c478bd9Sstevel@tonic-gate if (NF == 0) { c = -c; continue } 17137c478bd9Sstevel@tonic-gate if (c > 0) print 17147c478bd9Sstevel@tonic-gate } 1715daaffb31Sdp }' $wxfile > $FLIST 17167c478bd9Sstevel@tonic-gate 1717daaffb31Sdp print " Done." 1718daaffb31Sdp} 17197c478bd9Sstevel@tonic-gate 1720daaffb31Sdp# 1721daaffb31Sdp# flist_from_teamware [ <args-to-putback-n> ] 1722daaffb31Sdp# 1723daaffb31Sdp# Generate the file list by extracting file names from a putback -n. Some 1724daaffb31Sdp# names may come from the "update/create" messages and others from the 1725daaffb31Sdp# "currently checked out" warning. Renames are detected here too. Extract 1726daaffb31Sdp# values for CODEMGR_WS and CODEMGR_PARENT from the output of the putback 1727daaffb31Sdp# -n as well, but remove them if they are already defined. 1728daaffb31Sdp# 1729daaffb31Sdpfunction flist_from_teamware 1730daaffb31Sdp{ 1731cdf0c1d5Smjnelson if [[ -n $codemgr_parent && -z $parent_webrev ]]; then 1732daaffb31Sdp if [[ ! -d $codemgr_parent/Codemgr_wsdata ]]; then 1733daaffb31Sdp print -u2 "parent $codemgr_parent doesn't look like a" \ 1734daaffb31Sdp "valid teamware workspace" 17357c478bd9Sstevel@tonic-gate exit 1 17367c478bd9Sstevel@tonic-gate fi 1737daaffb31Sdp parent_args="-p $codemgr_parent" 17387c478bd9Sstevel@tonic-gate fi 17397c478bd9Sstevel@tonic-gate 1740daaffb31Sdp print " File list from: 'putback -n $parent_args $*' ... \c" 17417c478bd9Sstevel@tonic-gate 1742daaffb31Sdp putback -n $parent_args $* 2>&1 | 1743cdf0c1d5Smjnelson $AWK ' 1744daaffb31Sdp /^update:|^create:/ {print $2} 1745daaffb31Sdp /^Parent workspace:/ {printf("CODEMGR_PARENT=%s\n",$3)} 1746daaffb31Sdp /^Child workspace:/ {printf("CODEMGR_WS=%s\n",$3)} 1747daaffb31Sdp /^The following files are currently checked out/ {p = 1; continue} 1748daaffb31Sdp NF == 0 {p=0 ; continue} 1749daaffb31Sdp /^rename/ {old=$3} 1750daaffb31Sdp $1 == "to:" {print $2, old} 1751daaffb31Sdp /^"/ {continue} 1752daaffb31Sdp p == 1 {print $1}' | 1753daaffb31Sdp sort -r -k 1,1 -u | sort > $FLIST 17547c478bd9Sstevel@tonic-gate 1755daaffb31Sdp print " Done." 1756daaffb31Sdp} 1757daaffb31Sdp 1758cdf0c1d5Smjnelson# 1759cdf0c1d5Smjnelson# Call hg-active to get the active list output in the wx active list format 1760cdf0c1d5Smjnelson# 1761cdf0c1d5Smjnelsonfunction hg_active_wxfile 1762cdf0c1d5Smjnelson{ 1763cdf0c1d5Smjnelson typeset child=$1 1764cdf0c1d5Smjnelson typeset parent=$2 1765cdf0c1d5Smjnelson 1766cdf0c1d5Smjnelson TMPFLIST=/tmp/$$.active 17679a70fc3bSMark J. Nelson $HG_ACTIVE -w $child -p $parent -o $TMPFLIST 1768cdf0c1d5Smjnelson wxfile=$TMPFLIST 1769cdf0c1d5Smjnelson} 1770cdf0c1d5Smjnelson 1771cdf0c1d5Smjnelson# 1772cdf0c1d5Smjnelson# flist_from_mercurial 1773cdf0c1d5Smjnelson# Call hg-active to get a wx-style active list, and hand it off to 1774cdf0c1d5Smjnelson# flist_from_wx 1775cdf0c1d5Smjnelson# 1776cdf0c1d5Smjnelsonfunction flist_from_mercurial 1777cdf0c1d5Smjnelson{ 1778cdf0c1d5Smjnelson typeset child=$1 1779cdf0c1d5Smjnelson typeset parent=$2 1780cdf0c1d5Smjnelson 1781cdf0c1d5Smjnelson print " File list from: hg-active -p $parent ...\c" 1782cdf0c1d5Smjnelson if [[ ! -x $HG_ACTIVE ]]; then 1783cdf0c1d5Smjnelson print # Blank line for the \c above 1784cdf0c1d5Smjnelson print -u2 "Error: hg-active tool not found. Exiting" 1785cdf0c1d5Smjnelson exit 1 1786cdf0c1d5Smjnelson fi 1787cdf0c1d5Smjnelson hg_active_wxfile $child $parent 1788cdf0c1d5Smjnelson 1789cdf0c1d5Smjnelson # flist_from_wx prints the Done, so we don't have to. 1790cdf0c1d5Smjnelson flist_from_wx $TMPFLIST 1791cdf0c1d5Smjnelson} 1792cdf0c1d5Smjnelson 1793cdf0c1d5Smjnelson# 17948bcea973SRichard Lowe# Transform a specified 'git log' output format into a wx-like active list. 17958bcea973SRichard Lowe# 17968bcea973SRichard Lowefunction git_wxfile 17978bcea973SRichard Lowe{ 17988bcea973SRichard Lowe typeset child="$1" 17998bcea973SRichard Lowe typeset parent="$2" 18008bcea973SRichard Lowe 18018bcea973SRichard Lowe TMPFLIST=/tmp/$$.active 18028bcea973SRichard Lowe $PERL -e 'my (%files, %realfiles, $msg); 18038bcea973SRichard Lowe my $branch = $ARGV[0]; 18048bcea973SRichard Lowe 18058bcea973SRichard Lowe open(F, "git diff -M --name-status $branch |"); 18068bcea973SRichard Lowe while (<F>) { 18078bcea973SRichard Lowe chomp; 18088bcea973SRichard Lowe if (/^R(\d+)\s+([^ ]+)\s+([^ ]+)/) { # rename 18098bcea973SRichard Lowe if ($1 >= 75) { # Probably worth treating as a rename 18103cb02613SRichard Lowe $realfiles{$3} = $2; 18118bcea973SRichard Lowe } else { 18128bcea973SRichard Lowe $realfiles{$3} = $3; 18138bcea973SRichard Lowe $realfiles{$2} = $2; 18148bcea973SRichard Lowe } 18158bcea973SRichard Lowe } else { 18168bcea973SRichard Lowe my $f = (split /\s+/, $_)[1]; 18178bcea973SRichard Lowe $realfiles{$f} = $f; 18188bcea973SRichard Lowe } 18198bcea973SRichard Lowe } 18208bcea973SRichard Lowe close(F); 18218bcea973SRichard Lowe 18228bcea973SRichard Lowe my $state = 1; # 0|comments, 1|files 18238bcea973SRichard Lowe open(F, "git whatchanged --pretty=format:%B $branch.. |"); 18248bcea973SRichard Lowe while (<F>) { 18258bcea973SRichard Lowe chomp; 18268bcea973SRichard Lowe if (/^:[0-9]{6}/) { 18278bcea973SRichard Lowe my $fname = (split /\t/, $_)[1]; 18288bcea973SRichard Lowe next if !defined($realfiles{$fname}); # No real change 18298bcea973SRichard Lowe $state = 1; 18303cb02613SRichard Lowe chomp $msg; 18313cb02613SRichard Lowe $files{$fname} .= $msg; 18328bcea973SRichard Lowe } else { 18338bcea973SRichard Lowe if ($state == 1) { 18348bcea973SRichard Lowe $state = 0; 18358bcea973SRichard Lowe $msg = /^\n/ ? "" : "\n"; 18368bcea973SRichard Lowe } 18378bcea973SRichard Lowe $msg .= "$_\n" if ($_); 18388bcea973SRichard Lowe } 18398bcea973SRichard Lowe } 18408bcea973SRichard Lowe close(F); 18418bcea973SRichard Lowe 18428bcea973SRichard Lowe for (sort keys %files) { 18438bcea973SRichard Lowe if ($realfiles{$_} ne $_) { 18443cb02613SRichard Lowe print "$_ $realfiles{$_}\n$files{$_}\n\n"; 18458bcea973SRichard Lowe } else { 18463cb02613SRichard Lowe print "$_\n$files{$_}\n\n" 18478bcea973SRichard Lowe } 18488bcea973SRichard Lowe }' ${parent} > $TMPFLIST 18498bcea973SRichard Lowe 18508bcea973SRichard Lowe wxfile=$TMPFLIST 18518bcea973SRichard Lowe} 18528bcea973SRichard Lowe 18538bcea973SRichard Lowe# 18548bcea973SRichard Lowe# flist_from_git 18558bcea973SRichard Lowe# Build a wx-style active list, and hand it off to flist_from_wx 18568bcea973SRichard Lowe# 18578bcea973SRichard Lowefunction flist_from_git 18588bcea973SRichard Lowe{ 18598bcea973SRichard Lowe typeset child=$1 18608bcea973SRichard Lowe typeset parent=$2 18618bcea973SRichard Lowe 18628bcea973SRichard Lowe print " File list from: git ...\c" 18638bcea973SRichard Lowe git_wxfile "$child" "$parent"; 18648bcea973SRichard Lowe 18658bcea973SRichard Lowe # flist_from_wx prints the Done, so we don't have to. 18668bcea973SRichard Lowe flist_from_wx $TMPFLIST 18678bcea973SRichard Lowe} 18688bcea973SRichard Lowe 18698bcea973SRichard Lowe# 1870cdf0c1d5Smjnelson# flist_from_subversion 1871cdf0c1d5Smjnelson# 1872cdf0c1d5Smjnelson# Generate the file list by extracting file names from svn status. 1873cdf0c1d5Smjnelson# 1874cdf0c1d5Smjnelsonfunction flist_from_subversion 1875cdf0c1d5Smjnelson{ 1876cdf0c1d5Smjnelson CWS=$1 1877cdf0c1d5Smjnelson OLDPWD=$2 1878cdf0c1d5Smjnelson 1879cdf0c1d5Smjnelson cd $CWS 1880cdf0c1d5Smjnelson print -u2 " File list from: svn status ... \c" 1881cdf0c1d5Smjnelson svn status | $AWK '/^[ACDMR]/ { print $NF }' > $FLIST 1882cdf0c1d5Smjnelson print -u2 " Done." 1883cdf0c1d5Smjnelson cd $OLDPWD 1884cdf0c1d5Smjnelson} 1885cdf0c1d5Smjnelson 1886daaffb31Sdpfunction env_from_flist 1887daaffb31Sdp{ 1888daaffb31Sdp [[ -r $FLIST ]] || return 1889daaffb31Sdp 1890daaffb31Sdp # 1891daaffb31Sdp # Use "eval" to set env variables that are listed in the file 1892daaffb31Sdp # list. Then copy those into our local versions of those 1893daaffb31Sdp # variables if they have not been set already. 1894daaffb31Sdp # 1895b0088928SVladimir Kotal eval `$SED -e "s/#.*$//" $FLIST | $GREP = ` 18967c478bd9Sstevel@tonic-gate 1897cdf0c1d5Smjnelson if [[ -z $codemgr_ws && -n $CODEMGR_WS ]]; then 1898cdf0c1d5Smjnelson codemgr_ws=$CODEMGR_WS 1899cdf0c1d5Smjnelson export CODEMGR_WS 1900cdf0c1d5Smjnelson fi 19017c478bd9Sstevel@tonic-gate 1902daaffb31Sdp # 1903daaffb31Sdp # Check to see if CODEMGR_PARENT is set in the flist file. 1904daaffb31Sdp # 1905cdf0c1d5Smjnelson if [[ -z $codemgr_parent && -n $CODEMGR_PARENT ]]; then 1906daaffb31Sdp codemgr_parent=$CODEMGR_PARENT 1907cdf0c1d5Smjnelson export CODEMGR_PARENT 1908daaffb31Sdp fi 1909daaffb31Sdp} 1910daaffb31Sdp 191114983201Sdpfunction look_for_prog 191214983201Sdp{ 191314983201Sdp typeset path 191414983201Sdp typeset ppath 191514983201Sdp typeset progname=$1 191614983201Sdp 191714983201Sdp ppath=$PATH 191814983201Sdp ppath=$ppath:/usr/sfw/bin:/usr/bin:/usr/sbin 191914983201Sdp ppath=$ppath:/opt/teamware/bin:/opt/onbld/bin 1920cdf0c1d5Smjnelson ppath=$ppath:/opt/onbld/bin/`uname -p` 192114983201Sdp 192214983201Sdp PATH=$ppath prog=`whence $progname` 192314983201Sdp if [[ -n $prog ]]; then 192414983201Sdp print $prog 192514983201Sdp fi 192614983201Sdp} 192714983201Sdp 1928cdf0c1d5Smjnelsonfunction get_file_mode 1929cdf0c1d5Smjnelson{ 1930cdf0c1d5Smjnelson $PERL -e ' 1931cdf0c1d5Smjnelson if (@stat = stat($ARGV[0])) { 1932cdf0c1d5Smjnelson $mode = $stat[2] & 0777; 1933cdf0c1d5Smjnelson printf "%03o\n", $mode; 1934cdf0c1d5Smjnelson exit 0; 1935cdf0c1d5Smjnelson } else { 1936cdf0c1d5Smjnelson exit 1; 1937cdf0c1d5Smjnelson } 1938cdf0c1d5Smjnelson ' $1 1939cdf0c1d5Smjnelson} 1940cdf0c1d5Smjnelson 1941cdf0c1d5Smjnelsonfunction build_old_new_teamware 1942cdf0c1d5Smjnelson{ 1943cdf0c1d5Smjnelson typeset olddir="$1" 1944cdf0c1d5Smjnelson typeset newdir="$2" 1945cdf0c1d5Smjnelson 1946cdf0c1d5Smjnelson # If the child's version doesn't exist then 1947cdf0c1d5Smjnelson # get a readonly copy. 1948cdf0c1d5Smjnelson 1949cdf0c1d5Smjnelson if [[ ! -f $CWS/$DIR/$F && -f $CWS/$DIR/SCCS/s.$F ]]; then 1950cdf0c1d5Smjnelson $SCCS get -s -p $CWS/$DIR/$F > $CWS/$DIR/$F 1951cdf0c1d5Smjnelson fi 1952cdf0c1d5Smjnelson 1953cdf0c1d5Smjnelson # The following two sections propagate file permissions the 1954cdf0c1d5Smjnelson # same way SCCS does. If the file is already under version 1955cdf0c1d5Smjnelson # control, always use permissions from the SCCS/s.file. If 1956cdf0c1d5Smjnelson # the file is not under SCCS control, use permissions from the 1957cdf0c1d5Smjnelson # working copy. In all cases, the file copied to the webrev 1958cdf0c1d5Smjnelson # is set to read only, and group/other permissions are set to 1959cdf0c1d5Smjnelson # match those of the file owner. This way, even if the file 1960cdf0c1d5Smjnelson # is currently checked out, the webrev will display the final 1961cdf0c1d5Smjnelson # permissions that would result after check in. 1962cdf0c1d5Smjnelson 1963cdf0c1d5Smjnelson # 1964cdf0c1d5Smjnelson # Snag new version of file. 1965cdf0c1d5Smjnelson # 1966cdf0c1d5Smjnelson rm -f $newdir/$DIR/$F 1967cdf0c1d5Smjnelson cp $CWS/$DIR/$F $newdir/$DIR/$F 1968cdf0c1d5Smjnelson if [[ -f $CWS/$DIR/SCCS/s.$F ]]; then 1969cdf0c1d5Smjnelson chmod `get_file_mode $CWS/$DIR/SCCS/s.$F` \ 1970cdf0c1d5Smjnelson $newdir/$DIR/$F 1971cdf0c1d5Smjnelson fi 1972cdf0c1d5Smjnelson chmod u-w,go=u $newdir/$DIR/$F 1973cdf0c1d5Smjnelson 1974cdf0c1d5Smjnelson # 1975cdf0c1d5Smjnelson # Get the parent's version of the file. First see whether the 1976cdf0c1d5Smjnelson # child's version is checked out and get the parent's version 1977cdf0c1d5Smjnelson # with keywords expanded or unexpanded as appropriate. 1978cdf0c1d5Smjnelson # 1979cdf0c1d5Smjnelson if [[ -f $PWS/$PDIR/$PF && ! -f $PWS/$PDIR/SCCS/s.$PF && \ 1980cdf0c1d5Smjnelson ! -f $PWS/$PDIR/SCCS/p.$PF ]]; then 1981cdf0c1d5Smjnelson # Parent is not a real workspace, but just a raw 1982cdf0c1d5Smjnelson # directory tree - use the file that's there as 1983cdf0c1d5Smjnelson # the old file. 1984cdf0c1d5Smjnelson 1985cdf0c1d5Smjnelson rm -f $olddir/$PDIR/$PF 1986cdf0c1d5Smjnelson cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF 1987cdf0c1d5Smjnelson else 1988cdf0c1d5Smjnelson if [[ -f $PWS/$PDIR/SCCS/s.$PF ]]; then 1989cdf0c1d5Smjnelson real_parent=$PWS 1990cdf0c1d5Smjnelson else 1991cdf0c1d5Smjnelson real_parent=$RWS 1992cdf0c1d5Smjnelson fi 1993cdf0c1d5Smjnelson 1994cdf0c1d5Smjnelson rm -f $olddir/$PDIR/$PF 1995cdf0c1d5Smjnelson 1996cdf0c1d5Smjnelson if [[ -f $real_parent/$PDIR/$PF ]]; then 1997cdf0c1d5Smjnelson if [ -f $CWS/$DIR/SCCS/p.$F ]; then 1998cdf0c1d5Smjnelson $SCCS get -s -p -k $real_parent/$PDIR/$PF > \ 1999cdf0c1d5Smjnelson $olddir/$PDIR/$PF 2000cdf0c1d5Smjnelson else 2001cdf0c1d5Smjnelson $SCCS get -s -p $real_parent/$PDIR/$PF > \ 2002cdf0c1d5Smjnelson $olddir/$PDIR/$PF 2003cdf0c1d5Smjnelson fi 2004cdf0c1d5Smjnelson chmod `get_file_mode $real_parent/$PDIR/SCCS/s.$PF` \ 2005cdf0c1d5Smjnelson $olddir/$PDIR/$PF 2006cdf0c1d5Smjnelson fi 2007cdf0c1d5Smjnelson fi 2008cdf0c1d5Smjnelson if [[ -f $olddir/$PDIR/$PF ]]; then 2009cdf0c1d5Smjnelson chmod u-w,go=u $olddir/$PDIR/$PF 2010cdf0c1d5Smjnelson fi 2011cdf0c1d5Smjnelson} 2012cdf0c1d5Smjnelson 2013cdf0c1d5Smjnelsonfunction build_old_new_mercurial 2014cdf0c1d5Smjnelson{ 2015cdf0c1d5Smjnelson typeset olddir="$1" 2016cdf0c1d5Smjnelson typeset newdir="$2" 2017cdf0c1d5Smjnelson typeset old_mode= 2018cdf0c1d5Smjnelson typeset new_mode= 2019cdf0c1d5Smjnelson typeset file 2020cdf0c1d5Smjnelson 2021cdf0c1d5Smjnelson # 2022cdf0c1d5Smjnelson # Get old file mode, from the parent revision manifest entry. 2023cdf0c1d5Smjnelson # Mercurial only stores a "file is executable" flag, but the 2024cdf0c1d5Smjnelson # manifest will display an octal mode "644" or "755". 2025cdf0c1d5Smjnelson # 2026cdf0c1d5Smjnelson if [[ "$PDIR" == "." ]]; then 2027cdf0c1d5Smjnelson file="$PF" 2028cdf0c1d5Smjnelson else 2029cdf0c1d5Smjnelson file="$PDIR/$PF" 2030cdf0c1d5Smjnelson fi 2031b0088928SVladimir Kotal file=`echo $file | $SED 's#/#\\\/#g'` 2032cdf0c1d5Smjnelson # match the exact filename, and return only the permission digits 2033b0088928SVladimir Kotal old_mode=`$SED -n -e "/^\\(...\\) . ${file}$/s//\\1/p" \ 2034cdf0c1d5Smjnelson < $HG_PARENT_MANIFEST` 2035cdf0c1d5Smjnelson 2036cdf0c1d5Smjnelson # 2037cdf0c1d5Smjnelson # Get new file mode, directly from the filesystem. 2038cdf0c1d5Smjnelson # Normalize the mode to match Mercurial's behavior. 2039cdf0c1d5Smjnelson # 2040cdf0c1d5Smjnelson new_mode=`get_file_mode $CWS/$DIR/$F` 2041cdf0c1d5Smjnelson if [[ -n "$new_mode" ]]; then 2042cdf0c1d5Smjnelson if [[ "$new_mode" = *[1357]* ]]; then 2043cdf0c1d5Smjnelson new_mode=755 2044cdf0c1d5Smjnelson else 2045cdf0c1d5Smjnelson new_mode=644 2046cdf0c1d5Smjnelson fi 2047cdf0c1d5Smjnelson fi 2048cdf0c1d5Smjnelson 2049cdf0c1d5Smjnelson # 2050cdf0c1d5Smjnelson # new version of the file. 2051cdf0c1d5Smjnelson # 2052cdf0c1d5Smjnelson rm -rf $newdir/$DIR/$F 2053cdf0c1d5Smjnelson if [[ -e $CWS/$DIR/$F ]]; then 2054cdf0c1d5Smjnelson cp $CWS/$DIR/$F $newdir/$DIR/$F 2055cdf0c1d5Smjnelson if [[ -n $new_mode ]]; then 2056cdf0c1d5Smjnelson chmod $new_mode $newdir/$DIR/$F 2057cdf0c1d5Smjnelson else 2058cdf0c1d5Smjnelson # should never happen 2059cdf0c1d5Smjnelson print -u2 "ERROR: set mode of $newdir/$DIR/$F" 2060cdf0c1d5Smjnelson fi 2061cdf0c1d5Smjnelson fi 2062cdf0c1d5Smjnelson 2063cdf0c1d5Smjnelson # 2064cdf0c1d5Smjnelson # parent's version of the file 2065cdf0c1d5Smjnelson # 2066cdf0c1d5Smjnelson # Note that we get this from the last version common to both 2067cdf0c1d5Smjnelson # ourselves and the parent. References are via $CWS since we have no 2068cdf0c1d5Smjnelson # guarantee that the parent workspace is reachable via the filesystem. 2069cdf0c1d5Smjnelson # 2070cdf0c1d5Smjnelson if [[ -n $parent_webrev && -e $PWS/$PDIR/$PF ]]; then 2071cdf0c1d5Smjnelson cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF 2072cdf0c1d5Smjnelson elif [[ -n $HG_PARENT ]]; then 2073cdf0c1d5Smjnelson hg cat -R $CWS -r $HG_PARENT $CWS/$PDIR/$PF > \ 2074cdf0c1d5Smjnelson $olddir/$PDIR/$PF 2>/dev/null 2075cdf0c1d5Smjnelson 207602d26c39SVladimir Kotal if (( $? != 0 )); then 2077cdf0c1d5Smjnelson rm -f $olddir/$PDIR/$PF 2078cdf0c1d5Smjnelson else 2079cdf0c1d5Smjnelson if [[ -n $old_mode ]]; then 2080cdf0c1d5Smjnelson chmod $old_mode $olddir/$PDIR/$PF 2081cdf0c1d5Smjnelson else 2082cdf0c1d5Smjnelson # should never happen 2083cdf0c1d5Smjnelson print -u2 "ERROR: set mode of $olddir/$PDIR/$PF" 2084cdf0c1d5Smjnelson fi 2085cdf0c1d5Smjnelson fi 2086cdf0c1d5Smjnelson fi 2087cdf0c1d5Smjnelson} 2088cdf0c1d5Smjnelson 20898bcea973SRichard Lowefunction build_old_new_git 20908bcea973SRichard Lowe{ 20918bcea973SRichard Lowe typeset olddir="$1" 20928bcea973SRichard Lowe typeset newdir="$2" 20938bcea973SRichard Lowe typeset o_mode= 20948bcea973SRichard Lowe typeset n_mode= 20958bcea973SRichard Lowe typeset o_object= 20968bcea973SRichard Lowe typeset n_object= 20978bcea973SRichard Lowe typeset OWD=$PWD 20988bcea973SRichard Lowe typeset file 20998bcea973SRichard Lowe typeset type 21008bcea973SRichard Lowe 21018bcea973SRichard Lowe cd $CWS 21028bcea973SRichard Lowe 21038bcea973SRichard Lowe # 21048bcea973SRichard Lowe # Get old file and its mode from the git object tree 21058bcea973SRichard Lowe # 21068bcea973SRichard Lowe if [[ "$PDIR" == "." ]]; then 21078bcea973SRichard Lowe file="$PF" 21088bcea973SRichard Lowe else 21098bcea973SRichard Lowe file="$PDIR/$PF" 21108bcea973SRichard Lowe fi 21118bcea973SRichard Lowe 21128bcea973SRichard Lowe if [[ -n $parent_webrev && -e $PWS/$PDIR/$PF ]]; then 21138bcea973SRichard Lowe cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF 21148bcea973SRichard Lowe else 21158bcea973SRichard Lowe $GIT ls-tree $GIT_PARENT $file | read o_mode type o_object junk 21168bcea973SRichard Lowe $GIT cat-file $type $o_object > $olddir/$file 2>/dev/null 21178bcea973SRichard Lowe 21188bcea973SRichard Lowe if (( $? != 0 )); then 21198bcea973SRichard Lowe rm -f $olddir/$file 21208bcea973SRichard Lowe elif [[ -n $o_mode ]]; then 21218bcea973SRichard Lowe # Strip the first 3 digits, to get a regular octal mode 21228bcea973SRichard Lowe o_mode=${o_mode/???/} 21238bcea973SRichard Lowe chmod $o_mode $olddir/$file 21248bcea973SRichard Lowe else 21258bcea973SRichard Lowe # should never happen 21268bcea973SRichard Lowe print -u2 "ERROR: set mode of $olddir/$file" 21278bcea973SRichard Lowe fi 21288bcea973SRichard Lowe fi 21298bcea973SRichard Lowe 21308bcea973SRichard Lowe # 21318bcea973SRichard Lowe # new version of the file. 21328bcea973SRichard Lowe # 21338bcea973SRichard Lowe if [[ "$DIR" == "." ]]; then 21348bcea973SRichard Lowe file="$F" 21358bcea973SRichard Lowe else 21368bcea973SRichard Lowe file="$DIR/$F" 21378bcea973SRichard Lowe fi 21388bcea973SRichard Lowe rm -rf $newdir/$file 21398bcea973SRichard Lowe 21408bcea973SRichard Lowe if [[ -e $CWS/$DIR/$F ]]; then 21418bcea973SRichard Lowe cp $CWS/$DIR/$F $newdir/$DIR/$F 21428bcea973SRichard Lowe chmod $(get_file_mode $CWS/$DIR/$F) $newdir/$DIR/$F 21438bcea973SRichard Lowe fi 21448bcea973SRichard Lowe cd $OWD 21458bcea973SRichard Lowe} 21468bcea973SRichard Lowe 2147cdf0c1d5Smjnelsonfunction build_old_new_subversion 2148cdf0c1d5Smjnelson{ 2149cdf0c1d5Smjnelson typeset olddir="$1" 2150cdf0c1d5Smjnelson typeset newdir="$2" 2151cdf0c1d5Smjnelson 2152cdf0c1d5Smjnelson # Snag new version of file. 2153cdf0c1d5Smjnelson rm -f $newdir/$DIR/$F 2154cdf0c1d5Smjnelson [[ -e $CWS/$DIR/$F ]] && cp $CWS/$DIR/$F $newdir/$DIR/$F 2155cdf0c1d5Smjnelson 2156cdf0c1d5Smjnelson if [[ -n $PWS && -e $PWS/$PDIR/$PF ]]; then 2157cdf0c1d5Smjnelson cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF 2158cdf0c1d5Smjnelson else 2159cdf0c1d5Smjnelson # Get the parent's version of the file. 2160cdf0c1d5Smjnelson svn status $CWS/$DIR/$F | read stat file 2161cdf0c1d5Smjnelson if [[ $stat != "A" ]]; then 2162cdf0c1d5Smjnelson svn cat -r BASE $CWS/$DIR/$F > $olddir/$PDIR/$PF 2163cdf0c1d5Smjnelson fi 2164cdf0c1d5Smjnelson fi 2165cdf0c1d5Smjnelson} 2166cdf0c1d5Smjnelson 2167cdf0c1d5Smjnelsonfunction build_old_new_unknown 2168cdf0c1d5Smjnelson{ 2169cdf0c1d5Smjnelson typeset olddir="$1" 2170cdf0c1d5Smjnelson typeset newdir="$2" 2171cdf0c1d5Smjnelson 2172cdf0c1d5Smjnelson # 2173cdf0c1d5Smjnelson # Snag new version of file. 2174cdf0c1d5Smjnelson # 2175cdf0c1d5Smjnelson rm -f $newdir/$DIR/$F 2176cdf0c1d5Smjnelson [[ -e $CWS/$DIR/$F ]] && cp $CWS/$DIR/$F $newdir/$DIR/$F 2177cdf0c1d5Smjnelson 2178cdf0c1d5Smjnelson # 2179cdf0c1d5Smjnelson # Snag the parent's version of the file. 2180cdf0c1d5Smjnelson # 2181cdf0c1d5Smjnelson if [[ -f $PWS/$PDIR/$PF ]]; then 2182cdf0c1d5Smjnelson rm -f $olddir/$PDIR/$PF 2183cdf0c1d5Smjnelson cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF 2184cdf0c1d5Smjnelson fi 2185cdf0c1d5Smjnelson} 2186cdf0c1d5Smjnelson 2187cdf0c1d5Smjnelsonfunction build_old_new 2188cdf0c1d5Smjnelson{ 2189cdf0c1d5Smjnelson typeset WDIR=$1 2190cdf0c1d5Smjnelson typeset PWS=$2 2191cdf0c1d5Smjnelson typeset PDIR=$3 2192cdf0c1d5Smjnelson typeset PF=$4 2193cdf0c1d5Smjnelson typeset CWS=$5 2194cdf0c1d5Smjnelson typeset DIR=$6 2195cdf0c1d5Smjnelson typeset F=$7 2196cdf0c1d5Smjnelson 2197cdf0c1d5Smjnelson typeset olddir="$WDIR/raw_files/old" 2198cdf0c1d5Smjnelson typeset newdir="$WDIR/raw_files/new" 2199cdf0c1d5Smjnelson 2200cdf0c1d5Smjnelson mkdir -p $olddir/$PDIR 2201cdf0c1d5Smjnelson mkdir -p $newdir/$DIR 2202cdf0c1d5Smjnelson 2203cdf0c1d5Smjnelson if [[ $SCM_MODE == "teamware" ]]; then 2204cdf0c1d5Smjnelson build_old_new_teamware "$olddir" "$newdir" 2205cdf0c1d5Smjnelson elif [[ $SCM_MODE == "mercurial" ]]; then 2206cdf0c1d5Smjnelson build_old_new_mercurial "$olddir" "$newdir" 22078bcea973SRichard Lowe elif [[ $SCM_MODE == "git" ]]; then 22088bcea973SRichard Lowe build_old_new_git "$olddir" "$newdir" 2209cdf0c1d5Smjnelson elif [[ $SCM_MODE == "subversion" ]]; then 2210cdf0c1d5Smjnelson build_old_new_subversion "$olddir" "$newdir" 2211cdf0c1d5Smjnelson elif [[ $SCM_MODE == "unknown" ]]; then 2212cdf0c1d5Smjnelson build_old_new_unknown "$olddir" "$newdir" 2213cdf0c1d5Smjnelson fi 2214cdf0c1d5Smjnelson 2215cdf0c1d5Smjnelson if [[ ! -f $olddir/$PDIR/$PF && ! -f $newdir/$DIR/$F ]]; then 2216cdf0c1d5Smjnelson print "*** Error: file not in parent or child" 2217cdf0c1d5Smjnelson return 1 2218cdf0c1d5Smjnelson fi 2219cdf0c1d5Smjnelson return 0 2220cdf0c1d5Smjnelson} 2221cdf0c1d5Smjnelson 2222cdf0c1d5Smjnelson 2223daaffb31Sdp# 2224daaffb31Sdp# Usage message. 2225daaffb31Sdp# 2226daaffb31Sdpfunction usage 2227daaffb31Sdp{ 2228daaffb31Sdp print 'Usage:\twebrev [common-options] 2229daaffb31Sdp webrev [common-options] ( <file> | - ) 2230daaffb31Sdp webrev [common-options] -w <wx file> 2231daaffb31Sdp 2232daaffb31SdpOptions: 22330fd2682eSMark J. Nelson -C <filename>: Use <filename> for the information tracking configuration. 2234ba44d8a2SVladimir Kotal -D: delete remote webrev 2235daaffb31Sdp -i <filename>: Include <filename> in the index.html file. 22360fd2682eSMark J. Nelson -I <filename>: Use <filename> for the information tracking registry. 2237ba44d8a2SVladimir Kotal -n: do not generate the webrev (useful with -U) 2238ba44d8a2SVladimir Kotal -O: Print bugids/arc cases suitable for OpenSolaris. 2239daaffb31Sdp -o <outdir>: Output webrev to specified directory. 2240daaffb31Sdp -p <compare-against>: Use specified parent wkspc or basis for comparison 224102d26c39SVladimir Kotal -t <remote_target>: Specify remote destination for webrev upload 224202d26c39SVladimir Kotal -U: upload the webrev to remote destination 2243daaffb31Sdp -w <wxfile>: Use specified wx active file. 2244daaffb31Sdp 2245daaffb31SdpEnvironment: 2246daaffb31Sdp WDIR: Control the output directory. 2247ba44d8a2SVladimir Kotal WEBREV_TRASH_DIR: Set directory for webrev delete. 2248daaffb31Sdp 2249cdf0c1d5SmjnelsonSCM Specific Options: 2250cdf0c1d5Smjnelson TeamWare: webrev [common-options] -l [arguments to 'putback'] 2251cdf0c1d5Smjnelson 2252daaffb31SdpSCM Environment: 2253cdf0c1d5Smjnelson CODEMGR_WS: Workspace location. 2254cdf0c1d5Smjnelson CODEMGR_PARENT: Parent workspace location. 2255daaffb31Sdp' 2256daaffb31Sdp 2257daaffb31Sdp exit 2 2258daaffb31Sdp} 2259daaffb31Sdp 2260daaffb31Sdp# 2261daaffb31Sdp# 2262daaffb31Sdp# Main program starts here 2263daaffb31Sdp# 2264daaffb31Sdp# 2265daaffb31Sdp 2266daaffb31Sdptrap "rm -f /tmp/$$.* ; exit" 0 1 2 3 15 2267daaffb31Sdp 2268daaffb31Sdpset +o noclobber 2269daaffb31Sdp 22708bcea973SRichard LowePATH=$(/bin/dirname "$(whence $0)"):$PATH 2271cdf0c1d5Smjnelson 227214983201Sdp[[ -z $WDIFF ]] && WDIFF=`look_for_prog wdiff` 227314983201Sdp[[ -z $WX ]] && WX=`look_for_prog wx` 2274cdf0c1d5Smjnelson[[ -z $HG_ACTIVE ]] && HG_ACTIVE=`look_for_prog hg-active` 22758bcea973SRichard Lowe[[ -z $GIT ]] && GIT=`look_for_prog git` 2276cdf0c1d5Smjnelson[[ -z $WHICH_SCM ]] && WHICH_SCM=`look_for_prog which_scm` 227714983201Sdp[[ -z $CODEREVIEW ]] && CODEREVIEW=`look_for_prog codereview` 227814983201Sdp[[ -z $PS2PDF ]] && PS2PDF=`look_for_prog ps2pdf` 227914983201Sdp[[ -z $PERL ]] && PERL=`look_for_prog perl` 228002d26c39SVladimir Kotal[[ -z $RSYNC ]] && RSYNC=`look_for_prog rsync` 2281cdf0c1d5Smjnelson[[ -z $SCCS ]] && SCCS=`look_for_prog sccs` 2282cdf0c1d5Smjnelson[[ -z $AWK ]] && AWK=`look_for_prog nawk` 2283cdf0c1d5Smjnelson[[ -z $AWK ]] && AWK=`look_for_prog gawk` 2284cdf0c1d5Smjnelson[[ -z $AWK ]] && AWK=`look_for_prog awk` 228502d26c39SVladimir Kotal[[ -z $SCP ]] && SCP=`look_for_prog scp` 2286b0088928SVladimir Kotal[[ -z $SED ]] && SED=`look_for_prog sed` 228702d26c39SVladimir Kotal[[ -z $SFTP ]] && SFTP=`look_for_prog sftp` 2288e6ccc173SEdward Pilatowicz[[ -z $SORT ]] && SORT=`look_for_prog sort` 228902d26c39SVladimir Kotal[[ -z $MKTEMP ]] && MKTEMP=`look_for_prog mktemp` 229002d26c39SVladimir Kotal[[ -z $GREP ]] && GREP=`look_for_prog grep` 2291ba44d8a2SVladimir Kotal[[ -z $FIND ]] && FIND=`look_for_prog find` 2292cdf0c1d5Smjnelson 2293ba44d8a2SVladimir Kotal# set name of trash directory for remote webrev deletion 2294ba44d8a2SVladimir KotalTRASH_DIR=".trash" 2295ba44d8a2SVladimir Kotal[[ -n $WEBREV_TRASH_DIR ]] && TRASH_DIR=$WEBREV_TRASH_DIR 229614983201Sdp 229714983201Sdpif [[ ! -x $PERL ]]; then 229814983201Sdp print -u2 "Error: No perl interpreter found. Exiting." 229914983201Sdp exit 1 2300daaffb31Sdpfi 230114983201Sdp 2302cdf0c1d5Smjnelsonif [[ ! -x $WHICH_SCM ]]; then 2303cdf0c1d5Smjnelson print -u2 "Error: Could not find which_scm. Exiting." 2304cdf0c1d5Smjnelson exit 1 2305cdf0c1d5Smjnelsonfi 2306cdf0c1d5Smjnelson 230714983201Sdp# 230814983201Sdp# These aren't fatal, but we want to note them to the user. 230914983201Sdp# We don't warn on the absence of 'wx' until later when we've 231014983201Sdp# determined that we actually need to try to invoke it. 231114983201Sdp# 231214983201Sdp[[ ! -x $CODEREVIEW ]] && print -u2 "WARNING: codereview(1) not found." 231314983201Sdp[[ ! -x $PS2PDF ]] && print -u2 "WARNING: ps2pdf(1) not found." 231414983201Sdp[[ ! -x $WDIFF ]] && print -u2 "WARNING: wdiff not found." 2315daaffb31Sdp 2316daaffb31Sdp# Declare global total counters. 2317daaffb31Sdpinteger TOTL TINS TDEL TMOD TUNC 2318daaffb31Sdp 2319ba44d8a2SVladimir Kotal# default remote host for upload/delete 2320ba44d8a2SVladimir Kotaltypeset -r DEFAULT_REMOTE_HOST="cr.opensolaris.org" 2321b0088928SVladimir Kotal# prefixes for upload targets 2322b0088928SVladimir Kotaltypeset -r rsync_prefix="rsync://" 2323b0088928SVladimir Kotaltypeset -r ssh_prefix="ssh://" 2324ba44d8a2SVladimir Kotal 23250fd2682eSMark J. NelsonCflag= 2326ba44d8a2SVladimir KotalDflag= 232714983201Sdpflist_mode= 232814983201Sdpflist_file= 2329daaffb31Sdpiflag= 23300fd2682eSMark J. NelsonIflag= 233102d26c39SVladimir Kotallflag= 233202d26c39SVladimir KotalNflag= 233302d26c39SVladimir Kotalnflag= 233402d26c39SVladimir KotalOflag= 2335daaffb31Sdpoflag= 2336daaffb31Sdppflag= 233702d26c39SVladimir Kotaltflag= 233802d26c39SVladimir Kotaluflag= 233902d26c39SVladimir KotalUflag= 2340daaffb31Sdpwflag= 234102d26c39SVladimir Kotalremote_target= 2342ba44d8a2SVladimir Kotal 2343ba44d8a2SVladimir Kotal# 2344ba44d8a2SVladimir Kotal# NOTE: when adding/removing options it is necessary to sync the list 2345ba44d8a2SVladimir Kotal# with usr/src/tools/onbld/hgext/cdm.py 2346ba44d8a2SVladimir Kotal# 234725cc4e45SVladimir Kotalwhile getopts "C:Di:I:lnNo:Op:t:Uw" opt 2348daaffb31Sdpdo 2349daaffb31Sdp case $opt in 23500fd2682eSMark J. Nelson C) Cflag=1 23510fd2682eSMark J. Nelson ITSCONF=$OPTARG;; 23520fd2682eSMark J. Nelson 2353ba44d8a2SVladimir Kotal D) Dflag=1;; 2354ba44d8a2SVladimir Kotal 2355daaffb31Sdp i) iflag=1 2356daaffb31Sdp INCLUDE_FILE=$OPTARG;; 2357daaffb31Sdp 23580fd2682eSMark J. Nelson I) Iflag=1 23590fd2682eSMark J. Nelson ITSREG=$OPTARG;; 23600fd2682eSMark J. Nelson 2361daaffb31Sdp # 2362daaffb31Sdp # If -l has been specified, we need to abort further options 2363daaffb31Sdp # processing, because subsequent arguments are going to be 2364daaffb31Sdp # arguments to 'putback -n'. 2365daaffb31Sdp # 2366daaffb31Sdp l) lflag=1 2367daaffb31Sdp break;; 2368daaffb31Sdp 236902d26c39SVladimir Kotal N) Nflag=1;; 237002d26c39SVladimir Kotal 237102d26c39SVladimir Kotal n) nflag=1;; 2372daaffb31Sdp 2373daaffb31Sdp O) Oflag=1;; 2374daaffb31Sdp 237502d26c39SVladimir Kotal o) oflag=1 23769d3952abSVladimir Kotal # Strip the trailing slash to correctly form remote target. 23779d3952abSVladimir Kotal WDIR=${OPTARG%/};; 237802d26c39SVladimir Kotal 237902d26c39SVladimir Kotal p) pflag=1 238002d26c39SVladimir Kotal codemgr_parent=$OPTARG;; 238102d26c39SVladimir Kotal 238202d26c39SVladimir Kotal t) tflag=1 238302d26c39SVladimir Kotal remote_target=$OPTARG;; 238402d26c39SVladimir Kotal 238502d26c39SVladimir Kotal U) Uflag=1;; 238602d26c39SVladimir Kotal 238702d26c39SVladimir Kotal w) wflag=1;; 23883df69ef3SDarren Moffat 2389daaffb31Sdp ?) usage;; 2390daaffb31Sdp esac 2391daaffb31Sdpdone 2392daaffb31Sdp 2393daaffb31SdpFLIST=/tmp/$$.flist 2394daaffb31Sdp 2395daaffb31Sdpif [[ -n $wflag && -n $lflag ]]; then 2396daaffb31Sdp usage 2397daaffb31Sdpfi 2398daaffb31Sdp 239902d26c39SVladimir Kotal# more sanity checking 240002d26c39SVladimir Kotalif [[ -n $nflag && -z $Uflag ]]; then 2401ba44d8a2SVladimir Kotal print "it does not make sense to skip webrev generation" \ 2402ba44d8a2SVladimir Kotal "without -U" 240302d26c39SVladimir Kotal exit 1 240402d26c39SVladimir Kotalfi 240502d26c39SVladimir Kotal 2406ba44d8a2SVladimir Kotalif [[ -n $tflag && -z $Uflag && -z $Dflag ]]; then 2407ba44d8a2SVladimir Kotal echo "remote target has to be used only for upload or delete" 240802d26c39SVladimir Kotal exit 1 240902d26c39SVladimir Kotalfi 241002d26c39SVladimir Kotal 2411daaffb31Sdp# 24122d9224a3SMark J. Nelson# For the invocation "webrev -n -U" with no other options, webrev will assume 24132d9224a3SMark J. Nelson# that the webrev exists in ${CWS}/webrev, but will upload it using the name 24142d9224a3SMark J. Nelson# $(basename ${CWS}). So we need to get CWS set before we skip any remaining 24152d9224a3SMark J. Nelson# logic. 24162d9224a3SMark J. Nelson# 24172d9224a3SMark J. Nelson$WHICH_SCM | read SCM_MODE junk || exit 1 24182d9224a3SMark J. Nelsonif [[ $SCM_MODE == "teamware" ]]; then 24192d9224a3SMark J. Nelson # 24202d9224a3SMark J. Nelson # Teamware priorities: 24212d9224a3SMark J. Nelson # 1. CODEMGR_WS from the environment 24222d9224a3SMark J. Nelson # 2. workspace name 24232d9224a3SMark J. Nelson # 24242d9224a3SMark J. Nelson [[ -z $codemgr_ws && -n $CODEMGR_WS ]] && codemgr_ws=$CODEMGR_WS 24252d9224a3SMark J. Nelson if [[ -n $codemgr_ws && ! -d $codemgr_ws ]]; then 24262d9224a3SMark J. Nelson print -u2 "$codemgr_ws: no such workspace" 24272d9224a3SMark J. Nelson exit 1 24282d9224a3SMark J. Nelson fi 24292d9224a3SMark J. Nelson [[ -z $codemgr_ws ]] && codemgr_ws=$(workspace name) 24302d9224a3SMark J. Nelson codemgr_ws=$(cd $codemgr_ws;print $PWD) 24312d9224a3SMark J. Nelson CODEMGR_WS=$codemgr_ws 24322d9224a3SMark J. Nelson CWS=$codemgr_ws 24332d9224a3SMark J. Nelsonelif [[ $SCM_MODE == "mercurial" ]]; then 24342d9224a3SMark J. Nelson # 24352d9224a3SMark J. Nelson # Mercurial priorities: 24362d9224a3SMark J. Nelson # 1. hg root from CODEMGR_WS environment variable 243778add226Sjmcp # 1a. hg root from CODEMGR_WS/usr/closed if we're somewhere under 243878add226Sjmcp # usr/closed when we run webrev 24392d9224a3SMark J. Nelson # 2. hg root from directory of invocation 24402d9224a3SMark J. Nelson # 244178add226Sjmcp if [[ ${PWD} =~ "usr/closed" ]]; then 244278add226Sjmcp testparent=${CODEMGR_WS}/usr/closed 244378add226Sjmcp # If we're in OpenSolaris mode, we enforce a minor policy: 244478add226Sjmcp # help to make sure the reviewer doesn't accidentally publish 244578add226Sjmcp # source which is under usr/closed 244678add226Sjmcp if [[ -n "$Oflag" ]]; then 244778add226Sjmcp print -u2 "OpenSolaris output not permitted with" \ 244878add226Sjmcp "usr/closed changes" 244978add226Sjmcp exit 1 245078add226Sjmcp fi 245178add226Sjmcp else 245278add226Sjmcp testparent=${CODEMGR_WS} 245378add226Sjmcp fi 245478add226Sjmcp [[ -z $codemgr_ws && -n $testparent ]] && \ 245578add226Sjmcp codemgr_ws=$(hg root -R $testparent 2>/dev/null) 24562d9224a3SMark J. Nelson [[ -z $codemgr_ws ]] && codemgr_ws=$(hg root 2>/dev/null) 24572d9224a3SMark J. Nelson CWS=$codemgr_ws 24588bcea973SRichard Loweelif [[ $SCM_MODE == "git" ]]; then 24598bcea973SRichard Lowe # 24608bcea973SRichard Lowe # Git priorities: 24618bcea973SRichard Lowe # 1. git rev-parse --git-dir from CODEMGR_WS environment variable 24628bcea973SRichard Lowe # 2. git rev-parse --git-dir from directory of invocation 24638bcea973SRichard Lowe # 24648bcea973SRichard Lowe [[ -z $codemgr_ws && -n $CODEMGR_WS ]] && \ 24658bcea973SRichard Lowe codemgr_ws=$($GIT --git-dir=$CODEMGR_WS/.git rev-parse --git-dir \ 24668bcea973SRichard Lowe 2>/dev/null) 24678bcea973SRichard Lowe [[ -z $codemgr_ws ]] && \ 24688bcea973SRichard Lowe codemgr_ws=$($GIT rev-parse --git-dir 2>/dev/null) 24698bcea973SRichard Lowe 24708bcea973SRichard Lowe if [[ "$codemgr_ws" == ".git" ]]; then 24718bcea973SRichard Lowe codemgr_ws="${PWD}/${codemgr_ws}" 24728bcea973SRichard Lowe fi 24738bcea973SRichard Lowe 24748bcea973SRichard Lowe codemgr_ws=$(dirname $codemgr_ws) # Lose the '/.git' 24758bcea973SRichard Lowe CWS="$codemgr_ws" 24762d9224a3SMark J. Nelsonelif [[ $SCM_MODE == "subversion" ]]; then 24772d9224a3SMark J. Nelson # 24782d9224a3SMark J. Nelson # Subversion priorities: 24792d9224a3SMark J. Nelson # 1. CODEMGR_WS from environment 24802d9224a3SMark J. Nelson # 2. Relative path from current directory to SVN repository root 24812d9224a3SMark J. Nelson # 24822d9224a3SMark J. Nelson if [[ -n $CODEMGR_WS && -d $CODEMGR_WS/.svn ]]; then 24832d9224a3SMark J. Nelson CWS=$CODEMGR_WS 24842d9224a3SMark J. Nelson else 24852d9224a3SMark J. Nelson svn info | while read line; do 24862d9224a3SMark J. Nelson if [[ $line == "URL: "* ]]; then 24872d9224a3SMark J. Nelson url=${line#URL: } 24882d9224a3SMark J. Nelson elif [[ $line == "Repository Root: "* ]]; then 24892d9224a3SMark J. Nelson repo=${line#Repository Root: } 24902d9224a3SMark J. Nelson fi 24912d9224a3SMark J. Nelson done 24922d9224a3SMark J. Nelson 24932d9224a3SMark J. Nelson rel=${url#$repo} 24942d9224a3SMark J. Nelson CWS=${PWD%$rel} 24952d9224a3SMark J. Nelson fi 24962d9224a3SMark J. Nelsonfi 24972d9224a3SMark J. Nelson 24982d9224a3SMark J. Nelson# 24992d9224a3SMark J. Nelson# If no SCM has been determined, take either the environment setting 25002d9224a3SMark J. Nelson# setting for CODEMGR_WS, or the current directory if that wasn't set. 25012d9224a3SMark J. Nelson# 25022d9224a3SMark J. Nelsonif [[ -z ${CWS} ]]; then 25032d9224a3SMark J. Nelson CWS=${CODEMGR_WS:-.} 25042d9224a3SMark J. Nelsonfi 25052d9224a3SMark J. Nelson 25062d9224a3SMark J. Nelson# 25070fd2682eSMark J. Nelson# If the command line options indicate no webrev generation, either 25080fd2682eSMark J. Nelson# explicitly (-n) or implicitly (-D but not -U), then there's a whole 25090fd2682eSMark J. Nelson# ton of logic we can skip. 25100fd2682eSMark J. Nelson# 25110fd2682eSMark J. Nelson# Instead of increasing indentation, we intentionally leave this loop 25120fd2682eSMark J. Nelson# body open here, and exit via break from multiple points within. 25130fd2682eSMark J. Nelson# Search for DO_EVERYTHING below to find the break points and closure. 25140fd2682eSMark J. Nelson# 25150fd2682eSMark J. Nelsonfor do_everything in 1; do 25160fd2682eSMark J. Nelson 25170fd2682eSMark J. Nelson# DO_EVERYTHING: break point 25180fd2682eSMark J. Nelsonif [[ -n $nflag || ( -z $Uflag && -n $Dflag ) ]]; then 25190fd2682eSMark J. Nelson break 25200fd2682eSMark J. Nelsonfi 25210fd2682eSMark J. Nelson 25220fd2682eSMark J. Nelson# 2523daaffb31Sdp# If this manually set as the parent, and it appears to be an earlier webrev, 2524daaffb31Sdp# then note that fact and set the parent to the raw_files/new subdirectory. 2525daaffb31Sdp# 2526daaffb31Sdpif [[ -n $pflag && -d $codemgr_parent/raw_files/new ]]; then 25278bcea973SRichard Lowe parent_webrev=$(readlink -f "$codemgr_parent") 25288bcea973SRichard Lowe codemgr_parent=$(readlink -f "$codemgr_parent/raw_files/new") 2529daaffb31Sdpfi 2530daaffb31Sdp 2531daaffb31Sdpif [[ -z $wflag && -z $lflag ]]; then 2532daaffb31Sdp shift $(($OPTIND - 1)) 2533daaffb31Sdp 2534daaffb31Sdp if [[ $1 == "-" ]]; then 2535daaffb31Sdp cat > $FLIST 253614983201Sdp flist_mode="stdin" 253714983201Sdp flist_done=1 253814983201Sdp shift 2539daaffb31Sdp elif [[ -n $1 ]]; then 254014983201Sdp if [[ ! -r $1 ]]; then 2541daaffb31Sdp print -u2 "$1: no such file or not readable" 2542daaffb31Sdp usage 2543daaffb31Sdp fi 2544daaffb31Sdp cat $1 > $FLIST 254514983201Sdp flist_mode="file" 254614983201Sdp flist_file=$1 254714983201Sdp flist_done=1 254814983201Sdp shift 2549daaffb31Sdp else 255014983201Sdp flist_mode="auto" 2551daaffb31Sdp fi 2552daaffb31Sdpfi 2553daaffb31Sdp 2554daaffb31Sdp# 2555daaffb31Sdp# Before we go on to further consider -l and -w, work out which SCM we think 2556daaffb31Sdp# is in use. 2557daaffb31Sdp# 2558cdf0c1d5Smjnelsoncase "$SCM_MODE" in 25598bcea973SRichard Loweteamware|mercurial|git|subversion) 2560cdf0c1d5Smjnelson ;; 2561cdf0c1d5Smjnelsonunknown) 2562cdf0c1d5Smjnelson if [[ $flist_mode == "auto" ]]; then 2563cdf0c1d5Smjnelson print -u2 "Unable to determine SCM in use and file list not specified" 2564cdf0c1d5Smjnelson print -u2 "See which_scm(1) for SCM detection information." 25657c478bd9Sstevel@tonic-gate exit 1 25667c478bd9Sstevel@tonic-gate fi 2567cdf0c1d5Smjnelson ;; 2568cdf0c1d5Smjnelson*) 2569cdf0c1d5Smjnelson if [[ $flist_mode == "auto" ]]; then 2570cdf0c1d5Smjnelson print -u2 "Unsupported SCM in use ($SCM_MODE) and file list not specified" 2571cdf0c1d5Smjnelson exit 1 2572cdf0c1d5Smjnelson fi 2573cdf0c1d5Smjnelson ;; 2574cdf0c1d5Smjnelsonesac 25757c478bd9Sstevel@tonic-gate 2576daaffb31Sdpprint -u2 " SCM detected: $SCM_MODE" 2577daaffb31Sdp 2578daaffb31Sdpif [[ -n $lflag ]]; then 2579daaffb31Sdp # 2580daaffb31Sdp # If the -l flag is given instead of the name of a file list, 2581daaffb31Sdp # then generate the file list by extracting file names from a 2582daaffb31Sdp # putback -n. 2583daaffb31Sdp # 2584daaffb31Sdp shift $(($OPTIND - 1)) 2585cdf0c1d5Smjnelson if [[ $SCM_MODE == "teamware" ]]; then 2586daaffb31Sdp flist_from_teamware "$*" 2587cdf0c1d5Smjnelson else 2588cdf0c1d5Smjnelson print -u2 -- "Error: -l option only applies to TeamWare" 2589cdf0c1d5Smjnelson exit 1 2590cdf0c1d5Smjnelson fi 2591daaffb31Sdp flist_done=1 2592daaffb31Sdp shift $# 2593daaffb31Sdpelif [[ -n $wflag ]]; then 2594daaffb31Sdp # 2595daaffb31Sdp # If the -w is given then assume the file list is in Bonwick's "wx" 2596daaffb31Sdp # command format, i.e. pathname lines alternating with SCCS comment 2597daaffb31Sdp # lines with blank lines as separators. Use the SCCS comments later 2598daaffb31Sdp # in building the index.html file. 2599daaffb31Sdp # 2600daaffb31Sdp shift $(($OPTIND - 1)) 2601daaffb31Sdp wxfile=$1 2602daaffb31Sdp if [[ -z $wxfile && -n $CODEMGR_WS ]]; then 2603daaffb31Sdp if [[ -r $CODEMGR_WS/wx/active ]]; then 2604daaffb31Sdp wxfile=$CODEMGR_WS/wx/active 2605daaffb31Sdp fi 2606daaffb31Sdp fi 2607daaffb31Sdp 2608daaffb31Sdp [[ -z $wxfile ]] && print -u2 "wx file not specified, and could not " \ 2609daaffb31Sdp "be auto-detected (check \$CODEMGR_WS)" && exit 1 2610daaffb31Sdp 2611cdf0c1d5Smjnelson if [[ ! -r $wxfile ]]; then 2612cdf0c1d5Smjnelson print -u2 "$wxfile: no such file or not readable" 2613cdf0c1d5Smjnelson usage 2614cdf0c1d5Smjnelson fi 2615cdf0c1d5Smjnelson 2616daaffb31Sdp print -u2 " File list from: wx 'active' file '$wxfile' ... \c" 2617daaffb31Sdp flist_from_wx $wxfile 2618daaffb31Sdp flist_done=1 2619daaffb31Sdp if [[ -n "$*" ]]; then 2620daaffb31Sdp shift 2621daaffb31Sdp fi 262214983201Sdpelif [[ $flist_mode == "stdin" ]]; then 262314983201Sdp print -u2 " File list from: standard input" 262414983201Sdpelif [[ $flist_mode == "file" ]]; then 262514983201Sdp print -u2 " File list from: $flist_file" 2626daaffb31Sdpfi 2627daaffb31Sdp 2628daaffb31Sdpif [[ $# -gt 0 ]]; then 262914983201Sdp print -u2 "WARNING: unused arguments: $*" 2630daaffb31Sdpfi 2631daaffb31Sdp 26322d9224a3SMark J. Nelson# 26332d9224a3SMark J. Nelson# Before we entered the DO_EVERYTHING loop, we should have already set CWS 26342d9224a3SMark J. Nelson# and CODEMGR_WS as needed. Here, we set the parent workspace. 26352d9224a3SMark J. Nelson# 26362d9224a3SMark J. Nelson 2637daaffb31Sdpif [[ $SCM_MODE == "teamware" ]]; then 26382d9224a3SMark J. Nelson 2639daaffb31Sdp # 26402d9224a3SMark J. Nelson # Teamware priorities: 2641daaffb31Sdp # 26422d9224a3SMark J. Nelson # 1) via -p command line option 2643daaffb31Sdp # 2) in the user environment 2644daaffb31Sdp # 3) in the flist 26452d9224a3SMark J. Nelson # 4) automatically based on the workspace 2646daaffb31Sdp # 2647daaffb31Sdp 2648daaffb31Sdp # 26492d9224a3SMark J. Nelson # For 1, codemgr_parent will already be set. Here's 2: 2650daaffb31Sdp # 2651daaffb31Sdp [[ -z $codemgr_parent && -n $CODEMGR_PARENT ]] && \ 2652daaffb31Sdp codemgr_parent=$CODEMGR_PARENT 2653daaffb31Sdp if [[ -n $codemgr_parent && ! -d $codemgr_parent ]]; then 2654daaffb31Sdp print -u2 "$codemgr_parent: no such directory" 26557c478bd9Sstevel@tonic-gate exit 1 26567c478bd9Sstevel@tonic-gate fi 26577c478bd9Sstevel@tonic-gate 2658daaffb31Sdp # 2659daaffb31Sdp # If we're in auto-detect mode and we haven't already gotten the file 2660daaffb31Sdp # list, then see if we can get it by probing for wx. 2661daaffb31Sdp # 266214983201Sdp if [[ -z $flist_done && $flist_mode == "auto" && -n $codemgr_ws ]]; then 266314983201Sdp if [[ ! -x $WX ]]; then 266414983201Sdp print -u2 "WARNING: wx not found!" 2665daaffb31Sdp fi 26667c478bd9Sstevel@tonic-gate 2667daaffb31Sdp # 2668daaffb31Sdp # We need to use wx list -w so that we get renamed files, etc. 2669daaffb31Sdp # but only if a wx active file exists-- otherwise wx will 2670daaffb31Sdp # hang asking us to initialize our wx information. 2671daaffb31Sdp # 267214983201Sdp if [[ -x $WX && -f $codemgr_ws/wx/active ]]; then 2673daaffb31Sdp print -u2 " File list from: 'wx list -w' ... \c" 2674daaffb31Sdp $WX list -w > $FLIST 2675daaffb31Sdp $WX comments > /tmp/$$.wx_comments 2676daaffb31Sdp wxfile=/tmp/$$.wx_comments 2677daaffb31Sdp print -u2 "done" 2678daaffb31Sdp flist_done=1 2679daaffb31Sdp fi 2680daaffb31Sdp fi 2681daaffb31Sdp 2682daaffb31Sdp # 2683daaffb31Sdp # If by hook or by crook we've gotten a file list by now (perhaps 2684daaffb31Sdp # from the command line), eval it to extract environment variables from 26852d9224a3SMark J. Nelson # it: This is method 3 for finding the parent. 2686daaffb31Sdp # 2687daaffb31Sdp if [[ -z $flist_done ]]; then 2688daaffb31Sdp flist_from_teamware 2689daaffb31Sdp fi 26902d9224a3SMark J. Nelson env_from_flist 2691daaffb31Sdp 2692daaffb31Sdp # 2693daaffb31Sdp # (4) If we still don't have a value for codemgr_parent, get it 2694daaffb31Sdp # from workspace. 2695daaffb31Sdp # 2696daaffb31Sdp [[ -z $codemgr_parent ]] && codemgr_parent=`workspace parent` 2697daaffb31Sdp if [[ ! -d $codemgr_parent ]]; then 2698daaffb31Sdp print -u2 "$CODEMGR_PARENT: no such parent workspace" 2699daaffb31Sdp exit 1 2700daaffb31Sdp fi 2701daaffb31Sdp 2702daaffb31Sdp PWS=$codemgr_parent 2703cdf0c1d5Smjnelson 2704cdf0c1d5Smjnelson [[ -n $parent_webrev ]] && RWS=$(workspace parent $CWS) 2705cdf0c1d5Smjnelson 2706cdf0c1d5Smjnelsonelif [[ $SCM_MODE == "mercurial" ]]; then 2707cdf0c1d5Smjnelson # 2708cdf0c1d5Smjnelson # Parent can either be specified with -p 2709cdf0c1d5Smjnelson # Specified with CODEMGR_PARENT in the environment 2710cdf0c1d5Smjnelson # or taken from hg's default path. 2711cdf0c1d5Smjnelson # 2712cdf0c1d5Smjnelson 2713cdf0c1d5Smjnelson if [[ -z $codemgr_parent && -n $CODEMGR_PARENT ]]; then 2714cdf0c1d5Smjnelson codemgr_parent=$CODEMGR_PARENT 2715cdf0c1d5Smjnelson fi 2716cdf0c1d5Smjnelson 2717cdf0c1d5Smjnelson if [[ -z $codemgr_parent ]]; then 2718cdf0c1d5Smjnelson codemgr_parent=`hg path -R $codemgr_ws default 2>/dev/null` 2719cdf0c1d5Smjnelson fi 2720cdf0c1d5Smjnelson 2721cdf0c1d5Smjnelson PWS=$codemgr_parent 2722cdf0c1d5Smjnelson 2723cdf0c1d5Smjnelson # 2724cdf0c1d5Smjnelson # If the parent is a webrev, we want to do some things against 2725cdf0c1d5Smjnelson # the natural workspace parent (file list, comments, etc) 2726cdf0c1d5Smjnelson # 2727cdf0c1d5Smjnelson if [[ -n $parent_webrev ]]; then 2728cdf0c1d5Smjnelson real_parent=$(hg path -R $codemgr_ws default 2>/dev/null) 2729cdf0c1d5Smjnelson else 2730cdf0c1d5Smjnelson real_parent=$PWS 2731cdf0c1d5Smjnelson fi 2732cdf0c1d5Smjnelson 2733cdf0c1d5Smjnelson # 2734cdf0c1d5Smjnelson # If hg-active exists, then we run it. In the case of no explicit 2735cdf0c1d5Smjnelson # flist given, we'll use it for our comments. In the case of an 2736cdf0c1d5Smjnelson # explicit flist given we'll try to use it for comments for any 2737cdf0c1d5Smjnelson # files mentioned in the flist. 2738cdf0c1d5Smjnelson # 2739cdf0c1d5Smjnelson if [[ -z $flist_done ]]; then 2740cdf0c1d5Smjnelson flist_from_mercurial $CWS $real_parent 2741cdf0c1d5Smjnelson flist_done=1 2742cdf0c1d5Smjnelson fi 2743cdf0c1d5Smjnelson 2744cdf0c1d5Smjnelson # 2745cdf0c1d5Smjnelson # If we have a file list now, pull out any variables set 2746cdf0c1d5Smjnelson # therein. We do this now (rather than when we possibly use 2747cdf0c1d5Smjnelson # hg-active to find comments) to avoid stomping specifications 2748cdf0c1d5Smjnelson # in the user-specified flist. 2749cdf0c1d5Smjnelson # 2750cdf0c1d5Smjnelson if [[ -n $flist_done ]]; then 2751cdf0c1d5Smjnelson env_from_flist 2752cdf0c1d5Smjnelson fi 2753cdf0c1d5Smjnelson 2754cdf0c1d5Smjnelson # 2755cdf0c1d5Smjnelson # Only call hg-active if we don't have a wx formatted file already 2756cdf0c1d5Smjnelson # 2757cdf0c1d5Smjnelson if [[ -x $HG_ACTIVE && -z $wxfile ]]; then 2758cdf0c1d5Smjnelson print " Comments from: hg-active -p $real_parent ...\c" 2759cdf0c1d5Smjnelson hg_active_wxfile $CWS $real_parent 2760cdf0c1d5Smjnelson print " Done." 2761cdf0c1d5Smjnelson fi 2762cdf0c1d5Smjnelson 2763cdf0c1d5Smjnelson # 2764cdf0c1d5Smjnelson # At this point we must have a wx flist either from hg-active, 2765cdf0c1d5Smjnelson # or in general. Use it to try and find our parent revision, 2766cdf0c1d5Smjnelson # if we don't have one. 2767cdf0c1d5Smjnelson # 2768cdf0c1d5Smjnelson if [[ -z $HG_PARENT ]]; then 2769b0088928SVladimir Kotal eval `$SED -e "s/#.*$//" $wxfile | $GREP HG_PARENT=` 2770cdf0c1d5Smjnelson fi 2771cdf0c1d5Smjnelson 2772cdf0c1d5Smjnelson # 2773cdf0c1d5Smjnelson # If we still don't have a parent, we must have been given a 2774cdf0c1d5Smjnelson # wx-style active list with no HG_PARENT specification, run 2775cdf0c1d5Smjnelson # hg-active and pull an HG_PARENT out of it, ignore the rest. 2776cdf0c1d5Smjnelson # 2777cdf0c1d5Smjnelson if [[ -z $HG_PARENT && -x $HG_ACTIVE ]]; then 2778cdf0c1d5Smjnelson $HG_ACTIVE -w $codemgr_ws -p $real_parent | \ 2779b0088928SVladimir Kotal eval `$SED -e "s/#.*$//" | $GREP HG_PARENT=` 2780cdf0c1d5Smjnelson elif [[ -z $HG_PARENT ]]; then 2781cdf0c1d5Smjnelson print -u2 "Error: Cannot discover parent revision" 2782cdf0c1d5Smjnelson exit 1 2783cdf0c1d5Smjnelson fi 27848bcea973SRichard Lowe 27858bcea973SRichard Lowe pnode=$(trim_digest $HG_PARENT) 27868bcea973SRichard Lowe PRETTY_PWS="${PWS} (at ${pnode})" 27878bcea973SRichard Lowe cnode=$(hg parent -R $codemgr_ws --template '{node|short}' \ 27888bcea973SRichard Lowe 2>/dev/null) 27898bcea973SRichard Lowe PRETTY_CWS="${CWS} (at ${cnode})"} 27908bcea973SRichard Loweelif [[ $SCM_MODE == "git" ]]; then 27918bcea973SRichard Lowe # 27928bcea973SRichard Lowe # Parent can either be specified with -p, or specified with 27938bcea973SRichard Lowe # CODEMGR_PARENT in the environment. 27948bcea973SRichard Lowe # 27958bcea973SRichard Lowe 27968bcea973SRichard Lowe if [[ -z $codemgr_parent && -n $CODEMGR_PARENT ]]; then 27978bcea973SRichard Lowe codemgr_parent=$CODEMGR_PARENT 27988bcea973SRichard Lowe fi 27998bcea973SRichard Lowe 28008bcea973SRichard Lowe # Try to figure out the parent based on the branch the current 28018bcea973SRichard Lowe # branch is tracking, if we fail, use origin/master 28028bcea973SRichard Lowe this_branch=$($GIT branch | nawk '$1 == "*" { print $2 }') 28038bcea973SRichard Lowe par_branch="origin/master" 28048bcea973SRichard Lowe 28058bcea973SRichard Lowe # If we're not on a branch there's nothing we can do 28068bcea973SRichard Lowe if [[ $this_branch != "(no branch)" ]]; then 28078bcea973SRichard Lowe $GIT for-each-ref \ 28088bcea973SRichard Lowe --format='%(refname:short) %(upstream:short)' refs/heads/ | \ 28098bcea973SRichard Lowe while read local remote; do \ 28108bcea973SRichard Lowe [[ "$local" == "$this_branch" ]] && par_branch="$remote"; \ 28118bcea973SRichard Lowe done 28128bcea973SRichard Lowe fi 28138bcea973SRichard Lowe 28148bcea973SRichard Lowe if [[ -z $codemgr_parent ]]; then 28158bcea973SRichard Lowe codemgr_parent=$par_branch 28168bcea973SRichard Lowe fi 28178bcea973SRichard Lowe PWS=$codemgr_parent 28188bcea973SRichard Lowe 28198bcea973SRichard Lowe # 28208bcea973SRichard Lowe # If the parent is a webrev, we want to do some things against 28218bcea973SRichard Lowe # the natural workspace parent (file list, comments, etc) 28228bcea973SRichard Lowe # 28238bcea973SRichard Lowe if [[ -n $parent_webrev ]]; then 28248bcea973SRichard Lowe real_parent=$par_branch 28258bcea973SRichard Lowe else 28268bcea973SRichard Lowe real_parent=$PWS 28278bcea973SRichard Lowe fi 28288bcea973SRichard Lowe 28298bcea973SRichard Lowe if [[ -z $flist_done ]]; then 28308bcea973SRichard Lowe flist_from_git "$CWS" "$real_parent" 28318bcea973SRichard Lowe flist_done=1 28328bcea973SRichard Lowe fi 28338bcea973SRichard Lowe 28348bcea973SRichard Lowe # 28358bcea973SRichard Lowe # If we have a file list now, pull out any variables set 28368bcea973SRichard Lowe # therein. 28378bcea973SRichard Lowe # 28388bcea973SRichard Lowe if [[ -n $flist_done ]]; then 28398bcea973SRichard Lowe env_from_flist 28408bcea973SRichard Lowe fi 28418bcea973SRichard Lowe 28428bcea973SRichard Lowe # 28438bcea973SRichard Lowe # If we don't have a wx-format file list, build one we can pull change 28448bcea973SRichard Lowe # comments from. 28458bcea973SRichard Lowe # 28468bcea973SRichard Lowe if [[ -z $wxfile ]]; then 28478bcea973SRichard Lowe print " Comments from: git...\c" 28488bcea973SRichard Lowe git_wxfile "$CWS" "$real_parent" 28498bcea973SRichard Lowe print " Done." 28508bcea973SRichard Lowe fi 28518bcea973SRichard Lowe 28528bcea973SRichard Lowe if [[ -z $GIT_PARENT ]]; then 28538bcea973SRichard Lowe GIT_PARENT=$($GIT merge-base "$real_parent" HEAD) 28548bcea973SRichard Lowe fi 28558bcea973SRichard Lowe if [[ -z $GIT_PARENT ]]; then 28568bcea973SRichard Lowe print -u2 "Error: Cannot discover parent revision" 28578bcea973SRichard Lowe exit 1 28588bcea973SRichard Lowe fi 28598bcea973SRichard Lowe 28608bcea973SRichard Lowe pnode=$(trim_digest $GIT_PARENT) 28618bcea973SRichard Lowe 28628bcea973SRichard Lowe if [[ $real_parent == */* ]]; then 28638bcea973SRichard Lowe origin=$(echo $real_parent | cut -d/ -f1) 28648bcea973SRichard Lowe origin=$($GIT remote -v | \ 28658bcea973SRichard Lowe $AWK '$1 == "'$origin'" { print $2; exit }') 28668bcea973SRichard Lowe PRETTY_PWS="${PWS} (${origin} at ${pnode})" 28678bcea973SRichard Lowe else 28688bcea973SRichard Lowe PRETTY_PWS="${PWS} (at ${pnode})" 28698bcea973SRichard Lowe fi 28708bcea973SRichard Lowe 28718bcea973SRichard Lowe cnode=$($GIT --git-dir=${codemgr_ws}/.git rev-parse --short=12 HEAD \ 28728bcea973SRichard Lowe 2>/dev/null) 28738bcea973SRichard Lowe PRETTY_CWS="${CWS} (at ${cnode})" 2874cdf0c1d5Smjnelsonelif [[ $SCM_MODE == "subversion" ]]; then 2875cdf0c1d5Smjnelson 2876cdf0c1d5Smjnelson # 2877cdf0c1d5Smjnelson # We only will have a real parent workspace in the case one 2878cdf0c1d5Smjnelson # was specified (be it an older webrev, or another checkout). 2879cdf0c1d5Smjnelson # 2880cdf0c1d5Smjnelson [[ -n $codemgr_parent ]] && PWS=$codemgr_parent 2881cdf0c1d5Smjnelson 2882cdf0c1d5Smjnelson if [[ -z $flist_done && $flist_mode == "auto" ]]; then 2883cdf0c1d5Smjnelson flist_from_subversion $CWS $OLDPWD 2884cdf0c1d5Smjnelson fi 2885cdf0c1d5Smjnelsonelse 2886cdf0c1d5Smjnelson if [[ $SCM_MODE == "unknown" ]]; then 2887cdf0c1d5Smjnelson print -u2 " Unknown type of SCM in use" 2888cdf0c1d5Smjnelson else 2889cdf0c1d5Smjnelson print -u2 " Unsupported SCM in use: $SCM_MODE" 2890cdf0c1d5Smjnelson fi 2891cdf0c1d5Smjnelson 2892cdf0c1d5Smjnelson env_from_flist 2893cdf0c1d5Smjnelson 2894cdf0c1d5Smjnelson if [[ -z $CODEMGR_WS ]]; then 2895cdf0c1d5Smjnelson print -u2 "SCM not detected/supported and CODEMGR_WS not specified" 2896cdf0c1d5Smjnelson exit 1 2897cdf0c1d5Smjnelson fi 2898cdf0c1d5Smjnelson 2899cdf0c1d5Smjnelson if [[ -z $CODEMGR_PARENT ]]; then 2900cdf0c1d5Smjnelson print -u2 "SCM not detected/supported and CODEMGR_PARENT not specified" 2901cdf0c1d5Smjnelson exit 1 2902cdf0c1d5Smjnelson fi 2903cdf0c1d5Smjnelson 2904cdf0c1d5Smjnelson CWS=$CODEMGR_WS 2905cdf0c1d5Smjnelson PWS=$CODEMGR_PARENT 2906daaffb31Sdpfi 2907daaffb31Sdp 2908daaffb31Sdp# 2909daaffb31Sdp# If the user didn't specify a -i option, check to see if there is a 2910daaffb31Sdp# webrev-info file in the workspace directory. 2911daaffb31Sdp# 2912daaffb31Sdpif [[ -z $iflag && -r "$CWS/webrev-info" ]]; then 2913daaffb31Sdp iflag=1 2914daaffb31Sdp INCLUDE_FILE="$CWS/webrev-info" 2915daaffb31Sdpfi 2916daaffb31Sdp 2917daaffb31Sdpif [[ -n $iflag ]]; then 2918daaffb31Sdp if [[ ! -r $INCLUDE_FILE ]]; then 2919daaffb31Sdp print -u2 "include file '$INCLUDE_FILE' does not exist or is" \ 2920daaffb31Sdp "not readable." 2921daaffb31Sdp exit 1 2922daaffb31Sdp else 2923daaffb31Sdp # 2924daaffb31Sdp # $INCLUDE_FILE may be a relative path, and the script alters 2925daaffb31Sdp # PWD, so we just stash a copy in /tmp. 2926daaffb31Sdp # 2927daaffb31Sdp cp $INCLUDE_FILE /tmp/$$.include 2928daaffb31Sdp fi 2929daaffb31Sdpfi 2930daaffb31Sdp 29310fd2682eSMark J. Nelson# DO_EVERYTHING: break point 29320fd2682eSMark J. Nelsonif [[ -n $Nflag ]]; then 29330fd2682eSMark J. Nelson break 29340fd2682eSMark J. Nelsonfi 29350fd2682eSMark J. Nelson 29360fd2682eSMark J. Nelsontypeset -A itsinfo 29370fd2682eSMark J. Nelsontypeset -r its_sed_script=/tmp/$$.its_sed 29380fd2682eSMark J. Nelsonvalid_prefixes= 29390fd2682eSMark J. Nelsonif [[ -z $nflag ]]; then 29408bcea973SRichard Lowe DEFREGFILE="$(/bin/dirname "$(whence $0)")/../etc/its.reg" 29410fd2682eSMark J. Nelson if [[ -n $Iflag ]]; then 29420fd2682eSMark J. Nelson REGFILE=$ITSREG 29430fd2682eSMark J. Nelson elif [[ -r $HOME/.its.reg ]]; then 29440fd2682eSMark J. Nelson REGFILE=$HOME/.its.reg 29450fd2682eSMark J. Nelson else 29460fd2682eSMark J. Nelson REGFILE=$DEFREGFILE 29470fd2682eSMark J. Nelson fi 29480fd2682eSMark J. Nelson if [[ ! -r $REGFILE ]]; then 29490fd2682eSMark J. Nelson print "ERROR: Unable to read database registry file $REGFILE" 29500fd2682eSMark J. Nelson exit 1 29510fd2682eSMark J. Nelson elif [[ $REGFILE != $DEFREGFILE ]]; then 29520fd2682eSMark J. Nelson print " its.reg from: $REGFILE" 29530fd2682eSMark J. Nelson fi 29540fd2682eSMark J. Nelson 29550fd2682eSMark J. Nelson $SED -e '/^#/d' -e '/^[ ]*$/d' $REGFILE | while read LINE; do 29560fd2682eSMark J. Nelson 29570fd2682eSMark J. Nelson name=${LINE%%=*} 29580fd2682eSMark J. Nelson value="${LINE#*=}" 29590fd2682eSMark J. Nelson 29600fd2682eSMark J. Nelson if [[ $name == PREFIX ]]; then 29610fd2682eSMark J. Nelson p=${value} 29620fd2682eSMark J. Nelson valid_prefixes="${p} ${valid_prefixes}" 29630fd2682eSMark J. Nelson else 29640fd2682eSMark J. Nelson itsinfo["${p}_${name}"]="${value}" 29650fd2682eSMark J. Nelson fi 29660fd2682eSMark J. Nelson done 29670fd2682eSMark J. Nelson 29680fd2682eSMark J. Nelson 29698bcea973SRichard Lowe DEFCONFFILE="$(/bin/dirname "$(whence $0)")/../etc/its.conf" 29700fd2682eSMark J. Nelson CONFFILES=$DEFCONFFILE 29710fd2682eSMark J. Nelson if [[ -r $HOME/.its.conf ]]; then 29720fd2682eSMark J. Nelson CONFFILES="${CONFFILES} $HOME/.its.conf" 29730fd2682eSMark J. Nelson fi 29740fd2682eSMark J. Nelson if [[ -n $Cflag ]]; then 29750fd2682eSMark J. Nelson CONFFILES="${CONFFILES} ${ITSCONF}" 29760fd2682eSMark J. Nelson fi 29770fd2682eSMark J. Nelson its_domain= 29780fd2682eSMark J. Nelson its_priority= 29790fd2682eSMark J. Nelson for cf in ${CONFFILES}; do 29800fd2682eSMark J. Nelson if [[ ! -r $cf ]]; then 29810fd2682eSMark J. Nelson print "ERROR: Unable to read database configuration file $cf" 29820fd2682eSMark J. Nelson exit 1 29830fd2682eSMark J. Nelson elif [[ $cf != $DEFCONFFILE ]]; then 29840fd2682eSMark J. Nelson print " its.conf: reading $cf" 29850fd2682eSMark J. Nelson fi 29860fd2682eSMark J. Nelson $SED -e '/^#/d' -e '/^[ ]*$/d' $cf | while read LINE; do 29870fd2682eSMark J. Nelson eval "${LINE}" 29880fd2682eSMark J. Nelson done 29890fd2682eSMark J. Nelson done 29900fd2682eSMark J. Nelson 29910fd2682eSMark J. Nelson # 29920fd2682eSMark J. Nelson # If an information tracking system is explicitly identified by prefix, 29930fd2682eSMark J. Nelson # we want to disregard the specified priorities and resolve it accordingly. 29940fd2682eSMark J. Nelson # 29950fd2682eSMark J. Nelson # To that end, we'll build a sed script to do each valid prefix in turn. 29960fd2682eSMark J. Nelson # 29970fd2682eSMark J. Nelson for p in ${valid_prefixes}; do 29980fd2682eSMark J. Nelson # 29990fd2682eSMark J. Nelson # When an informational URL was provided, translate it to a 30000fd2682eSMark J. Nelson # hyperlink. When omitted, simply use the prefix text. 30010fd2682eSMark J. Nelson # 30020fd2682eSMark J. Nelson if [[ -z ${itsinfo["${p}_INFO"]} ]]; then 30030fd2682eSMark J. Nelson itsinfo["${p}_INFO"]=${p} 30040fd2682eSMark J. Nelson else 30050fd2682eSMark J. Nelson itsinfo["${p}_INFO"]="<a href=\\\"${itsinfo["${p}_INFO"]}\\\">${p}</a>" 30060fd2682eSMark J. Nelson fi 30070fd2682eSMark J. Nelson 30080fd2682eSMark J. Nelson # 30090fd2682eSMark J. Nelson # Assume that, for this invocation of webrev, all references 30100fd2682eSMark J. Nelson # to this information tracking system should resolve through 30110fd2682eSMark J. Nelson # the same URL. 30120fd2682eSMark J. Nelson # 30130fd2682eSMark J. Nelson # If the caller specified -O, then always use EXTERNAL_URL. 30140fd2682eSMark J. Nelson # 30150fd2682eSMark J. Nelson # Otherwise, look in the list of domains for a matching 30160fd2682eSMark J. Nelson # INTERNAL_URL. 30170fd2682eSMark J. Nelson # 30180fd2682eSMark J. Nelson [[ -z $Oflag ]] && for d in ${its_domain}; do 30190fd2682eSMark J. Nelson if [[ -n ${itsinfo["${p}_INTERNAL_URL_${d}"]} ]]; then 30200fd2682eSMark J. Nelson itsinfo["${p}_URL"]="${itsinfo[${p}_INTERNAL_URL_${d}]}" 30210fd2682eSMark J. Nelson break 30220fd2682eSMark J. Nelson fi 30230fd2682eSMark J. Nelson done 30240fd2682eSMark J. Nelson if [[ -z ${itsinfo["${p}_URL"]} ]]; then 30250fd2682eSMark J. Nelson itsinfo["${p}_URL"]="${itsinfo[${p}_EXTERNAL_URL]}" 30260fd2682eSMark J. Nelson fi 30270fd2682eSMark J. Nelson 30280fd2682eSMark J. Nelson # 30290fd2682eSMark J. Nelson # Turn the destination URL into a hyperlink 30300fd2682eSMark J. Nelson # 30310fd2682eSMark J. Nelson itsinfo["${p}_URL"]="<a href=\\\"${itsinfo[${p}_URL]}\\\">&</a>" 30320fd2682eSMark J. Nelson 30332f54b716SRichard Lowe # The character class below contains a literal tab 30342f54b716SRichard Lowe print "/^${p}[: ]/ { 30350fd2682eSMark J. Nelson s;${itsinfo[${p}_REGEX]};${itsinfo[${p}_URL]};g 30360fd2682eSMark J. Nelson s;^${p};${itsinfo[${p}_INFO]}; 30370fd2682eSMark J. Nelson }" >> ${its_sed_script} 30380fd2682eSMark J. Nelson done 30390fd2682eSMark J. Nelson 30400fd2682eSMark J. Nelson # 30410fd2682eSMark J. Nelson # The previous loop took care of explicit specification. Now use 30420fd2682eSMark J. Nelson # the configured priorities to attempt implicit translations. 30430fd2682eSMark J. Nelson # 30440fd2682eSMark J. Nelson for p in ${its_priority}; do 30450fd2682eSMark J. Nelson print "/^${itsinfo[${p}_REGEX]}[ ]/ { 30462f54b716SRichard Lowe s;^${itsinfo[${p}_REGEX]};${itsinfo[${p}_URL]};g 30470fd2682eSMark J. Nelson }" >> ${its_sed_script} 30480fd2682eSMark J. Nelson done 30490fd2682eSMark J. Nelsonfi 30500fd2682eSMark J. Nelson 30510fd2682eSMark J. Nelson# 30520fd2682eSMark J. Nelson# Search for DO_EVERYTHING above for matching "for" statement 30530fd2682eSMark J. Nelson# and explanation of this terminator. 30540fd2682eSMark J. Nelson# 30550fd2682eSMark J. Nelsondone 30560fd2682eSMark J. Nelson 3057daaffb31Sdp# 3058daaffb31Sdp# Output directory. 3059daaffb31Sdp# 3060daaffb31SdpWDIR=${WDIR:-$CWS/webrev} 3061daaffb31Sdp 3062daaffb31Sdp# 306302d26c39SVladimir Kotal# Name of the webrev, derived from the workspace name or output directory; 306402d26c39SVladimir Kotal# in the future this could potentially be an option. 3065daaffb31Sdp# 306602d26c39SVladimir Kotalif [[ -n $oflag ]]; then 306702d26c39SVladimir Kotal WNAME=${WDIR##*/} 306802d26c39SVladimir Kotalelse 3069daaffb31Sdp WNAME=${CWS##*/} 307002d26c39SVladimir Kotalfi 307102d26c39SVladimir Kotal 3072ba44d8a2SVladimir Kotal# Make sure remote target is well formed for remote upload/delete. 3073ba44d8a2SVladimir Kotalif [[ -n $Dflag || -n $Uflag ]]; then 3074b0088928SVladimir Kotal # 3075ba44d8a2SVladimir Kotal # If remote target is not specified, build it from scratch using 3076ba44d8a2SVladimir Kotal # the default values. 3077b0088928SVladimir Kotal # 3078ba44d8a2SVladimir Kotal if [[ -z $tflag ]]; then 3079ba44d8a2SVladimir Kotal remote_target=${DEFAULT_REMOTE_HOST}:${WNAME} 3080ba44d8a2SVladimir Kotal else 3081b0088928SVladimir Kotal # 3082b0088928SVladimir Kotal # Check upload target prefix first. 3083b0088928SVladimir Kotal # 3084b0088928SVladimir Kotal if [[ "${remote_target}" != ${rsync_prefix}* && 3085b0088928SVladimir Kotal "${remote_target}" != ${ssh_prefix}* ]]; then 3086b0088928SVladimir Kotal print "ERROR: invalid prefix of upload URI" \ 3087b0088928SVladimir Kotal "($remote_target)" 3088b0088928SVladimir Kotal exit 1 3089b0088928SVladimir Kotal fi 3090b0088928SVladimir Kotal # 3091ba44d8a2SVladimir Kotal # If destination specification is not in the form of 3092ba44d8a2SVladimir Kotal # host_spec:remote_dir then assume it is just remote hostname 3093ba44d8a2SVladimir Kotal # and append a colon and destination directory formed from 3094ba44d8a2SVladimir Kotal # local webrev directory name. 3095b0088928SVladimir Kotal # 3096b0088928SVladimir Kotal typeset target_no_prefix=${remote_target##*://} 3097b0088928SVladimir Kotal if [[ ${target_no_prefix} == *:* ]]; then 3098ba44d8a2SVladimir Kotal if [[ "${remote_target}" == *: ]]; then 3099b0088928SVladimir Kotal remote_target=${remote_target}${WNAME} 3100ba44d8a2SVladimir Kotal fi 3101b0088928SVladimir Kotal else 3102b0088928SVladimir Kotal if [[ ${target_no_prefix} == */* ]]; then 3103b0088928SVladimir Kotal print "ERROR: badly formed upload URI" \ 3104b0088928SVladimir Kotal "($remote_target)" 3105b0088928SVladimir Kotal exit 1 3106b0088928SVladimir Kotal else 3107b0088928SVladimir Kotal remote_target=${remote_target}:${WNAME} 3108ba44d8a2SVladimir Kotal fi 3109ba44d8a2SVladimir Kotal fi 3110ba44d8a2SVladimir Kotal fi 3111ba44d8a2SVladimir Kotal 3112b0088928SVladimir Kotal # 3113b0088928SVladimir Kotal # Strip trailing slash. Each upload method will deal with directory 3114b0088928SVladimir Kotal # specification separately. 3115b0088928SVladimir Kotal # 3116b0088928SVladimir Kotal remote_target=${remote_target%/} 3117b0088928SVladimir Kotalfi 3118b0088928SVladimir Kotal 3119b0088928SVladimir Kotal# 3120ba44d8a2SVladimir Kotal# Option -D by itself (option -U not present) implies no webrev generation. 3121b0088928SVladimir Kotal# 3122ba44d8a2SVladimir Kotalif [[ -z $Uflag && -n $Dflag ]]; then 3123b0088928SVladimir Kotal delete_webrev 1 1 3124ba44d8a2SVladimir Kotal exit $? 3125ba44d8a2SVladimir Kotalfi 3126ba44d8a2SVladimir Kotal 3127b0088928SVladimir Kotal# 3128ba44d8a2SVladimir Kotal# Do not generate the webrev, just upload it or delete it. 3129b0088928SVladimir Kotal# 3130ba44d8a2SVladimir Kotalif [[ -n $nflag ]]; then 3131ba44d8a2SVladimir Kotal if [[ -n $Dflag ]]; then 3132b0088928SVladimir Kotal delete_webrev 1 1 3133ba44d8a2SVladimir Kotal (( $? == 0 )) || exit $? 3134ba44d8a2SVladimir Kotal fi 3135ba44d8a2SVladimir Kotal if [[ -n $Uflag ]]; then 313602d26c39SVladimir Kotal upload_webrev 313702d26c39SVladimir Kotal exit $? 313802d26c39SVladimir Kotal fi 3139ba44d8a2SVladimir Kotalfi 3140daaffb31Sdp 3141e0e0293aSjmcpif [ "${WDIR%%/*}" ]; then 31427c478bd9Sstevel@tonic-gate WDIR=$PWD/$WDIR 31437c478bd9Sstevel@tonic-gatefi 3144daaffb31Sdp 3145daaffb31Sdpif [[ ! -d $WDIR ]]; then 3146daaffb31Sdp mkdir -p $WDIR 3147ba44d8a2SVladimir Kotal (( $? != 0 )) && exit 1 31487c478bd9Sstevel@tonic-gatefi 31497c478bd9Sstevel@tonic-gate 3150daaffb31Sdp# 3151daaffb31Sdp# Summarize what we're going to do. 3152daaffb31Sdp# 31538bcea973SRichard Loweprint " Workspace: ${PRETTY_CWS:-$CWS}" 3154daaffb31Sdpif [[ -n $parent_webrev ]]; then 3155daaffb31Sdp print "Compare against: webrev at $parent_webrev" 3156daaffb31Sdpelse 31578bcea973SRichard Lowe print "Compare against: ${PRETTY_PWS:-$PWS}" 3158cdf0c1d5Smjnelsonfi 3159daaffb31Sdp 3160daaffb31Sdp[[ -n $INCLUDE_FILE ]] && print " Including: $INCLUDE_FILE" 3161daaffb31Sdpprint " Output to: $WDIR" 3162daaffb31Sdp 3163daaffb31Sdp# 31647c478bd9Sstevel@tonic-gate# Save the file list in the webrev dir 3165daaffb31Sdp# 3166daaffb31Sdp[[ ! $FLIST -ef $WDIR/file.list ]] && cp $FLIST $WDIR/file.list 31677c478bd9Sstevel@tonic-gate 3168daaffb31Sdprm -f $WDIR/$WNAME.patch 3169daaffb31Sdprm -f $WDIR/$WNAME.ps 3170daaffb31Sdprm -f $WDIR/$WNAME.pdf 31717c478bd9Sstevel@tonic-gate 3172daaffb31Sdptouch $WDIR/$WNAME.patch 31737c478bd9Sstevel@tonic-gate 3174daaffb31Sdpprint " Output Files:" 3175daaffb31Sdp 3176daaffb31Sdp# 3177daaffb31Sdp# Clean up the file list: Remove comments, blank lines and env variables. 3178daaffb31Sdp# 3179b0088928SVladimir Kotal$SED -e "s/#.*$//" -e "/=/d" -e "/^[ ]*$/d" $FLIST > /tmp/$$.flist.clean 3180daaffb31SdpFLIST=/tmp/$$.flist.clean 3181daaffb31Sdp 3182daaffb31Sdp# 3183cdf0c1d5Smjnelson# For Mercurial, create a cache of manifest entries. 3184cdf0c1d5Smjnelson# 3185cdf0c1d5Smjnelsonif [[ $SCM_MODE == "mercurial" ]]; then 3186cdf0c1d5Smjnelson # 3187cdf0c1d5Smjnelson # Transform the FLIST into a temporary sed script that matches 3188cdf0c1d5Smjnelson # relevant entries in the Mercurial manifest as follows: 3189cdf0c1d5Smjnelson # 1) The script will be used against the parent revision manifest, 3190cdf0c1d5Smjnelson # so for FLIST lines that have two filenames (a renamed file) 3191cdf0c1d5Smjnelson # keep only the old name. 3192cdf0c1d5Smjnelson # 2) Escape all forward slashes the filename. 3193cdf0c1d5Smjnelson # 3) Change the filename into another sed command that matches 3194cdf0c1d5Smjnelson # that file in "hg manifest -v" output: start of line, three 3195cdf0c1d5Smjnelson # octal digits for file permissions, space, a file type flag 3196cdf0c1d5Smjnelson # character, space, the filename, end of line. 3197e6ccc173SEdward Pilatowicz # 4) Eliminate any duplicate entries. (This can occur if a 3198e6ccc173SEdward Pilatowicz # file has been used as the source of an hg cp and it's 3199e6ccc173SEdward Pilatowicz # also been modified in the same changeset.) 3200cdf0c1d5Smjnelson # 3201cdf0c1d5Smjnelson SEDFILE=/tmp/$$.manifest.sed 3202b0088928SVladimir Kotal $SED ' 3203cdf0c1d5Smjnelson s#^[^ ]* ## 3204cdf0c1d5Smjnelson s#/#\\\/#g 3205cdf0c1d5Smjnelson s#^.*$#/^... . &$/p# 3206e6ccc173SEdward Pilatowicz ' < $FLIST | $SORT -u > $SEDFILE 3207cdf0c1d5Smjnelson 3208cdf0c1d5Smjnelson # 3209cdf0c1d5Smjnelson # Apply the generated script to the output of "hg manifest -v" 3210cdf0c1d5Smjnelson # to get the relevant subset for this webrev. 3211cdf0c1d5Smjnelson # 3212cdf0c1d5Smjnelson HG_PARENT_MANIFEST=/tmp/$$.manifest 3213cdf0c1d5Smjnelson hg -R $CWS manifest -v -r $HG_PARENT | 3214b0088928SVladimir Kotal $SED -n -f $SEDFILE > $HG_PARENT_MANIFEST 3215cdf0c1d5Smjnelsonfi 3216cdf0c1d5Smjnelson 3217cdf0c1d5Smjnelson# 3218daaffb31Sdp# First pass through the files: generate the per-file webrev HTML-files. 3219daaffb31Sdp# 3220daaffb31Sdpcat $FLIST | while read LINE 32217c478bd9Sstevel@tonic-gatedo 32227c478bd9Sstevel@tonic-gate set - $LINE 32237c478bd9Sstevel@tonic-gate P=$1 32247c478bd9Sstevel@tonic-gate 3225daaffb31Sdp # 3226daaffb31Sdp # Normally, each line in the file list is just a pathname of a 3227daaffb31Sdp # file that has been modified or created in the child. A file 3228daaffb31Sdp # that is renamed in the child workspace has two names on the 3229daaffb31Sdp # line: new name followed by the old name. 3230daaffb31Sdp # 3231daaffb31Sdp oldname="" 3232daaffb31Sdp oldpath="" 3233daaffb31Sdp rename= 3234daaffb31Sdp if [[ $# -eq 2 ]]; then 32357c478bd9Sstevel@tonic-gate PP=$2 # old filename 3236e6ccc173SEdward Pilatowicz if [[ -f $PP ]]; then 3237e6ccc173SEdward Pilatowicz oldname=" (copied from $PP)" 3238e6ccc173SEdward Pilatowicz else 3239e6ccc173SEdward Pilatowicz oldname=" (renamed from $PP)" 3240e6ccc173SEdward Pilatowicz fi 3241daaffb31Sdp oldpath="$PP" 3242daaffb31Sdp rename=1 32437c478bd9Sstevel@tonic-gate PDIR=${PP%/*} 3244daaffb31Sdp if [[ $PDIR == $PP ]]; then 32457c478bd9Sstevel@tonic-gate PDIR="." # File at root of workspace 32467c478bd9Sstevel@tonic-gate fi 32477c478bd9Sstevel@tonic-gate 32487c478bd9Sstevel@tonic-gate PF=${PP##*/} 32497c478bd9Sstevel@tonic-gate 32507c478bd9Sstevel@tonic-gate DIR=${P%/*} 3251daaffb31Sdp if [[ $DIR == $P ]]; then 32527c478bd9Sstevel@tonic-gate DIR="." # File at root of workspace 32537c478bd9Sstevel@tonic-gate fi 32547c478bd9Sstevel@tonic-gate 32557c478bd9Sstevel@tonic-gate F=${P##*/} 3256daaffb31Sdp 32577c478bd9Sstevel@tonic-gate else 32587c478bd9Sstevel@tonic-gate DIR=${P%/*} 3259daaffb31Sdp if [[ "$DIR" == "$P" ]]; then 32607c478bd9Sstevel@tonic-gate DIR="." # File at root of workspace 32617c478bd9Sstevel@tonic-gate fi 32627c478bd9Sstevel@tonic-gate 32637c478bd9Sstevel@tonic-gate F=${P##*/} 32647c478bd9Sstevel@tonic-gate 32657c478bd9Sstevel@tonic-gate PP=$P 32667c478bd9Sstevel@tonic-gate PDIR=$DIR 32677c478bd9Sstevel@tonic-gate PF=$F 32687c478bd9Sstevel@tonic-gate fi 32697c478bd9Sstevel@tonic-gate 3270daaffb31Sdp COMM=`getcomments html $P $PP` 32717c478bd9Sstevel@tonic-gate 3272daaffb31Sdp print "\t$P$oldname\n\t\t\c" 32737c478bd9Sstevel@tonic-gate 32747c478bd9Sstevel@tonic-gate # Make the webrev mirror directory if necessary 32757c478bd9Sstevel@tonic-gate mkdir -p $WDIR/$DIR 32767c478bd9Sstevel@tonic-gate 3277daaffb31Sdp # 3278cdf0c1d5Smjnelson # We stash old and new files into parallel directories in $WDIR 3279daaffb31Sdp # and do our diffs there. This makes it possible to generate 3280daaffb31Sdp # clean looking diffs which don't have absolute paths present. 3281daaffb31Sdp # 3282daaffb31Sdp 3283cdf0c1d5Smjnelson build_old_new "$WDIR" "$PWS" "$PDIR" "$PF" "$CWS" "$DIR" "$F" || \ 32847c478bd9Sstevel@tonic-gate continue 32857c478bd9Sstevel@tonic-gate 3286cdf0c1d5Smjnelson # 3287cdf0c1d5Smjnelson # Keep the old PWD around, so we can safely switch back after 3288cdf0c1d5Smjnelson # diff generation, such that build_old_new runs in a 3289cdf0c1d5Smjnelson # consistent environment. 3290cdf0c1d5Smjnelson # 3291cdf0c1d5Smjnelson OWD=$PWD 3292daaffb31Sdp cd $WDIR/raw_files 3293daaffb31Sdp ofile=old/$PDIR/$PF 3294daaffb31Sdp nfile=new/$DIR/$F 32957c478bd9Sstevel@tonic-gate 3296daaffb31Sdp mv_but_nodiff= 3297daaffb31Sdp cmp $ofile $nfile > /dev/null 2>&1 3298daaffb31Sdp if [[ $? == 0 && $rename == 1 ]]; then 3299daaffb31Sdp mv_but_nodiff=1 3300daaffb31Sdp fi 3301daaffb31Sdp 3302daaffb31Sdp # 3303daaffb31Sdp # If we have old and new versions of the file then run the appropriate 3304daaffb31Sdp # diffs. This is complicated by a couple of factors: 3305daaffb31Sdp # 3306daaffb31Sdp # - renames must be handled specially: we emit a 'remove' 3307daaffb31Sdp # diff and an 'add' diff 3308daaffb31Sdp # - new files and deleted files must be handled specially 3309daaffb31Sdp # - Solaris patch(1m) can't cope with file creation 3310daaffb31Sdp # (and hence renames) as of this writing. 3311daaffb31Sdp # - To make matters worse, gnu patch doesn't interpret the 3312daaffb31Sdp # output of Solaris diff properly when it comes to 3313daaffb31Sdp # adds and deletes. We need to do some "cleansing" 3314daaffb31Sdp # transformations: 3315daaffb31Sdp # [to add a file] @@ -1,0 +X,Y @@ --> @@ -0,0 +X,Y @@ 3316daaffb31Sdp # [to del a file] @@ -X,Y +1,0 @@ --> @@ -X,Y +0,0 @@ 3317daaffb31Sdp # 3318b0088928SVladimir Kotal cleanse_rmfile="$SED 's/^\(@@ [0-9+,-]*\) [0-9+,-]* @@$/\1 +0,0 @@/'" 3319b0088928SVladimir Kotal cleanse_newfile="$SED 's/^@@ [0-9+,-]* \([0-9+,-]* @@\)$/@@ -0,0 \1/'" 3320daaffb31Sdp 3321daaffb31Sdp rm -f $WDIR/$DIR/$F.patch 3322daaffb31Sdp if [[ -z $rename ]]; then 3323e0e0293aSjmcp if [ ! -f "$ofile" ]; then 3324daaffb31Sdp diff -u /dev/null $nfile | sh -c "$cleanse_newfile" \ 3325daaffb31Sdp > $WDIR/$DIR/$F.patch 3326e0e0293aSjmcp elif [ ! -f "$nfile" ]; then 3327daaffb31Sdp diff -u $ofile /dev/null | sh -c "$cleanse_rmfile" \ 3328daaffb31Sdp > $WDIR/$DIR/$F.patch 3329daaffb31Sdp else 3330daaffb31Sdp diff -u $ofile $nfile > $WDIR/$DIR/$F.patch 3331daaffb31Sdp fi 3332daaffb31Sdp else 3333daaffb31Sdp diff -u $ofile /dev/null | sh -c "$cleanse_rmfile" \ 3334daaffb31Sdp > $WDIR/$DIR/$F.patch 3335daaffb31Sdp 3336daaffb31Sdp diff -u /dev/null $nfile | sh -c "$cleanse_newfile" \ 3337daaffb31Sdp >> $WDIR/$DIR/$F.patch 3338daaffb31Sdp fi 3339daaffb31Sdp 3340daaffb31Sdp # 3341daaffb31Sdp # Tack the patch we just made onto the accumulated patch for the 3342daaffb31Sdp # whole wad. 3343daaffb31Sdp # 3344daaffb31Sdp cat $WDIR/$DIR/$F.patch >> $WDIR/$WNAME.patch 3345daaffb31Sdp 3346daaffb31Sdp print " patch\c" 3347daaffb31Sdp 3348daaffb31Sdp if [[ -f $ofile && -f $nfile && -z $mv_but_nodiff ]]; then 3349daaffb31Sdp 3350daaffb31Sdp ${CDIFFCMD:-diff -bt -C 5} $ofile $nfile > $WDIR/$DIR/$F.cdiff 3351daaffb31Sdp diff_to_html $F $DIR/$F "C" "$COMM" < $WDIR/$DIR/$F.cdiff \ 3352daaffb31Sdp > $WDIR/$DIR/$F.cdiff.html 33537c478bd9Sstevel@tonic-gate print " cdiffs\c" 33547c478bd9Sstevel@tonic-gate 3355daaffb31Sdp ${UDIFFCMD:-diff -bt -U 5} $ofile $nfile > $WDIR/$DIR/$F.udiff 3356daaffb31Sdp diff_to_html $F $DIR/$F "U" "$COMM" < $WDIR/$DIR/$F.udiff \ 3357daaffb31Sdp > $WDIR/$DIR/$F.udiff.html 3358daaffb31Sdp 33597c478bd9Sstevel@tonic-gate print " udiffs\c" 33607c478bd9Sstevel@tonic-gate 33617c478bd9Sstevel@tonic-gate if [[ -x $WDIFF ]]; then 3362daaffb31Sdp $WDIFF -c "$COMM" \ 3363daaffb31Sdp -t "$WNAME Wdiff $DIR/$F" $ofile $nfile > \ 3364daaffb31Sdp $WDIR/$DIR/$F.wdiff.html 2>/dev/null 3365daaffb31Sdp if [[ $? -eq 0 ]]; then 33667c478bd9Sstevel@tonic-gate print " wdiffs\c" 3367daaffb31Sdp else 3368daaffb31Sdp print " wdiffs[fail]\c" 3369daaffb31Sdp fi 33707c478bd9Sstevel@tonic-gate fi 33717c478bd9Sstevel@tonic-gate 3372daaffb31Sdp sdiff_to_html $ofile $nfile $F $DIR "$COMM" \ 3373daaffb31Sdp > $WDIR/$DIR/$F.sdiff.html 33747c478bd9Sstevel@tonic-gate print " sdiffs\c" 33757c478bd9Sstevel@tonic-gate 33767c478bd9Sstevel@tonic-gate print " frames\c" 33777c478bd9Sstevel@tonic-gate 33787c478bd9Sstevel@tonic-gate rm -f $WDIR/$DIR/$F.cdiff $WDIR/$DIR/$F.udiff 33797c478bd9Sstevel@tonic-gate 3380daaffb31Sdp difflines $ofile $nfile > $WDIR/$DIR/$F.count 3381daaffb31Sdp 3382daaffb31Sdp elif [[ -f $ofile && -f $nfile && -n $mv_but_nodiff ]]; then 3383daaffb31Sdp # renamed file: may also have differences 3384daaffb31Sdp difflines $ofile $nfile > $WDIR/$DIR/$F.count 3385daaffb31Sdp elif [[ -f $nfile ]]; then 33867c478bd9Sstevel@tonic-gate # new file: count added lines 3387daaffb31Sdp difflines /dev/null $nfile > $WDIR/$DIR/$F.count 3388daaffb31Sdp elif [[ -f $ofile ]]; then 33897c478bd9Sstevel@tonic-gate # old file: count deleted lines 3390daaffb31Sdp difflines $ofile /dev/null > $WDIR/$DIR/$F.count 33917c478bd9Sstevel@tonic-gate fi 33927c478bd9Sstevel@tonic-gate 3393daaffb31Sdp # 3394daaffb31Sdp # Now we generate the postscript for this file. We generate diffs 3395daaffb31Sdp # only in the event that there is delta, or the file is new (it seems 3396daaffb31Sdp # tree-killing to print out the contents of deleted files). 3397daaffb31Sdp # 3398daaffb31Sdp if [[ -f $nfile ]]; then 3399daaffb31Sdp ocr=$ofile 3400daaffb31Sdp [[ ! -f $ofile ]] && ocr=/dev/null 3401daaffb31Sdp 3402daaffb31Sdp if [[ -z $mv_but_nodiff ]]; then 3403daaffb31Sdp textcomm=`getcomments text $P $PP` 340414983201Sdp if [[ -x $CODEREVIEW ]]; then 340514983201Sdp $CODEREVIEW -y "$textcomm" \ 340614983201Sdp -e $ocr $nfile \ 340714983201Sdp > /tmp/$$.psfile 2>/dev/null && 340814983201Sdp cat /tmp/$$.psfile >> $WDIR/$WNAME.ps 3409daaffb31Sdp if [[ $? -eq 0 ]]; then 3410daaffb31Sdp print " ps\c" 3411daaffb31Sdp else 3412daaffb31Sdp print " ps[fail]\c" 3413daaffb31Sdp fi 3414daaffb31Sdp fi 3415daaffb31Sdp fi 341614983201Sdp fi 3417daaffb31Sdp 3418cdf0c1d5Smjnelson if [[ -f $ofile ]]; then 3419cdf0c1d5Smjnelson source_to_html Old $PP < $ofile > $WDIR/$DIR/$F-.html 34207c478bd9Sstevel@tonic-gate print " old\c" 34217c478bd9Sstevel@tonic-gate fi 34227c478bd9Sstevel@tonic-gate 3423daaffb31Sdp if [[ -f $nfile ]]; then 3424daaffb31Sdp source_to_html New $P < $nfile > $WDIR/$DIR/$F.html 34257c478bd9Sstevel@tonic-gate print " new\c" 34267c478bd9Sstevel@tonic-gate fi 34277c478bd9Sstevel@tonic-gate 3428cdf0c1d5Smjnelson cd $OWD 3429cdf0c1d5Smjnelson 3430daaffb31Sdp print 34317c478bd9Sstevel@tonic-gatedone 34327c478bd9Sstevel@tonic-gate 3433daaffb31Sdpframe_nav_js > $WDIR/ancnav.js 34347c478bd9Sstevel@tonic-gateframe_navigation > $WDIR/ancnav.html 3435daaffb31Sdp 343614983201Sdpif [[ ! -f $WDIR/$WNAME.ps ]]; then 343714983201Sdp print " Generating PDF: Skipped: no output available" 343814983201Sdpelif [[ -x $CODEREVIEW && -x $PS2PDF ]]; then 343914983201Sdp print " Generating PDF: \c" 344014983201Sdp fix_postscript $WDIR/$WNAME.ps | $PS2PDF - > $WDIR/$WNAME.pdf 3441daaffb31Sdp print "Done." 344214983201Sdpelse 344314983201Sdp print " Generating PDF: Skipped: missing 'ps2pdf' or 'codereview'" 344414983201Sdpfi 34457c478bd9Sstevel@tonic-gate 3446e0e0293aSjmcp# If we're in OpenSolaris mode and there's a closed dir under $WDIR, 3447e0e0293aSjmcp# delete it - prevent accidental publishing of closed source 3448e0e0293aSjmcp 3449e0e0293aSjmcpif [[ -n "$Oflag" ]]; then 3450ba44d8a2SVladimir Kotal $FIND $WDIR -type d -name closed -exec /bin/rm -rf {} \; 3451e0e0293aSjmcpfi 3452e0e0293aSjmcp 34537c478bd9Sstevel@tonic-gate# Now build the index.html file that contains 34547c478bd9Sstevel@tonic-gate# links to the source files and their diffs. 34557c478bd9Sstevel@tonic-gate 34567c478bd9Sstevel@tonic-gatecd $CWS 34577c478bd9Sstevel@tonic-gate 34587c478bd9Sstevel@tonic-gate# Save total changed lines for Code Inspection. 3459daaffb31Sdpprint "$TOTL" > $WDIR/TotalChangedLines 34607c478bd9Sstevel@tonic-gate 3461daaffb31Sdpprint " index.html: \c" 34627c478bd9Sstevel@tonic-gateINDEXFILE=$WDIR/index.html 34637c478bd9Sstevel@tonic-gateexec 3<&1 # duplicate stdout to FD3. 34647c478bd9Sstevel@tonic-gateexec 1<&- # Close stdout. 34657c478bd9Sstevel@tonic-gateexec > $INDEXFILE # Open stdout to index file. 34667c478bd9Sstevel@tonic-gate 3467daaffb31Sdpprint "$HTML<head>$STDHEAD" 3468daaffb31Sdpprint "<title>$WNAME</title>" 3469daaffb31Sdpprint "</head>" 3470daaffb31Sdpprint "<body id=\"SUNWwebrev\">" 3471daaffb31Sdpprint "<div class=\"summary\">" 3472daaffb31Sdpprint "<h2>Code Review for $WNAME</h2>" 34737c478bd9Sstevel@tonic-gate 3474daaffb31Sdpprint "<table>" 34757c478bd9Sstevel@tonic-gate 3476daaffb31Sdp# 3477cdf0c1d5Smjnelson# Get the preparer's name: 3478daaffb31Sdp# 3479cdf0c1d5Smjnelson# If the SCM detected is Mercurial, and the configuration property 3480cdf0c1d5Smjnelson# ui.username is available, use that, but be careful to properly escape 3481cdf0c1d5Smjnelson# angle brackets (HTML syntax characters) in the email address. 3482cdf0c1d5Smjnelson# 3483cdf0c1d5Smjnelson# Otherwise, use the current userid in the form "John Doe (jdoe)", but 3484cdf0c1d5Smjnelson# to maintain compatibility with passwd(4), we must support '&' substitutions. 3485cdf0c1d5Smjnelson# 3486cdf0c1d5Smjnelsonpreparer= 3487cdf0c1d5Smjnelsonif [[ "$SCM_MODE" == mercurial ]]; then 3488cdf0c1d5Smjnelson preparer=`hg showconfig ui.username 2>/dev/null` 3489cdf0c1d5Smjnelson if [[ -n "$preparer" ]]; then 3490cdf0c1d5Smjnelson preparer="$(echo "$preparer" | html_quote)" 3491cdf0c1d5Smjnelson fi 3492cdf0c1d5Smjnelsonfi 3493cdf0c1d5Smjnelsonif [[ -z "$preparer" ]]; then 3494cdf0c1d5Smjnelson preparer=$( 3495cdf0c1d5Smjnelson $PERL -e ' 3496cdf0c1d5Smjnelson ($login, $pw, $uid, $gid, $quota, $cmt, $gcos) = getpwuid($<); 3497cdf0c1d5Smjnelson if ($login) { 3498cdf0c1d5Smjnelson $gcos =~ s/\&/ucfirst($login)/e; 3499cdf0c1d5Smjnelson printf "%s (%s)\n", $gcos, $login; 3500cdf0c1d5Smjnelson } else { 3501cdf0c1d5Smjnelson printf "(unknown)\n"; 3502cdf0c1d5Smjnelson } 3503cdf0c1d5Smjnelson ') 3504daaffb31Sdpfi 3505daaffb31Sdp 350648bc00d6SjmcpPREPDATE=$(LC_ALL=C /usr/bin/date +%Y-%b-%d\ %R\ %z\ %Z) 350748bc00d6Sjmcpprint "<tr><th>Prepared by:</th><td>$preparer on $PREPDATE</td></tr>" 35088bcea973SRichard Loweprint "<tr><th>Workspace:</th><td>${PRETTY_CWS:-$CWS}" 3509cdf0c1d5Smjnelsonprint "</td></tr>" 3510daaffb31Sdpprint "<tr><th>Compare against:</th><td>" 3511daaffb31Sdpif [[ -n $parent_webrev ]]; then 3512daaffb31Sdp print "webrev at $parent_webrev" 3513daaffb31Sdpelse 35148bcea973SRichard Lowe print "${PRETTY_PWS:-$PWS}" 3515daaffb31Sdpfi 3516daaffb31Sdpprint "</td></tr>" 3517daaffb31Sdpprint "<tr><th>Summary of changes:</th><td>" 3518daaffb31SdpprintCI $TOTL $TINS $TDEL $TMOD $TUNC 3519daaffb31Sdpprint "</td></tr>" 3520daaffb31Sdp 3521daaffb31Sdpif [[ -f $WDIR/$WNAME.patch ]]; then 3522371d72daSLubomir Sedlacik wpatch_url="$(print $WNAME.patch | url_encode)" 3523daaffb31Sdp print "<tr><th>Patch of changes:</th><td>" 3524371d72daSLubomir Sedlacik print "<a href=\"$wpatch_url\">$WNAME.patch</a></td></tr>" 3525daaffb31Sdpfi 3526daaffb31Sdpif [[ -f $WDIR/$WNAME.pdf ]]; then 3527371d72daSLubomir Sedlacik wpdf_url="$(print $WNAME.pdf | url_encode)" 3528daaffb31Sdp print "<tr><th>Printable review:</th><td>" 3529371d72daSLubomir Sedlacik print "<a href=\"$wpdf_url\">$WNAME.pdf</a></td></tr>" 3530daaffb31Sdpfi 3531daaffb31Sdp 3532daaffb31Sdpif [[ -n "$iflag" ]]; then 3533daaffb31Sdp print "<tr><th>Author comments:</th><td><div>" 3534daaffb31Sdp cat /tmp/$$.include 3535daaffb31Sdp print "</div></td></tr>" 3536daaffb31Sdpfi 3537daaffb31Sdpprint "</table>" 3538daaffb31Sdpprint "</div>" 3539daaffb31Sdp 3540daaffb31Sdp# 3541daaffb31Sdp# Second pass through the files: generate the rest of the index file 3542daaffb31Sdp# 3543daaffb31Sdpcat $FLIST | while read LINE 35447c478bd9Sstevel@tonic-gatedo 35457c478bd9Sstevel@tonic-gate set - $LINE 35467c478bd9Sstevel@tonic-gate P=$1 35477c478bd9Sstevel@tonic-gate 3548daaffb31Sdp if [[ $# == 2 ]]; then 35497c478bd9Sstevel@tonic-gate PP=$2 3550cdf0c1d5Smjnelson oldname="$PP" 35517c478bd9Sstevel@tonic-gate else 35527c478bd9Sstevel@tonic-gate PP=$P 3553daaffb31Sdp oldname="" 3554daaffb31Sdp fi 3555daaffb31Sdp 3556cdf0c1d5Smjnelson mv_but_nodiff= 3557cdf0c1d5Smjnelson cmp $WDIR/raw_files/old/$PP $WDIR/raw_files/new/$P > /dev/null 2>&1 3558cdf0c1d5Smjnelson if [[ $? == 0 && -n "$oldname" ]]; then 3559cdf0c1d5Smjnelson mv_but_nodiff=1 3560cdf0c1d5Smjnelson fi 3561cdf0c1d5Smjnelson 3562daaffb31Sdp DIR=${P%/*} 3563daaffb31Sdp if [[ $DIR == $P ]]; then 3564daaffb31Sdp DIR="." # File at root of workspace 35657c478bd9Sstevel@tonic-gate fi 35667c478bd9Sstevel@tonic-gate 35677c478bd9Sstevel@tonic-gate # Avoid processing the same file twice. 35687c478bd9Sstevel@tonic-gate # It's possible for renamed files to 35697c478bd9Sstevel@tonic-gate # appear twice in the file list 35707c478bd9Sstevel@tonic-gate 35717c478bd9Sstevel@tonic-gate F=$WDIR/$P 35727c478bd9Sstevel@tonic-gate 3573daaffb31Sdp print "<p>" 35747c478bd9Sstevel@tonic-gate 35757c478bd9Sstevel@tonic-gate # If there's a diffs file, make diffs links 35767c478bd9Sstevel@tonic-gate 3577daaffb31Sdp if [[ -f $F.cdiff.html ]]; then 3578371d72daSLubomir Sedlacik cdiff_url="$(print $P.cdiff.html | url_encode)" 3579371d72daSLubomir Sedlacik udiff_url="$(print $P.udiff.html | url_encode)" 3580371d72daSLubomir Sedlacik print "<a href=\"$cdiff_url\">Cdiffs</a>" 3581371d72daSLubomir Sedlacik print "<a href=\"$udiff_url\">Udiffs</a>" 35827c478bd9Sstevel@tonic-gate 3583daaffb31Sdp if [[ -f $F.wdiff.html && -x $WDIFF ]]; then 3584371d72daSLubomir Sedlacik wdiff_url="$(print $P.wdiff.html | url_encode)" 3585371d72daSLubomir Sedlacik print "<a href=\"$wdiff_url\">Wdiffs</a>" 35867c478bd9Sstevel@tonic-gate fi 35877c478bd9Sstevel@tonic-gate 3588371d72daSLubomir Sedlacik sdiff_url="$(print $P.sdiff.html | url_encode)" 3589371d72daSLubomir Sedlacik print "<a href=\"$sdiff_url\">Sdiffs</a>" 35907c478bd9Sstevel@tonic-gate 3591371d72daSLubomir Sedlacik frames_url="$(print $P.frames.html | url_encode)" 3592371d72daSLubomir Sedlacik print "<a href=\"$frames_url\">Frames</a>" 35937c478bd9Sstevel@tonic-gate else 3594daaffb31Sdp print " ------ ------ ------" 35957c478bd9Sstevel@tonic-gate 3596daaffb31Sdp if [[ -x $WDIFF ]]; then 35977c478bd9Sstevel@tonic-gate print " ------" 35987c478bd9Sstevel@tonic-gate fi 3599daaffb31Sdp 3600daaffb31Sdp print " ------" 36017c478bd9Sstevel@tonic-gate fi 36027c478bd9Sstevel@tonic-gate 36037c478bd9Sstevel@tonic-gate # If there's an old file, make the link 36047c478bd9Sstevel@tonic-gate 3605daaffb31Sdp if [[ -f $F-.html ]]; then 3606371d72daSLubomir Sedlacik oldfile_url="$(print $P-.html | url_encode)" 3607371d72daSLubomir Sedlacik print "<a href=\"$oldfile_url\">Old</a>" 36087c478bd9Sstevel@tonic-gate else 3609daaffb31Sdp print " ---" 36107c478bd9Sstevel@tonic-gate fi 36117c478bd9Sstevel@tonic-gate 36127c478bd9Sstevel@tonic-gate # If there's an new file, make the link 36137c478bd9Sstevel@tonic-gate 3614daaffb31Sdp if [[ -f $F.html ]]; then 3615371d72daSLubomir Sedlacik newfile_url="$(print $P.html | url_encode)" 3616371d72daSLubomir Sedlacik print "<a href=\"$newfile_url\">New</a>" 36177c478bd9Sstevel@tonic-gate else 3618daaffb31Sdp print " ---" 36197c478bd9Sstevel@tonic-gate fi 36207c478bd9Sstevel@tonic-gate 3621daaffb31Sdp if [[ -f $F.patch ]]; then 3622371d72daSLubomir Sedlacik patch_url="$(print $P.patch | url_encode)" 3623371d72daSLubomir Sedlacik print "<a href=\"$patch_url\">Patch</a>" 3624daaffb31Sdp else 3625daaffb31Sdp print " -----" 3626daaffb31Sdp fi 3627daaffb31Sdp 3628daaffb31Sdp if [[ -f $WDIR/raw_files/new/$P ]]; then 3629371d72daSLubomir Sedlacik rawfiles_url="$(print raw_files/new/$P | url_encode)" 3630371d72daSLubomir Sedlacik print "<a href=\"$rawfiles_url\">Raw</a>" 3631daaffb31Sdp else 3632daaffb31Sdp print " ---" 3633daaffb31Sdp fi 3634daaffb31Sdp 3635cdf0c1d5Smjnelson print "<b>$P</b>" 3636cdf0c1d5Smjnelson 3637cdf0c1d5Smjnelson # For renamed files, clearly state whether or not they are modified 3638e6ccc173SEdward Pilatowicz if [[ -f "$oldname" ]]; then 3639cdf0c1d5Smjnelson if [[ -n "$mv_but_nodiff" ]]; then 3640e6ccc173SEdward Pilatowicz print "<i>(copied from $oldname)</i>" 3641cdf0c1d5Smjnelson else 3642e6ccc173SEdward Pilatowicz print "<i>(copied and modified from $oldname)</i>" 3643e6ccc173SEdward Pilatowicz fi 3644e6ccc173SEdward Pilatowicz elif [[ -n "$oldname" ]]; then 3645e6ccc173SEdward Pilatowicz if [[ -n "$mv_but_nodiff" ]]; then 3646e6ccc173SEdward Pilatowicz print "<i>(renamed from $oldname)</i>" 3647e6ccc173SEdward Pilatowicz else 3648e6ccc173SEdward Pilatowicz print "<i>(renamed and modified from $oldname)</i>" 3649cdf0c1d5Smjnelson fi 3650cdf0c1d5Smjnelson fi 3651cdf0c1d5Smjnelson 3652cdf0c1d5Smjnelson # If there's an old file, but no new file, the file was deleted 3653cdf0c1d5Smjnelson if [[ -f $F-.html && ! -f $F.html ]]; then 3654cdf0c1d5Smjnelson print " <i>(deleted)</i>" 3655cdf0c1d5Smjnelson fi 3656daaffb31Sdp 3657daaffb31Sdp # 3658e0e0293aSjmcp # Check for usr/closed and deleted_files/usr/closed 3659daaffb31Sdp # 3660daaffb31Sdp if [ ! -z "$Oflag" ]; then 3661e0e0293aSjmcp if [[ $P == usr/closed/* || \ 3662e0e0293aSjmcp $P == deleted_files/usr/closed/* ]]; then 3663daaffb31Sdp print " <i>Closed source: omitted from" \ 3664daaffb31Sdp "this review</i>" 3665daaffb31Sdp fi 3666daaffb31Sdp fi 3667daaffb31Sdp 3668daaffb31Sdp print "</p>" 36697c478bd9Sstevel@tonic-gate # Insert delta comments 36707c478bd9Sstevel@tonic-gate 3671daaffb31Sdp print "<blockquote><pre>" 3672daaffb31Sdp getcomments html $P $PP 3673daaffb31Sdp print "</pre>" 36747c478bd9Sstevel@tonic-gate 36757c478bd9Sstevel@tonic-gate # Add additional comments comment 36767c478bd9Sstevel@tonic-gate 3677daaffb31Sdp print "<!-- Add comments to explain changes in $P here -->" 36787c478bd9Sstevel@tonic-gate 36797c478bd9Sstevel@tonic-gate # Add count of changes. 36807c478bd9Sstevel@tonic-gate 3681daaffb31Sdp if [[ -f $F.count ]]; then 36827c478bd9Sstevel@tonic-gate cat $F.count 36837c478bd9Sstevel@tonic-gate rm $F.count 36847c478bd9Sstevel@tonic-gate fi 3685cdf0c1d5Smjnelson 3686cdf0c1d5Smjnelson if [[ $SCM_MODE == "teamware" || 3687cdf0c1d5Smjnelson $SCM_MODE == "mercurial" || 3688cdf0c1d5Smjnelson $SCM_MODE == "unknown" ]]; then 3689cdf0c1d5Smjnelson 3690cdf0c1d5Smjnelson # Include warnings for important file mode situations: 3691cdf0c1d5Smjnelson # 1) New executable files 3692cdf0c1d5Smjnelson # 2) Permission changes of any kind 3693cdf0c1d5Smjnelson # 3) Existing executable files 3694cdf0c1d5Smjnelson 3695cdf0c1d5Smjnelson old_mode= 3696cdf0c1d5Smjnelson if [[ -f $WDIR/raw_files/old/$PP ]]; then 3697cdf0c1d5Smjnelson old_mode=`get_file_mode $WDIR/raw_files/old/$PP` 3698cdf0c1d5Smjnelson fi 3699cdf0c1d5Smjnelson 3700cdf0c1d5Smjnelson new_mode= 3701cdf0c1d5Smjnelson if [[ -f $WDIR/raw_files/new/$P ]]; then 3702cdf0c1d5Smjnelson new_mode=`get_file_mode $WDIR/raw_files/new/$P` 3703cdf0c1d5Smjnelson fi 3704cdf0c1d5Smjnelson 3705cdf0c1d5Smjnelson if [[ -z "$old_mode" && "$new_mode" = *[1357]* ]]; then 3706cdf0c1d5Smjnelson print "<span class=\"chmod\">" 3707cdf0c1d5Smjnelson print "<p>new executable file: mode $new_mode</p>" 3708cdf0c1d5Smjnelson print "</span>" 3709cdf0c1d5Smjnelson elif [[ -n "$old_mode" && -n "$new_mode" && 3710cdf0c1d5Smjnelson "$old_mode" != "$new_mode" ]]; then 3711cdf0c1d5Smjnelson print "<span class=\"chmod\">" 3712cdf0c1d5Smjnelson print "<p>mode change: $old_mode to $new_mode</p>" 3713cdf0c1d5Smjnelson print "</span>" 3714cdf0c1d5Smjnelson elif [[ "$new_mode" = *[1357]* ]]; then 3715cdf0c1d5Smjnelson print "<span class=\"chmod\">" 3716cdf0c1d5Smjnelson print "<p>executable file: mode $new_mode</p>" 3717cdf0c1d5Smjnelson print "</span>" 3718cdf0c1d5Smjnelson fi 3719cdf0c1d5Smjnelson fi 3720cdf0c1d5Smjnelson 3721daaffb31Sdp print "</blockquote>" 37227c478bd9Sstevel@tonic-gatedone 37237c478bd9Sstevel@tonic-gate 3724daaffb31Sdpprint 3725daaffb31Sdpprint 3726cac38512Smjnelsonprint "<hr></hr>" 3727daaffb31Sdpprint "<p style=\"font-size: small\">" 37289a70fc3bSMark J. Nelsonprint "This code review page was prepared using <b>$0</b>." 372987a4464eSChris Loveprint "Webrev is maintained by the <a href=\"http://www.illumos.org\">" 373087a4464eSChris Loveprint "illumos</a> project. The latest version may be obtained" 3731*7646c8f3SMarcel Telkaprint "<a href=\"http://src.illumos.org/source/xref/illumos-gate/usr/src/tools/scripts/webrev.sh\">here</a>.</p>" 3732daaffb31Sdpprint "</body>" 3733daaffb31Sdpprint "</html>" 37347c478bd9Sstevel@tonic-gate 37357c478bd9Sstevel@tonic-gateexec 1<&- # Close FD 1. 37367c478bd9Sstevel@tonic-gateexec 1<&3 # dup FD 3 to restore stdout. 37377c478bd9Sstevel@tonic-gateexec 3<&- # close FD 3. 37387c478bd9Sstevel@tonic-gate 3739daaffb31Sdpprint "Done." 374002d26c39SVladimir Kotal 3741b0088928SVladimir Kotal# 3742ba44d8a2SVladimir Kotal# If remote deletion was specified and fails do not continue. 3743b0088928SVladimir Kotal# 3744ba44d8a2SVladimir Kotalif [[ -n $Dflag ]]; then 3745b0088928SVladimir Kotal delete_webrev 1 1 3746ba44d8a2SVladimir Kotal (( $? == 0 )) || exit $? 3747ba44d8a2SVladimir Kotalfi 3748ba44d8a2SVladimir Kotal 374902d26c39SVladimir Kotalif [[ -n $Uflag ]]; then 375002d26c39SVladimir Kotal upload_webrev 375102d26c39SVladimir Kotal exit $? 375202d26c39SVladimir Kotalfi 3753