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 287646c8f3SMarcel Telka# Copyright 2012 Marcel Telka <marcel@telka.sk> 29d7b56f41SBart Coddens# Copyright 2014 Bart Coddens <bart.coddens@gmail.com> 302f54b716SRichard Lowe 31cdf0c1d5Smjnelson# 32daaffb31Sdp# This script takes a file list and a workspace and builds a set of html files 33daaffb31Sdp# suitable for doing a code review of source changes via a web page. 34daaffb31Sdp# Documentation is available via the manual page, webrev.1, or just 35daaffb31Sdp# type 'webrev -h'. 367c478bd9Sstevel@tonic-gate# 37daaffb31Sdp# Acknowledgements to contributors to webrev are listed in the webrev(1) 38daaffb31Sdp# man page. 397c478bd9Sstevel@tonic-gate# 40daaffb31Sdp 417c478bd9Sstevel@tonic-gateREMOVED_COLOR=brown 427c478bd9Sstevel@tonic-gateCHANGED_COLOR=blue 437c478bd9Sstevel@tonic-gateNEW_COLOR=blue 447c478bd9Sstevel@tonic-gate 45daaffb31SdpHTML='<?xml version="1.0"?> 46daaffb31Sdp<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 47daaffb31Sdp "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 48daaffb31Sdp<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">\n' 49daaffb31Sdp 50daaffb31SdpFRAMEHTML='<?xml version="1.0"?> 51daaffb31Sdp<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" 52daaffb31Sdp "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd"> 53daaffb31Sdp<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">\n' 54daaffb31Sdp 55cac38512SmjnelsonSTDHEAD='<meta http-equiv="cache-control" content="no-cache"></meta> 56*48ad9d01SRobert Mustacchi<meta http-equiv="Content-Type" content="text/xhtml;charset=utf-8"></meta> 57cac38512Smjnelson<meta http-equiv="Pragma" content="no-cache"></meta> 58cac38512Smjnelson<meta http-equiv="Expires" content="-1"></meta> 59daaffb31Sdp<!-- 60daaffb31Sdp Note to customizers: the body of the webrev is IDed as SUNWwebrev 61daaffb31Sdp to allow easy overriding by users of webrev via the userContent.css 62daaffb31Sdp mechanism available in some browsers. 63daaffb31Sdp 64daaffb31Sdp For example, to have all "removed" information be red instead of 65daaffb31Sdp brown, set a rule in your userContent.css file like: 66daaffb31Sdp 67daaffb31Sdp body#SUNWwebrev span.removed { color: red ! important; } 68daaffb31Sdp--> 69daaffb31Sdp<style type="text/css" media="screen"> 70daaffb31Sdpbody { 71daaffb31Sdp background-color: #eeeeee; 72daaffb31Sdp} 73daaffb31Sdphr { 74daaffb31Sdp border: none 0; 75daaffb31Sdp border-top: 1px solid #aaa; 76daaffb31Sdp height: 1px; 77daaffb31Sdp} 78daaffb31Sdpdiv.summary { 79daaffb31Sdp font-size: .8em; 80daaffb31Sdp border-bottom: 1px solid #aaa; 81daaffb31Sdp padding-left: 1em; 82daaffb31Sdp padding-right: 1em; 83daaffb31Sdp} 84daaffb31Sdpdiv.summary h2 { 85daaffb31Sdp margin-bottom: 0.3em; 86daaffb31Sdp} 87daaffb31Sdpdiv.summary table th { 88daaffb31Sdp text-align: right; 89daaffb31Sdp vertical-align: top; 90daaffb31Sdp white-space: nowrap; 91daaffb31Sdp} 92daaffb31Sdpspan.lineschanged { 93daaffb31Sdp font-size: 0.7em; 94daaffb31Sdp} 95daaffb31Sdpspan.oldmarker { 96daaffb31Sdp color: red; 97daaffb31Sdp font-size: large; 98daaffb31Sdp font-weight: bold; 99daaffb31Sdp} 100daaffb31Sdpspan.newmarker { 101daaffb31Sdp color: green; 102daaffb31Sdp font-size: large; 103daaffb31Sdp font-weight: bold; 104daaffb31Sdp} 105daaffb31Sdpspan.removed { 106daaffb31Sdp color: brown; 107daaffb31Sdp} 108daaffb31Sdpspan.changed { 109daaffb31Sdp color: blue; 110daaffb31Sdp} 111daaffb31Sdpspan.new { 112daaffb31Sdp color: blue; 113daaffb31Sdp font-weight: bold; 114daaffb31Sdp} 115cdf0c1d5Smjnelsonspan.chmod { 116cdf0c1d5Smjnelson font-size: 0.7em; 117cdf0c1d5Smjnelson color: #db7800; 118cdf0c1d5Smjnelson} 119daaffb31Sdpa.print { font-size: x-small; } 120daaffb31Sdpa:hover { background-color: #ffcc99; } 121daaffb31Sdp</style> 122daaffb31Sdp 123daaffb31Sdp<style type="text/css" media="print"> 124daaffb31Sdppre { font-size: 0.8em; font-family: courier, monospace; } 125daaffb31Sdpspan.removed { color: #444; font-style: italic } 126daaffb31Sdpspan.changed { font-weight: bold; } 127daaffb31Sdpspan.new { font-weight: bold; } 128daaffb31Sdpspan.newmarker { font-size: 1.2em; font-weight: bold; } 129daaffb31Sdpspan.oldmarker { font-size: 1.2em; font-weight: bold; } 130daaffb31Sdpa.print {display: none} 131daaffb31Sdphr { border: none 0; border-top: 1px solid #aaa; height: 1px; } 132daaffb31Sdp</style> 133daaffb31Sdp' 134daaffb31Sdp 135daaffb31Sdp# 136daaffb31Sdp# UDiffs need a slightly different CSS rule for 'new' items (we don't 137daaffb31Sdp# want them to be bolded as we do in cdiffs or sdiffs). 138daaffb31Sdp# 139daaffb31SdpUDIFFCSS=' 140daaffb31Sdp<style type="text/css" media="screen"> 141daaffb31Sdpspan.new { 142daaffb31Sdp color: blue; 143daaffb31Sdp font-weight: normal; 144daaffb31Sdp} 145daaffb31Sdp</style> 146daaffb31Sdp' 147daaffb31Sdp 148b0088928SVladimir Kotal# 149b0088928SVladimir Kotal# Display remote target with prefix and trailing slash. 150b0088928SVladimir Kotal# 151b0088928SVladimir Kotalfunction print_upload_header 152b0088928SVladimir Kotal{ 153b0088928SVladimir Kotal typeset -r prefix=$1 154b0088928SVladimir Kotal typeset display_target 155b0088928SVladimir Kotal 156b0088928SVladimir Kotal if [[ -z $tflag ]]; then 157b0088928SVladimir Kotal display_target=${prefix}${remote_target} 158b0088928SVladimir Kotal else 159b0088928SVladimir Kotal display_target=${remote_target} 160b0088928SVladimir Kotal fi 161b0088928SVladimir Kotal 162b0088928SVladimir Kotal if [[ ${display_target} != */ ]]; then 163b0088928SVladimir Kotal display_target=${display_target}/ 164b0088928SVladimir Kotal fi 165b0088928SVladimir Kotal 166b0088928SVladimir Kotal print " Upload to: ${display_target}\n" \ 167b0088928SVladimir Kotal " Uploading: \c" 168b0088928SVladimir Kotal} 169b0088928SVladimir Kotal 170b0088928SVladimir Kotal# 17102d26c39SVladimir Kotal# Upload the webrev via rsync. Return 0 on success, 1 on error. 172b0088928SVladimir Kotal# 173ba44d8a2SVladimir Kotalfunction rsync_upload 17402d26c39SVladimir Kotal{ 175b0088928SVladimir Kotal if (( $# != 2 )); then 176b0088928SVladimir Kotal print "\nERROR: rsync_upload: wrong usage ($#)" 177b0088928SVladimir Kotal exit 1 17802d26c39SVladimir Kotal fi 17902d26c39SVladimir Kotal 180b0088928SVladimir Kotal typeset -r dst=$1 181b0088928SVladimir Kotal integer -r print_err_msg=$2 18202d26c39SVladimir Kotal 183b0088928SVladimir Kotal print_upload_header ${rsync_prefix} 184b0088928SVladimir Kotal print "rsync ... \c" 1858a34f8dcSVladimir Kotal typeset -r err_msg=$( $MKTEMP /tmp/rsync_err.XXXXXX ) 186b0088928SVladimir Kotal if [[ -z $err_msg ]]; then 187b0088928SVladimir Kotal print "\nERROR: rsync_upload: cannot create temporary file" 188b0088928SVladimir Kotal return 1 189b0088928SVladimir Kotal fi 190b0088928SVladimir Kotal # 191b0088928SVladimir Kotal # The source directory must end with a slash in order to copy just 192b0088928SVladimir Kotal # directory contents, not the whole directory. 193b0088928SVladimir Kotal # 194b0088928SVladimir Kotal typeset src_dir=$WDIR 195b0088928SVladimir Kotal if [[ ${src_dir} != */ ]]; then 196b0088928SVladimir Kotal src_dir=${src_dir}/ 197b0088928SVladimir Kotal fi 198b0088928SVladimir Kotal $RSYNC -r -q ${src_dir} $dst 2>$err_msg 19902d26c39SVladimir Kotal if (( $? != 0 )); then 200b0088928SVladimir Kotal if (( ${print_err_msg} > 0 )); then 201b0088928SVladimir Kotal print "Failed.\nERROR: rsync failed" 202b0088928SVladimir Kotal print "src dir: '${src_dir}'\ndst dir: '$dst'" 203b0088928SVladimir Kotal print "error messages:" 204b0088928SVladimir Kotal $SED 's/^/> /' $err_msg 205b0088928SVladimir Kotal rm -f $err_msg 206b0088928SVladimir Kotal fi 20702d26c39SVladimir Kotal return 1 20802d26c39SVladimir Kotal fi 20902d26c39SVladimir Kotal 210b0088928SVladimir Kotal rm -f $err_msg 21102d26c39SVladimir Kotal print "Done." 21202d26c39SVladimir Kotal return 0 21302d26c39SVladimir Kotal} 21402d26c39SVladimir Kotal 215b0088928SVladimir Kotal# 216b0088928SVladimir Kotal# Create directories on remote host using SFTP. Return 0 on success, 217b0088928SVladimir Kotal# 1 on failure. 218b0088928SVladimir Kotal# 219b0088928SVladimir Kotalfunction remote_mkdirs 220b0088928SVladimir Kotal{ 221b0088928SVladimir Kotal typeset -r dir_spec=$1 2229d3952abSVladimir Kotal typeset -r host_spec=$2 223b0088928SVladimir Kotal 224b0088928SVladimir Kotal # 225b0088928SVladimir Kotal # If the supplied path is absolute we assume all directories are 226b0088928SVladimir Kotal # created, otherwise try to create all directories in the path 227b0088928SVladimir Kotal # except the last one which will be created by scp. 228b0088928SVladimir Kotal # 229b0088928SVladimir Kotal if [[ "${dir_spec}" == */* && "${dir_spec}" != /* ]]; then 230b0088928SVladimir Kotal print "mkdirs \c" 231b0088928SVladimir Kotal # 232b0088928SVladimir Kotal # Remove the last directory from directory specification. 233b0088928SVladimir Kotal # 234b0088928SVladimir Kotal typeset -r dirs_mk=${dir_spec%/*} 2358a34f8dcSVladimir Kotal typeset -r batch_file_mkdir=$( $MKTEMP \ 2368a34f8dcSVladimir Kotal /tmp/webrev_mkdir.XXXXXX ) 237b0088928SVladimir Kotal if [[ -z $batch_file_mkdir ]]; then 238b0088928SVladimir Kotal print "\nERROR: remote_mkdirs:" \ 239b0088928SVladimir Kotal "cannot create temporary file for batch file" 240b0088928SVladimir Kotal return 1 241b0088928SVladimir Kotal fi 242b0088928SVladimir Kotal OLDIFS=$IFS 243b0088928SVladimir Kotal IFS=/ 244b0088928SVladimir Kotal typeset dir 245b0088928SVladimir Kotal for dir in ${dirs_mk}; do 246b0088928SVladimir Kotal # 247b0088928SVladimir Kotal # Use the '-' prefix to ignore mkdir errors in order 248b0088928SVladimir Kotal # to avoid an error in case the directory already 249b0088928SVladimir Kotal # exists. We check the directory with chdir to be sure 250b0088928SVladimir Kotal # there is one. 251b0088928SVladimir Kotal # 252b0088928SVladimir Kotal print -- "-mkdir ${dir}" >> ${batch_file_mkdir} 253b0088928SVladimir Kotal print "chdir ${dir}" >> ${batch_file_mkdir} 254b0088928SVladimir Kotal done 255b0088928SVladimir Kotal IFS=$OLDIFS 2568a34f8dcSVladimir Kotal typeset -r sftp_err_msg=$( $MKTEMP /tmp/webrev_scp_err.XXXXXX ) 257b0088928SVladimir Kotal if [[ -z ${sftp_err_msg} ]]; then 258b0088928SVladimir Kotal print "\nERROR: remote_mkdirs:" \ 259b0088928SVladimir Kotal "cannot create temporary file for error messages" 260b0088928SVladimir Kotal return 1 261b0088928SVladimir Kotal fi 262b0088928SVladimir Kotal $SFTP -b ${batch_file_mkdir} ${host_spec} 2>${sftp_err_msg} 1>&2 263b0088928SVladimir Kotal if (( $? != 0 )); then 264b0088928SVladimir Kotal print "\nERROR: failed to create remote directories" 265b0088928SVladimir Kotal print "error messages:" 266b0088928SVladimir Kotal $SED 's/^/> /' ${sftp_err_msg} 267b0088928SVladimir Kotal rm -f ${sftp_err_msg} ${batch_file_mkdir} 268b0088928SVladimir Kotal return 1 269b0088928SVladimir Kotal fi 270b0088928SVladimir Kotal rm -f ${sftp_err_msg} ${batch_file_mkdir} 271b0088928SVladimir Kotal fi 272b0088928SVladimir Kotal 273b0088928SVladimir Kotal return 0 274b0088928SVladimir Kotal} 275b0088928SVladimir Kotal 276b0088928SVladimir Kotal# 27702d26c39SVladimir Kotal# Upload the webrev via SSH. Return 0 on success, 1 on error. 278b0088928SVladimir Kotal# 279ba44d8a2SVladimir Kotalfunction ssh_upload 28002d26c39SVladimir Kotal{ 28102d26c39SVladimir Kotal if (( $# != 1 )); then 282b0088928SVladimir Kotal print "\nERROR: ssh_upload: wrong number of arguments" 283b0088928SVladimir Kotal exit 1 28402d26c39SVladimir Kotal fi 28502d26c39SVladimir Kotal 28602d26c39SVladimir Kotal typeset dst=$1 28702d26c39SVladimir Kotal typeset -r host_spec=${dst%%:*} 288ba44d8a2SVladimir Kotal typeset -r dir_spec=${dst#*:} 28902d26c39SVladimir Kotal 290b0088928SVladimir Kotal # 291b0088928SVladimir Kotal # Display the upload information before calling delete_webrev 292b0088928SVladimir Kotal # because it will also print its progress. 293b0088928SVladimir Kotal # 294b0088928SVladimir Kotal print_upload_header ${ssh_prefix} 295b0088928SVladimir Kotal 296b0088928SVladimir Kotal # 297b0088928SVladimir Kotal # If the deletion was explicitly requested there is no need 298b0088928SVladimir Kotal # to perform it again. 299b0088928SVladimir Kotal # 300ba44d8a2SVladimir Kotal if [[ -z $Dflag ]]; then 301b0088928SVladimir Kotal # 302b0088928SVladimir Kotal # We do not care about return value because this might be 303b0088928SVladimir Kotal # the first time this directory is uploaded. 304b0088928SVladimir Kotal # 305ba44d8a2SVladimir Kotal delete_webrev 0 30602d26c39SVladimir Kotal fi 30702d26c39SVladimir Kotal 308b0088928SVladimir Kotal # 309b0088928SVladimir Kotal # Create remote directories. Any error reporting will be done 310b0088928SVladimir Kotal # in remote_mkdirs function. 311b0088928SVladimir Kotal # 3129d3952abSVladimir Kotal remote_mkdirs ${dir_spec} ${host_spec} 31302d26c39SVladimir Kotal if (( $? != 0 )); then 31402d26c39SVladimir Kotal return 1 31502d26c39SVladimir Kotal fi 31602d26c39SVladimir Kotal 317b0088928SVladimir Kotal print "upload ... \c" 3188a34f8dcSVladimir Kotal typeset -r scp_err_msg=$( $MKTEMP /tmp/scp_err.XXXXXX ) 319b0088928SVladimir Kotal if [[ -z ${scp_err_msg} ]]; then 320b0088928SVladimir Kotal print "\nERROR: ssh_upload:" \ 321b0088928SVladimir Kotal "cannot create temporary file for error messages" 322b0088928SVladimir Kotal return 1 323b0088928SVladimir Kotal fi 32402d26c39SVladimir Kotal $SCP -q -C -B -o PreferredAuthentications=publickey -r \ 325b0088928SVladimir Kotal $WDIR $dst 2>${scp_err_msg} 32602d26c39SVladimir Kotal if (( $? != 0 )); then 327b0088928SVladimir Kotal print "Failed.\nERROR: scp failed" 328b0088928SVladimir Kotal print "src dir: '$WDIR'\ndst dir: '$dst'" 329b0088928SVladimir Kotal print "error messages:" 330b0088928SVladimir Kotal $SED 's/^/> /' ${scp_err_msg} 331b0088928SVladimir Kotal rm -f ${scp_err_msg} 33202d26c39SVladimir Kotal return 1 33302d26c39SVladimir Kotal fi 33402d26c39SVladimir Kotal 335b0088928SVladimir Kotal rm -f ${scp_err_msg} 33602d26c39SVladimir Kotal print "Done." 33702d26c39SVladimir Kotal return 0 33802d26c39SVladimir Kotal} 33902d26c39SVladimir Kotal 34002d26c39SVladimir Kotal# 341ba44d8a2SVladimir Kotal# Delete webrev at remote site. Return 0 on success, 1 or exit code from sftp 342b0088928SVladimir Kotal# on failure. If first argument is 1 then perform the check of sftp return 343b0088928SVladimir Kotal# value otherwise ignore it. If second argument is present it means this run 344b0088928SVladimir Kotal# only performs deletion. 345ba44d8a2SVladimir Kotal# 346ba44d8a2SVladimir Kotalfunction delete_webrev 347ba44d8a2SVladimir Kotal{ 348b0088928SVladimir Kotal if (( $# < 1 )); then 349b0088928SVladimir Kotal print "delete_webrev: wrong number of arguments" 350b0088928SVladimir Kotal exit 1 351ba44d8a2SVladimir Kotal fi 352ba44d8a2SVladimir Kotal 353b0088928SVladimir Kotal integer -r check=$1 354b0088928SVladimir Kotal integer delete_only=0 355b0088928SVladimir Kotal if (( $# == 2 )); then 356b0088928SVladimir Kotal delete_only=1 357b0088928SVladimir Kotal fi 358b0088928SVladimir Kotal 359b0088928SVladimir Kotal # 360ba44d8a2SVladimir Kotal # Strip the transport specification part of remote target first. 361b0088928SVladimir Kotal # 362ba44d8a2SVladimir Kotal typeset -r stripped_target=${remote_target##*://} 363ba44d8a2SVladimir Kotal typeset -r host_spec=${stripped_target%%:*} 364ba44d8a2SVladimir Kotal typeset -r dir_spec=${stripped_target#*:} 365ba44d8a2SVladimir Kotal typeset dir_rm 366ba44d8a2SVladimir Kotal 367b0088928SVladimir Kotal # 368ba44d8a2SVladimir Kotal # Do not accept an absolute path. 369b0088928SVladimir Kotal # 370ba44d8a2SVladimir Kotal if [[ ${dir_spec} == /* ]]; then 371ba44d8a2SVladimir Kotal return 1 372ba44d8a2SVladimir Kotal fi 373ba44d8a2SVladimir Kotal 374b0088928SVladimir Kotal # 375ba44d8a2SVladimir Kotal # Strip the ending slash. 376b0088928SVladimir Kotal # 377ba44d8a2SVladimir Kotal if [[ ${dir_spec} == */ ]]; then 378ba44d8a2SVladimir Kotal dir_rm=${dir_spec%%/} 379ba44d8a2SVladimir Kotal else 380ba44d8a2SVladimir Kotal dir_rm=${dir_spec} 381ba44d8a2SVladimir Kotal fi 382ba44d8a2SVladimir Kotal 383b0088928SVladimir Kotal if (( ${delete_only} > 0 )); then 384b0088928SVladimir Kotal print " Removing: \c" 385b0088928SVladimir Kotal else 386b0088928SVladimir Kotal print "rmdir \c" 387b0088928SVladimir Kotal fi 388ba44d8a2SVladimir Kotal if [[ -z "$dir_rm" ]]; then 389b0088928SVladimir Kotal print "\nERROR: empty directory for removal" 390ba44d8a2SVladimir Kotal return 1 391ba44d8a2SVladimir Kotal fi 392ba44d8a2SVladimir Kotal 393b0088928SVladimir Kotal # 394ba44d8a2SVladimir Kotal # Prepare batch file. 395b0088928SVladimir Kotal # 3968a34f8dcSVladimir Kotal typeset -r batch_file_rm=$( $MKTEMP /tmp/webrev_remove.XXXXXX ) 397ba44d8a2SVladimir Kotal if [[ -z $batch_file_rm ]]; then 398b0088928SVladimir Kotal print "\nERROR: delete_webrev: cannot create temporary file" 399ba44d8a2SVladimir Kotal return 1 400ba44d8a2SVladimir Kotal fi 401ba44d8a2SVladimir Kotal print "rename $dir_rm $TRASH_DIR/removed.$$" > $batch_file_rm 402ba44d8a2SVladimir Kotal 403b0088928SVladimir Kotal # 404ba44d8a2SVladimir Kotal # Perform remote deletion and remove the batch file. 405b0088928SVladimir Kotal # 4068a34f8dcSVladimir Kotal typeset -r sftp_err_msg=$( $MKTEMP /tmp/webrev_scp_err.XXXXXX ) 407b0088928SVladimir Kotal if [[ -z ${sftp_err_msg} ]]; then 408b0088928SVladimir Kotal print "\nERROR: delete_webrev:" \ 409b0088928SVladimir Kotal "cannot create temporary file for error messages" 410b0088928SVladimir Kotal return 1 411b0088928SVladimir Kotal fi 412b0088928SVladimir Kotal $SFTP -b $batch_file_rm $host_spec 2>${sftp_err_msg} 1>&2 413ba44d8a2SVladimir Kotal integer -r ret=$? 414ba44d8a2SVladimir Kotal rm -f $batch_file_rm 415ba44d8a2SVladimir Kotal if (( $ret != 0 && $check > 0 )); then 416b0088928SVladimir Kotal print "Failed.\nERROR: failed to remove remote directories" 417b0088928SVladimir Kotal print "error messages:" 418b0088928SVladimir Kotal $SED 's/^/> /' ${sftp_err_msg} 419b0088928SVladimir Kotal rm -f ${sftp_err_msg} 420ba44d8a2SVladimir Kotal return $ret 421ba44d8a2SVladimir Kotal fi 422b0088928SVladimir Kotal rm -f ${sftp_err_msg} 423b0088928SVladimir Kotal if (( ${delete_only} > 0 )); then 424ba44d8a2SVladimir Kotal print "Done." 425b0088928SVladimir Kotal fi 426ba44d8a2SVladimir Kotal 427ba44d8a2SVladimir Kotal return 0 428ba44d8a2SVladimir Kotal} 429ba44d8a2SVladimir Kotal 430ba44d8a2SVladimir Kotal# 43102d26c39SVladimir Kotal# Upload webrev to remote site 43202d26c39SVladimir Kotal# 433ba44d8a2SVladimir Kotalfunction upload_webrev 43402d26c39SVladimir Kotal{ 435b0088928SVladimir Kotal integer ret 43602d26c39SVladimir Kotal 43702d26c39SVladimir Kotal if [[ ! -d "$WDIR" ]]; then 438b0088928SVladimir Kotal print "\nERROR: webrev directory '$WDIR' does not exist" 43902d26c39SVladimir Kotal return 1 44002d26c39SVladimir Kotal fi 44102d26c39SVladimir Kotal 442b0088928SVladimir Kotal # 44302d26c39SVladimir Kotal # Perform a late check to make sure we do not upload closed source 44402d26c39SVladimir Kotal # to remote target when -n is used. If the user used custom remote 44502d26c39SVladimir Kotal # target he probably knows what he is doing. 446b0088928SVladimir Kotal # 44702d26c39SVladimir Kotal if [[ -n $nflag && -z $tflag ]]; then 448ba44d8a2SVladimir Kotal $FIND $WDIR -type d -name closed \ 44902d26c39SVladimir Kotal | $GREP closed >/dev/null 45002d26c39SVladimir Kotal if (( $? == 0 )); then 451b0088928SVladimir Kotal print "\nERROR: directory '$WDIR' contains" \ 452b0088928SVladimir Kotal "\"closed\" directory" 45302d26c39SVladimir Kotal return 1 45402d26c39SVladimir Kotal fi 45502d26c39SVladimir Kotal fi 45602d26c39SVladimir Kotal 457b0088928SVladimir Kotal 458b0088928SVladimir Kotal # 459b0088928SVladimir Kotal # We have the URI for remote destination now so let's start the upload. 460b0088928SVladimir Kotal # 46102d26c39SVladimir Kotal if [[ -n $tflag ]]; then 46202d26c39SVladimir Kotal if [[ "${remote_target}" == ${rsync_prefix}?* ]]; then 463b0088928SVladimir Kotal rsync_upload ${remote_target##$rsync_prefix} 1 464b0088928SVladimir Kotal ret=$? 465b0088928SVladimir Kotal return $ret 46602d26c39SVladimir Kotal elif [[ "${remote_target}" == ${ssh_prefix}?* ]]; then 46702d26c39SVladimir Kotal ssh_upload ${remote_target##$ssh_prefix} 468b0088928SVladimir Kotal ret=$? 469b0088928SVladimir Kotal return $ret 47002d26c39SVladimir Kotal fi 47102d26c39SVladimir Kotal else 472b0088928SVladimir Kotal # 473b0088928SVladimir Kotal # Try rsync first and fallback to SSH in case it fails. 474b0088928SVladimir Kotal # 475b0088928SVladimir Kotal rsync_upload ${remote_target} 0 476b0088928SVladimir Kotal ret=$? 477b0088928SVladimir Kotal if (( $ret != 0 )); then 478b0088928SVladimir Kotal print "Failed. (falling back to SSH)" 479ba44d8a2SVladimir Kotal ssh_upload ${remote_target} 480b0088928SVladimir Kotal ret=$? 48102d26c39SVladimir Kotal fi 482b0088928SVladimir Kotal return $ret 48302d26c39SVladimir Kotal fi 48402d26c39SVladimir Kotal} 48502d26c39SVladimir Kotal 486daaffb31Sdp# 487371d72daSLubomir Sedlacik# input_cmd | url_encode | output_cmd 488371d72daSLubomir Sedlacik# 489371d72daSLubomir Sedlacik# URL-encode (percent-encode) reserved characters as defined in RFC 3986. 490371d72daSLubomir Sedlacik# 491371d72daSLubomir Sedlacik# Reserved characters are: :/?#[]@!$&'()*+,;= 492371d72daSLubomir Sedlacik# 493371d72daSLubomir Sedlacik# While not a reserved character itself, percent '%' is reserved by definition 494371d72daSLubomir Sedlacik# so encode it first to avoid recursive transformation, and skip '/' which is 495371d72daSLubomir Sedlacik# a path delimiter. 496371d72daSLubomir Sedlacik# 49725cc4e45SVladimir Kotal# The quotation character is deliberately not escaped in order to make 49825cc4e45SVladimir Kotal# the substitution work with GNU sed. 49925cc4e45SVladimir Kotal# 500371d72daSLubomir Sedlacikfunction url_encode 501371d72daSLubomir Sedlacik{ 502b0088928SVladimir Kotal $SED -e "s|%|%25|g" -e "s|:|%3A|g" -e "s|\&|%26|g" \ 503371d72daSLubomir Sedlacik -e "s|?|%3F|g" -e "s|#|%23|g" -e "s|\[|%5B|g" \ 504371d72daSLubomir Sedlacik -e "s|*|%2A|g" -e "s|@|%40|g" -e "s|\!|%21|g" \ 505371d72daSLubomir Sedlacik -e "s|=|%3D|g" -e "s|;|%3B|g" -e "s|\]|%5D|g" \ 50625cc4e45SVladimir Kotal -e "s|(|%28|g" -e "s|)|%29|g" -e "s|'|%27|g" \ 507371d72daSLubomir Sedlacik -e "s|+|%2B|g" -e "s|\,|%2C|g" -e "s|\\\$|%24|g" 508371d72daSLubomir Sedlacik} 509371d72daSLubomir Sedlacik 510371d72daSLubomir Sedlacik# 511daaffb31Sdp# input_cmd | html_quote | output_cmd 512daaffb31Sdp# or 513daaffb31Sdp# html_quote filename | output_cmd 5147c478bd9Sstevel@tonic-gate# 5157c478bd9Sstevel@tonic-gate# Make a piece of source code safe for display in an HTML <pre> block. 5167c478bd9Sstevel@tonic-gate# 5177c478bd9Sstevel@tonic-gatehtml_quote() 5187c478bd9Sstevel@tonic-gate{ 519b0088928SVladimir Kotal $SED -e "s/&/\&/g" -e "s/</\</g" -e "s/>/\>/g" "$@" | expand 5207c478bd9Sstevel@tonic-gate} 5217c478bd9Sstevel@tonic-gate 522daaffb31Sdp# 5238bcea973SRichard Lowe# Trim a digest-style revision to a conventionally readable yet useful length 5248bcea973SRichard Lowe# 5258bcea973SRichard Lowetrim_digest() 5268bcea973SRichard Lowe{ 5278bcea973SRichard Lowe typeset digest=$1 5288bcea973SRichard Lowe 5298bcea973SRichard Lowe echo $digest | $SED -e 's/\([0-9a-f]\{12\}\).*/\1/' 5308bcea973SRichard Lowe} 5318bcea973SRichard Lowe 5328bcea973SRichard Lowe# 5330fd2682eSMark J. Nelson# input_cmd | its2url | output_cmd 534daaffb31Sdp# 5350fd2682eSMark J. Nelson# Scan for information tracking system references and insert <a> links to the 5360fd2682eSMark J. Nelson# relevant databases. 537daaffb31Sdp# 5380fd2682eSMark J. Nelsonits2url() 5397c478bd9Sstevel@tonic-gate{ 5400fd2682eSMark J. Nelson $SED -f ${its_sed_script} 541daaffb31Sdp} 542daaffb31Sdp 5437c478bd9Sstevel@tonic-gate# 544daaffb31Sdp# strip_unchanged <infile> | output_cmd 5457c478bd9Sstevel@tonic-gate# 546daaffb31Sdp# Removes chunks of sdiff documents that have not changed. This makes it 547daaffb31Sdp# easier for a code reviewer to find the bits that have changed. 5487c478bd9Sstevel@tonic-gate# 549daaffb31Sdp# Deleted lines of text are replaced by a horizontal rule. Some 550daaffb31Sdp# identical lines are retained before and after the changed lines to 551daaffb31Sdp# provide some context. The number of these lines is controlled by the 552cdf0c1d5Smjnelson# variable C in the $AWK script below. 553daaffb31Sdp# 554daaffb31Sdp# The script detects changed lines as any line that has a "<span class=" 555daaffb31Sdp# string embedded (unchanged lines have no particular class and are not 556daaffb31Sdp# part of a <span>). Blank lines (without a sequence number) are also 557daaffb31Sdp# detected since they flag lines that have been inserted or deleted. 558daaffb31Sdp# 559daaffb31Sdpstrip_unchanged() 560daaffb31Sdp{ 561cdf0c1d5Smjnelson $AWK ' 562daaffb31Sdp BEGIN { C = c = 20 } 563cdf0c1d5Smjnelson NF == 0 || /<span class="/ { 564daaffb31Sdp if (c > C) { 565daaffb31Sdp c -= C 566daaffb31Sdp inx = 0 567daaffb31Sdp if (c > C) { 568cac38512Smjnelson print "\n</pre><hr></hr><pre>" 569daaffb31Sdp inx = c % C 570daaffb31Sdp c = C 571daaffb31Sdp } 572daaffb31Sdp 573daaffb31Sdp for (i = 0; i < c; i++) 574daaffb31Sdp print ln[(inx + i) % C] 575daaffb31Sdp } 576daaffb31Sdp c = 0; 577daaffb31Sdp print 578daaffb31Sdp next 579daaffb31Sdp } 580daaffb31Sdp { if (c >= C) { 581daaffb31Sdp ln[c % C] = $0 582daaffb31Sdp c++; 583daaffb31Sdp next; 584daaffb31Sdp } 585daaffb31Sdp c++; 586daaffb31Sdp print 587daaffb31Sdp } 588cac38512Smjnelson END { if (c > (C * 2)) print "\n</pre><hr></hr>" } 589daaffb31Sdp 590daaffb31Sdp ' $1 591daaffb31Sdp} 592daaffb31Sdp 593daaffb31Sdp# 594daaffb31Sdp# sdiff_to_html 595daaffb31Sdp# 596daaffb31Sdp# This function takes two files as arguments, obtains their diff, and 597daaffb31Sdp# processes the diff output to present the files as an HTML document with 598daaffb31Sdp# the files displayed side-by-side, differences shown in color. It also 599daaffb31Sdp# takes a delta comment, rendered as an HTML snippet, as the third 600daaffb31Sdp# argument. The function takes two files as arguments, then the name of 601daaffb31Sdp# file, the path, and the comment. The HTML will be delivered on stdout, 602daaffb31Sdp# e.g. 603daaffb31Sdp# 604daaffb31Sdp# $ sdiff_to_html old/usr/src/tools/scripts/webrev.sh \ 605daaffb31Sdp# new/usr/src/tools/scripts/webrev.sh \ 606daaffb31Sdp# webrev.sh usr/src/tools/scripts \ 607daaffb31Sdp# '<a href="http://monaco.sfbay.sun.com/detail.jsp?cr=1234567"> 608daaffb31Sdp# 1234567</a> my bugid' > <file>.html 609daaffb31Sdp# 610daaffb31Sdp# framed_sdiff() is then called which creates $2.frames.html 611daaffb31Sdp# in the webrev tree. 612daaffb31Sdp# 613daaffb31Sdp# FYI: This function is rather unusual in its use of awk. The initial 614daaffb31Sdp# diff run produces conventional diff output showing changed lines mixed 615daaffb31Sdp# with editing codes. The changed lines are ignored - we're interested in 616daaffb31Sdp# the editing codes, e.g. 6177c478bd9Sstevel@tonic-gate# 6187c478bd9Sstevel@tonic-gate# 8c8 6197c478bd9Sstevel@tonic-gate# 57a61 6207c478bd9Sstevel@tonic-gate# 63c66,76 6217c478bd9Sstevel@tonic-gate# 68,93d80 6227c478bd9Sstevel@tonic-gate# 106d90 6237c478bd9Sstevel@tonic-gate# 108,110d91 6247c478bd9Sstevel@tonic-gate# 625daaffb31Sdp# These editing codes are parsed by the awk script and used to generate 626daaffb31Sdp# another awk script that generates HTML, e.g the above lines would turn 627daaffb31Sdp# into something like this: 6287c478bd9Sstevel@tonic-gate# 6297c478bd9Sstevel@tonic-gate# BEGIN { printf "<pre>\n" } 6307c478bd9Sstevel@tonic-gate# function sp(n) {for (i=0;i<n;i++)printf "\n"} 631daaffb31Sdp# function wl(n) {printf "<font color=%s>%4d %s </font>\n", n, NR, $0} 6327c478bd9Sstevel@tonic-gate# NR==8 {wl("#7A7ADD");next} 6337c478bd9Sstevel@tonic-gate# NR==54 {wl("#7A7ADD");sp(3);next} 6347c478bd9Sstevel@tonic-gate# NR==56 {wl("#7A7ADD");next} 6357c478bd9Sstevel@tonic-gate# NR==57 {wl("black");printf "\n"; next} 6367c478bd9Sstevel@tonic-gate# : : 6377c478bd9Sstevel@tonic-gate# 638daaffb31Sdp# This script is then run on the original source file to generate the 639daaffb31Sdp# HTML that corresponds to the source file. 6407c478bd9Sstevel@tonic-gate# 641daaffb31Sdp# The two HTML files are then combined into a single piece of HTML that 642daaffb31Sdp# uses an HTML table construct to present the files side by side. You'll 643daaffb31Sdp# notice that the changes are color-coded: 6447c478bd9Sstevel@tonic-gate# 6457c478bd9Sstevel@tonic-gate# black - unchanged lines 6467c478bd9Sstevel@tonic-gate# blue - changed lines 6477c478bd9Sstevel@tonic-gate# bold blue - new lines 6487c478bd9Sstevel@tonic-gate# brown - deleted lines 6497c478bd9Sstevel@tonic-gate# 650daaffb31Sdp# Blank lines are inserted in each file to keep unchanged lines in sync 651daaffb31Sdp# (side-by-side). This format is familiar to users of sdiff(1) or 652daaffb31Sdp# Teamware's filemerge tool. 653daaffb31Sdp# 654daaffb31Sdpsdiff_to_html() 655daaffb31Sdp{ 6567c478bd9Sstevel@tonic-gate diff -b $1 $2 > /tmp/$$.diffs 6577c478bd9Sstevel@tonic-gate 658daaffb31Sdp TNAME=$3 659daaffb31Sdp TPATH=$4 660daaffb31Sdp COMMENT=$5 661daaffb31Sdp 6627c478bd9Sstevel@tonic-gate # 6637c478bd9Sstevel@tonic-gate # Now we have the diffs, generate the HTML for the old file. 6647c478bd9Sstevel@tonic-gate # 665cdf0c1d5Smjnelson $AWK ' 6667c478bd9Sstevel@tonic-gate BEGIN { 6677c478bd9Sstevel@tonic-gate printf "function sp(n) {for (i=0;i<n;i++)printf \"\\n\"}\n" 668daaffb31Sdp printf "function removed() " 669daaffb31Sdp printf "{printf \"<span class=\\\"removed\\\">%%4d %%s</span>\\n\", NR, $0}\n" 670daaffb31Sdp printf "function changed() " 671daaffb31Sdp printf "{printf \"<span class=\\\"changed\\\">%%4d %%s</span>\\n\", NR, $0}\n" 672daaffb31Sdp printf "function bl() {printf \"%%4d %%s\\n\", NR, $0}\n" 6737c478bd9Sstevel@tonic-gate} 6747c478bd9Sstevel@tonic-gate /^</ {next} 6757c478bd9Sstevel@tonic-gate /^>/ {next} 6767c478bd9Sstevel@tonic-gate /^---/ {next} 677daaffb31Sdp 6787c478bd9Sstevel@tonic-gate { 6797c478bd9Sstevel@tonic-gate split($1, a, /[cad]/) ; 6807c478bd9Sstevel@tonic-gate if (index($1, "a")) { 6817c478bd9Sstevel@tonic-gate if (a[1] == 0) { 6827c478bd9Sstevel@tonic-gate n = split(a[2], r, /,/); 6837c478bd9Sstevel@tonic-gate if (n == 1) 6847c478bd9Sstevel@tonic-gate printf "BEGIN\t\t{sp(1)}\n" 6857c478bd9Sstevel@tonic-gate else 6867c478bd9Sstevel@tonic-gate printf "BEGIN\t\t{sp(%d)}\n",\ 6877c478bd9Sstevel@tonic-gate (r[2] - r[1]) + 1 6887c478bd9Sstevel@tonic-gate next 6897c478bd9Sstevel@tonic-gate } 6907c478bd9Sstevel@tonic-gate 6917c478bd9Sstevel@tonic-gate printf "NR==%s\t\t{", a[1] 6927c478bd9Sstevel@tonic-gate n = split(a[2], r, /,/); 6937c478bd9Sstevel@tonic-gate s = r[1]; 6947c478bd9Sstevel@tonic-gate if (n == 1) 6957c478bd9Sstevel@tonic-gate printf "bl();printf \"\\n\"; next}\n" 6967c478bd9Sstevel@tonic-gate else { 6977c478bd9Sstevel@tonic-gate n = r[2] - r[1] 6987c478bd9Sstevel@tonic-gate printf "bl();sp(%d);next}\n",\ 6997c478bd9Sstevel@tonic-gate (r[2] - r[1]) + 1 7007c478bd9Sstevel@tonic-gate } 7017c478bd9Sstevel@tonic-gate next 7027c478bd9Sstevel@tonic-gate } 7037c478bd9Sstevel@tonic-gate if (index($1, "d")) { 7047c478bd9Sstevel@tonic-gate n = split(a[1], r, /,/); 7057c478bd9Sstevel@tonic-gate n1 = r[1] 7067c478bd9Sstevel@tonic-gate n2 = r[2] 7077c478bd9Sstevel@tonic-gate if (n == 1) 708daaffb31Sdp printf "NR==%s\t\t{removed(); next}\n" , n1 7097c478bd9Sstevel@tonic-gate else 710daaffb31Sdp printf "NR==%s,NR==%s\t{removed(); next}\n" , n1, n2 7117c478bd9Sstevel@tonic-gate next 7127c478bd9Sstevel@tonic-gate } 7137c478bd9Sstevel@tonic-gate if (index($1, "c")) { 7147c478bd9Sstevel@tonic-gate n = split(a[1], r, /,/); 7157c478bd9Sstevel@tonic-gate n1 = r[1] 7167c478bd9Sstevel@tonic-gate n2 = r[2] 7177c478bd9Sstevel@tonic-gate final = n2 7187c478bd9Sstevel@tonic-gate d1 = 0 7197c478bd9Sstevel@tonic-gate if (n == 1) 720daaffb31Sdp printf "NR==%s\t\t{changed();" , n1 7217c478bd9Sstevel@tonic-gate else { 7227c478bd9Sstevel@tonic-gate d1 = n2 - n1 723daaffb31Sdp printf "NR==%s,NR==%s\t{changed();" , n1, n2 7247c478bd9Sstevel@tonic-gate } 7257c478bd9Sstevel@tonic-gate m = split(a[2], r, /,/); 7267c478bd9Sstevel@tonic-gate n1 = r[1] 7277c478bd9Sstevel@tonic-gate n2 = r[2] 7287c478bd9Sstevel@tonic-gate if (m > 1) { 7297c478bd9Sstevel@tonic-gate d2 = n2 - n1 7307c478bd9Sstevel@tonic-gate if (d2 > d1) { 7317c478bd9Sstevel@tonic-gate if (n > 1) printf "if (NR==%d)", final 7327c478bd9Sstevel@tonic-gate printf "sp(%d);", d2 - d1 7337c478bd9Sstevel@tonic-gate } 7347c478bd9Sstevel@tonic-gate } 7357c478bd9Sstevel@tonic-gate printf "next}\n" ; 7367c478bd9Sstevel@tonic-gate 7377c478bd9Sstevel@tonic-gate next 7387c478bd9Sstevel@tonic-gate } 7397c478bd9Sstevel@tonic-gate } 7407c478bd9Sstevel@tonic-gate 741daaffb31Sdp END { printf "{printf \"%%4d %%s\\n\", NR, $0 }\n" } 742daaffb31Sdp ' /tmp/$$.diffs > /tmp/$$.file1 7437c478bd9Sstevel@tonic-gate 7447c478bd9Sstevel@tonic-gate # 7457c478bd9Sstevel@tonic-gate # Now generate the HTML for the new file 7467c478bd9Sstevel@tonic-gate # 747cdf0c1d5Smjnelson $AWK ' 7487c478bd9Sstevel@tonic-gate BEGIN { 7497c478bd9Sstevel@tonic-gate printf "function sp(n) {for (i=0;i<n;i++)printf \"\\n\"}\n" 750daaffb31Sdp printf "function new() " 751daaffb31Sdp printf "{printf \"<span class=\\\"new\\\">%%4d %%s</span>\\n\", NR, $0}\n" 752daaffb31Sdp printf "function changed() " 753daaffb31Sdp printf "{printf \"<span class=\\\"changed\\\">%%4d %%s</span>\\n\", NR, $0}\n" 754daaffb31Sdp printf "function bl() {printf \"%%4d %%s\\n\", NR, $0}\n" 7557c478bd9Sstevel@tonic-gate } 756daaffb31Sdp 7577c478bd9Sstevel@tonic-gate /^</ {next} 7587c478bd9Sstevel@tonic-gate /^>/ {next} 7597c478bd9Sstevel@tonic-gate /^---/ {next} 760daaffb31Sdp 7617c478bd9Sstevel@tonic-gate { 7627c478bd9Sstevel@tonic-gate split($1, a, /[cad]/) ; 7637c478bd9Sstevel@tonic-gate if (index($1, "d")) { 7647c478bd9Sstevel@tonic-gate if (a[2] == 0) { 7657c478bd9Sstevel@tonic-gate n = split(a[1], r, /,/); 7667c478bd9Sstevel@tonic-gate if (n == 1) 7677c478bd9Sstevel@tonic-gate printf "BEGIN\t\t{sp(1)}\n" 7687c478bd9Sstevel@tonic-gate else 7697c478bd9Sstevel@tonic-gate printf "BEGIN\t\t{sp(%d)}\n",\ 7707c478bd9Sstevel@tonic-gate (r[2] - r[1]) + 1 7717c478bd9Sstevel@tonic-gate next 7727c478bd9Sstevel@tonic-gate } 7737c478bd9Sstevel@tonic-gate 7747c478bd9Sstevel@tonic-gate printf "NR==%s\t\t{", a[2] 7757c478bd9Sstevel@tonic-gate n = split(a[1], r, /,/); 7767c478bd9Sstevel@tonic-gate s = r[1]; 7777c478bd9Sstevel@tonic-gate if (n == 1) 7787c478bd9Sstevel@tonic-gate printf "bl();printf \"\\n\"; next}\n" 7797c478bd9Sstevel@tonic-gate else { 7807c478bd9Sstevel@tonic-gate n = r[2] - r[1] 7817c478bd9Sstevel@tonic-gate printf "bl();sp(%d);next}\n",\ 7827c478bd9Sstevel@tonic-gate (r[2] - r[1]) + 1 7837c478bd9Sstevel@tonic-gate } 7847c478bd9Sstevel@tonic-gate next 7857c478bd9Sstevel@tonic-gate } 7867c478bd9Sstevel@tonic-gate if (index($1, "a")) { 7877c478bd9Sstevel@tonic-gate n = split(a[2], r, /,/); 7887c478bd9Sstevel@tonic-gate n1 = r[1] 7897c478bd9Sstevel@tonic-gate n2 = r[2] 7907c478bd9Sstevel@tonic-gate if (n == 1) 791daaffb31Sdp printf "NR==%s\t\t{new() ; next}\n" , n1 7927c478bd9Sstevel@tonic-gate else 793daaffb31Sdp printf "NR==%s,NR==%s\t{new() ; next}\n" , n1, n2 7947c478bd9Sstevel@tonic-gate next 7957c478bd9Sstevel@tonic-gate } 7967c478bd9Sstevel@tonic-gate if (index($1, "c")) { 7977c478bd9Sstevel@tonic-gate n = split(a[2], r, /,/); 7987c478bd9Sstevel@tonic-gate n1 = r[1] 7997c478bd9Sstevel@tonic-gate n2 = r[2] 8007c478bd9Sstevel@tonic-gate final = n2 8017c478bd9Sstevel@tonic-gate d2 = 0; 8027c478bd9Sstevel@tonic-gate if (n == 1) { 8037c478bd9Sstevel@tonic-gate final = n1 804daaffb31Sdp printf "NR==%s\t\t{changed();" , n1 8057c478bd9Sstevel@tonic-gate } else { 8067c478bd9Sstevel@tonic-gate d2 = n2 - n1 807daaffb31Sdp printf "NR==%s,NR==%s\t{changed();" , n1, n2 8087c478bd9Sstevel@tonic-gate } 8097c478bd9Sstevel@tonic-gate m = split(a[1], r, /,/); 8107c478bd9Sstevel@tonic-gate n1 = r[1] 8117c478bd9Sstevel@tonic-gate n2 = r[2] 8127c478bd9Sstevel@tonic-gate if (m > 1) { 8137c478bd9Sstevel@tonic-gate d1 = n2 - n1 8147c478bd9Sstevel@tonic-gate if (d1 > d2) { 8157c478bd9Sstevel@tonic-gate if (n > 1) printf "if (NR==%d)", final 8167c478bd9Sstevel@tonic-gate printf "sp(%d);", d1 - d2 8177c478bd9Sstevel@tonic-gate } 8187c478bd9Sstevel@tonic-gate } 8197c478bd9Sstevel@tonic-gate printf "next}\n" ; 8207c478bd9Sstevel@tonic-gate next 8217c478bd9Sstevel@tonic-gate } 8227c478bd9Sstevel@tonic-gate } 823daaffb31Sdp END { printf "{printf \"%%4d %%s\\n\", NR, $0 }\n" } 8247c478bd9Sstevel@tonic-gate ' /tmp/$$.diffs > /tmp/$$.file2 8257c478bd9Sstevel@tonic-gate 826daaffb31Sdp # 827cdf0c1d5Smjnelson # Post-process the HTML files by running them back through $AWK 828daaffb31Sdp # 829cdf0c1d5Smjnelson html_quote < $1 | $AWK -f /tmp/$$.file1 > /tmp/$$.file1.html 8307c478bd9Sstevel@tonic-gate 831cdf0c1d5Smjnelson html_quote < $2 | $AWK -f /tmp/$$.file2 > /tmp/$$.file2.html 8327c478bd9Sstevel@tonic-gate 833daaffb31Sdp # 834daaffb31Sdp # Now combine into a valid HTML file and side-by-side into a table 835daaffb31Sdp # 836daaffb31Sdp print "$HTML<head>$STDHEAD" 837cdf0c1d5Smjnelson print "<title>$WNAME Sdiff $TPATH/$TNAME</title>" 838daaffb31Sdp print "</head><body id=\"SUNWwebrev\">" 839daaffb31Sdp print "<a class=\"print\" href=\"javascript:print()\">Print this page</a>" 840daaffb31Sdp print "<pre>$COMMENT</pre>\n" 841daaffb31Sdp print "<table><tr valign=\"top\">" 842daaffb31Sdp print "<td><pre>" 8437c478bd9Sstevel@tonic-gate 8447c478bd9Sstevel@tonic-gate strip_unchanged /tmp/$$.file1.html 8457c478bd9Sstevel@tonic-gate 846daaffb31Sdp print "</pre></td><td><pre>" 8477c478bd9Sstevel@tonic-gate 8487c478bd9Sstevel@tonic-gate strip_unchanged /tmp/$$.file2.html 8497c478bd9Sstevel@tonic-gate 850daaffb31Sdp print "</pre></td>" 851daaffb31Sdp print "</tr></table>" 852daaffb31Sdp print "</body></html>" 8537c478bd9Sstevel@tonic-gate 854daaffb31Sdp framed_sdiff $TNAME $TPATH /tmp/$$.file1.html /tmp/$$.file2.html \ 855daaffb31Sdp "$COMMENT" 8567c478bd9Sstevel@tonic-gate} 8577c478bd9Sstevel@tonic-gate 8587c478bd9Sstevel@tonic-gate 859daaffb31Sdp# 860daaffb31Sdp# framed_sdiff <filename> <filepath> <lhsfile> <rhsfile> <comment> 861daaffb31Sdp# 862daaffb31Sdp# Expects lefthand and righthand side html files created by sdiff_to_html. 863daaffb31Sdp# We use insert_anchors() to augment those with HTML navigation anchors, 864daaffb31Sdp# and then emit the main frame. Content is placed into: 865daaffb31Sdp# 866daaffb31Sdp# $WDIR/DIR/$TNAME.lhs.html 867daaffb31Sdp# $WDIR/DIR/$TNAME.rhs.html 868daaffb31Sdp# $WDIR/DIR/$TNAME.frames.html 869daaffb31Sdp# 870daaffb31Sdp# NOTE: We rely on standard usage of $WDIR and $DIR. 871daaffb31Sdp# 8727c478bd9Sstevel@tonic-gatefunction framed_sdiff 8737c478bd9Sstevel@tonic-gate{ 8747c478bd9Sstevel@tonic-gate typeset TNAME=$1 875daaffb31Sdp typeset TPATH=$2 876daaffb31Sdp typeset lhsfile=$3 877daaffb31Sdp typeset rhsfile=$4 878daaffb31Sdp typeset comments=$5 8797c478bd9Sstevel@tonic-gate typeset RTOP 880daaffb31Sdp 8817c478bd9Sstevel@tonic-gate # Enable html files to access WDIR via a relative path. 882daaffb31Sdp RTOP=$(relative_dir $TPATH $WDIR) 883daaffb31Sdp 884daaffb31Sdp # Make the rhs/lhs files and output the frameset file. 885daaffb31Sdp print "$HTML<head>$STDHEAD" > $WDIR/$DIR/$TNAME.lhs.html 886daaffb31Sdp 887daaffb31Sdp cat >> $WDIR/$DIR/$TNAME.lhs.html <<-EOF 8888b3b7b16SMark J. Nelson <script type="text/javascript" src="${RTOP}ancnav.js"></script> 8897c478bd9Sstevel@tonic-gate </head> 890daaffb31Sdp <body id="SUNWwebrev" onkeypress="keypress(event);"> 891cac38512Smjnelson <a name="0"></a> 892cac38512Smjnelson <pre>$comments</pre><hr></hr> 893daaffb31Sdp EOF 894daaffb31Sdp 895daaffb31Sdp cp $WDIR/$DIR/$TNAME.lhs.html $WDIR/$DIR/$TNAME.rhs.html 896daaffb31Sdp 897daaffb31Sdp insert_anchors $lhsfile >> $WDIR/$DIR/$TNAME.lhs.html 898daaffb31Sdp insert_anchors $rhsfile >> $WDIR/$DIR/$TNAME.rhs.html 899daaffb31Sdp 900daaffb31Sdp close='</body></html>' 901daaffb31Sdp 902daaffb31Sdp print $close >> $WDIR/$DIR/$TNAME.lhs.html 903daaffb31Sdp print $close >> $WDIR/$DIR/$TNAME.rhs.html 904daaffb31Sdp 905daaffb31Sdp print "$FRAMEHTML<head>$STDHEAD" > $WDIR/$DIR/$TNAME.frames.html 906daaffb31Sdp print "<title>$WNAME Framed-Sdiff " \ 907daaffb31Sdp "$TPATH/$TNAME</title> </head>" >> $WDIR/$DIR/$TNAME.frames.html 908daaffb31Sdp cat >> $WDIR/$DIR/$TNAME.frames.html <<-EOF 909daaffb31Sdp <frameset rows="*,60"> 910daaffb31Sdp <frameset cols="50%,50%"> 911cac38512Smjnelson <frame src="$TNAME.lhs.html" scrolling="auto" name="lhs"></frame> 912cac38512Smjnelson <frame src="$TNAME.rhs.html" scrolling="auto" name="rhs"></frame> 913daaffb31Sdp </frameset> 9148b3b7b16SMark J. Nelson <frame src="${RTOP}ancnav.html" scrolling="no" marginwidth="0" 915cac38512Smjnelson marginheight="0" name="nav"></frame> 916daaffb31Sdp <noframes> 917daaffb31Sdp <body id="SUNWwebrev"> 918daaffb31Sdp Alas 'frames' webrev requires that your browser supports frames 9197c478bd9Sstevel@tonic-gate and has the feature enabled. 920daaffb31Sdp </body> 921daaffb31Sdp </noframes> 922daaffb31Sdp </frameset> 9237c478bd9Sstevel@tonic-gate </html> 9247c478bd9Sstevel@tonic-gate EOF 9257c478bd9Sstevel@tonic-gate} 9267c478bd9Sstevel@tonic-gate 9277c478bd9Sstevel@tonic-gate 928daaffb31Sdp# 929daaffb31Sdp# fix_postscript 930daaffb31Sdp# 931daaffb31Sdp# Merge codereview output files to a single conforming postscript file, by: 932daaffb31Sdp# - removing all extraneous headers/trailers 933daaffb31Sdp# - making the page numbers right 934daaffb31Sdp# - removing pages devoid of contents which confuse some 935daaffb31Sdp# postscript readers. 936daaffb31Sdp# 937daaffb31Sdp# From Casper. 938daaffb31Sdp# 939daaffb31Sdpfunction fix_postscript 9407c478bd9Sstevel@tonic-gate{ 941daaffb31Sdp infile=$1 9427c478bd9Sstevel@tonic-gate 943daaffb31Sdp cat > /tmp/$$.crmerge.pl << \EOF 9447c478bd9Sstevel@tonic-gate 945daaffb31Sdp print scalar(<>); # %!PS-Adobe--- 946daaffb31Sdp print "%%Orientation: Landscape\n"; 9477c478bd9Sstevel@tonic-gate 948daaffb31Sdp $pno = 0; 949daaffb31Sdp $doprint = 1; 950daaffb31Sdp 951daaffb31Sdp $page = ""; 952daaffb31Sdp 953daaffb31Sdp while (<>) { 954daaffb31Sdp next if (/^%%Pages:\s*\d+/); 955daaffb31Sdp 956daaffb31Sdp if (/^%%Page:/) { 957daaffb31Sdp if ($pno == 0 || $page =~ /\)S/) { 958daaffb31Sdp # Header or single page containing text 959daaffb31Sdp print "%%Page: ? $pno\n" if ($pno > 0); 960daaffb31Sdp print $page; 961daaffb31Sdp $pno++; 962daaffb31Sdp } else { 963daaffb31Sdp # Empty page, skip it. 9647c478bd9Sstevel@tonic-gate } 965daaffb31Sdp $page = ""; 966daaffb31Sdp $doprint = 1; 9677c478bd9Sstevel@tonic-gate next; 9687c478bd9Sstevel@tonic-gate } 9697c478bd9Sstevel@tonic-gate 970daaffb31Sdp # Skip from %%Trailer of one document to Endprolog 971daaffb31Sdp # %%Page of the next 972daaffb31Sdp $doprint = 0 if (/^%%Trailer/); 973daaffb31Sdp $page .= $_ if ($doprint); 9747c478bd9Sstevel@tonic-gate } 9757c478bd9Sstevel@tonic-gate 976daaffb31Sdp if ($page =~ /\)S/) { 977daaffb31Sdp print "%%Page: ? $pno\n"; 978daaffb31Sdp print $page; 979daaffb31Sdp } else { 980daaffb31Sdp $pno--; 981daaffb31Sdp } 982daaffb31Sdp print "%%Trailer\n%%Pages: $pno\n"; 983daaffb31SdpEOF 984daaffb31Sdp 98514983201Sdp $PERL /tmp/$$.crmerge.pl < $infile 986daaffb31Sdp} 987daaffb31Sdp 988daaffb31Sdp 989daaffb31Sdp# 990daaffb31Sdp# input_cmd | insert_anchors | output_cmd 991daaffb31Sdp# 9927c478bd9Sstevel@tonic-gate# Flag blocks of difference with sequentially numbered invisible 993daaffb31Sdp# anchors. These are used to drive the frames version of the 9947c478bd9Sstevel@tonic-gate# sdiffs output. 9957c478bd9Sstevel@tonic-gate# 9967c478bd9Sstevel@tonic-gate# NOTE: Anchor zero flags the top of the file irrespective of changes, 9977c478bd9Sstevel@tonic-gate# an additional anchor is also appended to flag the bottom. 9987c478bd9Sstevel@tonic-gate# 999daaffb31Sdp# The script detects changed lines as any line that has a "<span 1000daaffb31Sdp# class=" string embedded (unchanged lines have no class set and are 1001daaffb31Sdp# not part of a <span>. Blank lines (without a sequence number) 10027c478bd9Sstevel@tonic-gate# are also detected since they flag lines that have been inserted or 10037c478bd9Sstevel@tonic-gate# deleted. 10047c478bd9Sstevel@tonic-gate# 1005daaffb31Sdpfunction insert_anchors 1006daaffb31Sdp{ 1007cdf0c1d5Smjnelson $AWK ' 10087c478bd9Sstevel@tonic-gate function ia() { 1009daaffb31Sdp printf "<a name=\"%d\" id=\"anc%d\"></a>", anc, anc++; 10107c478bd9Sstevel@tonic-gate } 1011daaffb31Sdp 10127c478bd9Sstevel@tonic-gate BEGIN { 1013daaffb31Sdp anc=1; 10147c478bd9Sstevel@tonic-gate inblock=1; 1015daaffb31Sdp printf "<pre>\n"; 10167c478bd9Sstevel@tonic-gate } 1017daaffb31Sdp NF == 0 || /^<span class=/ { 10187c478bd9Sstevel@tonic-gate if (inblock == 0) { 10197c478bd9Sstevel@tonic-gate ia(); 10207c478bd9Sstevel@tonic-gate inblock=1; 10217c478bd9Sstevel@tonic-gate } 10227c478bd9Sstevel@tonic-gate print; 10237c478bd9Sstevel@tonic-gate next; 10247c478bd9Sstevel@tonic-gate } 10257c478bd9Sstevel@tonic-gate { 10267c478bd9Sstevel@tonic-gate inblock=0; 10277c478bd9Sstevel@tonic-gate print; 10287c478bd9Sstevel@tonic-gate } 10297c478bd9Sstevel@tonic-gate END { 10307c478bd9Sstevel@tonic-gate ia(); 1031daaffb31Sdp 1032daaffb31Sdp printf "<b style=\"font-size: large; color: red\">"; 1033daaffb31Sdp printf "--- EOF ---</b>" 10347c478bd9Sstevel@tonic-gate for(i=0;i<8;i++) printf "\n\n\n\n\n\n\n\n\n\n"; 1035daaffb31Sdp printf "</pre>" 1036daaffb31Sdp printf "<form name=\"eof\">"; 1037cac38512Smjnelson printf "<input name=\"value\" value=\"%d\" " \ 1038cac38512Smjnelson "type=\"hidden\"></input>", anc - 1; 1039daaffb31Sdp printf "</form>"; 10407c478bd9Sstevel@tonic-gate } 10417c478bd9Sstevel@tonic-gate ' $1 10427c478bd9Sstevel@tonic-gate} 10437c478bd9Sstevel@tonic-gate 10447c478bd9Sstevel@tonic-gate 1045daaffb31Sdp# 1046daaffb31Sdp# relative_dir 1047daaffb31Sdp# 1048daaffb31Sdp# Print a relative return path from $1 to $2. For example if 1049daaffb31Sdp# $1=/tmp/myreview/raw_files/usr/src/tools/scripts and $2=/tmp/myreview, 1050daaffb31Sdp# this function would print "../../../../". 1051daaffb31Sdp# 1052daaffb31Sdp# In the event that $1 is not in $2 a warning is printed to stderr, 1053daaffb31Sdp# and $2 is returned-- the result of this is that the resulting webrev 1054daaffb31Sdp# is not relocatable. 1055daaffb31Sdp# 1056daaffb31Sdpfunction relative_dir 10577c478bd9Sstevel@tonic-gate{ 1058daaffb31Sdp typeset cur="${1##$2?(/)}" 10598b3b7b16SMark J. Nelson 10608b3b7b16SMark J. Nelson # 10618b3b7b16SMark J. Nelson # If the first path was specified absolutely, and it does 10628b3b7b16SMark J. Nelson # not start with the second path, it's an error. 10638b3b7b16SMark J. Nelson # 10640fd2682eSMark J. Nelson if [[ "$cur" = "/${1#/}" ]]; then 1065daaffb31Sdp # Should never happen. 106614983201Sdp print -u2 "\nWARNING: relative_dir: \"$1\" not relative " 1067daaffb31Sdp print -u2 "to \"$2\". Check input paths. Framed webrev " 1068daaffb31Sdp print -u2 "will not be relocatable!" 1069daaffb31Sdp print $2 1070daaffb31Sdp return 1071daaffb31Sdp fi 1072daaffb31Sdp 10738b3b7b16SMark J. Nelson # 10748b3b7b16SMark J. Nelson # This is kind of ugly. The sed script will do the following: 10758b3b7b16SMark J. Nelson # 10768b3b7b16SMark J. Nelson # 1. Strip off a leading "." or "./": this is important to get 10778b3b7b16SMark J. Nelson # the correct arcnav links for files in $WDIR. 10788b3b7b16SMark J. Nelson # 2. Strip off a trailing "/": this is not strictly necessary, 10798b3b7b16SMark J. Nelson # but is kind of nice, since it doesn't end up in "//" at 10808b3b7b16SMark J. Nelson # the end of a relative path. 10818b3b7b16SMark J. Nelson # 3. Replace all remaining sequences of non-"/" with "..": the 10828b3b7b16SMark J. Nelson # assumption here is that each dirname represents another 10838b3b7b16SMark J. Nelson # level of relative separation. 10848b3b7b16SMark J. Nelson # 4. Append a trailing "/" only for non-empty paths: this way 10858b3b7b16SMark J. Nelson # the caller doesn't need to duplicate this logic, and does 10868b3b7b16SMark J. Nelson # not end up using $RTOP/file for files in $WDIR. 10878b3b7b16SMark J. Nelson # 10880fd2682eSMark J. Nelson print $cur | $SED -e '{ 10898b3b7b16SMark J. Nelson s:^\./*:: 10908b3b7b16SMark J. Nelson s:/$:: 10918b3b7b16SMark J. Nelson s:[^/][^/]*:..:g 10920fd2682eSMark J. Nelson s:^\(..*\)$:\1/: 10930fd2682eSMark J. Nelson }' 10947c478bd9Sstevel@tonic-gate} 10957c478bd9Sstevel@tonic-gate 1096daaffb31Sdp# 1097daaffb31Sdp# frame_nav_js 1098daaffb31Sdp# 1099daaffb31Sdp# Emit javascript for frame navigation 1100daaffb31Sdp# 1101daaffb31Sdpfunction frame_nav_js 11027c478bd9Sstevel@tonic-gate{ 11037c478bd9Sstevel@tonic-gatecat << \EOF 11047c478bd9Sstevel@tonic-gatevar myInt; 11057c478bd9Sstevel@tonic-gatevar scrolling=0; 1106daaffb31Sdpvar sfactor = 3; 11077c478bd9Sstevel@tonic-gatevar scount=10; 11087c478bd9Sstevel@tonic-gate 11097c478bd9Sstevel@tonic-gatefunction scrollByPix() { 11107c478bd9Sstevel@tonic-gate if (scount<=0) { 11117c478bd9Sstevel@tonic-gate sfactor*=1.2; 11127c478bd9Sstevel@tonic-gate scount=10; 11137c478bd9Sstevel@tonic-gate } 11147c478bd9Sstevel@tonic-gate parent.lhs.scrollBy(0,sfactor); 11157c478bd9Sstevel@tonic-gate parent.rhs.scrollBy(0,sfactor); 11167c478bd9Sstevel@tonic-gate scount--; 11177c478bd9Sstevel@tonic-gate} 11187c478bd9Sstevel@tonic-gate 1119daaffb31Sdpfunction scrollToAnc(num) { 1120daaffb31Sdp 1121daaffb31Sdp // Update the value of the anchor in the form which we use as 1122daaffb31Sdp // storage for this value. setAncValue() will take care of 1123daaffb31Sdp // correcting for overflow and underflow of the value and return 1124daaffb31Sdp // us the new value. 1125daaffb31Sdp num = setAncValue(num); 1126daaffb31Sdp 1127daaffb31Sdp // Set location and scroll back a little to expose previous 1128daaffb31Sdp // lines. 1129daaffb31Sdp // 1130daaffb31Sdp // Note that this could be improved: it is possible although 1131daaffb31Sdp // complex to compute the x and y position of an anchor, and to 1132daaffb31Sdp // scroll to that location directly. 1133daaffb31Sdp // 11347c478bd9Sstevel@tonic-gate parent.lhs.location.replace(parent.lhs.location.pathname + "#" + num); 11357c478bd9Sstevel@tonic-gate parent.rhs.location.replace(parent.rhs.location.pathname + "#" + num); 1136daaffb31Sdp 11377c478bd9Sstevel@tonic-gate parent.lhs.scrollBy(0,-30); 11387c478bd9Sstevel@tonic-gate parent.rhs.scrollBy(0,-30); 11397c478bd9Sstevel@tonic-gate} 11407c478bd9Sstevel@tonic-gate 1141daaffb31Sdpfunction getAncValue() 1142daaffb31Sdp{ 1143daaffb31Sdp return (parseInt(parent.nav.document.diff.real.value)); 1144daaffb31Sdp} 1145daaffb31Sdp 1146daaffb31Sdpfunction setAncValue(val) 1147daaffb31Sdp{ 1148daaffb31Sdp if (val <= 0) { 1149daaffb31Sdp val = 0; 1150daaffb31Sdp parent.nav.document.diff.real.value = val; 1151daaffb31Sdp parent.nav.document.diff.display.value = "BOF"; 1152daaffb31Sdp return (val); 1153daaffb31Sdp } 1154daaffb31Sdp 1155daaffb31Sdp // 1156daaffb31Sdp // The way we compute the max anchor value is to stash it 1157daaffb31Sdp // inline in the left and right hand side pages-- it's the same 1158daaffb31Sdp // on each side, so we pluck from the left. 1159daaffb31Sdp // 1160daaffb31Sdp maxval = parent.lhs.document.eof.value.value; 1161daaffb31Sdp if (val < maxval) { 1162daaffb31Sdp parent.nav.document.diff.real.value = val; 1163daaffb31Sdp parent.nav.document.diff.display.value = val.toString(); 1164daaffb31Sdp return (val); 1165daaffb31Sdp } 1166daaffb31Sdp 1167daaffb31Sdp // this must be: val >= maxval 1168daaffb31Sdp val = maxval; 1169daaffb31Sdp parent.nav.document.diff.real.value = val; 1170daaffb31Sdp parent.nav.document.diff.display.value = "EOF"; 1171daaffb31Sdp return (val); 1172daaffb31Sdp} 1173daaffb31Sdp 11747c478bd9Sstevel@tonic-gatefunction stopScroll() { 11757c478bd9Sstevel@tonic-gate if (scrolling==1) { 11767c478bd9Sstevel@tonic-gate clearInterval(myInt); 11777c478bd9Sstevel@tonic-gate scrolling=0; 11787c478bd9Sstevel@tonic-gate } 11797c478bd9Sstevel@tonic-gate} 11807c478bd9Sstevel@tonic-gate 11817c478bd9Sstevel@tonic-gatefunction startScroll() { 11827c478bd9Sstevel@tonic-gate stopScroll(); 11837c478bd9Sstevel@tonic-gate scrolling=1; 11847c478bd9Sstevel@tonic-gate myInt=setInterval("scrollByPix()",10); 11857c478bd9Sstevel@tonic-gate} 11867c478bd9Sstevel@tonic-gate 11877c478bd9Sstevel@tonic-gatefunction handlePress(b) { 1188daaffb31Sdp 11897c478bd9Sstevel@tonic-gate switch (b) { 11907c478bd9Sstevel@tonic-gate case 1 : 1191daaffb31Sdp scrollToAnc(-1); 11927c478bd9Sstevel@tonic-gate break; 11937c478bd9Sstevel@tonic-gate case 2 : 1194daaffb31Sdp scrollToAnc(getAncValue() - 1); 11957c478bd9Sstevel@tonic-gate break; 11967c478bd9Sstevel@tonic-gate case 3 : 11977c478bd9Sstevel@tonic-gate sfactor=-3; 11987c478bd9Sstevel@tonic-gate startScroll(); 11997c478bd9Sstevel@tonic-gate break; 12007c478bd9Sstevel@tonic-gate case 4 : 12017c478bd9Sstevel@tonic-gate sfactor=3; 12027c478bd9Sstevel@tonic-gate startScroll(); 12037c478bd9Sstevel@tonic-gate break; 12047c478bd9Sstevel@tonic-gate case 5 : 1205daaffb31Sdp scrollToAnc(getAncValue() + 1); 12067c478bd9Sstevel@tonic-gate break; 12077c478bd9Sstevel@tonic-gate case 6 : 1208daaffb31Sdp scrollToAnc(999999); 12097c478bd9Sstevel@tonic-gate break; 12107c478bd9Sstevel@tonic-gate } 12117c478bd9Sstevel@tonic-gate} 12127c478bd9Sstevel@tonic-gate 12137c478bd9Sstevel@tonic-gatefunction handleRelease(b) { 12147c478bd9Sstevel@tonic-gate stopScroll(); 12157c478bd9Sstevel@tonic-gate} 12167c478bd9Sstevel@tonic-gate 1217daaffb31Sdpfunction keypress(ev) { 1218daaffb31Sdp var keynum; 1219daaffb31Sdp var keychar; 1220daaffb31Sdp 1221daaffb31Sdp if (window.event) { // IE 1222daaffb31Sdp keynum = ev.keyCode; 1223daaffb31Sdp } else if (ev.which) { // non-IE 1224daaffb31Sdp keynum = ev.which; 1225daaffb31Sdp } 1226daaffb31Sdp 1227daaffb31Sdp keychar = String.fromCharCode(keynum); 1228daaffb31Sdp 1229daaffb31Sdp if (keychar == "k") { 1230daaffb31Sdp handlePress(2); 1231daaffb31Sdp return (0); 1232daaffb31Sdp } else if (keychar == "j" || keychar == " ") { 1233daaffb31Sdp handlePress(5); 1234daaffb31Sdp return (0); 1235daaffb31Sdp } 1236daaffb31Sdp return (1); 1237daaffb31Sdp} 1238daaffb31Sdp 12397c478bd9Sstevel@tonic-gatefunction ValidateDiffNum(){ 1240daaffb31Sdp val = parent.nav.document.diff.display.value; 1241daaffb31Sdp if (val == "EOF") { 1242daaffb31Sdp scrollToAnc(999999); 1243daaffb31Sdp return; 1244daaffb31Sdp } 1245daaffb31Sdp 1246daaffb31Sdp if (val == "BOF") { 1247daaffb31Sdp scrollToAnc(0); 1248daaffb31Sdp return; 1249daaffb31Sdp } 1250daaffb31Sdp 1251daaffb31Sdp i=parseInt(val); 12527c478bd9Sstevel@tonic-gate if (isNaN(i)) { 1253daaffb31Sdp parent.nav.document.diff.display.value = getAncValue(); 12547c478bd9Sstevel@tonic-gate } else { 1255daaffb31Sdp scrollToAnc(i); 12567c478bd9Sstevel@tonic-gate } 12577c478bd9Sstevel@tonic-gate return false; 12587c478bd9Sstevel@tonic-gate} 12597c478bd9Sstevel@tonic-gate 1260daaffb31SdpEOF 1261daaffb31Sdp} 1262daaffb31Sdp 1263daaffb31Sdp# 1264daaffb31Sdp# frame_navigation 1265daaffb31Sdp# 1266daaffb31Sdp# Output anchor navigation file for framed sdiffs. 1267daaffb31Sdp# 1268daaffb31Sdpfunction frame_navigation 1269daaffb31Sdp{ 1270daaffb31Sdp print "$HTML<head>$STDHEAD" 1271daaffb31Sdp 1272daaffb31Sdp cat << \EOF 1273daaffb31Sdp<title>Anchor Navigation</title> 1274daaffb31Sdp<meta http-equiv="Content-Script-Type" content="text/javascript"> 1275daaffb31Sdp<meta http-equiv="Content-Type" content="text/html"> 1276daaffb31Sdp 1277daaffb31Sdp<style type="text/css"> 1278daaffb31Sdp div.button td { padding-left: 5px; padding-right: 5px; 1279daaffb31Sdp background-color: #eee; text-align: center; 1280daaffb31Sdp border: 1px #444 outset; cursor: pointer; } 1281daaffb31Sdp div.button a { font-weight: bold; color: black } 1282daaffb31Sdp div.button td:hover { background: #ffcc99; } 1283daaffb31Sdp</style> 1284daaffb31SdpEOF 1285daaffb31Sdp 1286cac38512Smjnelson print "<script type=\"text/javascript\" src=\"ancnav.js\"></script>" 1287daaffb31Sdp 1288daaffb31Sdp cat << \EOF 12897c478bd9Sstevel@tonic-gate</head> 1290daaffb31Sdp<body id="SUNWwebrev" bgcolor="#eeeeee" onload="document.diff.real.focus();" 1291daaffb31Sdp onkeypress="keypress(event);"> 12927c478bd9Sstevel@tonic-gate <noscript lang="javascript"> 12937c478bd9Sstevel@tonic-gate <center> 1294cac38512Smjnelson <p><big>Framed Navigation controls require Javascript</big><br></br> 12957c478bd9Sstevel@tonic-gate Either this browser is incompatable or javascript is not enabled</p> 12967c478bd9Sstevel@tonic-gate </center> 12977c478bd9Sstevel@tonic-gate </noscript> 12987c478bd9Sstevel@tonic-gate <table width="100%" border="0" align="center"> 1299daaffb31Sdp <tr> 1300daaffb31Sdp <td valign="middle" width="25%">Diff navigation: 1301daaffb31Sdp Use 'j' and 'k' for next and previous diffs; or use buttons 1302daaffb31Sdp at right</td> 1303daaffb31Sdp <td align="center" valign="top" width="50%"> 13047c478bd9Sstevel@tonic-gate <div class="button"> 1305daaffb31Sdp <table border="0" align="center"> 1306daaffb31Sdp <tr> 1307daaffb31Sdp <td> 13087c478bd9Sstevel@tonic-gate <a onMouseDown="handlePress(1);return true;" 13097c478bd9Sstevel@tonic-gate onMouseUp="handleRelease(1);return true;" 13107c478bd9Sstevel@tonic-gate onMouseOut="handleRelease(1);return true;" 13117c478bd9Sstevel@tonic-gate onClick="return false;" 13127c478bd9Sstevel@tonic-gate title="Go to Beginning Of file">BOF</a></td> 1313daaffb31Sdp <td> 13147c478bd9Sstevel@tonic-gate <a onMouseDown="handlePress(3);return true;" 13157c478bd9Sstevel@tonic-gate onMouseUp="handleRelease(3);return true;" 13167c478bd9Sstevel@tonic-gate onMouseOut="handleRelease(3);return true;" 13177c478bd9Sstevel@tonic-gate title="Scroll Up: Press and Hold to accelerate" 1318daaffb31Sdp onClick="return false;">Scroll Up</a></td> 1319daaffb31Sdp <td> 13207c478bd9Sstevel@tonic-gate <a onMouseDown="handlePress(2);return true;" 13217c478bd9Sstevel@tonic-gate onMouseUp="handleRelease(2);return true;" 13227c478bd9Sstevel@tonic-gate onMouseOut="handleRelease(2);return true;" 13237c478bd9Sstevel@tonic-gate title="Go to previous Diff" 13247c478bd9Sstevel@tonic-gate onClick="return false;">Prev Diff</a> 13257c478bd9Sstevel@tonic-gate </td></tr> 1326daaffb31Sdp 13277c478bd9Sstevel@tonic-gate <tr> 1328daaffb31Sdp <td> 13297c478bd9Sstevel@tonic-gate <a onMouseDown="handlePress(6);return true;" 13307c478bd9Sstevel@tonic-gate onMouseUp="handleRelease(6);return true;" 13317c478bd9Sstevel@tonic-gate onMouseOut="handleRelease(6);return true;" 13327c478bd9Sstevel@tonic-gate onClick="return false;" 13337c478bd9Sstevel@tonic-gate title="Go to End Of File">EOF</a></td> 1334daaffb31Sdp <td> 13357c478bd9Sstevel@tonic-gate <a onMouseDown="handlePress(4);return true;" 13367c478bd9Sstevel@tonic-gate onMouseUp="handleRelease(4);return true;" 13377c478bd9Sstevel@tonic-gate onMouseOut="handleRelease(4);return true;" 13387c478bd9Sstevel@tonic-gate title="Scroll Down: Press and Hold to accelerate" 1339daaffb31Sdp onClick="return false;">Scroll Down</a></td> 1340daaffb31Sdp <td> 13417c478bd9Sstevel@tonic-gate <a onMouseDown="handlePress(5);return true;" 13427c478bd9Sstevel@tonic-gate onMouseUp="handleRelease(5);return true;" 13437c478bd9Sstevel@tonic-gate onMouseOut="handleRelease(5);return true;" 13447c478bd9Sstevel@tonic-gate title="Go to next Diff" 13457c478bd9Sstevel@tonic-gate onClick="return false;">Next Diff</a></td> 1346daaffb31Sdp </tr> 1347daaffb31Sdp </table> 1348daaffb31Sdp </div> 1349daaffb31Sdp </td> 13507c478bd9Sstevel@tonic-gate <th valign="middle" width="25%"> 1351daaffb31Sdp <form action="" name="diff" onsubmit="return ValidateDiffNum();"> 1352cac38512Smjnelson <input name="display" value="BOF" size="8" type="text"></input> 1353cac38512Smjnelson <input name="real" value="0" size="8" type="hidden"></input> 13547c478bd9Sstevel@tonic-gate </form> 13557c478bd9Sstevel@tonic-gate </th> 1356daaffb31Sdp </tr> 13577c478bd9Sstevel@tonic-gate </table> 13587c478bd9Sstevel@tonic-gate </body> 13597c478bd9Sstevel@tonic-gate</html> 13607c478bd9Sstevel@tonic-gateEOF 13617c478bd9Sstevel@tonic-gate} 13627c478bd9Sstevel@tonic-gate 13637c478bd9Sstevel@tonic-gate 1364daaffb31Sdp 1365daaffb31Sdp# 1366daaffb31Sdp# diff_to_html <filename> <filepath> { U | C } <comment> 1367daaffb31Sdp# 1368daaffb31Sdp# Processes the output of diff to produce an HTML file representing either 1369daaffb31Sdp# context or unified diffs. 1370daaffb31Sdp# 13717c478bd9Sstevel@tonic-gatediff_to_html() 13727c478bd9Sstevel@tonic-gate{ 13737c478bd9Sstevel@tonic-gate TNAME=$1 1374daaffb31Sdp TPATH=$2 1375daaffb31Sdp DIFFTYPE=$3 1376daaffb31Sdp COMMENT=$4 1377daaffb31Sdp 1378daaffb31Sdp print "$HTML<head>$STDHEAD" 1379daaffb31Sdp print "<title>$WNAME ${DIFFTYPE}diff $TPATH</title>" 1380daaffb31Sdp 1381daaffb31Sdp if [[ $DIFFTYPE == "U" ]]; then 1382daaffb31Sdp print "$UDIFFCSS" 1383daaffb31Sdp fi 1384daaffb31Sdp 1385daaffb31Sdp cat <<-EOF 1386daaffb31Sdp </head> 1387daaffb31Sdp <body id="SUNWwebrev"> 1388daaffb31Sdp <a class="print" href="javascript:print()">Print this page</a> 1389daaffb31Sdp <pre>$COMMENT</pre> 1390daaffb31Sdp <pre> 1391daaffb31Sdp EOF 13927c478bd9Sstevel@tonic-gate 1393cdf0c1d5Smjnelson html_quote | $AWK ' 1394daaffb31Sdp /^--- new/ { next } 1395daaffb31Sdp /^\+\+\+ new/ { next } 1396daaffb31Sdp /^--- old/ { next } 1397daaffb31Sdp /^\*\*\* old/ { next } 1398daaffb31Sdp /^\*\*\*\*/ { next } 13997c478bd9Sstevel@tonic-gate /^-------/ { printf "<center><h1>%s</h1></center>\n", $0; next } 1400cac38512Smjnelson /^\@\@.*\@\@$/ { printf "</pre><hr></hr><pre>\n"; 1401daaffb31Sdp printf "<span class=\"newmarker\">%s</span>\n", $0; 1402daaffb31Sdp next} 1403daaffb31Sdp 1404cac38512Smjnelson /^\*\*\*/ { printf "<hr></hr><span class=\"oldmarker\">%s</span>\n", $0; 1405daaffb31Sdp next} 1406daaffb31Sdp /^---/ { printf "<span class=\"newmarker\">%s</span>\n", $0; 1407daaffb31Sdp next} 1408daaffb31Sdp /^\+/ {printf "<span class=\"new\">%s</span>\n", $0; next} 1409daaffb31Sdp /^!/ {printf "<span class=\"changed\">%s</span>\n", $0; next} 1410daaffb31Sdp /^-/ {printf "<span class=\"removed\">%s</span>\n", $0; next} 1411daaffb31Sdp {printf "%s\n", $0; next} 14127c478bd9Sstevel@tonic-gate ' 1413daaffb31Sdp 1414daaffb31Sdp print "</pre></body></html>\n" 14157c478bd9Sstevel@tonic-gate} 14167c478bd9Sstevel@tonic-gate 14177c478bd9Sstevel@tonic-gate 1418daaffb31Sdp# 1419daaffb31Sdp# source_to_html { new | old } <filename> 1420daaffb31Sdp# 1421daaffb31Sdp# Process a plain vanilla source file to transform it into an HTML file. 1422daaffb31Sdp# 14237c478bd9Sstevel@tonic-gatesource_to_html() 14247c478bd9Sstevel@tonic-gate{ 14257c478bd9Sstevel@tonic-gate WHICH=$1 14267c478bd9Sstevel@tonic-gate TNAME=$2 14277c478bd9Sstevel@tonic-gate 1428daaffb31Sdp print "$HTML<head>$STDHEAD" 1429cdf0c1d5Smjnelson print "<title>$WNAME $WHICH $TNAME</title>" 1430daaffb31Sdp print "<body id=\"SUNWwebrev\">" 1431daaffb31Sdp print "<pre>" 1432cdf0c1d5Smjnelson html_quote | $AWK '{line += 1 ; printf "%4d %s\n", line, $0 }' 1433daaffb31Sdp print "</pre></body></html>" 14347c478bd9Sstevel@tonic-gate} 14357c478bd9Sstevel@tonic-gate 1436daaffb31Sdp# 1437cdf0c1d5Smjnelson# comments_from_wx {text|html} filepath 1438daaffb31Sdp# 1439cdf0c1d5Smjnelson# Given the pathname of a file, find its location in a "wx" active 1440cdf0c1d5Smjnelson# file list and print the following comment. Output is either text or 1441cdf0c1d5Smjnelson# HTML; if the latter, embedded bugids (sequence of 5 or more digits) 1442cdf0c1d5Smjnelson# are turned into URLs. 1443cdf0c1d5Smjnelson# 1444cdf0c1d5Smjnelson# This is also used with Mercurial and the file list provided by hg-active. 1445daaffb31Sdp# 1446daaffb31Sdpcomments_from_wx() 14477c478bd9Sstevel@tonic-gate{ 1448daaffb31Sdp typeset fmt=$1 1449daaffb31Sdp typeset p=$2 14507c478bd9Sstevel@tonic-gate 1451cdf0c1d5Smjnelson comm=`$AWK ' 1452daaffb31Sdp $1 == "'$p'" { 14537c478bd9Sstevel@tonic-gate do getline ; while (NF > 0) 14547c478bd9Sstevel@tonic-gate getline 14557c478bd9Sstevel@tonic-gate while (NF > 0) { print ; getline } 14567c478bd9Sstevel@tonic-gate exit 1457daaffb31Sdp }' < $wxfile` 1458daaffb31Sdp 1459cdf0c1d5Smjnelson if [[ -z $comm ]]; then 1460cdf0c1d5Smjnelson comm="*** NO COMMENTS ***" 1461cdf0c1d5Smjnelson fi 1462cdf0c1d5Smjnelson 1463daaffb31Sdp if [[ $fmt == "text" ]]; then 1464cdf0c1d5Smjnelson print -- "$comm" 1465daaffb31Sdp return 1466daaffb31Sdp fi 1467daaffb31Sdp 14680fd2682eSMark J. Nelson print -- "$comm" | html_quote | its2url 1469cdf0c1d5Smjnelson 14707c478bd9Sstevel@tonic-gate} 14717c478bd9Sstevel@tonic-gate 14727c478bd9Sstevel@tonic-gate# 1473daaffb31Sdp# getcomments {text|html} filepath parentpath 1474daaffb31Sdp# 1475daaffb31Sdp# Fetch the comments depending on what SCM mode we're in. 1476daaffb31Sdp# 1477daaffb31Sdpgetcomments() 1478daaffb31Sdp{ 1479daaffb31Sdp typeset fmt=$1 1480daaffb31Sdp typeset p=$2 1481daaffb31Sdp typeset pp=$3 14827c478bd9Sstevel@tonic-gate 14833df69ef3SDarren Moffat if [[ -n $Nflag ]]; then 14843df69ef3SDarren Moffat return 14853df69ef3SDarren Moffat fi 1486cdf0c1d5Smjnelson # 1487cdf0c1d5Smjnelson # Mercurial support uses a file list in wx format, so this 1488cdf0c1d5Smjnelson # will be used there, too 1489cdf0c1d5Smjnelson # 1490daaffb31Sdp if [[ -n $wxfile ]]; then 1491daaffb31Sdp comments_from_wx $fmt $p 1492daaffb31Sdp fi 1493daaffb31Sdp} 1494daaffb31Sdp 1495daaffb31Sdp# 1496daaffb31Sdp# printCI <total-changed> <inserted> <deleted> <modified> <unchanged> 1497daaffb31Sdp# 1498daaffb31Sdp# Print out Code Inspection figures similar to sccs-prt(1) format. 1499daaffb31Sdp# 1500daaffb31Sdpfunction printCI 1501daaffb31Sdp{ 1502daaffb31Sdp integer tot=$1 ins=$2 del=$3 mod=$4 unc=$5 1503daaffb31Sdp typeset str 1504daaffb31Sdp if (( tot == 1 )); then 1505daaffb31Sdp str="line" 1506daaffb31Sdp else 1507daaffb31Sdp str="lines" 1508daaffb31Sdp fi 1509daaffb31Sdp printf '%d %s changed: %d ins; %d del; %d mod; %d unchg\n' \ 1510daaffb31Sdp $tot $str $ins $del $mod $unc 1511daaffb31Sdp} 1512daaffb31Sdp 1513daaffb31Sdp 1514daaffb31Sdp# 1515daaffb31Sdp# difflines <oldfile> <newfile> 1516daaffb31Sdp# 1517daaffb31Sdp# Calculate and emit number of added, removed, modified and unchanged lines, 1518daaffb31Sdp# and total lines changed, the sum of added + removed + modified. 1519daaffb31Sdp# 15207c478bd9Sstevel@tonic-gatefunction difflines 15217c478bd9Sstevel@tonic-gate{ 1522daaffb31Sdp integer tot mod del ins unc err 15237c478bd9Sstevel@tonic-gate typeset filename 15247c478bd9Sstevel@tonic-gate 1525cdf0c1d5Smjnelson eval $( diff -e $1 $2 | $AWK ' 1526daaffb31Sdp # Change range of lines: N,Nc 15277c478bd9Sstevel@tonic-gate /^[0-9]*,[0-9]*c$/ { 15287c478bd9Sstevel@tonic-gate n=split(substr($1,1,length($1)-1), counts, ","); 15297c478bd9Sstevel@tonic-gate if (n != 2) { 15307c478bd9Sstevel@tonic-gate error=2 15317c478bd9Sstevel@tonic-gate exit; 15327c478bd9Sstevel@tonic-gate } 1533daaffb31Sdp # 1534daaffb31Sdp # 3,5c means lines 3 , 4 and 5 are changed, a total of 3 lines. 1535daaffb31Sdp # following would be 5 - 3 = 2! Hence +1 for correction. 1536daaffb31Sdp # 15377c478bd9Sstevel@tonic-gate r=(counts[2]-counts[1])+1; 1538daaffb31Sdp 1539daaffb31Sdp # 1540daaffb31Sdp # Now count replacement lines: each represents a change instead 1541daaffb31Sdp # of a delete, so increment c and decrement r. 1542daaffb31Sdp # 15437c478bd9Sstevel@tonic-gate while (getline != /^\.$/) { 15447c478bd9Sstevel@tonic-gate c++; 15457c478bd9Sstevel@tonic-gate r--; 15467c478bd9Sstevel@tonic-gate } 1547daaffb31Sdp # 1548daaffb31Sdp # If there were more replacement lines than original lines, 1549daaffb31Sdp # then r will be negative; in this case there are no deletions, 1550daaffb31Sdp # but there are r changes that should be counted as adds, and 1551daaffb31Sdp # since r is negative, subtract it from a and add it to c. 1552daaffb31Sdp # 15537c478bd9Sstevel@tonic-gate if (r < 0) { 15547c478bd9Sstevel@tonic-gate a-=r; 15557c478bd9Sstevel@tonic-gate c+=r; 15567c478bd9Sstevel@tonic-gate } 1557daaffb31Sdp 1558daaffb31Sdp # 1559daaffb31Sdp # If there were more original lines than replacement lines, then 1560daaffb31Sdp # r will be positive; in this case, increment d by that much. 1561daaffb31Sdp # 15627c478bd9Sstevel@tonic-gate if (r > 0) { 15637c478bd9Sstevel@tonic-gate d+=r; 15647c478bd9Sstevel@tonic-gate } 15657c478bd9Sstevel@tonic-gate next; 15667c478bd9Sstevel@tonic-gate } 15677c478bd9Sstevel@tonic-gate 1568daaffb31Sdp # Change lines: Nc 15697c478bd9Sstevel@tonic-gate /^[0-9].*c$/ { 1570daaffb31Sdp # The first line is a replacement; any more are additions. 15717c478bd9Sstevel@tonic-gate if (getline != /^\.$/) { 15727c478bd9Sstevel@tonic-gate c++; 15737c478bd9Sstevel@tonic-gate while (getline != /^\.$/) a++; 15747c478bd9Sstevel@tonic-gate } 15757c478bd9Sstevel@tonic-gate next; 15767c478bd9Sstevel@tonic-gate } 15777c478bd9Sstevel@tonic-gate 1578daaffb31Sdp # Add lines: both Na and N,Na 15797c478bd9Sstevel@tonic-gate /^[0-9].*a$/ { 15807c478bd9Sstevel@tonic-gate while (getline != /^\.$/) a++; 15817c478bd9Sstevel@tonic-gate next; 15827c478bd9Sstevel@tonic-gate } 15837c478bd9Sstevel@tonic-gate 1584daaffb31Sdp # Delete range of lines: N,Nd 15857c478bd9Sstevel@tonic-gate /^[0-9]*,[0-9]*d$/ { 15867c478bd9Sstevel@tonic-gate n=split(substr($1,1,length($1)-1), counts, ","); 15877c478bd9Sstevel@tonic-gate if (n != 2) { 15887c478bd9Sstevel@tonic-gate error=2 15897c478bd9Sstevel@tonic-gate exit; 15907c478bd9Sstevel@tonic-gate } 1591daaffb31Sdp # 1592daaffb31Sdp # 3,5d means lines 3 , 4 and 5 are deleted, a total of 3 lines. 1593daaffb31Sdp # following would be 5 - 3 = 2! Hence +1 for correction. 1594daaffb31Sdp # 15957c478bd9Sstevel@tonic-gate r=(counts[2]-counts[1])+1; 15967c478bd9Sstevel@tonic-gate d+=r; 15977c478bd9Sstevel@tonic-gate next; 15987c478bd9Sstevel@tonic-gate } 15997c478bd9Sstevel@tonic-gate 1600daaffb31Sdp # Delete line: Nd. For example 10d says line 10 is deleted. 16017c478bd9Sstevel@tonic-gate /^[0-9]*d$/ {d++; next} 16027c478bd9Sstevel@tonic-gate 1603daaffb31Sdp # Should not get here! 16047c478bd9Sstevel@tonic-gate { 16057c478bd9Sstevel@tonic-gate error=1; 16067c478bd9Sstevel@tonic-gate exit; 16077c478bd9Sstevel@tonic-gate } 16087c478bd9Sstevel@tonic-gate 1609daaffb31Sdp # Finish off - print results 16107c478bd9Sstevel@tonic-gate END { 1611daaffb31Sdp printf("tot=%d;mod=%d;del=%d;ins=%d;err=%d\n", 16127c478bd9Sstevel@tonic-gate (c+d+a), c, d, a, error); 16137c478bd9Sstevel@tonic-gate }' ) 16147c478bd9Sstevel@tonic-gate 1615cdf0c1d5Smjnelson # End of $AWK, Check to see if any trouble occurred. 16167c478bd9Sstevel@tonic-gate if (( $? > 0 || err > 0 )); then 1617daaffb31Sdp print "Unexpected Error occurred reading" \ 1618daaffb31Sdp "\`diff -e $1 $2\`: \$?=$?, err=" $err 1619daaffb31Sdp return 1620daaffb31Sdp fi 1621daaffb31Sdp 16227c478bd9Sstevel@tonic-gate # Accumulate totals 16237c478bd9Sstevel@tonic-gate (( TOTL += tot )) 1624daaffb31Sdp (( TMOD += mod )) 16257c478bd9Sstevel@tonic-gate (( TDEL += del )) 16267c478bd9Sstevel@tonic-gate (( TINS += ins )) 16277c478bd9Sstevel@tonic-gate # Calculate unchanged lines 1628cdf0c1d5Smjnelson unc=`wc -l < $1` 16297c478bd9Sstevel@tonic-gate if (( unc > 0 )); then 1630daaffb31Sdp (( unc -= del + mod )) 16317c478bd9Sstevel@tonic-gate (( TUNC += unc )) 16327c478bd9Sstevel@tonic-gate fi 16337c478bd9Sstevel@tonic-gate # print summary 1634daaffb31Sdp print "<span class=\"lineschanged\">" 1635daaffb31Sdp printCI $tot $ins $del $mod $unc 1636daaffb31Sdp print "</span>" 16377c478bd9Sstevel@tonic-gate} 16387c478bd9Sstevel@tonic-gate 1639daaffb31Sdp 16407c478bd9Sstevel@tonic-gate# 1641daaffb31Sdp# flist_from_wx 1642daaffb31Sdp# 1643daaffb31Sdp# Sets up webrev to source its information from a wx-formatted file. 1644daaffb31Sdp# Sets the global 'wxfile' variable. 1645daaffb31Sdp# 1646daaffb31Sdpfunction flist_from_wx 16477c478bd9Sstevel@tonic-gate{ 1648daaffb31Sdp typeset argfile=$1 1649daaffb31Sdp if [[ -n ${argfile%%/*} ]]; then 1650daaffb31Sdp # 1651daaffb31Sdp # If the wx file pathname is relative then make it absolute 1652daaffb31Sdp # because the webrev does a "cd" later on. 1653daaffb31Sdp # 1654daaffb31Sdp wxfile=$PWD/$argfile 16557c478bd9Sstevel@tonic-gate else 1656daaffb31Sdp wxfile=$argfile 16577c478bd9Sstevel@tonic-gate fi 16587c478bd9Sstevel@tonic-gate 1659cdf0c1d5Smjnelson $AWK '{ c = 1; print; 16607c478bd9Sstevel@tonic-gate while (getline) { 16617c478bd9Sstevel@tonic-gate if (NF == 0) { c = -c; continue } 16627c478bd9Sstevel@tonic-gate if (c > 0) print 16637c478bd9Sstevel@tonic-gate } 1664daaffb31Sdp }' $wxfile > $FLIST 16657c478bd9Sstevel@tonic-gate 1666daaffb31Sdp print " Done." 1667daaffb31Sdp} 16687c478bd9Sstevel@tonic-gate 1669daaffb31Sdp# 1670cdf0c1d5Smjnelson# Call hg-active to get the active list output in the wx active list format 1671cdf0c1d5Smjnelson# 1672cdf0c1d5Smjnelsonfunction hg_active_wxfile 1673cdf0c1d5Smjnelson{ 1674cdf0c1d5Smjnelson typeset child=$1 1675cdf0c1d5Smjnelson typeset parent=$2 1676cdf0c1d5Smjnelson 1677cdf0c1d5Smjnelson TMPFLIST=/tmp/$$.active 16789a70fc3bSMark J. Nelson $HG_ACTIVE -w $child -p $parent -o $TMPFLIST 1679cdf0c1d5Smjnelson wxfile=$TMPFLIST 1680cdf0c1d5Smjnelson} 1681cdf0c1d5Smjnelson 1682cdf0c1d5Smjnelson# 1683cdf0c1d5Smjnelson# flist_from_mercurial 1684cdf0c1d5Smjnelson# Call hg-active to get a wx-style active list, and hand it off to 1685cdf0c1d5Smjnelson# flist_from_wx 1686cdf0c1d5Smjnelson# 1687cdf0c1d5Smjnelsonfunction flist_from_mercurial 1688cdf0c1d5Smjnelson{ 1689cdf0c1d5Smjnelson typeset child=$1 1690cdf0c1d5Smjnelson typeset parent=$2 1691cdf0c1d5Smjnelson 1692cdf0c1d5Smjnelson print " File list from: hg-active -p $parent ...\c" 1693cdf0c1d5Smjnelson if [[ ! -x $HG_ACTIVE ]]; then 1694cdf0c1d5Smjnelson print # Blank line for the \c above 1695cdf0c1d5Smjnelson print -u2 "Error: hg-active tool not found. Exiting" 1696cdf0c1d5Smjnelson exit 1 1697cdf0c1d5Smjnelson fi 1698cdf0c1d5Smjnelson hg_active_wxfile $child $parent 1699cdf0c1d5Smjnelson 1700cdf0c1d5Smjnelson # flist_from_wx prints the Done, so we don't have to. 1701cdf0c1d5Smjnelson flist_from_wx $TMPFLIST 1702cdf0c1d5Smjnelson} 1703cdf0c1d5Smjnelson 1704cdf0c1d5Smjnelson# 17058bcea973SRichard Lowe# Transform a specified 'git log' output format into a wx-like active list. 17068bcea973SRichard Lowe# 17078bcea973SRichard Lowefunction git_wxfile 17088bcea973SRichard Lowe{ 17098bcea973SRichard Lowe typeset child="$1" 17108bcea973SRichard Lowe typeset parent="$2" 17118bcea973SRichard Lowe 17128bcea973SRichard Lowe TMPFLIST=/tmp/$$.active 17138bcea973SRichard Lowe $PERL -e 'my (%files, %realfiles, $msg); 17148bcea973SRichard Lowe my $branch = $ARGV[0]; 17158bcea973SRichard Lowe 17168bcea973SRichard Lowe open(F, "git diff -M --name-status $branch |"); 17178bcea973SRichard Lowe while (<F>) { 17188bcea973SRichard Lowe chomp; 17198bcea973SRichard Lowe if (/^R(\d+)\s+([^ ]+)\s+([^ ]+)/) { # rename 17208bcea973SRichard Lowe if ($1 >= 75) { # Probably worth treating as a rename 17213cb02613SRichard Lowe $realfiles{$3} = $2; 17228bcea973SRichard Lowe } else { 17238bcea973SRichard Lowe $realfiles{$3} = $3; 17248bcea973SRichard Lowe $realfiles{$2} = $2; 17258bcea973SRichard Lowe } 17268bcea973SRichard Lowe } else { 17278bcea973SRichard Lowe my $f = (split /\s+/, $_)[1]; 17288bcea973SRichard Lowe $realfiles{$f} = $f; 17298bcea973SRichard Lowe } 17308bcea973SRichard Lowe } 17318bcea973SRichard Lowe close(F); 17328bcea973SRichard Lowe 17338bcea973SRichard Lowe my $state = 1; # 0|comments, 1|files 17348bcea973SRichard Lowe open(F, "git whatchanged --pretty=format:%B $branch.. |"); 17358bcea973SRichard Lowe while (<F>) { 17368bcea973SRichard Lowe chomp; 17378bcea973SRichard Lowe if (/^:[0-9]{6}/) { 17388bcea973SRichard Lowe my $fname = (split /\t/, $_)[1]; 17398bcea973SRichard Lowe next if !defined($realfiles{$fname}); # No real change 17408bcea973SRichard Lowe $state = 1; 17413cb02613SRichard Lowe chomp $msg; 17423cb02613SRichard Lowe $files{$fname} .= $msg; 17438bcea973SRichard Lowe } else { 17448bcea973SRichard Lowe if ($state == 1) { 17458bcea973SRichard Lowe $state = 0; 17468bcea973SRichard Lowe $msg = /^\n/ ? "" : "\n"; 17478bcea973SRichard Lowe } 17488bcea973SRichard Lowe $msg .= "$_\n" if ($_); 17498bcea973SRichard Lowe } 17508bcea973SRichard Lowe } 17518bcea973SRichard Lowe close(F); 17528bcea973SRichard Lowe 17538bcea973SRichard Lowe for (sort keys %files) { 17548bcea973SRichard Lowe if ($realfiles{$_} ne $_) { 17553cb02613SRichard Lowe print "$_ $realfiles{$_}\n$files{$_}\n\n"; 17568bcea973SRichard Lowe } else { 17573cb02613SRichard Lowe print "$_\n$files{$_}\n\n" 17588bcea973SRichard Lowe } 17598bcea973SRichard Lowe }' ${parent} > $TMPFLIST 17608bcea973SRichard Lowe 17618bcea973SRichard Lowe wxfile=$TMPFLIST 17628bcea973SRichard Lowe} 17638bcea973SRichard Lowe 17648bcea973SRichard Lowe# 17658bcea973SRichard Lowe# flist_from_git 17668bcea973SRichard Lowe# Build a wx-style active list, and hand it off to flist_from_wx 17678bcea973SRichard Lowe# 17688bcea973SRichard Lowefunction flist_from_git 17698bcea973SRichard Lowe{ 17708bcea973SRichard Lowe typeset child=$1 17718bcea973SRichard Lowe typeset parent=$2 17728bcea973SRichard Lowe 17738bcea973SRichard Lowe print " File list from: git ...\c" 17748bcea973SRichard Lowe git_wxfile "$child" "$parent"; 17758bcea973SRichard Lowe 17768bcea973SRichard Lowe # flist_from_wx prints the Done, so we don't have to. 17778bcea973SRichard Lowe flist_from_wx $TMPFLIST 17788bcea973SRichard Lowe} 17798bcea973SRichard Lowe 17808bcea973SRichard Lowe# 1781cdf0c1d5Smjnelson# flist_from_subversion 1782cdf0c1d5Smjnelson# 1783cdf0c1d5Smjnelson# Generate the file list by extracting file names from svn status. 1784cdf0c1d5Smjnelson# 1785cdf0c1d5Smjnelsonfunction flist_from_subversion 1786cdf0c1d5Smjnelson{ 1787cdf0c1d5Smjnelson CWS=$1 1788cdf0c1d5Smjnelson OLDPWD=$2 1789cdf0c1d5Smjnelson 1790cdf0c1d5Smjnelson cd $CWS 1791cdf0c1d5Smjnelson print -u2 " File list from: svn status ... \c" 1792cdf0c1d5Smjnelson svn status | $AWK '/^[ACDMR]/ { print $NF }' > $FLIST 1793cdf0c1d5Smjnelson print -u2 " Done." 1794cdf0c1d5Smjnelson cd $OLDPWD 1795cdf0c1d5Smjnelson} 1796cdf0c1d5Smjnelson 1797daaffb31Sdpfunction env_from_flist 1798daaffb31Sdp{ 1799daaffb31Sdp [[ -r $FLIST ]] || return 1800daaffb31Sdp 1801daaffb31Sdp # 1802daaffb31Sdp # Use "eval" to set env variables that are listed in the file 1803daaffb31Sdp # list. Then copy those into our local versions of those 1804daaffb31Sdp # variables if they have not been set already. 1805daaffb31Sdp # 1806b0088928SVladimir Kotal eval `$SED -e "s/#.*$//" $FLIST | $GREP = ` 18077c478bd9Sstevel@tonic-gate 1808cdf0c1d5Smjnelson if [[ -z $codemgr_ws && -n $CODEMGR_WS ]]; then 1809cdf0c1d5Smjnelson codemgr_ws=$CODEMGR_WS 1810cdf0c1d5Smjnelson export CODEMGR_WS 1811cdf0c1d5Smjnelson fi 18127c478bd9Sstevel@tonic-gate 1813daaffb31Sdp # 1814daaffb31Sdp # Check to see if CODEMGR_PARENT is set in the flist file. 1815daaffb31Sdp # 1816cdf0c1d5Smjnelson if [[ -z $codemgr_parent && -n $CODEMGR_PARENT ]]; then 1817daaffb31Sdp codemgr_parent=$CODEMGR_PARENT 1818cdf0c1d5Smjnelson export CODEMGR_PARENT 1819daaffb31Sdp fi 1820daaffb31Sdp} 1821daaffb31Sdp 182214983201Sdpfunction look_for_prog 182314983201Sdp{ 182414983201Sdp typeset path 182514983201Sdp typeset ppath 182614983201Sdp typeset progname=$1 182714983201Sdp 182814983201Sdp ppath=$PATH 182914983201Sdp ppath=$ppath:/usr/sfw/bin:/usr/bin:/usr/sbin 1830d7b56f41SBart Coddens ppath=$ppath:/opt/onbld/bin 1831cdf0c1d5Smjnelson ppath=$ppath:/opt/onbld/bin/`uname -p` 183214983201Sdp 183314983201Sdp PATH=$ppath prog=`whence $progname` 183414983201Sdp if [[ -n $prog ]]; then 183514983201Sdp print $prog 183614983201Sdp fi 183714983201Sdp} 183814983201Sdp 1839cdf0c1d5Smjnelsonfunction get_file_mode 1840cdf0c1d5Smjnelson{ 1841cdf0c1d5Smjnelson $PERL -e ' 1842cdf0c1d5Smjnelson if (@stat = stat($ARGV[0])) { 1843cdf0c1d5Smjnelson $mode = $stat[2] & 0777; 1844cdf0c1d5Smjnelson printf "%03o\n", $mode; 1845cdf0c1d5Smjnelson exit 0; 1846cdf0c1d5Smjnelson } else { 1847cdf0c1d5Smjnelson exit 1; 1848cdf0c1d5Smjnelson } 1849cdf0c1d5Smjnelson ' $1 1850cdf0c1d5Smjnelson} 1851cdf0c1d5Smjnelson 1852cdf0c1d5Smjnelsonfunction build_old_new_mercurial 1853cdf0c1d5Smjnelson{ 1854cdf0c1d5Smjnelson typeset olddir="$1" 1855cdf0c1d5Smjnelson typeset newdir="$2" 1856cdf0c1d5Smjnelson typeset old_mode= 1857cdf0c1d5Smjnelson typeset new_mode= 1858cdf0c1d5Smjnelson typeset file 1859cdf0c1d5Smjnelson 1860cdf0c1d5Smjnelson # 1861cdf0c1d5Smjnelson # Get old file mode, from the parent revision manifest entry. 1862cdf0c1d5Smjnelson # Mercurial only stores a "file is executable" flag, but the 1863cdf0c1d5Smjnelson # manifest will display an octal mode "644" or "755". 1864cdf0c1d5Smjnelson # 1865cdf0c1d5Smjnelson if [[ "$PDIR" == "." ]]; then 1866cdf0c1d5Smjnelson file="$PF" 1867cdf0c1d5Smjnelson else 1868cdf0c1d5Smjnelson file="$PDIR/$PF" 1869cdf0c1d5Smjnelson fi 1870b0088928SVladimir Kotal file=`echo $file | $SED 's#/#\\\/#g'` 1871cdf0c1d5Smjnelson # match the exact filename, and return only the permission digits 1872b0088928SVladimir Kotal old_mode=`$SED -n -e "/^\\(...\\) . ${file}$/s//\\1/p" \ 1873cdf0c1d5Smjnelson < $HG_PARENT_MANIFEST` 1874cdf0c1d5Smjnelson 1875cdf0c1d5Smjnelson # 1876cdf0c1d5Smjnelson # Get new file mode, directly from the filesystem. 1877cdf0c1d5Smjnelson # Normalize the mode to match Mercurial's behavior. 1878cdf0c1d5Smjnelson # 1879cdf0c1d5Smjnelson new_mode=`get_file_mode $CWS/$DIR/$F` 1880cdf0c1d5Smjnelson if [[ -n "$new_mode" ]]; then 1881cdf0c1d5Smjnelson if [[ "$new_mode" = *[1357]* ]]; then 1882cdf0c1d5Smjnelson new_mode=755 1883cdf0c1d5Smjnelson else 1884cdf0c1d5Smjnelson new_mode=644 1885cdf0c1d5Smjnelson fi 1886cdf0c1d5Smjnelson fi 1887cdf0c1d5Smjnelson 1888cdf0c1d5Smjnelson # 1889cdf0c1d5Smjnelson # new version of the file. 1890cdf0c1d5Smjnelson # 1891cdf0c1d5Smjnelson rm -rf $newdir/$DIR/$F 1892cdf0c1d5Smjnelson if [[ -e $CWS/$DIR/$F ]]; then 1893cdf0c1d5Smjnelson cp $CWS/$DIR/$F $newdir/$DIR/$F 1894cdf0c1d5Smjnelson if [[ -n $new_mode ]]; then 1895cdf0c1d5Smjnelson chmod $new_mode $newdir/$DIR/$F 1896cdf0c1d5Smjnelson else 1897cdf0c1d5Smjnelson # should never happen 1898cdf0c1d5Smjnelson print -u2 "ERROR: set mode of $newdir/$DIR/$F" 1899cdf0c1d5Smjnelson fi 1900cdf0c1d5Smjnelson fi 1901cdf0c1d5Smjnelson 1902cdf0c1d5Smjnelson # 1903cdf0c1d5Smjnelson # parent's version of the file 1904cdf0c1d5Smjnelson # 1905cdf0c1d5Smjnelson # Note that we get this from the last version common to both 1906cdf0c1d5Smjnelson # ourselves and the parent. References are via $CWS since we have no 1907cdf0c1d5Smjnelson # guarantee that the parent workspace is reachable via the filesystem. 1908cdf0c1d5Smjnelson # 1909cdf0c1d5Smjnelson if [[ -n $parent_webrev && -e $PWS/$PDIR/$PF ]]; then 1910cdf0c1d5Smjnelson cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF 1911cdf0c1d5Smjnelson elif [[ -n $HG_PARENT ]]; then 1912cdf0c1d5Smjnelson hg cat -R $CWS -r $HG_PARENT $CWS/$PDIR/$PF > \ 1913cdf0c1d5Smjnelson $olddir/$PDIR/$PF 2>/dev/null 1914cdf0c1d5Smjnelson 191502d26c39SVladimir Kotal if (( $? != 0 )); then 1916cdf0c1d5Smjnelson rm -f $olddir/$PDIR/$PF 1917cdf0c1d5Smjnelson else 1918cdf0c1d5Smjnelson if [[ -n $old_mode ]]; then 1919cdf0c1d5Smjnelson chmod $old_mode $olddir/$PDIR/$PF 1920cdf0c1d5Smjnelson else 1921cdf0c1d5Smjnelson # should never happen 1922cdf0c1d5Smjnelson print -u2 "ERROR: set mode of $olddir/$PDIR/$PF" 1923cdf0c1d5Smjnelson fi 1924cdf0c1d5Smjnelson fi 1925cdf0c1d5Smjnelson fi 1926cdf0c1d5Smjnelson} 1927cdf0c1d5Smjnelson 19288bcea973SRichard Lowefunction build_old_new_git 19298bcea973SRichard Lowe{ 19308bcea973SRichard Lowe typeset olddir="$1" 19318bcea973SRichard Lowe typeset newdir="$2" 19328bcea973SRichard Lowe typeset o_mode= 19338bcea973SRichard Lowe typeset n_mode= 19348bcea973SRichard Lowe typeset o_object= 19358bcea973SRichard Lowe typeset n_object= 19368bcea973SRichard Lowe typeset OWD=$PWD 19378bcea973SRichard Lowe typeset file 19388bcea973SRichard Lowe typeset type 19398bcea973SRichard Lowe 19408bcea973SRichard Lowe cd $CWS 19418bcea973SRichard Lowe 19428bcea973SRichard Lowe # 19438bcea973SRichard Lowe # Get old file and its mode from the git object tree 19448bcea973SRichard Lowe # 19458bcea973SRichard Lowe if [[ "$PDIR" == "." ]]; then 19468bcea973SRichard Lowe file="$PF" 19478bcea973SRichard Lowe else 19488bcea973SRichard Lowe file="$PDIR/$PF" 19498bcea973SRichard Lowe fi 19508bcea973SRichard Lowe 19518bcea973SRichard Lowe if [[ -n $parent_webrev && -e $PWS/$PDIR/$PF ]]; then 19528bcea973SRichard Lowe cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF 19538bcea973SRichard Lowe else 19548bcea973SRichard Lowe $GIT ls-tree $GIT_PARENT $file | read o_mode type o_object junk 19558bcea973SRichard Lowe $GIT cat-file $type $o_object > $olddir/$file 2>/dev/null 19568bcea973SRichard Lowe 19578bcea973SRichard Lowe if (( $? != 0 )); then 19588bcea973SRichard Lowe rm -f $olddir/$file 19598bcea973SRichard Lowe elif [[ -n $o_mode ]]; then 19608bcea973SRichard Lowe # Strip the first 3 digits, to get a regular octal mode 19618bcea973SRichard Lowe o_mode=${o_mode/???/} 19628bcea973SRichard Lowe chmod $o_mode $olddir/$file 19638bcea973SRichard Lowe else 19648bcea973SRichard Lowe # should never happen 19658bcea973SRichard Lowe print -u2 "ERROR: set mode of $olddir/$file" 19668bcea973SRichard Lowe fi 19678bcea973SRichard Lowe fi 19688bcea973SRichard Lowe 19698bcea973SRichard Lowe # 19708bcea973SRichard Lowe # new version of the file. 19718bcea973SRichard Lowe # 19728bcea973SRichard Lowe if [[ "$DIR" == "." ]]; then 19738bcea973SRichard Lowe file="$F" 19748bcea973SRichard Lowe else 19758bcea973SRichard Lowe file="$DIR/$F" 19768bcea973SRichard Lowe fi 19778bcea973SRichard Lowe rm -rf $newdir/$file 19788bcea973SRichard Lowe 19798bcea973SRichard Lowe if [[ -e $CWS/$DIR/$F ]]; then 19808bcea973SRichard Lowe cp $CWS/$DIR/$F $newdir/$DIR/$F 19818bcea973SRichard Lowe chmod $(get_file_mode $CWS/$DIR/$F) $newdir/$DIR/$F 19828bcea973SRichard Lowe fi 19838bcea973SRichard Lowe cd $OWD 19848bcea973SRichard Lowe} 19858bcea973SRichard Lowe 1986cdf0c1d5Smjnelsonfunction build_old_new_subversion 1987cdf0c1d5Smjnelson{ 1988cdf0c1d5Smjnelson typeset olddir="$1" 1989cdf0c1d5Smjnelson typeset newdir="$2" 1990cdf0c1d5Smjnelson 1991cdf0c1d5Smjnelson # Snag new version of file. 1992cdf0c1d5Smjnelson rm -f $newdir/$DIR/$F 1993cdf0c1d5Smjnelson [[ -e $CWS/$DIR/$F ]] && cp $CWS/$DIR/$F $newdir/$DIR/$F 1994cdf0c1d5Smjnelson 1995cdf0c1d5Smjnelson if [[ -n $PWS && -e $PWS/$PDIR/$PF ]]; then 1996cdf0c1d5Smjnelson cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF 1997cdf0c1d5Smjnelson else 1998cdf0c1d5Smjnelson # Get the parent's version of the file. 1999cdf0c1d5Smjnelson svn status $CWS/$DIR/$F | read stat file 2000cdf0c1d5Smjnelson if [[ $stat != "A" ]]; then 2001cdf0c1d5Smjnelson svn cat -r BASE $CWS/$DIR/$F > $olddir/$PDIR/$PF 2002cdf0c1d5Smjnelson fi 2003cdf0c1d5Smjnelson fi 2004cdf0c1d5Smjnelson} 2005cdf0c1d5Smjnelson 2006cdf0c1d5Smjnelsonfunction build_old_new_unknown 2007cdf0c1d5Smjnelson{ 2008cdf0c1d5Smjnelson typeset olddir="$1" 2009cdf0c1d5Smjnelson typeset newdir="$2" 2010cdf0c1d5Smjnelson 2011cdf0c1d5Smjnelson # 2012cdf0c1d5Smjnelson # Snag new version of file. 2013cdf0c1d5Smjnelson # 2014cdf0c1d5Smjnelson rm -f $newdir/$DIR/$F 2015cdf0c1d5Smjnelson [[ -e $CWS/$DIR/$F ]] && cp $CWS/$DIR/$F $newdir/$DIR/$F 2016cdf0c1d5Smjnelson 2017cdf0c1d5Smjnelson # 2018cdf0c1d5Smjnelson # Snag the parent's version of the file. 2019cdf0c1d5Smjnelson # 2020cdf0c1d5Smjnelson if [[ -f $PWS/$PDIR/$PF ]]; then 2021cdf0c1d5Smjnelson rm -f $olddir/$PDIR/$PF 2022cdf0c1d5Smjnelson cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF 2023cdf0c1d5Smjnelson fi 2024cdf0c1d5Smjnelson} 2025cdf0c1d5Smjnelson 2026cdf0c1d5Smjnelsonfunction build_old_new 2027cdf0c1d5Smjnelson{ 2028cdf0c1d5Smjnelson typeset WDIR=$1 2029cdf0c1d5Smjnelson typeset PWS=$2 2030cdf0c1d5Smjnelson typeset PDIR=$3 2031cdf0c1d5Smjnelson typeset PF=$4 2032cdf0c1d5Smjnelson typeset CWS=$5 2033cdf0c1d5Smjnelson typeset DIR=$6 2034cdf0c1d5Smjnelson typeset F=$7 2035cdf0c1d5Smjnelson 2036cdf0c1d5Smjnelson typeset olddir="$WDIR/raw_files/old" 2037cdf0c1d5Smjnelson typeset newdir="$WDIR/raw_files/new" 2038cdf0c1d5Smjnelson 2039cdf0c1d5Smjnelson mkdir -p $olddir/$PDIR 2040cdf0c1d5Smjnelson mkdir -p $newdir/$DIR 2041cdf0c1d5Smjnelson 2042d7b56f41SBart Coddens if [[ $SCM_MODE == "mercurial" ]]; then 2043cdf0c1d5Smjnelson build_old_new_mercurial "$olddir" "$newdir" 20448bcea973SRichard Lowe elif [[ $SCM_MODE == "git" ]]; then 20458bcea973SRichard Lowe build_old_new_git "$olddir" "$newdir" 2046cdf0c1d5Smjnelson elif [[ $SCM_MODE == "subversion" ]]; then 2047cdf0c1d5Smjnelson build_old_new_subversion "$olddir" "$newdir" 2048cdf0c1d5Smjnelson elif [[ $SCM_MODE == "unknown" ]]; then 2049cdf0c1d5Smjnelson build_old_new_unknown "$olddir" "$newdir" 2050cdf0c1d5Smjnelson fi 2051cdf0c1d5Smjnelson 2052cdf0c1d5Smjnelson if [[ ! -f $olddir/$PDIR/$PF && ! -f $newdir/$DIR/$F ]]; then 2053cdf0c1d5Smjnelson print "*** Error: file not in parent or child" 2054cdf0c1d5Smjnelson return 1 2055cdf0c1d5Smjnelson fi 2056cdf0c1d5Smjnelson return 0 2057cdf0c1d5Smjnelson} 2058cdf0c1d5Smjnelson 2059cdf0c1d5Smjnelson 2060daaffb31Sdp# 2061daaffb31Sdp# Usage message. 2062daaffb31Sdp# 2063daaffb31Sdpfunction usage 2064daaffb31Sdp{ 2065daaffb31Sdp print 'Usage:\twebrev [common-options] 2066daaffb31Sdp webrev [common-options] ( <file> | - ) 2067daaffb31Sdp webrev [common-options] -w <wx file> 2068daaffb31Sdp 2069daaffb31SdpOptions: 20700fd2682eSMark J. Nelson -C <filename>: Use <filename> for the information tracking configuration. 2071ba44d8a2SVladimir Kotal -D: delete remote webrev 2072daaffb31Sdp -i <filename>: Include <filename> in the index.html file. 20730fd2682eSMark J. Nelson -I <filename>: Use <filename> for the information tracking registry. 2074ba44d8a2SVladimir Kotal -n: do not generate the webrev (useful with -U) 2075ba44d8a2SVladimir Kotal -O: Print bugids/arc cases suitable for OpenSolaris. 2076daaffb31Sdp -o <outdir>: Output webrev to specified directory. 2077daaffb31Sdp -p <compare-against>: Use specified parent wkspc or basis for comparison 207802d26c39SVladimir Kotal -t <remote_target>: Specify remote destination for webrev upload 207902d26c39SVladimir Kotal -U: upload the webrev to remote destination 2080daaffb31Sdp -w <wxfile>: Use specified wx active file. 2081daaffb31Sdp 2082daaffb31SdpEnvironment: 2083daaffb31Sdp WDIR: Control the output directory. 2084ba44d8a2SVladimir Kotal WEBREV_TRASH_DIR: Set directory for webrev delete. 2085daaffb31Sdp 2086daaffb31SdpSCM Environment: 2087cdf0c1d5Smjnelson CODEMGR_WS: Workspace location. 2088cdf0c1d5Smjnelson CODEMGR_PARENT: Parent workspace location. 2089daaffb31Sdp' 2090daaffb31Sdp 2091daaffb31Sdp exit 2 2092daaffb31Sdp} 2093daaffb31Sdp 2094daaffb31Sdp# 2095daaffb31Sdp# 2096daaffb31Sdp# Main program starts here 2097daaffb31Sdp# 2098daaffb31Sdp# 2099daaffb31Sdp 2100daaffb31Sdptrap "rm -f /tmp/$$.* ; exit" 0 1 2 3 15 2101daaffb31Sdp 2102daaffb31Sdpset +o noclobber 2103daaffb31Sdp 21048bcea973SRichard LowePATH=$(/bin/dirname "$(whence $0)"):$PATH 2105cdf0c1d5Smjnelson 210614983201Sdp[[ -z $WDIFF ]] && WDIFF=`look_for_prog wdiff` 210714983201Sdp[[ -z $WX ]] && WX=`look_for_prog wx` 2108cdf0c1d5Smjnelson[[ -z $HG_ACTIVE ]] && HG_ACTIVE=`look_for_prog hg-active` 21098bcea973SRichard Lowe[[ -z $GIT ]] && GIT=`look_for_prog git` 2110cdf0c1d5Smjnelson[[ -z $WHICH_SCM ]] && WHICH_SCM=`look_for_prog which_scm` 211114983201Sdp[[ -z $CODEREVIEW ]] && CODEREVIEW=`look_for_prog codereview` 211214983201Sdp[[ -z $PS2PDF ]] && PS2PDF=`look_for_prog ps2pdf` 211314983201Sdp[[ -z $PERL ]] && PERL=`look_for_prog perl` 211402d26c39SVladimir Kotal[[ -z $RSYNC ]] && RSYNC=`look_for_prog rsync` 2115cdf0c1d5Smjnelson[[ -z $SCCS ]] && SCCS=`look_for_prog sccs` 2116cdf0c1d5Smjnelson[[ -z $AWK ]] && AWK=`look_for_prog nawk` 2117cdf0c1d5Smjnelson[[ -z $AWK ]] && AWK=`look_for_prog gawk` 2118cdf0c1d5Smjnelson[[ -z $AWK ]] && AWK=`look_for_prog awk` 211902d26c39SVladimir Kotal[[ -z $SCP ]] && SCP=`look_for_prog scp` 2120b0088928SVladimir Kotal[[ -z $SED ]] && SED=`look_for_prog sed` 212102d26c39SVladimir Kotal[[ -z $SFTP ]] && SFTP=`look_for_prog sftp` 2122e6ccc173SEdward Pilatowicz[[ -z $SORT ]] && SORT=`look_for_prog sort` 212302d26c39SVladimir Kotal[[ -z $MKTEMP ]] && MKTEMP=`look_for_prog mktemp` 212402d26c39SVladimir Kotal[[ -z $GREP ]] && GREP=`look_for_prog grep` 2125ba44d8a2SVladimir Kotal[[ -z $FIND ]] && FIND=`look_for_prog find` 2126cdf0c1d5Smjnelson 2127ba44d8a2SVladimir Kotal# set name of trash directory for remote webrev deletion 2128ba44d8a2SVladimir KotalTRASH_DIR=".trash" 2129ba44d8a2SVladimir Kotal[[ -n $WEBREV_TRASH_DIR ]] && TRASH_DIR=$WEBREV_TRASH_DIR 213014983201Sdp 213114983201Sdpif [[ ! -x $PERL ]]; then 213214983201Sdp print -u2 "Error: No perl interpreter found. Exiting." 213314983201Sdp exit 1 2134daaffb31Sdpfi 213514983201Sdp 2136cdf0c1d5Smjnelsonif [[ ! -x $WHICH_SCM ]]; then 2137cdf0c1d5Smjnelson print -u2 "Error: Could not find which_scm. Exiting." 2138cdf0c1d5Smjnelson exit 1 2139cdf0c1d5Smjnelsonfi 2140cdf0c1d5Smjnelson 214114983201Sdp# 214214983201Sdp# These aren't fatal, but we want to note them to the user. 214314983201Sdp# We don't warn on the absence of 'wx' until later when we've 214414983201Sdp# determined that we actually need to try to invoke it. 214514983201Sdp# 214614983201Sdp[[ ! -x $CODEREVIEW ]] && print -u2 "WARNING: codereview(1) not found." 214714983201Sdp[[ ! -x $PS2PDF ]] && print -u2 "WARNING: ps2pdf(1) not found." 214814983201Sdp[[ ! -x $WDIFF ]] && print -u2 "WARNING: wdiff not found." 2149daaffb31Sdp 2150daaffb31Sdp# Declare global total counters. 2151daaffb31Sdpinteger TOTL TINS TDEL TMOD TUNC 2152daaffb31Sdp 2153ba44d8a2SVladimir Kotal# default remote host for upload/delete 2154ba44d8a2SVladimir Kotaltypeset -r DEFAULT_REMOTE_HOST="cr.opensolaris.org" 2155b0088928SVladimir Kotal# prefixes for upload targets 2156b0088928SVladimir Kotaltypeset -r rsync_prefix="rsync://" 2157b0088928SVladimir Kotaltypeset -r ssh_prefix="ssh://" 2158ba44d8a2SVladimir Kotal 21590fd2682eSMark J. NelsonCflag= 2160ba44d8a2SVladimir KotalDflag= 216114983201Sdpflist_mode= 216214983201Sdpflist_file= 2163daaffb31Sdpiflag= 21640fd2682eSMark J. NelsonIflag= 216502d26c39SVladimir Kotallflag= 216602d26c39SVladimir KotalNflag= 216702d26c39SVladimir Kotalnflag= 216802d26c39SVladimir KotalOflag= 2169daaffb31Sdpoflag= 2170daaffb31Sdppflag= 217102d26c39SVladimir Kotaltflag= 217202d26c39SVladimir Kotaluflag= 217302d26c39SVladimir KotalUflag= 2174daaffb31Sdpwflag= 217502d26c39SVladimir Kotalremote_target= 2176ba44d8a2SVladimir Kotal 2177ba44d8a2SVladimir Kotal# 2178ba44d8a2SVladimir Kotal# NOTE: when adding/removing options it is necessary to sync the list 2179ba44d8a2SVladimir Kotal# with usr/src/tools/onbld/hgext/cdm.py 2180ba44d8a2SVladimir Kotal# 218125cc4e45SVladimir Kotalwhile getopts "C:Di:I:lnNo:Op:t:Uw" opt 2182daaffb31Sdpdo 2183daaffb31Sdp case $opt in 21840fd2682eSMark J. Nelson C) Cflag=1 21850fd2682eSMark J. Nelson ITSCONF=$OPTARG;; 21860fd2682eSMark J. Nelson 2187ba44d8a2SVladimir Kotal D) Dflag=1;; 2188ba44d8a2SVladimir Kotal 2189daaffb31Sdp i) iflag=1 2190daaffb31Sdp INCLUDE_FILE=$OPTARG;; 2191daaffb31Sdp 21920fd2682eSMark J. Nelson I) Iflag=1 21930fd2682eSMark J. Nelson ITSREG=$OPTARG;; 21940fd2682eSMark J. Nelson 219502d26c39SVladimir Kotal N) Nflag=1;; 219602d26c39SVladimir Kotal 219702d26c39SVladimir Kotal n) nflag=1;; 2198daaffb31Sdp 2199daaffb31Sdp O) Oflag=1;; 2200daaffb31Sdp 220102d26c39SVladimir Kotal o) oflag=1 22029d3952abSVladimir Kotal # Strip the trailing slash to correctly form remote target. 22039d3952abSVladimir Kotal WDIR=${OPTARG%/};; 220402d26c39SVladimir Kotal 220502d26c39SVladimir Kotal p) pflag=1 220602d26c39SVladimir Kotal codemgr_parent=$OPTARG;; 220702d26c39SVladimir Kotal 220802d26c39SVladimir Kotal t) tflag=1 220902d26c39SVladimir Kotal remote_target=$OPTARG;; 221002d26c39SVladimir Kotal 221102d26c39SVladimir Kotal U) Uflag=1;; 221202d26c39SVladimir Kotal 221302d26c39SVladimir Kotal w) wflag=1;; 22143df69ef3SDarren Moffat 2215daaffb31Sdp ?) usage;; 2216daaffb31Sdp esac 2217daaffb31Sdpdone 2218daaffb31Sdp 2219daaffb31SdpFLIST=/tmp/$$.flist 2220daaffb31Sdp 2221daaffb31Sdpif [[ -n $wflag && -n $lflag ]]; then 2222daaffb31Sdp usage 2223daaffb31Sdpfi 2224daaffb31Sdp 222502d26c39SVladimir Kotal# more sanity checking 222602d26c39SVladimir Kotalif [[ -n $nflag && -z $Uflag ]]; then 2227ba44d8a2SVladimir Kotal print "it does not make sense to skip webrev generation" \ 2228ba44d8a2SVladimir Kotal "without -U" 222902d26c39SVladimir Kotal exit 1 223002d26c39SVladimir Kotalfi 223102d26c39SVladimir Kotal 2232ba44d8a2SVladimir Kotalif [[ -n $tflag && -z $Uflag && -z $Dflag ]]; then 2233ba44d8a2SVladimir Kotal echo "remote target has to be used only for upload or delete" 223402d26c39SVladimir Kotal exit 1 223502d26c39SVladimir Kotalfi 223602d26c39SVladimir Kotal 2237daaffb31Sdp# 22382d9224a3SMark J. Nelson# For the invocation "webrev -n -U" with no other options, webrev will assume 22392d9224a3SMark J. Nelson# that the webrev exists in ${CWS}/webrev, but will upload it using the name 22402d9224a3SMark J. Nelson# $(basename ${CWS}). So we need to get CWS set before we skip any remaining 22412d9224a3SMark J. Nelson# logic. 22422d9224a3SMark J. Nelson# 22432d9224a3SMark J. Nelson$WHICH_SCM | read SCM_MODE junk || exit 1 2244d7b56f41SBart Coddensif [[ $SCM_MODE == "mercurial" ]]; then 22452d9224a3SMark J. Nelson # 22462d9224a3SMark J. Nelson # Mercurial priorities: 22472d9224a3SMark J. Nelson # 1. hg root from CODEMGR_WS environment variable 224878add226Sjmcp # 1a. hg root from CODEMGR_WS/usr/closed if we're somewhere under 224978add226Sjmcp # usr/closed when we run webrev 22502d9224a3SMark J. Nelson # 2. hg root from directory of invocation 22512d9224a3SMark J. Nelson # 225278add226Sjmcp if [[ ${PWD} =~ "usr/closed" ]]; then 225378add226Sjmcp testparent=${CODEMGR_WS}/usr/closed 225478add226Sjmcp # If we're in OpenSolaris mode, we enforce a minor policy: 225578add226Sjmcp # help to make sure the reviewer doesn't accidentally publish 225678add226Sjmcp # source which is under usr/closed 225778add226Sjmcp if [[ -n "$Oflag" ]]; then 225878add226Sjmcp print -u2 "OpenSolaris output not permitted with" \ 225978add226Sjmcp "usr/closed changes" 226078add226Sjmcp exit 1 226178add226Sjmcp fi 226278add226Sjmcp else 226378add226Sjmcp testparent=${CODEMGR_WS} 226478add226Sjmcp fi 226578add226Sjmcp [[ -z $codemgr_ws && -n $testparent ]] && \ 226678add226Sjmcp codemgr_ws=$(hg root -R $testparent 2>/dev/null) 22672d9224a3SMark J. Nelson [[ -z $codemgr_ws ]] && codemgr_ws=$(hg root 2>/dev/null) 22682d9224a3SMark J. Nelson CWS=$codemgr_ws 22698bcea973SRichard Loweelif [[ $SCM_MODE == "git" ]]; then 22708bcea973SRichard Lowe # 22718bcea973SRichard Lowe # Git priorities: 22728bcea973SRichard Lowe # 1. git rev-parse --git-dir from CODEMGR_WS environment variable 22738bcea973SRichard Lowe # 2. git rev-parse --git-dir from directory of invocation 22748bcea973SRichard Lowe # 22758bcea973SRichard Lowe [[ -z $codemgr_ws && -n $CODEMGR_WS ]] && \ 22768bcea973SRichard Lowe codemgr_ws=$($GIT --git-dir=$CODEMGR_WS/.git rev-parse --git-dir \ 22778bcea973SRichard Lowe 2>/dev/null) 22788bcea973SRichard Lowe [[ -z $codemgr_ws ]] && \ 22798bcea973SRichard Lowe codemgr_ws=$($GIT rev-parse --git-dir 2>/dev/null) 22808bcea973SRichard Lowe 22818bcea973SRichard Lowe if [[ "$codemgr_ws" == ".git" ]]; then 22828bcea973SRichard Lowe codemgr_ws="${PWD}/${codemgr_ws}" 22838bcea973SRichard Lowe fi 22848bcea973SRichard Lowe 22858bcea973SRichard Lowe codemgr_ws=$(dirname $codemgr_ws) # Lose the '/.git' 22868bcea973SRichard Lowe CWS="$codemgr_ws" 22872d9224a3SMark J. Nelsonelif [[ $SCM_MODE == "subversion" ]]; then 22882d9224a3SMark J. Nelson # 22892d9224a3SMark J. Nelson # Subversion priorities: 22902d9224a3SMark J. Nelson # 1. CODEMGR_WS from environment 22912d9224a3SMark J. Nelson # 2. Relative path from current directory to SVN repository root 22922d9224a3SMark J. Nelson # 22932d9224a3SMark J. Nelson if [[ -n $CODEMGR_WS && -d $CODEMGR_WS/.svn ]]; then 22942d9224a3SMark J. Nelson CWS=$CODEMGR_WS 22952d9224a3SMark J. Nelson else 22962d9224a3SMark J. Nelson svn info | while read line; do 22972d9224a3SMark J. Nelson if [[ $line == "URL: "* ]]; then 22982d9224a3SMark J. Nelson url=${line#URL: } 22992d9224a3SMark J. Nelson elif [[ $line == "Repository Root: "* ]]; then 23002d9224a3SMark J. Nelson repo=${line#Repository Root: } 23012d9224a3SMark J. Nelson fi 23022d9224a3SMark J. Nelson done 23032d9224a3SMark J. Nelson 23042d9224a3SMark J. Nelson rel=${url#$repo} 23052d9224a3SMark J. Nelson CWS=${PWD%$rel} 23062d9224a3SMark J. Nelson fi 23072d9224a3SMark J. Nelsonfi 23082d9224a3SMark J. Nelson 23092d9224a3SMark J. Nelson# 23102d9224a3SMark J. Nelson# If no SCM has been determined, take either the environment setting 23112d9224a3SMark J. Nelson# setting for CODEMGR_WS, or the current directory if that wasn't set. 23122d9224a3SMark J. Nelson# 23132d9224a3SMark J. Nelsonif [[ -z ${CWS} ]]; then 23142d9224a3SMark J. Nelson CWS=${CODEMGR_WS:-.} 23152d9224a3SMark J. Nelsonfi 23162d9224a3SMark J. Nelson 23172d9224a3SMark J. Nelson# 23180fd2682eSMark J. Nelson# If the command line options indicate no webrev generation, either 23190fd2682eSMark J. Nelson# explicitly (-n) or implicitly (-D but not -U), then there's a whole 23200fd2682eSMark J. Nelson# ton of logic we can skip. 23210fd2682eSMark J. Nelson# 23220fd2682eSMark J. Nelson# Instead of increasing indentation, we intentionally leave this loop 23230fd2682eSMark J. Nelson# body open here, and exit via break from multiple points within. 23240fd2682eSMark J. Nelson# Search for DO_EVERYTHING below to find the break points and closure. 23250fd2682eSMark J. Nelson# 23260fd2682eSMark J. Nelsonfor do_everything in 1; do 23270fd2682eSMark J. Nelson 23280fd2682eSMark J. Nelson# DO_EVERYTHING: break point 23290fd2682eSMark J. Nelsonif [[ -n $nflag || ( -z $Uflag && -n $Dflag ) ]]; then 23300fd2682eSMark J. Nelson break 23310fd2682eSMark J. Nelsonfi 23320fd2682eSMark J. Nelson 23330fd2682eSMark J. Nelson# 2334daaffb31Sdp# If this manually set as the parent, and it appears to be an earlier webrev, 2335daaffb31Sdp# then note that fact and set the parent to the raw_files/new subdirectory. 2336daaffb31Sdp# 2337daaffb31Sdpif [[ -n $pflag && -d $codemgr_parent/raw_files/new ]]; then 23388bcea973SRichard Lowe parent_webrev=$(readlink -f "$codemgr_parent") 23398bcea973SRichard Lowe codemgr_parent=$(readlink -f "$codemgr_parent/raw_files/new") 2340daaffb31Sdpfi 2341daaffb31Sdp 2342daaffb31Sdpif [[ -z $wflag && -z $lflag ]]; then 2343daaffb31Sdp shift $(($OPTIND - 1)) 2344daaffb31Sdp 2345daaffb31Sdp if [[ $1 == "-" ]]; then 2346daaffb31Sdp cat > $FLIST 234714983201Sdp flist_mode="stdin" 234814983201Sdp flist_done=1 234914983201Sdp shift 2350daaffb31Sdp elif [[ -n $1 ]]; then 235114983201Sdp if [[ ! -r $1 ]]; then 2352daaffb31Sdp print -u2 "$1: no such file or not readable" 2353daaffb31Sdp usage 2354daaffb31Sdp fi 2355daaffb31Sdp cat $1 > $FLIST 235614983201Sdp flist_mode="file" 235714983201Sdp flist_file=$1 235814983201Sdp flist_done=1 235914983201Sdp shift 2360daaffb31Sdp else 236114983201Sdp flist_mode="auto" 2362daaffb31Sdp fi 2363daaffb31Sdpfi 2364daaffb31Sdp 2365daaffb31Sdp# 2366daaffb31Sdp# Before we go on to further consider -l and -w, work out which SCM we think 2367daaffb31Sdp# is in use. 2368daaffb31Sdp# 2369cdf0c1d5Smjnelsoncase "$SCM_MODE" in 2370d7b56f41SBart Coddensmercurial|git|subversion) 2371cdf0c1d5Smjnelson ;; 2372cdf0c1d5Smjnelsonunknown) 2373cdf0c1d5Smjnelson if [[ $flist_mode == "auto" ]]; then 2374cdf0c1d5Smjnelson print -u2 "Unable to determine SCM in use and file list not specified" 2375cdf0c1d5Smjnelson print -u2 "See which_scm(1) for SCM detection information." 23767c478bd9Sstevel@tonic-gate exit 1 23777c478bd9Sstevel@tonic-gate fi 2378cdf0c1d5Smjnelson ;; 2379cdf0c1d5Smjnelson*) 2380cdf0c1d5Smjnelson if [[ $flist_mode == "auto" ]]; then 2381cdf0c1d5Smjnelson print -u2 "Unsupported SCM in use ($SCM_MODE) and file list not specified" 2382cdf0c1d5Smjnelson exit 1 2383cdf0c1d5Smjnelson fi 2384cdf0c1d5Smjnelson ;; 2385cdf0c1d5Smjnelsonesac 23867c478bd9Sstevel@tonic-gate 2387daaffb31Sdpprint -u2 " SCM detected: $SCM_MODE" 2388daaffb31Sdp 2389d7b56f41SBart Coddensif [[ -n $wflag ]]; then 2390daaffb31Sdp # 2391daaffb31Sdp # If the -w is given then assume the file list is in Bonwick's "wx" 2392daaffb31Sdp # command format, i.e. pathname lines alternating with SCCS comment 2393daaffb31Sdp # lines with blank lines as separators. Use the SCCS comments later 2394daaffb31Sdp # in building the index.html file. 2395daaffb31Sdp # 2396daaffb31Sdp shift $(($OPTIND - 1)) 2397daaffb31Sdp wxfile=$1 2398daaffb31Sdp if [[ -z $wxfile && -n $CODEMGR_WS ]]; then 2399daaffb31Sdp if [[ -r $CODEMGR_WS/wx/active ]]; then 2400daaffb31Sdp wxfile=$CODEMGR_WS/wx/active 2401daaffb31Sdp fi 2402daaffb31Sdp fi 2403daaffb31Sdp 2404daaffb31Sdp [[ -z $wxfile ]] && print -u2 "wx file not specified, and could not " \ 2405daaffb31Sdp "be auto-detected (check \$CODEMGR_WS)" && exit 1 2406daaffb31Sdp 2407cdf0c1d5Smjnelson if [[ ! -r $wxfile ]]; then 2408cdf0c1d5Smjnelson print -u2 "$wxfile: no such file or not readable" 2409cdf0c1d5Smjnelson usage 2410cdf0c1d5Smjnelson fi 2411cdf0c1d5Smjnelson 2412daaffb31Sdp print -u2 " File list from: wx 'active' file '$wxfile' ... \c" 2413daaffb31Sdp flist_from_wx $wxfile 2414daaffb31Sdp flist_done=1 2415daaffb31Sdp if [[ -n "$*" ]]; then 2416daaffb31Sdp shift 2417daaffb31Sdp fi 241814983201Sdpelif [[ $flist_mode == "stdin" ]]; then 241914983201Sdp print -u2 " File list from: standard input" 242014983201Sdpelif [[ $flist_mode == "file" ]]; then 242114983201Sdp print -u2 " File list from: $flist_file" 2422daaffb31Sdpfi 2423daaffb31Sdp 2424daaffb31Sdpif [[ $# -gt 0 ]]; then 242514983201Sdp print -u2 "WARNING: unused arguments: $*" 2426daaffb31Sdpfi 2427daaffb31Sdp 24282d9224a3SMark J. Nelson# 24292d9224a3SMark J. Nelson# Before we entered the DO_EVERYTHING loop, we should have already set CWS 24302d9224a3SMark J. Nelson# and CODEMGR_WS as needed. Here, we set the parent workspace. 24312d9224a3SMark J. Nelson# 2432d7b56f41SBart Coddensif [[ $SCM_MODE == "mercurial" ]]; then 2433cdf0c1d5Smjnelson # 2434cdf0c1d5Smjnelson # Parent can either be specified with -p 2435cdf0c1d5Smjnelson # Specified with CODEMGR_PARENT in the environment 2436cdf0c1d5Smjnelson # or taken from hg's default path. 2437cdf0c1d5Smjnelson # 2438cdf0c1d5Smjnelson 2439cdf0c1d5Smjnelson if [[ -z $codemgr_parent && -n $CODEMGR_PARENT ]]; then 2440cdf0c1d5Smjnelson codemgr_parent=$CODEMGR_PARENT 2441cdf0c1d5Smjnelson fi 2442cdf0c1d5Smjnelson 2443cdf0c1d5Smjnelson if [[ -z $codemgr_parent ]]; then 2444cdf0c1d5Smjnelson codemgr_parent=`hg path -R $codemgr_ws default 2>/dev/null` 2445cdf0c1d5Smjnelson fi 2446cdf0c1d5Smjnelson 2447cdf0c1d5Smjnelson PWS=$codemgr_parent 2448cdf0c1d5Smjnelson 2449cdf0c1d5Smjnelson # 2450cdf0c1d5Smjnelson # If the parent is a webrev, we want to do some things against 2451cdf0c1d5Smjnelson # the natural workspace parent (file list, comments, etc) 2452cdf0c1d5Smjnelson # 2453cdf0c1d5Smjnelson if [[ -n $parent_webrev ]]; then 2454cdf0c1d5Smjnelson real_parent=$(hg path -R $codemgr_ws default 2>/dev/null) 2455cdf0c1d5Smjnelson else 2456cdf0c1d5Smjnelson real_parent=$PWS 2457cdf0c1d5Smjnelson fi 2458cdf0c1d5Smjnelson 2459cdf0c1d5Smjnelson # 2460cdf0c1d5Smjnelson # If hg-active exists, then we run it. In the case of no explicit 2461cdf0c1d5Smjnelson # flist given, we'll use it for our comments. In the case of an 2462cdf0c1d5Smjnelson # explicit flist given we'll try to use it for comments for any 2463cdf0c1d5Smjnelson # files mentioned in the flist. 2464cdf0c1d5Smjnelson # 2465cdf0c1d5Smjnelson if [[ -z $flist_done ]]; then 2466cdf0c1d5Smjnelson flist_from_mercurial $CWS $real_parent 2467cdf0c1d5Smjnelson flist_done=1 2468cdf0c1d5Smjnelson fi 2469cdf0c1d5Smjnelson 2470cdf0c1d5Smjnelson # 2471cdf0c1d5Smjnelson # If we have a file list now, pull out any variables set 2472cdf0c1d5Smjnelson # therein. We do this now (rather than when we possibly use 2473cdf0c1d5Smjnelson # hg-active to find comments) to avoid stomping specifications 2474cdf0c1d5Smjnelson # in the user-specified flist. 2475cdf0c1d5Smjnelson # 2476cdf0c1d5Smjnelson if [[ -n $flist_done ]]; then 2477cdf0c1d5Smjnelson env_from_flist 2478cdf0c1d5Smjnelson fi 2479cdf0c1d5Smjnelson 2480cdf0c1d5Smjnelson # 2481cdf0c1d5Smjnelson # Only call hg-active if we don't have a wx formatted file already 2482cdf0c1d5Smjnelson # 2483cdf0c1d5Smjnelson if [[ -x $HG_ACTIVE && -z $wxfile ]]; then 2484cdf0c1d5Smjnelson print " Comments from: hg-active -p $real_parent ...\c" 2485cdf0c1d5Smjnelson hg_active_wxfile $CWS $real_parent 2486cdf0c1d5Smjnelson print " Done." 2487cdf0c1d5Smjnelson fi 2488cdf0c1d5Smjnelson 2489cdf0c1d5Smjnelson # 2490cdf0c1d5Smjnelson # At this point we must have a wx flist either from hg-active, 2491cdf0c1d5Smjnelson # or in general. Use it to try and find our parent revision, 2492cdf0c1d5Smjnelson # if we don't have one. 2493cdf0c1d5Smjnelson # 2494cdf0c1d5Smjnelson if [[ -z $HG_PARENT ]]; then 2495b0088928SVladimir Kotal eval `$SED -e "s/#.*$//" $wxfile | $GREP HG_PARENT=` 2496cdf0c1d5Smjnelson fi 2497cdf0c1d5Smjnelson 2498cdf0c1d5Smjnelson # 2499cdf0c1d5Smjnelson # If we still don't have a parent, we must have been given a 2500cdf0c1d5Smjnelson # wx-style active list with no HG_PARENT specification, run 2501cdf0c1d5Smjnelson # hg-active and pull an HG_PARENT out of it, ignore the rest. 2502cdf0c1d5Smjnelson # 2503cdf0c1d5Smjnelson if [[ -z $HG_PARENT && -x $HG_ACTIVE ]]; then 2504cdf0c1d5Smjnelson $HG_ACTIVE -w $codemgr_ws -p $real_parent | \ 2505b0088928SVladimir Kotal eval `$SED -e "s/#.*$//" | $GREP HG_PARENT=` 2506cdf0c1d5Smjnelson elif [[ -z $HG_PARENT ]]; then 2507cdf0c1d5Smjnelson print -u2 "Error: Cannot discover parent revision" 2508cdf0c1d5Smjnelson exit 1 2509cdf0c1d5Smjnelson fi 25108bcea973SRichard Lowe 25118bcea973SRichard Lowe pnode=$(trim_digest $HG_PARENT) 25128bcea973SRichard Lowe PRETTY_PWS="${PWS} (at ${pnode})" 25138bcea973SRichard Lowe cnode=$(hg parent -R $codemgr_ws --template '{node|short}' \ 25148bcea973SRichard Lowe 2>/dev/null) 25158bcea973SRichard Lowe PRETTY_CWS="${CWS} (at ${cnode})"} 25168bcea973SRichard Loweelif [[ $SCM_MODE == "git" ]]; then 25178bcea973SRichard Lowe # 25188bcea973SRichard Lowe # Parent can either be specified with -p, or specified with 25198bcea973SRichard Lowe # CODEMGR_PARENT in the environment. 25208bcea973SRichard Lowe # 25218bcea973SRichard Lowe 25228bcea973SRichard Lowe if [[ -z $codemgr_parent && -n $CODEMGR_PARENT ]]; then 25238bcea973SRichard Lowe codemgr_parent=$CODEMGR_PARENT 25248bcea973SRichard Lowe fi 25258bcea973SRichard Lowe 25268bcea973SRichard Lowe # Try to figure out the parent based on the branch the current 25278bcea973SRichard Lowe # branch is tracking, if we fail, use origin/master 25288bcea973SRichard Lowe this_branch=$($GIT branch | nawk '$1 == "*" { print $2 }') 25298bcea973SRichard Lowe par_branch="origin/master" 25308bcea973SRichard Lowe 25318bcea973SRichard Lowe # If we're not on a branch there's nothing we can do 25328bcea973SRichard Lowe if [[ $this_branch != "(no branch)" ]]; then 25338bcea973SRichard Lowe $GIT for-each-ref \ 25348bcea973SRichard Lowe --format='%(refname:short) %(upstream:short)' refs/heads/ | \ 25358bcea973SRichard Lowe while read local remote; do \ 25368bcea973SRichard Lowe [[ "$local" == "$this_branch" ]] && par_branch="$remote"; \ 25378bcea973SRichard Lowe done 25388bcea973SRichard Lowe fi 25398bcea973SRichard Lowe 25408bcea973SRichard Lowe if [[ -z $codemgr_parent ]]; then 25418bcea973SRichard Lowe codemgr_parent=$par_branch 25428bcea973SRichard Lowe fi 25438bcea973SRichard Lowe PWS=$codemgr_parent 25448bcea973SRichard Lowe 25458bcea973SRichard Lowe # 25468bcea973SRichard Lowe # If the parent is a webrev, we want to do some things against 25478bcea973SRichard Lowe # the natural workspace parent (file list, comments, etc) 25488bcea973SRichard Lowe # 25498bcea973SRichard Lowe if [[ -n $parent_webrev ]]; then 25508bcea973SRichard Lowe real_parent=$par_branch 25518bcea973SRichard Lowe else 25528bcea973SRichard Lowe real_parent=$PWS 25538bcea973SRichard Lowe fi 25548bcea973SRichard Lowe 25558bcea973SRichard Lowe if [[ -z $flist_done ]]; then 25568bcea973SRichard Lowe flist_from_git "$CWS" "$real_parent" 25578bcea973SRichard Lowe flist_done=1 25588bcea973SRichard Lowe fi 25598bcea973SRichard Lowe 25608bcea973SRichard Lowe # 25618bcea973SRichard Lowe # If we have a file list now, pull out any variables set 25628bcea973SRichard Lowe # therein. 25638bcea973SRichard Lowe # 25648bcea973SRichard Lowe if [[ -n $flist_done ]]; then 25658bcea973SRichard Lowe env_from_flist 25668bcea973SRichard Lowe fi 25678bcea973SRichard Lowe 25688bcea973SRichard Lowe # 25698bcea973SRichard Lowe # If we don't have a wx-format file list, build one we can pull change 25708bcea973SRichard Lowe # comments from. 25718bcea973SRichard Lowe # 25728bcea973SRichard Lowe if [[ -z $wxfile ]]; then 25738bcea973SRichard Lowe print " Comments from: git...\c" 25748bcea973SRichard Lowe git_wxfile "$CWS" "$real_parent" 25758bcea973SRichard Lowe print " Done." 25768bcea973SRichard Lowe fi 25778bcea973SRichard Lowe 25788bcea973SRichard Lowe if [[ -z $GIT_PARENT ]]; then 25798bcea973SRichard Lowe GIT_PARENT=$($GIT merge-base "$real_parent" HEAD) 25808bcea973SRichard Lowe fi 25818bcea973SRichard Lowe if [[ -z $GIT_PARENT ]]; then 25828bcea973SRichard Lowe print -u2 "Error: Cannot discover parent revision" 25838bcea973SRichard Lowe exit 1 25848bcea973SRichard Lowe fi 25858bcea973SRichard Lowe 25868bcea973SRichard Lowe pnode=$(trim_digest $GIT_PARENT) 25878bcea973SRichard Lowe 25888bcea973SRichard Lowe if [[ $real_parent == */* ]]; then 25898bcea973SRichard Lowe origin=$(echo $real_parent | cut -d/ -f1) 25908bcea973SRichard Lowe origin=$($GIT remote -v | \ 25918bcea973SRichard Lowe $AWK '$1 == "'$origin'" { print $2; exit }') 25928bcea973SRichard Lowe PRETTY_PWS="${PWS} (${origin} at ${pnode})" 25938bcea973SRichard Lowe else 25948bcea973SRichard Lowe PRETTY_PWS="${PWS} (at ${pnode})" 25958bcea973SRichard Lowe fi 25968bcea973SRichard Lowe 25978bcea973SRichard Lowe cnode=$($GIT --git-dir=${codemgr_ws}/.git rev-parse --short=12 HEAD \ 25988bcea973SRichard Lowe 2>/dev/null) 25998bcea973SRichard Lowe PRETTY_CWS="${CWS} (at ${cnode})" 2600cdf0c1d5Smjnelsonelif [[ $SCM_MODE == "subversion" ]]; then 2601cdf0c1d5Smjnelson 2602cdf0c1d5Smjnelson # 2603cdf0c1d5Smjnelson # We only will have a real parent workspace in the case one 2604cdf0c1d5Smjnelson # was specified (be it an older webrev, or another checkout). 2605cdf0c1d5Smjnelson # 2606cdf0c1d5Smjnelson [[ -n $codemgr_parent ]] && PWS=$codemgr_parent 2607cdf0c1d5Smjnelson 2608cdf0c1d5Smjnelson if [[ -z $flist_done && $flist_mode == "auto" ]]; then 2609cdf0c1d5Smjnelson flist_from_subversion $CWS $OLDPWD 2610cdf0c1d5Smjnelson fi 2611cdf0c1d5Smjnelsonelse 2612cdf0c1d5Smjnelson if [[ $SCM_MODE == "unknown" ]]; then 2613cdf0c1d5Smjnelson print -u2 " Unknown type of SCM in use" 2614cdf0c1d5Smjnelson else 2615cdf0c1d5Smjnelson print -u2 " Unsupported SCM in use: $SCM_MODE" 2616cdf0c1d5Smjnelson fi 2617cdf0c1d5Smjnelson 2618cdf0c1d5Smjnelson env_from_flist 2619cdf0c1d5Smjnelson 2620cdf0c1d5Smjnelson if [[ -z $CODEMGR_WS ]]; then 2621cdf0c1d5Smjnelson print -u2 "SCM not detected/supported and CODEMGR_WS not specified" 2622cdf0c1d5Smjnelson exit 1 2623cdf0c1d5Smjnelson fi 2624cdf0c1d5Smjnelson 2625cdf0c1d5Smjnelson if [[ -z $CODEMGR_PARENT ]]; then 2626cdf0c1d5Smjnelson print -u2 "SCM not detected/supported and CODEMGR_PARENT not specified" 2627cdf0c1d5Smjnelson exit 1 2628cdf0c1d5Smjnelson fi 2629cdf0c1d5Smjnelson 2630cdf0c1d5Smjnelson CWS=$CODEMGR_WS 2631cdf0c1d5Smjnelson PWS=$CODEMGR_PARENT 2632daaffb31Sdpfi 2633daaffb31Sdp 2634daaffb31Sdp# 2635daaffb31Sdp# If the user didn't specify a -i option, check to see if there is a 2636daaffb31Sdp# webrev-info file in the workspace directory. 2637daaffb31Sdp# 2638daaffb31Sdpif [[ -z $iflag && -r "$CWS/webrev-info" ]]; then 2639daaffb31Sdp iflag=1 2640daaffb31Sdp INCLUDE_FILE="$CWS/webrev-info" 2641daaffb31Sdpfi 2642daaffb31Sdp 2643daaffb31Sdpif [[ -n $iflag ]]; then 2644daaffb31Sdp if [[ ! -r $INCLUDE_FILE ]]; then 2645daaffb31Sdp print -u2 "include file '$INCLUDE_FILE' does not exist or is" \ 2646daaffb31Sdp "not readable." 2647daaffb31Sdp exit 1 2648daaffb31Sdp else 2649daaffb31Sdp # 2650daaffb31Sdp # $INCLUDE_FILE may be a relative path, and the script alters 2651daaffb31Sdp # PWD, so we just stash a copy in /tmp. 2652daaffb31Sdp # 2653daaffb31Sdp cp $INCLUDE_FILE /tmp/$$.include 2654daaffb31Sdp fi 2655daaffb31Sdpfi 2656daaffb31Sdp 26570fd2682eSMark J. Nelson# DO_EVERYTHING: break point 26580fd2682eSMark J. Nelsonif [[ -n $Nflag ]]; then 26590fd2682eSMark J. Nelson break 26600fd2682eSMark J. Nelsonfi 26610fd2682eSMark J. Nelson 26620fd2682eSMark J. Nelsontypeset -A itsinfo 26630fd2682eSMark J. Nelsontypeset -r its_sed_script=/tmp/$$.its_sed 26640fd2682eSMark J. Nelsonvalid_prefixes= 26650fd2682eSMark J. Nelsonif [[ -z $nflag ]]; then 26668bcea973SRichard Lowe DEFREGFILE="$(/bin/dirname "$(whence $0)")/../etc/its.reg" 26670fd2682eSMark J. Nelson if [[ -n $Iflag ]]; then 26680fd2682eSMark J. Nelson REGFILE=$ITSREG 26690fd2682eSMark J. Nelson elif [[ -r $HOME/.its.reg ]]; then 26700fd2682eSMark J. Nelson REGFILE=$HOME/.its.reg 26710fd2682eSMark J. Nelson else 26720fd2682eSMark J. Nelson REGFILE=$DEFREGFILE 26730fd2682eSMark J. Nelson fi 26740fd2682eSMark J. Nelson if [[ ! -r $REGFILE ]]; then 26750fd2682eSMark J. Nelson print "ERROR: Unable to read database registry file $REGFILE" 26760fd2682eSMark J. Nelson exit 1 26770fd2682eSMark J. Nelson elif [[ $REGFILE != $DEFREGFILE ]]; then 26780fd2682eSMark J. Nelson print " its.reg from: $REGFILE" 26790fd2682eSMark J. Nelson fi 26800fd2682eSMark J. Nelson 26810fd2682eSMark J. Nelson $SED -e '/^#/d' -e '/^[ ]*$/d' $REGFILE | while read LINE; do 26820fd2682eSMark J. Nelson 26830fd2682eSMark J. Nelson name=${LINE%%=*} 26840fd2682eSMark J. Nelson value="${LINE#*=}" 26850fd2682eSMark J. Nelson 26860fd2682eSMark J. Nelson if [[ $name == PREFIX ]]; then 26870fd2682eSMark J. Nelson p=${value} 26880fd2682eSMark J. Nelson valid_prefixes="${p} ${valid_prefixes}" 26890fd2682eSMark J. Nelson else 26900fd2682eSMark J. Nelson itsinfo["${p}_${name}"]="${value}" 26910fd2682eSMark J. Nelson fi 26920fd2682eSMark J. Nelson done 26930fd2682eSMark J. Nelson 26940fd2682eSMark J. Nelson 26958bcea973SRichard Lowe DEFCONFFILE="$(/bin/dirname "$(whence $0)")/../etc/its.conf" 26960fd2682eSMark J. Nelson CONFFILES=$DEFCONFFILE 26970fd2682eSMark J. Nelson if [[ -r $HOME/.its.conf ]]; then 26980fd2682eSMark J. Nelson CONFFILES="${CONFFILES} $HOME/.its.conf" 26990fd2682eSMark J. Nelson fi 27000fd2682eSMark J. Nelson if [[ -n $Cflag ]]; then 27010fd2682eSMark J. Nelson CONFFILES="${CONFFILES} ${ITSCONF}" 27020fd2682eSMark J. Nelson fi 27030fd2682eSMark J. Nelson its_domain= 27040fd2682eSMark J. Nelson its_priority= 27050fd2682eSMark J. Nelson for cf in ${CONFFILES}; do 27060fd2682eSMark J. Nelson if [[ ! -r $cf ]]; then 27070fd2682eSMark J. Nelson print "ERROR: Unable to read database configuration file $cf" 27080fd2682eSMark J. Nelson exit 1 27090fd2682eSMark J. Nelson elif [[ $cf != $DEFCONFFILE ]]; then 27100fd2682eSMark J. Nelson print " its.conf: reading $cf" 27110fd2682eSMark J. Nelson fi 27120fd2682eSMark J. Nelson $SED -e '/^#/d' -e '/^[ ]*$/d' $cf | while read LINE; do 27130fd2682eSMark J. Nelson eval "${LINE}" 27140fd2682eSMark J. Nelson done 27150fd2682eSMark J. Nelson done 27160fd2682eSMark J. Nelson 27170fd2682eSMark J. Nelson # 27180fd2682eSMark J. Nelson # If an information tracking system is explicitly identified by prefix, 27190fd2682eSMark J. Nelson # we want to disregard the specified priorities and resolve it accordingly. 27200fd2682eSMark J. Nelson # 27210fd2682eSMark J. Nelson # To that end, we'll build a sed script to do each valid prefix in turn. 27220fd2682eSMark J. Nelson # 27230fd2682eSMark J. Nelson for p in ${valid_prefixes}; do 27240fd2682eSMark J. Nelson # 27250fd2682eSMark J. Nelson # When an informational URL was provided, translate it to a 27260fd2682eSMark J. Nelson # hyperlink. When omitted, simply use the prefix text. 27270fd2682eSMark J. Nelson # 27280fd2682eSMark J. Nelson if [[ -z ${itsinfo["${p}_INFO"]} ]]; then 27290fd2682eSMark J. Nelson itsinfo["${p}_INFO"]=${p} 27300fd2682eSMark J. Nelson else 27310fd2682eSMark J. Nelson itsinfo["${p}_INFO"]="<a href=\\\"${itsinfo["${p}_INFO"]}\\\">${p}</a>" 27320fd2682eSMark J. Nelson fi 27330fd2682eSMark J. Nelson 27340fd2682eSMark J. Nelson # 27350fd2682eSMark J. Nelson # Assume that, for this invocation of webrev, all references 27360fd2682eSMark J. Nelson # to this information tracking system should resolve through 27370fd2682eSMark J. Nelson # the same URL. 27380fd2682eSMark J. Nelson # 27390fd2682eSMark J. Nelson # If the caller specified -O, then always use EXTERNAL_URL. 27400fd2682eSMark J. Nelson # 27410fd2682eSMark J. Nelson # Otherwise, look in the list of domains for a matching 27420fd2682eSMark J. Nelson # INTERNAL_URL. 27430fd2682eSMark J. Nelson # 27440fd2682eSMark J. Nelson [[ -z $Oflag ]] && for d in ${its_domain}; do 27450fd2682eSMark J. Nelson if [[ -n ${itsinfo["${p}_INTERNAL_URL_${d}"]} ]]; then 27460fd2682eSMark J. Nelson itsinfo["${p}_URL"]="${itsinfo[${p}_INTERNAL_URL_${d}]}" 27470fd2682eSMark J. Nelson break 27480fd2682eSMark J. Nelson fi 27490fd2682eSMark J. Nelson done 27500fd2682eSMark J. Nelson if [[ -z ${itsinfo["${p}_URL"]} ]]; then 27510fd2682eSMark J. Nelson itsinfo["${p}_URL"]="${itsinfo[${p}_EXTERNAL_URL]}" 27520fd2682eSMark J. Nelson fi 27530fd2682eSMark J. Nelson 27540fd2682eSMark J. Nelson # 27550fd2682eSMark J. Nelson # Turn the destination URL into a hyperlink 27560fd2682eSMark J. Nelson # 27570fd2682eSMark J. Nelson itsinfo["${p}_URL"]="<a href=\\\"${itsinfo[${p}_URL]}\\\">&</a>" 27580fd2682eSMark J. Nelson 27592f54b716SRichard Lowe # The character class below contains a literal tab 27602f54b716SRichard Lowe print "/^${p}[: ]/ { 27610fd2682eSMark J. Nelson s;${itsinfo[${p}_REGEX]};${itsinfo[${p}_URL]};g 27620fd2682eSMark J. Nelson s;^${p};${itsinfo[${p}_INFO]}; 27630fd2682eSMark J. Nelson }" >> ${its_sed_script} 27640fd2682eSMark J. Nelson done 27650fd2682eSMark J. Nelson 27660fd2682eSMark J. Nelson # 27670fd2682eSMark J. Nelson # The previous loop took care of explicit specification. Now use 27680fd2682eSMark J. Nelson # the configured priorities to attempt implicit translations. 27690fd2682eSMark J. Nelson # 27700fd2682eSMark J. Nelson for p in ${its_priority}; do 27710fd2682eSMark J. Nelson print "/^${itsinfo[${p}_REGEX]}[ ]/ { 27722f54b716SRichard Lowe s;^${itsinfo[${p}_REGEX]};${itsinfo[${p}_URL]};g 27730fd2682eSMark J. Nelson }" >> ${its_sed_script} 27740fd2682eSMark J. Nelson done 27750fd2682eSMark J. Nelsonfi 27760fd2682eSMark J. Nelson 27770fd2682eSMark J. Nelson# 27780fd2682eSMark J. Nelson# Search for DO_EVERYTHING above for matching "for" statement 27790fd2682eSMark J. Nelson# and explanation of this terminator. 27800fd2682eSMark J. Nelson# 27810fd2682eSMark J. Nelsondone 27820fd2682eSMark J. Nelson 2783daaffb31Sdp# 2784daaffb31Sdp# Output directory. 2785daaffb31Sdp# 2786daaffb31SdpWDIR=${WDIR:-$CWS/webrev} 2787daaffb31Sdp 2788daaffb31Sdp# 278902d26c39SVladimir Kotal# Name of the webrev, derived from the workspace name or output directory; 279002d26c39SVladimir Kotal# in the future this could potentially be an option. 2791daaffb31Sdp# 279202d26c39SVladimir Kotalif [[ -n $oflag ]]; then 279302d26c39SVladimir Kotal WNAME=${WDIR##*/} 279402d26c39SVladimir Kotalelse 2795daaffb31Sdp WNAME=${CWS##*/} 279602d26c39SVladimir Kotalfi 279702d26c39SVladimir Kotal 2798ba44d8a2SVladimir Kotal# Make sure remote target is well formed for remote upload/delete. 2799ba44d8a2SVladimir Kotalif [[ -n $Dflag || -n $Uflag ]]; then 2800b0088928SVladimir Kotal # 2801ba44d8a2SVladimir Kotal # If remote target is not specified, build it from scratch using 2802ba44d8a2SVladimir Kotal # the default values. 2803b0088928SVladimir Kotal # 2804ba44d8a2SVladimir Kotal if [[ -z $tflag ]]; then 2805ba44d8a2SVladimir Kotal remote_target=${DEFAULT_REMOTE_HOST}:${WNAME} 2806ba44d8a2SVladimir Kotal else 2807b0088928SVladimir Kotal # 2808b0088928SVladimir Kotal # Check upload target prefix first. 2809b0088928SVladimir Kotal # 2810b0088928SVladimir Kotal if [[ "${remote_target}" != ${rsync_prefix}* && 2811b0088928SVladimir Kotal "${remote_target}" != ${ssh_prefix}* ]]; then 2812b0088928SVladimir Kotal print "ERROR: invalid prefix of upload URI" \ 2813b0088928SVladimir Kotal "($remote_target)" 2814b0088928SVladimir Kotal exit 1 2815b0088928SVladimir Kotal fi 2816b0088928SVladimir Kotal # 2817ba44d8a2SVladimir Kotal # If destination specification is not in the form of 2818ba44d8a2SVladimir Kotal # host_spec:remote_dir then assume it is just remote hostname 2819ba44d8a2SVladimir Kotal # and append a colon and destination directory formed from 2820ba44d8a2SVladimir Kotal # local webrev directory name. 2821b0088928SVladimir Kotal # 2822b0088928SVladimir Kotal typeset target_no_prefix=${remote_target##*://} 2823b0088928SVladimir Kotal if [[ ${target_no_prefix} == *:* ]]; then 2824ba44d8a2SVladimir Kotal if [[ "${remote_target}" == *: ]]; then 2825b0088928SVladimir Kotal remote_target=${remote_target}${WNAME} 2826ba44d8a2SVladimir Kotal fi 2827b0088928SVladimir Kotal else 2828b0088928SVladimir Kotal if [[ ${target_no_prefix} == */* ]]; then 2829b0088928SVladimir Kotal print "ERROR: badly formed upload URI" \ 2830b0088928SVladimir Kotal "($remote_target)" 2831b0088928SVladimir Kotal exit 1 2832b0088928SVladimir Kotal else 2833b0088928SVladimir Kotal remote_target=${remote_target}:${WNAME} 2834ba44d8a2SVladimir Kotal fi 2835ba44d8a2SVladimir Kotal fi 2836ba44d8a2SVladimir Kotal fi 2837ba44d8a2SVladimir Kotal 2838b0088928SVladimir Kotal # 2839b0088928SVladimir Kotal # Strip trailing slash. Each upload method will deal with directory 2840b0088928SVladimir Kotal # specification separately. 2841b0088928SVladimir Kotal # 2842b0088928SVladimir Kotal remote_target=${remote_target%/} 2843b0088928SVladimir Kotalfi 2844b0088928SVladimir Kotal 2845b0088928SVladimir Kotal# 2846ba44d8a2SVladimir Kotal# Option -D by itself (option -U not present) implies no webrev generation. 2847b0088928SVladimir Kotal# 2848ba44d8a2SVladimir Kotalif [[ -z $Uflag && -n $Dflag ]]; then 2849b0088928SVladimir Kotal delete_webrev 1 1 2850ba44d8a2SVladimir Kotal exit $? 2851ba44d8a2SVladimir Kotalfi 2852ba44d8a2SVladimir Kotal 2853b0088928SVladimir Kotal# 2854ba44d8a2SVladimir Kotal# Do not generate the webrev, just upload it or delete it. 2855b0088928SVladimir Kotal# 2856ba44d8a2SVladimir Kotalif [[ -n $nflag ]]; then 2857ba44d8a2SVladimir Kotal if [[ -n $Dflag ]]; then 2858b0088928SVladimir Kotal delete_webrev 1 1 2859ba44d8a2SVladimir Kotal (( $? == 0 )) || exit $? 2860ba44d8a2SVladimir Kotal fi 2861ba44d8a2SVladimir Kotal if [[ -n $Uflag ]]; then 286202d26c39SVladimir Kotal upload_webrev 286302d26c39SVladimir Kotal exit $? 286402d26c39SVladimir Kotal fi 2865ba44d8a2SVladimir Kotalfi 2866daaffb31Sdp 2867e0e0293aSjmcpif [ "${WDIR%%/*}" ]; then 28687c478bd9Sstevel@tonic-gate WDIR=$PWD/$WDIR 28697c478bd9Sstevel@tonic-gatefi 2870daaffb31Sdp 2871daaffb31Sdpif [[ ! -d $WDIR ]]; then 2872daaffb31Sdp mkdir -p $WDIR 2873ba44d8a2SVladimir Kotal (( $? != 0 )) && exit 1 28747c478bd9Sstevel@tonic-gatefi 28757c478bd9Sstevel@tonic-gate 2876daaffb31Sdp# 2877daaffb31Sdp# Summarize what we're going to do. 2878daaffb31Sdp# 28798bcea973SRichard Loweprint " Workspace: ${PRETTY_CWS:-$CWS}" 2880daaffb31Sdpif [[ -n $parent_webrev ]]; then 2881daaffb31Sdp print "Compare against: webrev at $parent_webrev" 2882daaffb31Sdpelse 28838bcea973SRichard Lowe print "Compare against: ${PRETTY_PWS:-$PWS}" 2884cdf0c1d5Smjnelsonfi 2885daaffb31Sdp 2886daaffb31Sdp[[ -n $INCLUDE_FILE ]] && print " Including: $INCLUDE_FILE" 2887daaffb31Sdpprint " Output to: $WDIR" 2888daaffb31Sdp 2889daaffb31Sdp# 28907c478bd9Sstevel@tonic-gate# Save the file list in the webrev dir 2891daaffb31Sdp# 2892daaffb31Sdp[[ ! $FLIST -ef $WDIR/file.list ]] && cp $FLIST $WDIR/file.list 28937c478bd9Sstevel@tonic-gate 2894daaffb31Sdprm -f $WDIR/$WNAME.patch 2895daaffb31Sdprm -f $WDIR/$WNAME.ps 2896daaffb31Sdprm -f $WDIR/$WNAME.pdf 28977c478bd9Sstevel@tonic-gate 2898daaffb31Sdptouch $WDIR/$WNAME.patch 28997c478bd9Sstevel@tonic-gate 2900daaffb31Sdpprint " Output Files:" 2901daaffb31Sdp 2902daaffb31Sdp# 2903daaffb31Sdp# Clean up the file list: Remove comments, blank lines and env variables. 2904daaffb31Sdp# 2905b0088928SVladimir Kotal$SED -e "s/#.*$//" -e "/=/d" -e "/^[ ]*$/d" $FLIST > /tmp/$$.flist.clean 2906daaffb31SdpFLIST=/tmp/$$.flist.clean 2907daaffb31Sdp 2908daaffb31Sdp# 2909cdf0c1d5Smjnelson# For Mercurial, create a cache of manifest entries. 2910cdf0c1d5Smjnelson# 2911cdf0c1d5Smjnelsonif [[ $SCM_MODE == "mercurial" ]]; then 2912cdf0c1d5Smjnelson # 2913cdf0c1d5Smjnelson # Transform the FLIST into a temporary sed script that matches 2914cdf0c1d5Smjnelson # relevant entries in the Mercurial manifest as follows: 2915cdf0c1d5Smjnelson # 1) The script will be used against the parent revision manifest, 2916cdf0c1d5Smjnelson # so for FLIST lines that have two filenames (a renamed file) 2917cdf0c1d5Smjnelson # keep only the old name. 2918cdf0c1d5Smjnelson # 2) Escape all forward slashes the filename. 2919cdf0c1d5Smjnelson # 3) Change the filename into another sed command that matches 2920cdf0c1d5Smjnelson # that file in "hg manifest -v" output: start of line, three 2921cdf0c1d5Smjnelson # octal digits for file permissions, space, a file type flag 2922cdf0c1d5Smjnelson # character, space, the filename, end of line. 2923e6ccc173SEdward Pilatowicz # 4) Eliminate any duplicate entries. (This can occur if a 2924e6ccc173SEdward Pilatowicz # file has been used as the source of an hg cp and it's 2925e6ccc173SEdward Pilatowicz # also been modified in the same changeset.) 2926cdf0c1d5Smjnelson # 2927cdf0c1d5Smjnelson SEDFILE=/tmp/$$.manifest.sed 2928b0088928SVladimir Kotal $SED ' 2929cdf0c1d5Smjnelson s#^[^ ]* ## 2930cdf0c1d5Smjnelson s#/#\\\/#g 2931cdf0c1d5Smjnelson s#^.*$#/^... . &$/p# 2932e6ccc173SEdward Pilatowicz ' < $FLIST | $SORT -u > $SEDFILE 2933cdf0c1d5Smjnelson 2934cdf0c1d5Smjnelson # 2935cdf0c1d5Smjnelson # Apply the generated script to the output of "hg manifest -v" 2936cdf0c1d5Smjnelson # to get the relevant subset for this webrev. 2937cdf0c1d5Smjnelson # 2938cdf0c1d5Smjnelson HG_PARENT_MANIFEST=/tmp/$$.manifest 2939cdf0c1d5Smjnelson hg -R $CWS manifest -v -r $HG_PARENT | 2940b0088928SVladimir Kotal $SED -n -f $SEDFILE > $HG_PARENT_MANIFEST 2941cdf0c1d5Smjnelsonfi 2942cdf0c1d5Smjnelson 2943cdf0c1d5Smjnelson# 2944daaffb31Sdp# First pass through the files: generate the per-file webrev HTML-files. 2945daaffb31Sdp# 2946daaffb31Sdpcat $FLIST | while read LINE 29477c478bd9Sstevel@tonic-gatedo 29487c478bd9Sstevel@tonic-gate set - $LINE 29497c478bd9Sstevel@tonic-gate P=$1 29507c478bd9Sstevel@tonic-gate 2951daaffb31Sdp # 2952daaffb31Sdp # Normally, each line in the file list is just a pathname of a 2953daaffb31Sdp # file that has been modified or created in the child. A file 2954daaffb31Sdp # that is renamed in the child workspace has two names on the 2955daaffb31Sdp # line: new name followed by the old name. 2956daaffb31Sdp # 2957daaffb31Sdp oldname="" 2958daaffb31Sdp oldpath="" 2959daaffb31Sdp rename= 2960daaffb31Sdp if [[ $# -eq 2 ]]; then 29617c478bd9Sstevel@tonic-gate PP=$2 # old filename 2962e6ccc173SEdward Pilatowicz if [[ -f $PP ]]; then 2963e6ccc173SEdward Pilatowicz oldname=" (copied from $PP)" 2964e6ccc173SEdward Pilatowicz else 2965e6ccc173SEdward Pilatowicz oldname=" (renamed from $PP)" 2966e6ccc173SEdward Pilatowicz fi 2967daaffb31Sdp oldpath="$PP" 2968daaffb31Sdp rename=1 29697c478bd9Sstevel@tonic-gate PDIR=${PP%/*} 2970daaffb31Sdp if [[ $PDIR == $PP ]]; then 29717c478bd9Sstevel@tonic-gate PDIR="." # File at root of workspace 29727c478bd9Sstevel@tonic-gate fi 29737c478bd9Sstevel@tonic-gate 29747c478bd9Sstevel@tonic-gate PF=${PP##*/} 29757c478bd9Sstevel@tonic-gate 29767c478bd9Sstevel@tonic-gate DIR=${P%/*} 2977daaffb31Sdp if [[ $DIR == $P ]]; then 29787c478bd9Sstevel@tonic-gate DIR="." # File at root of workspace 29797c478bd9Sstevel@tonic-gate fi 29807c478bd9Sstevel@tonic-gate 29817c478bd9Sstevel@tonic-gate F=${P##*/} 2982daaffb31Sdp 29837c478bd9Sstevel@tonic-gate else 29847c478bd9Sstevel@tonic-gate DIR=${P%/*} 2985daaffb31Sdp if [[ "$DIR" == "$P" ]]; then 29867c478bd9Sstevel@tonic-gate DIR="." # File at root of workspace 29877c478bd9Sstevel@tonic-gate fi 29887c478bd9Sstevel@tonic-gate 29897c478bd9Sstevel@tonic-gate F=${P##*/} 29907c478bd9Sstevel@tonic-gate 29917c478bd9Sstevel@tonic-gate PP=$P 29927c478bd9Sstevel@tonic-gate PDIR=$DIR 29937c478bd9Sstevel@tonic-gate PF=$F 29947c478bd9Sstevel@tonic-gate fi 29957c478bd9Sstevel@tonic-gate 2996daaffb31Sdp COMM=`getcomments html $P $PP` 29977c478bd9Sstevel@tonic-gate 2998daaffb31Sdp print "\t$P$oldname\n\t\t\c" 29997c478bd9Sstevel@tonic-gate 30007c478bd9Sstevel@tonic-gate # Make the webrev mirror directory if necessary 30017c478bd9Sstevel@tonic-gate mkdir -p $WDIR/$DIR 30027c478bd9Sstevel@tonic-gate 3003daaffb31Sdp # 3004cdf0c1d5Smjnelson # We stash old and new files into parallel directories in $WDIR 3005daaffb31Sdp # and do our diffs there. This makes it possible to generate 3006daaffb31Sdp # clean looking diffs which don't have absolute paths present. 3007daaffb31Sdp # 3008daaffb31Sdp 3009cdf0c1d5Smjnelson build_old_new "$WDIR" "$PWS" "$PDIR" "$PF" "$CWS" "$DIR" "$F" || \ 30107c478bd9Sstevel@tonic-gate continue 30117c478bd9Sstevel@tonic-gate 3012cdf0c1d5Smjnelson # 3013cdf0c1d5Smjnelson # Keep the old PWD around, so we can safely switch back after 3014cdf0c1d5Smjnelson # diff generation, such that build_old_new runs in a 3015cdf0c1d5Smjnelson # consistent environment. 3016cdf0c1d5Smjnelson # 3017cdf0c1d5Smjnelson OWD=$PWD 3018daaffb31Sdp cd $WDIR/raw_files 3019daaffb31Sdp ofile=old/$PDIR/$PF 3020daaffb31Sdp nfile=new/$DIR/$F 30217c478bd9Sstevel@tonic-gate 3022daaffb31Sdp mv_but_nodiff= 3023daaffb31Sdp cmp $ofile $nfile > /dev/null 2>&1 3024daaffb31Sdp if [[ $? == 0 && $rename == 1 ]]; then 3025daaffb31Sdp mv_but_nodiff=1 3026daaffb31Sdp fi 3027daaffb31Sdp 3028daaffb31Sdp # 3029daaffb31Sdp # If we have old and new versions of the file then run the appropriate 3030daaffb31Sdp # diffs. This is complicated by a couple of factors: 3031daaffb31Sdp # 3032daaffb31Sdp # - renames must be handled specially: we emit a 'remove' 3033daaffb31Sdp # diff and an 'add' diff 3034daaffb31Sdp # - new files and deleted files must be handled specially 3035daaffb31Sdp # - Solaris patch(1m) can't cope with file creation 3036daaffb31Sdp # (and hence renames) as of this writing. 3037daaffb31Sdp # - To make matters worse, gnu patch doesn't interpret the 3038daaffb31Sdp # output of Solaris diff properly when it comes to 3039daaffb31Sdp # adds and deletes. We need to do some "cleansing" 3040daaffb31Sdp # transformations: 3041daaffb31Sdp # [to add a file] @@ -1,0 +X,Y @@ --> @@ -0,0 +X,Y @@ 3042daaffb31Sdp # [to del a file] @@ -X,Y +1,0 @@ --> @@ -X,Y +0,0 @@ 3043daaffb31Sdp # 3044b0088928SVladimir Kotal cleanse_rmfile="$SED 's/^\(@@ [0-9+,-]*\) [0-9+,-]* @@$/\1 +0,0 @@/'" 3045b0088928SVladimir Kotal cleanse_newfile="$SED 's/^@@ [0-9+,-]* \([0-9+,-]* @@\)$/@@ -0,0 \1/'" 3046daaffb31Sdp 3047daaffb31Sdp rm -f $WDIR/$DIR/$F.patch 3048daaffb31Sdp if [[ -z $rename ]]; then 3049e0e0293aSjmcp if [ ! -f "$ofile" ]; then 3050daaffb31Sdp diff -u /dev/null $nfile | sh -c "$cleanse_newfile" \ 3051daaffb31Sdp > $WDIR/$DIR/$F.patch 3052e0e0293aSjmcp elif [ ! -f "$nfile" ]; then 3053daaffb31Sdp diff -u $ofile /dev/null | sh -c "$cleanse_rmfile" \ 3054daaffb31Sdp > $WDIR/$DIR/$F.patch 3055daaffb31Sdp else 3056daaffb31Sdp diff -u $ofile $nfile > $WDIR/$DIR/$F.patch 3057daaffb31Sdp fi 3058daaffb31Sdp else 3059daaffb31Sdp diff -u $ofile /dev/null | sh -c "$cleanse_rmfile" \ 3060daaffb31Sdp > $WDIR/$DIR/$F.patch 3061daaffb31Sdp 3062daaffb31Sdp diff -u /dev/null $nfile | sh -c "$cleanse_newfile" \ 3063daaffb31Sdp >> $WDIR/$DIR/$F.patch 3064daaffb31Sdp fi 3065daaffb31Sdp 3066daaffb31Sdp # 3067daaffb31Sdp # Tack the patch we just made onto the accumulated patch for the 3068daaffb31Sdp # whole wad. 3069daaffb31Sdp # 3070daaffb31Sdp cat $WDIR/$DIR/$F.patch >> $WDIR/$WNAME.patch 3071daaffb31Sdp 3072daaffb31Sdp print " patch\c" 3073daaffb31Sdp 3074daaffb31Sdp if [[ -f $ofile && -f $nfile && -z $mv_but_nodiff ]]; then 3075daaffb31Sdp 3076daaffb31Sdp ${CDIFFCMD:-diff -bt -C 5} $ofile $nfile > $WDIR/$DIR/$F.cdiff 3077daaffb31Sdp diff_to_html $F $DIR/$F "C" "$COMM" < $WDIR/$DIR/$F.cdiff \ 3078daaffb31Sdp > $WDIR/$DIR/$F.cdiff.html 30797c478bd9Sstevel@tonic-gate print " cdiffs\c" 30807c478bd9Sstevel@tonic-gate 3081daaffb31Sdp ${UDIFFCMD:-diff -bt -U 5} $ofile $nfile > $WDIR/$DIR/$F.udiff 3082daaffb31Sdp diff_to_html $F $DIR/$F "U" "$COMM" < $WDIR/$DIR/$F.udiff \ 3083daaffb31Sdp > $WDIR/$DIR/$F.udiff.html 3084daaffb31Sdp 30857c478bd9Sstevel@tonic-gate print " udiffs\c" 30867c478bd9Sstevel@tonic-gate 30877c478bd9Sstevel@tonic-gate if [[ -x $WDIFF ]]; then 3088daaffb31Sdp $WDIFF -c "$COMM" \ 3089daaffb31Sdp -t "$WNAME Wdiff $DIR/$F" $ofile $nfile > \ 3090daaffb31Sdp $WDIR/$DIR/$F.wdiff.html 2>/dev/null 3091daaffb31Sdp if [[ $? -eq 0 ]]; then 30927c478bd9Sstevel@tonic-gate print " wdiffs\c" 3093daaffb31Sdp else 3094daaffb31Sdp print " wdiffs[fail]\c" 3095daaffb31Sdp fi 30967c478bd9Sstevel@tonic-gate fi 30977c478bd9Sstevel@tonic-gate 3098daaffb31Sdp sdiff_to_html $ofile $nfile $F $DIR "$COMM" \ 3099daaffb31Sdp > $WDIR/$DIR/$F.sdiff.html 31007c478bd9Sstevel@tonic-gate print " sdiffs\c" 31017c478bd9Sstevel@tonic-gate 31027c478bd9Sstevel@tonic-gate print " frames\c" 31037c478bd9Sstevel@tonic-gate 31047c478bd9Sstevel@tonic-gate rm -f $WDIR/$DIR/$F.cdiff $WDIR/$DIR/$F.udiff 31057c478bd9Sstevel@tonic-gate 3106daaffb31Sdp difflines $ofile $nfile > $WDIR/$DIR/$F.count 3107daaffb31Sdp 3108daaffb31Sdp elif [[ -f $ofile && -f $nfile && -n $mv_but_nodiff ]]; then 3109daaffb31Sdp # renamed file: may also have differences 3110daaffb31Sdp difflines $ofile $nfile > $WDIR/$DIR/$F.count 3111daaffb31Sdp elif [[ -f $nfile ]]; then 31127c478bd9Sstevel@tonic-gate # new file: count added lines 3113daaffb31Sdp difflines /dev/null $nfile > $WDIR/$DIR/$F.count 3114daaffb31Sdp elif [[ -f $ofile ]]; then 31157c478bd9Sstevel@tonic-gate # old file: count deleted lines 3116daaffb31Sdp difflines $ofile /dev/null > $WDIR/$DIR/$F.count 31177c478bd9Sstevel@tonic-gate fi 31187c478bd9Sstevel@tonic-gate 3119daaffb31Sdp # 3120daaffb31Sdp # Now we generate the postscript for this file. We generate diffs 3121daaffb31Sdp # only in the event that there is delta, or the file is new (it seems 3122daaffb31Sdp # tree-killing to print out the contents of deleted files). 3123daaffb31Sdp # 3124daaffb31Sdp if [[ -f $nfile ]]; then 3125daaffb31Sdp ocr=$ofile 3126daaffb31Sdp [[ ! -f $ofile ]] && ocr=/dev/null 3127daaffb31Sdp 3128daaffb31Sdp if [[ -z $mv_but_nodiff ]]; then 3129daaffb31Sdp textcomm=`getcomments text $P $PP` 313014983201Sdp if [[ -x $CODEREVIEW ]]; then 313114983201Sdp $CODEREVIEW -y "$textcomm" \ 313214983201Sdp -e $ocr $nfile \ 313314983201Sdp > /tmp/$$.psfile 2>/dev/null && 313414983201Sdp cat /tmp/$$.psfile >> $WDIR/$WNAME.ps 3135daaffb31Sdp if [[ $? -eq 0 ]]; then 3136daaffb31Sdp print " ps\c" 3137daaffb31Sdp else 3138daaffb31Sdp print " ps[fail]\c" 3139daaffb31Sdp fi 3140daaffb31Sdp fi 3141daaffb31Sdp fi 314214983201Sdp fi 3143daaffb31Sdp 3144cdf0c1d5Smjnelson if [[ -f $ofile ]]; then 3145cdf0c1d5Smjnelson source_to_html Old $PP < $ofile > $WDIR/$DIR/$F-.html 31467c478bd9Sstevel@tonic-gate print " old\c" 31477c478bd9Sstevel@tonic-gate fi 31487c478bd9Sstevel@tonic-gate 3149daaffb31Sdp if [[ -f $nfile ]]; then 3150daaffb31Sdp source_to_html New $P < $nfile > $WDIR/$DIR/$F.html 31517c478bd9Sstevel@tonic-gate print " new\c" 31527c478bd9Sstevel@tonic-gate fi 31537c478bd9Sstevel@tonic-gate 3154cdf0c1d5Smjnelson cd $OWD 3155cdf0c1d5Smjnelson 3156daaffb31Sdp print 31577c478bd9Sstevel@tonic-gatedone 31587c478bd9Sstevel@tonic-gate 3159daaffb31Sdpframe_nav_js > $WDIR/ancnav.js 31607c478bd9Sstevel@tonic-gateframe_navigation > $WDIR/ancnav.html 3161daaffb31Sdp 316214983201Sdpif [[ ! -f $WDIR/$WNAME.ps ]]; then 316314983201Sdp print " Generating PDF: Skipped: no output available" 316414983201Sdpelif [[ -x $CODEREVIEW && -x $PS2PDF ]]; then 316514983201Sdp print " Generating PDF: \c" 316614983201Sdp fix_postscript $WDIR/$WNAME.ps | $PS2PDF - > $WDIR/$WNAME.pdf 3167daaffb31Sdp print "Done." 316814983201Sdpelse 316914983201Sdp print " Generating PDF: Skipped: missing 'ps2pdf' or 'codereview'" 317014983201Sdpfi 31717c478bd9Sstevel@tonic-gate 3172e0e0293aSjmcp# If we're in OpenSolaris mode and there's a closed dir under $WDIR, 3173e0e0293aSjmcp# delete it - prevent accidental publishing of closed source 3174e0e0293aSjmcp 3175e0e0293aSjmcpif [[ -n "$Oflag" ]]; then 3176ba44d8a2SVladimir Kotal $FIND $WDIR -type d -name closed -exec /bin/rm -rf {} \; 3177e0e0293aSjmcpfi 3178e0e0293aSjmcp 31797c478bd9Sstevel@tonic-gate# Now build the index.html file that contains 31807c478bd9Sstevel@tonic-gate# links to the source files and their diffs. 31817c478bd9Sstevel@tonic-gate 31827c478bd9Sstevel@tonic-gatecd $CWS 31837c478bd9Sstevel@tonic-gate 31847c478bd9Sstevel@tonic-gate# Save total changed lines for Code Inspection. 3185daaffb31Sdpprint "$TOTL" > $WDIR/TotalChangedLines 31867c478bd9Sstevel@tonic-gate 3187daaffb31Sdpprint " index.html: \c" 31887c478bd9Sstevel@tonic-gateINDEXFILE=$WDIR/index.html 31897c478bd9Sstevel@tonic-gateexec 3<&1 # duplicate stdout to FD3. 31907c478bd9Sstevel@tonic-gateexec 1<&- # Close stdout. 31917c478bd9Sstevel@tonic-gateexec > $INDEXFILE # Open stdout to index file. 31927c478bd9Sstevel@tonic-gate 3193daaffb31Sdpprint "$HTML<head>$STDHEAD" 3194daaffb31Sdpprint "<title>$WNAME</title>" 3195daaffb31Sdpprint "</head>" 3196daaffb31Sdpprint "<body id=\"SUNWwebrev\">" 3197daaffb31Sdpprint "<div class=\"summary\">" 3198daaffb31Sdpprint "<h2>Code Review for $WNAME</h2>" 31997c478bd9Sstevel@tonic-gate 3200daaffb31Sdpprint "<table>" 32017c478bd9Sstevel@tonic-gate 3202daaffb31Sdp# 3203cdf0c1d5Smjnelson# Get the preparer's name: 3204daaffb31Sdp# 3205cdf0c1d5Smjnelson# If the SCM detected is Mercurial, and the configuration property 3206cdf0c1d5Smjnelson# ui.username is available, use that, but be careful to properly escape 3207cdf0c1d5Smjnelson# angle brackets (HTML syntax characters) in the email address. 3208cdf0c1d5Smjnelson# 3209cdf0c1d5Smjnelson# Otherwise, use the current userid in the form "John Doe (jdoe)", but 3210cdf0c1d5Smjnelson# to maintain compatibility with passwd(4), we must support '&' substitutions. 3211cdf0c1d5Smjnelson# 3212cdf0c1d5Smjnelsonpreparer= 3213cdf0c1d5Smjnelsonif [[ "$SCM_MODE" == mercurial ]]; then 3214cdf0c1d5Smjnelson preparer=`hg showconfig ui.username 2>/dev/null` 3215cdf0c1d5Smjnelson if [[ -n "$preparer" ]]; then 3216cdf0c1d5Smjnelson preparer="$(echo "$preparer" | html_quote)" 3217cdf0c1d5Smjnelson fi 3218cdf0c1d5Smjnelsonfi 3219cdf0c1d5Smjnelsonif [[ -z "$preparer" ]]; then 3220cdf0c1d5Smjnelson preparer=$( 3221cdf0c1d5Smjnelson $PERL -e ' 3222cdf0c1d5Smjnelson ($login, $pw, $uid, $gid, $quota, $cmt, $gcos) = getpwuid($<); 3223cdf0c1d5Smjnelson if ($login) { 3224cdf0c1d5Smjnelson $gcos =~ s/\&/ucfirst($login)/e; 3225cdf0c1d5Smjnelson printf "%s (%s)\n", $gcos, $login; 3226cdf0c1d5Smjnelson } else { 3227cdf0c1d5Smjnelson printf "(unknown)\n"; 3228cdf0c1d5Smjnelson } 3229cdf0c1d5Smjnelson ') 3230daaffb31Sdpfi 3231daaffb31Sdp 323248bc00d6SjmcpPREPDATE=$(LC_ALL=C /usr/bin/date +%Y-%b-%d\ %R\ %z\ %Z) 323348bc00d6Sjmcpprint "<tr><th>Prepared by:</th><td>$preparer on $PREPDATE</td></tr>" 32348bcea973SRichard Loweprint "<tr><th>Workspace:</th><td>${PRETTY_CWS:-$CWS}" 3235cdf0c1d5Smjnelsonprint "</td></tr>" 3236daaffb31Sdpprint "<tr><th>Compare against:</th><td>" 3237daaffb31Sdpif [[ -n $parent_webrev ]]; then 3238daaffb31Sdp print "webrev at $parent_webrev" 3239daaffb31Sdpelse 32408bcea973SRichard Lowe print "${PRETTY_PWS:-$PWS}" 3241daaffb31Sdpfi 3242daaffb31Sdpprint "</td></tr>" 3243daaffb31Sdpprint "<tr><th>Summary of changes:</th><td>" 3244daaffb31SdpprintCI $TOTL $TINS $TDEL $TMOD $TUNC 3245daaffb31Sdpprint "</td></tr>" 3246daaffb31Sdp 3247daaffb31Sdpif [[ -f $WDIR/$WNAME.patch ]]; then 3248371d72daSLubomir Sedlacik wpatch_url="$(print $WNAME.patch | url_encode)" 3249daaffb31Sdp print "<tr><th>Patch of changes:</th><td>" 3250371d72daSLubomir Sedlacik print "<a href=\"$wpatch_url\">$WNAME.patch</a></td></tr>" 3251daaffb31Sdpfi 3252daaffb31Sdpif [[ -f $WDIR/$WNAME.pdf ]]; then 3253371d72daSLubomir Sedlacik wpdf_url="$(print $WNAME.pdf | url_encode)" 3254daaffb31Sdp print "<tr><th>Printable review:</th><td>" 3255371d72daSLubomir Sedlacik print "<a href=\"$wpdf_url\">$WNAME.pdf</a></td></tr>" 3256daaffb31Sdpfi 3257daaffb31Sdp 3258daaffb31Sdpif [[ -n "$iflag" ]]; then 3259daaffb31Sdp print "<tr><th>Author comments:</th><td><div>" 3260daaffb31Sdp cat /tmp/$$.include 3261daaffb31Sdp print "</div></td></tr>" 3262daaffb31Sdpfi 3263daaffb31Sdpprint "</table>" 3264daaffb31Sdpprint "</div>" 3265daaffb31Sdp 3266daaffb31Sdp# 3267daaffb31Sdp# Second pass through the files: generate the rest of the index file 3268daaffb31Sdp# 3269daaffb31Sdpcat $FLIST | while read LINE 32707c478bd9Sstevel@tonic-gatedo 32717c478bd9Sstevel@tonic-gate set - $LINE 32727c478bd9Sstevel@tonic-gate P=$1 32737c478bd9Sstevel@tonic-gate 3274daaffb31Sdp if [[ $# == 2 ]]; then 32757c478bd9Sstevel@tonic-gate PP=$2 3276cdf0c1d5Smjnelson oldname="$PP" 32777c478bd9Sstevel@tonic-gate else 32787c478bd9Sstevel@tonic-gate PP=$P 3279daaffb31Sdp oldname="" 3280daaffb31Sdp fi 3281daaffb31Sdp 3282cdf0c1d5Smjnelson mv_but_nodiff= 3283cdf0c1d5Smjnelson cmp $WDIR/raw_files/old/$PP $WDIR/raw_files/new/$P > /dev/null 2>&1 3284cdf0c1d5Smjnelson if [[ $? == 0 && -n "$oldname" ]]; then 3285cdf0c1d5Smjnelson mv_but_nodiff=1 3286cdf0c1d5Smjnelson fi 3287cdf0c1d5Smjnelson 3288daaffb31Sdp DIR=${P%/*} 3289daaffb31Sdp if [[ $DIR == $P ]]; then 3290daaffb31Sdp DIR="." # File at root of workspace 32917c478bd9Sstevel@tonic-gate fi 32927c478bd9Sstevel@tonic-gate 32937c478bd9Sstevel@tonic-gate # Avoid processing the same file twice. 32947c478bd9Sstevel@tonic-gate # It's possible for renamed files to 32957c478bd9Sstevel@tonic-gate # appear twice in the file list 32967c478bd9Sstevel@tonic-gate 32977c478bd9Sstevel@tonic-gate F=$WDIR/$P 32987c478bd9Sstevel@tonic-gate 3299daaffb31Sdp print "<p>" 33007c478bd9Sstevel@tonic-gate 33017c478bd9Sstevel@tonic-gate # If there's a diffs file, make diffs links 33027c478bd9Sstevel@tonic-gate 3303daaffb31Sdp if [[ -f $F.cdiff.html ]]; then 3304371d72daSLubomir Sedlacik cdiff_url="$(print $P.cdiff.html | url_encode)" 3305371d72daSLubomir Sedlacik udiff_url="$(print $P.udiff.html | url_encode)" 3306371d72daSLubomir Sedlacik print "<a href=\"$cdiff_url\">Cdiffs</a>" 3307371d72daSLubomir Sedlacik print "<a href=\"$udiff_url\">Udiffs</a>" 33087c478bd9Sstevel@tonic-gate 3309daaffb31Sdp if [[ -f $F.wdiff.html && -x $WDIFF ]]; then 3310371d72daSLubomir Sedlacik wdiff_url="$(print $P.wdiff.html | url_encode)" 3311371d72daSLubomir Sedlacik print "<a href=\"$wdiff_url\">Wdiffs</a>" 33127c478bd9Sstevel@tonic-gate fi 33137c478bd9Sstevel@tonic-gate 3314371d72daSLubomir Sedlacik sdiff_url="$(print $P.sdiff.html | url_encode)" 3315371d72daSLubomir Sedlacik print "<a href=\"$sdiff_url\">Sdiffs</a>" 33167c478bd9Sstevel@tonic-gate 3317371d72daSLubomir Sedlacik frames_url="$(print $P.frames.html | url_encode)" 3318371d72daSLubomir Sedlacik print "<a href=\"$frames_url\">Frames</a>" 33197c478bd9Sstevel@tonic-gate else 3320daaffb31Sdp print " ------ ------ ------" 33217c478bd9Sstevel@tonic-gate 3322daaffb31Sdp if [[ -x $WDIFF ]]; then 33237c478bd9Sstevel@tonic-gate print " ------" 33247c478bd9Sstevel@tonic-gate fi 3325daaffb31Sdp 3326daaffb31Sdp print " ------" 33277c478bd9Sstevel@tonic-gate fi 33287c478bd9Sstevel@tonic-gate 33297c478bd9Sstevel@tonic-gate # If there's an old file, make the link 33307c478bd9Sstevel@tonic-gate 3331daaffb31Sdp if [[ -f $F-.html ]]; then 3332371d72daSLubomir Sedlacik oldfile_url="$(print $P-.html | url_encode)" 3333371d72daSLubomir Sedlacik print "<a href=\"$oldfile_url\">Old</a>" 33347c478bd9Sstevel@tonic-gate else 3335daaffb31Sdp print " ---" 33367c478bd9Sstevel@tonic-gate fi 33377c478bd9Sstevel@tonic-gate 33387c478bd9Sstevel@tonic-gate # If there's an new file, make the link 33397c478bd9Sstevel@tonic-gate 3340daaffb31Sdp if [[ -f $F.html ]]; then 3341371d72daSLubomir Sedlacik newfile_url="$(print $P.html | url_encode)" 3342371d72daSLubomir Sedlacik print "<a href=\"$newfile_url\">New</a>" 33437c478bd9Sstevel@tonic-gate else 3344daaffb31Sdp print " ---" 33457c478bd9Sstevel@tonic-gate fi 33467c478bd9Sstevel@tonic-gate 3347daaffb31Sdp if [[ -f $F.patch ]]; then 3348371d72daSLubomir Sedlacik patch_url="$(print $P.patch | url_encode)" 3349371d72daSLubomir Sedlacik print "<a href=\"$patch_url\">Patch</a>" 3350daaffb31Sdp else 3351daaffb31Sdp print " -----" 3352daaffb31Sdp fi 3353daaffb31Sdp 3354daaffb31Sdp if [[ -f $WDIR/raw_files/new/$P ]]; then 3355371d72daSLubomir Sedlacik rawfiles_url="$(print raw_files/new/$P | url_encode)" 3356371d72daSLubomir Sedlacik print "<a href=\"$rawfiles_url\">Raw</a>" 3357daaffb31Sdp else 3358daaffb31Sdp print " ---" 3359daaffb31Sdp fi 3360daaffb31Sdp 3361cdf0c1d5Smjnelson print "<b>$P</b>" 3362cdf0c1d5Smjnelson 3363cdf0c1d5Smjnelson # For renamed files, clearly state whether or not they are modified 3364e6ccc173SEdward Pilatowicz if [[ -f "$oldname" ]]; then 3365cdf0c1d5Smjnelson if [[ -n "$mv_but_nodiff" ]]; then 3366e6ccc173SEdward Pilatowicz print "<i>(copied from $oldname)</i>" 3367cdf0c1d5Smjnelson else 3368e6ccc173SEdward Pilatowicz print "<i>(copied and modified from $oldname)</i>" 3369e6ccc173SEdward Pilatowicz fi 3370e6ccc173SEdward Pilatowicz elif [[ -n "$oldname" ]]; then 3371e6ccc173SEdward Pilatowicz if [[ -n "$mv_but_nodiff" ]]; then 3372e6ccc173SEdward Pilatowicz print "<i>(renamed from $oldname)</i>" 3373e6ccc173SEdward Pilatowicz else 3374e6ccc173SEdward Pilatowicz print "<i>(renamed and modified from $oldname)</i>" 3375cdf0c1d5Smjnelson fi 3376cdf0c1d5Smjnelson fi 3377cdf0c1d5Smjnelson 3378cdf0c1d5Smjnelson # If there's an old file, but no new file, the file was deleted 3379cdf0c1d5Smjnelson if [[ -f $F-.html && ! -f $F.html ]]; then 3380cdf0c1d5Smjnelson print " <i>(deleted)</i>" 3381cdf0c1d5Smjnelson fi 3382daaffb31Sdp 3383daaffb31Sdp # 3384e0e0293aSjmcp # Check for usr/closed and deleted_files/usr/closed 3385daaffb31Sdp # 3386daaffb31Sdp if [ ! -z "$Oflag" ]; then 3387e0e0293aSjmcp if [[ $P == usr/closed/* || \ 3388e0e0293aSjmcp $P == deleted_files/usr/closed/* ]]; then 3389daaffb31Sdp print " <i>Closed source: omitted from" \ 3390daaffb31Sdp "this review</i>" 3391daaffb31Sdp fi 3392daaffb31Sdp fi 3393daaffb31Sdp 3394daaffb31Sdp print "</p>" 33957c478bd9Sstevel@tonic-gate # Insert delta comments 33967c478bd9Sstevel@tonic-gate 3397daaffb31Sdp print "<blockquote><pre>" 3398daaffb31Sdp getcomments html $P $PP 3399daaffb31Sdp print "</pre>" 34007c478bd9Sstevel@tonic-gate 34017c478bd9Sstevel@tonic-gate # Add additional comments comment 34027c478bd9Sstevel@tonic-gate 3403daaffb31Sdp print "<!-- Add comments to explain changes in $P here -->" 34047c478bd9Sstevel@tonic-gate 34057c478bd9Sstevel@tonic-gate # Add count of changes. 34067c478bd9Sstevel@tonic-gate 3407daaffb31Sdp if [[ -f $F.count ]]; then 34087c478bd9Sstevel@tonic-gate cat $F.count 34097c478bd9Sstevel@tonic-gate rm $F.count 34107c478bd9Sstevel@tonic-gate fi 3411cdf0c1d5Smjnelson 3412d7b56f41SBart Coddens if [[ $SCM_MODE == "mercurial" || 3413cdf0c1d5Smjnelson $SCM_MODE == "unknown" ]]; then 3414cdf0c1d5Smjnelson 3415cdf0c1d5Smjnelson # Include warnings for important file mode situations: 3416cdf0c1d5Smjnelson # 1) New executable files 3417cdf0c1d5Smjnelson # 2) Permission changes of any kind 3418cdf0c1d5Smjnelson # 3) Existing executable files 3419cdf0c1d5Smjnelson 3420cdf0c1d5Smjnelson old_mode= 3421cdf0c1d5Smjnelson if [[ -f $WDIR/raw_files/old/$PP ]]; then 3422cdf0c1d5Smjnelson old_mode=`get_file_mode $WDIR/raw_files/old/$PP` 3423cdf0c1d5Smjnelson fi 3424cdf0c1d5Smjnelson 3425cdf0c1d5Smjnelson new_mode= 3426cdf0c1d5Smjnelson if [[ -f $WDIR/raw_files/new/$P ]]; then 3427cdf0c1d5Smjnelson new_mode=`get_file_mode $WDIR/raw_files/new/$P` 3428cdf0c1d5Smjnelson fi 3429cdf0c1d5Smjnelson 3430cdf0c1d5Smjnelson if [[ -z "$old_mode" && "$new_mode" = *[1357]* ]]; then 3431cdf0c1d5Smjnelson print "<span class=\"chmod\">" 3432cdf0c1d5Smjnelson print "<p>new executable file: mode $new_mode</p>" 3433cdf0c1d5Smjnelson print "</span>" 3434cdf0c1d5Smjnelson elif [[ -n "$old_mode" && -n "$new_mode" && 3435cdf0c1d5Smjnelson "$old_mode" != "$new_mode" ]]; then 3436cdf0c1d5Smjnelson print "<span class=\"chmod\">" 3437cdf0c1d5Smjnelson print "<p>mode change: $old_mode to $new_mode</p>" 3438cdf0c1d5Smjnelson print "</span>" 3439cdf0c1d5Smjnelson elif [[ "$new_mode" = *[1357]* ]]; then 3440cdf0c1d5Smjnelson print "<span class=\"chmod\">" 3441cdf0c1d5Smjnelson print "<p>executable file: mode $new_mode</p>" 3442cdf0c1d5Smjnelson print "</span>" 3443cdf0c1d5Smjnelson fi 3444cdf0c1d5Smjnelson fi 3445cdf0c1d5Smjnelson 3446daaffb31Sdp print "</blockquote>" 34477c478bd9Sstevel@tonic-gatedone 34487c478bd9Sstevel@tonic-gate 3449daaffb31Sdpprint 3450daaffb31Sdpprint 3451cac38512Smjnelsonprint "<hr></hr>" 3452daaffb31Sdpprint "<p style=\"font-size: small\">" 34539a70fc3bSMark J. Nelsonprint "This code review page was prepared using <b>$0</b>." 345487a4464eSChris Loveprint "Webrev is maintained by the <a href=\"http://www.illumos.org\">" 345587a4464eSChris Loveprint "illumos</a> project. The latest version may be obtained" 34567646c8f3SMarcel Telkaprint "<a href=\"http://src.illumos.org/source/xref/illumos-gate/usr/src/tools/scripts/webrev.sh\">here</a>.</p>" 3457daaffb31Sdpprint "</body>" 3458daaffb31Sdpprint "</html>" 34597c478bd9Sstevel@tonic-gate 34607c478bd9Sstevel@tonic-gateexec 1<&- # Close FD 1. 34617c478bd9Sstevel@tonic-gateexec 1<&3 # dup FD 3 to restore stdout. 34627c478bd9Sstevel@tonic-gateexec 3<&- # close FD 3. 34637c478bd9Sstevel@tonic-gate 3464daaffb31Sdpprint "Done." 346502d26c39SVladimir Kotal 3466b0088928SVladimir Kotal# 3467ba44d8a2SVladimir Kotal# If remote deletion was specified and fails do not continue. 3468b0088928SVladimir Kotal# 3469ba44d8a2SVladimir Kotalif [[ -n $Dflag ]]; then 3470b0088928SVladimir Kotal delete_webrev 1 1 3471ba44d8a2SVladimir Kotal (( $? == 0 )) || exit $? 3472ba44d8a2SVladimir Kotalfi 3473ba44d8a2SVladimir Kotal 347402d26c39SVladimir Kotalif [[ -n $Uflag ]]; then 347502d26c39SVladimir Kotal upload_webrev 347602d26c39SVladimir Kotal exit $? 347702d26c39SVladimir Kotalfi 3478