19196SMark.J.Nelson@Sun.COM#!/usr/bin/ksh93 -p 20Sstevel@tonic-gate# 30Sstevel@tonic-gate# CDDL HEADER START 40Sstevel@tonic-gate# 50Sstevel@tonic-gate# The contents of this file are subject to the terms of the 63252Sdp# Common Development and Distribution License (the "License"). 73252Sdp# You may not use this file except in compliance with the License. 80Sstevel@tonic-gate# 90Sstevel@tonic-gate# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 100Sstevel@tonic-gate# or http://www.opensolaris.org/os/licensing. 110Sstevel@tonic-gate# See the License for the specific language governing permissions 120Sstevel@tonic-gate# and limitations under the License. 130Sstevel@tonic-gate# 140Sstevel@tonic-gate# When distributing Covered Code, include this CDDL HEADER in each 150Sstevel@tonic-gate# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 160Sstevel@tonic-gate# If applicable, add the following below this CDDL HEADER, with the 170Sstevel@tonic-gate# fields enclosed by brackets "[]" replaced with your own identifying 180Sstevel@tonic-gate# information: Portions Copyright [yyyy] [name of copyright owner] 190Sstevel@tonic-gate# 200Sstevel@tonic-gate# CDDL HEADER END 210Sstevel@tonic-gate# 227298SMark.J.Nelson@Sun.COM 230Sstevel@tonic-gate# 24*12776SJames.McPherson@Sun.COM# Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. 250Sstevel@tonic-gate# 267078Smjnelson 277078Smjnelson# 283252Sdp# This script takes a file list and a workspace and builds a set of html files 293252Sdp# suitable for doing a code review of source changes via a web page. 303252Sdp# Documentation is available via the manual page, webrev.1, or just 313252Sdp# type 'webrev -h'. 320Sstevel@tonic-gate# 333252Sdp# Acknowledgements to contributors to webrev are listed in the webrev(1) 343252Sdp# man page. 350Sstevel@tonic-gate# 363252Sdp 370Sstevel@tonic-gateREMOVED_COLOR=brown 380Sstevel@tonic-gateCHANGED_COLOR=blue 390Sstevel@tonic-gateNEW_COLOR=blue 400Sstevel@tonic-gate 413252SdpHTML='<?xml version="1.0"?> 423252Sdp<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 433252Sdp "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 443252Sdp<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">\n' 453252Sdp 463252SdpFRAMEHTML='<?xml version="1.0"?> 473252Sdp<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" 483252Sdp "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd"> 493252Sdp<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">\n' 503252Sdp 516922SmjnelsonSTDHEAD='<meta http-equiv="cache-control" content="no-cache"></meta> 526922Smjnelson<meta http-equiv="Pragma" content="no-cache"></meta> 536922Smjnelson<meta http-equiv="Expires" content="-1"></meta> 543252Sdp<!-- 553252Sdp Note to customizers: the body of the webrev is IDed as SUNWwebrev 563252Sdp to allow easy overriding by users of webrev via the userContent.css 573252Sdp mechanism available in some browsers. 583252Sdp 593252Sdp For example, to have all "removed" information be red instead of 603252Sdp brown, set a rule in your userContent.css file like: 613252Sdp 623252Sdp body#SUNWwebrev span.removed { color: red ! important; } 633252Sdp--> 643252Sdp<style type="text/css" media="screen"> 653252Sdpbody { 663252Sdp background-color: #eeeeee; 673252Sdp} 683252Sdphr { 693252Sdp border: none 0; 703252Sdp border-top: 1px solid #aaa; 713252Sdp height: 1px; 723252Sdp} 733252Sdpdiv.summary { 743252Sdp font-size: .8em; 753252Sdp border-bottom: 1px solid #aaa; 763252Sdp padding-left: 1em; 773252Sdp padding-right: 1em; 783252Sdp} 793252Sdpdiv.summary h2 { 803252Sdp margin-bottom: 0.3em; 813252Sdp} 823252Sdpdiv.summary table th { 833252Sdp text-align: right; 843252Sdp vertical-align: top; 853252Sdp white-space: nowrap; 863252Sdp} 873252Sdpspan.lineschanged { 883252Sdp font-size: 0.7em; 893252Sdp} 903252Sdpspan.oldmarker { 913252Sdp color: red; 923252Sdp font-size: large; 933252Sdp font-weight: bold; 943252Sdp} 953252Sdpspan.newmarker { 963252Sdp color: green; 973252Sdp font-size: large; 983252Sdp font-weight: bold; 993252Sdp} 1003252Sdpspan.removed { 1013252Sdp color: brown; 1023252Sdp} 1033252Sdpspan.changed { 1043252Sdp color: blue; 1053252Sdp} 1063252Sdpspan.new { 1073252Sdp color: blue; 1083252Sdp font-weight: bold; 1093252Sdp} 1107078Smjnelsonspan.chmod { 1117078Smjnelson font-size: 0.7em; 1127078Smjnelson color: #db7800; 1137078Smjnelson} 1143252Sdpa.print { font-size: x-small; } 1153252Sdpa:hover { background-color: #ffcc99; } 1163252Sdp</style> 1173252Sdp 1183252Sdp<style type="text/css" media="print"> 1193252Sdppre { font-size: 0.8em; font-family: courier, monospace; } 1203252Sdpspan.removed { color: #444; font-style: italic } 1213252Sdpspan.changed { font-weight: bold; } 1223252Sdpspan.new { font-weight: bold; } 1233252Sdpspan.newmarker { font-size: 1.2em; font-weight: bold; } 1243252Sdpspan.oldmarker { font-size: 1.2em; font-weight: bold; } 1253252Sdpa.print {display: none} 1263252Sdphr { border: none 0; border-top: 1px solid #aaa; height: 1px; } 1273252Sdp</style> 1283252Sdp' 1293252Sdp 1303252Sdp# 1313252Sdp# UDiffs need a slightly different CSS rule for 'new' items (we don't 1323252Sdp# want them to be bolded as we do in cdiffs or sdiffs). 1333252Sdp# 1343252SdpUDIFFCSS=' 1353252Sdp<style type="text/css" media="screen"> 1363252Sdpspan.new { 1373252Sdp color: blue; 1383252Sdp font-weight: normal; 1393252Sdp} 1403252Sdp</style> 1413252Sdp' 1423252Sdp 1439079SVladimir.Kotal@Sun.COM# 1449079SVladimir.Kotal@Sun.COM# Display remote target with prefix and trailing slash. 1459079SVladimir.Kotal@Sun.COM# 1469079SVladimir.Kotal@Sun.COMfunction print_upload_header 1479079SVladimir.Kotal@Sun.COM{ 1489079SVladimir.Kotal@Sun.COM typeset -r prefix=$1 1499079SVladimir.Kotal@Sun.COM typeset display_target 1509079SVladimir.Kotal@Sun.COM 1519079SVladimir.Kotal@Sun.COM if [[ -z $tflag ]]; then 1529079SVladimir.Kotal@Sun.COM display_target=${prefix}${remote_target} 1539079SVladimir.Kotal@Sun.COM else 1549079SVladimir.Kotal@Sun.COM display_target=${remote_target} 1559079SVladimir.Kotal@Sun.COM fi 1569079SVladimir.Kotal@Sun.COM 1579079SVladimir.Kotal@Sun.COM if [[ ${display_target} != */ ]]; then 1589079SVladimir.Kotal@Sun.COM display_target=${display_target}/ 1599079SVladimir.Kotal@Sun.COM fi 1609079SVladimir.Kotal@Sun.COM 1619079SVladimir.Kotal@Sun.COM print " Upload to: ${display_target}\n" \ 1629079SVladimir.Kotal@Sun.COM " Uploading: \c" 1639079SVladimir.Kotal@Sun.COM} 1649079SVladimir.Kotal@Sun.COM 1659079SVladimir.Kotal@Sun.COM# 1668018SVladimir.Kotal@Sun.COM# Upload the webrev via rsync. Return 0 on success, 1 on error. 1679079SVladimir.Kotal@Sun.COM# 1688365SVladimir.Kotal@Sun.COMfunction rsync_upload 1698018SVladimir.Kotal@Sun.COM{ 1709079SVladimir.Kotal@Sun.COM if (( $# != 2 )); then 1719079SVladimir.Kotal@Sun.COM print "\nERROR: rsync_upload: wrong usage ($#)" 1729079SVladimir.Kotal@Sun.COM exit 1 1739079SVladimir.Kotal@Sun.COM fi 1749079SVladimir.Kotal@Sun.COM 1759079SVladimir.Kotal@Sun.COM typeset -r dst=$1 1769079SVladimir.Kotal@Sun.COM integer -r print_err_msg=$2 1779079SVladimir.Kotal@Sun.COM 1789079SVladimir.Kotal@Sun.COM print_upload_header ${rsync_prefix} 1799079SVladimir.Kotal@Sun.COM print "rsync ... \c" 1809503SVladimir.Kotal@Sun.COM typeset -r err_msg=$( $MKTEMP /tmp/rsync_err.XXXXXX ) 1819079SVladimir.Kotal@Sun.COM if [[ -z $err_msg ]]; then 1829079SVladimir.Kotal@Sun.COM print "\nERROR: rsync_upload: cannot create temporary file" 1838018SVladimir.Kotal@Sun.COM return 1 1848018SVladimir.Kotal@Sun.COM fi 1859079SVladimir.Kotal@Sun.COM # 1869079SVladimir.Kotal@Sun.COM # The source directory must end with a slash in order to copy just 1879079SVladimir.Kotal@Sun.COM # directory contents, not the whole directory. 1889079SVladimir.Kotal@Sun.COM # 1899079SVladimir.Kotal@Sun.COM typeset src_dir=$WDIR 1909079SVladimir.Kotal@Sun.COM if [[ ${src_dir} != */ ]]; then 1919079SVladimir.Kotal@Sun.COM src_dir=${src_dir}/ 1929079SVladimir.Kotal@Sun.COM fi 1939079SVladimir.Kotal@Sun.COM $RSYNC -r -q ${src_dir} $dst 2>$err_msg 1948018SVladimir.Kotal@Sun.COM if (( $? != 0 )); then 1959079SVladimir.Kotal@Sun.COM if (( ${print_err_msg} > 0 )); then 1969079SVladimir.Kotal@Sun.COM print "Failed.\nERROR: rsync failed" 1979079SVladimir.Kotal@Sun.COM print "src dir: '${src_dir}'\ndst dir: '$dst'" 1989079SVladimir.Kotal@Sun.COM print "error messages:" 1999079SVladimir.Kotal@Sun.COM $SED 's/^/> /' $err_msg 2009079SVladimir.Kotal@Sun.COM rm -f $err_msg 2019079SVladimir.Kotal@Sun.COM fi 2028018SVladimir.Kotal@Sun.COM return 1 2038018SVladimir.Kotal@Sun.COM fi 2048018SVladimir.Kotal@Sun.COM 2059079SVladimir.Kotal@Sun.COM rm -f $err_msg 2068018SVladimir.Kotal@Sun.COM print "Done." 2078018SVladimir.Kotal@Sun.COM return 0 2088018SVladimir.Kotal@Sun.COM} 2098018SVladimir.Kotal@Sun.COM 2109079SVladimir.Kotal@Sun.COM# 2119079SVladimir.Kotal@Sun.COM# Create directories on remote host using SFTP. Return 0 on success, 2129079SVladimir.Kotal@Sun.COM# 1 on failure. 2139079SVladimir.Kotal@Sun.COM# 2149079SVladimir.Kotal@Sun.COMfunction remote_mkdirs 2159079SVladimir.Kotal@Sun.COM{ 2169079SVladimir.Kotal@Sun.COM typeset -r dir_spec=$1 21711735SVladimir.Kotal@Sun.COM typeset -r host_spec=$2 2189079SVladimir.Kotal@Sun.COM 2199079SVladimir.Kotal@Sun.COM # 2209079SVladimir.Kotal@Sun.COM # If the supplied path is absolute we assume all directories are 2219079SVladimir.Kotal@Sun.COM # created, otherwise try to create all directories in the path 2229079SVladimir.Kotal@Sun.COM # except the last one which will be created by scp. 2239079SVladimir.Kotal@Sun.COM # 2249079SVladimir.Kotal@Sun.COM if [[ "${dir_spec}" == */* && "${dir_spec}" != /* ]]; then 2259079SVladimir.Kotal@Sun.COM print "mkdirs \c" 2269079SVladimir.Kotal@Sun.COM # 2279079SVladimir.Kotal@Sun.COM # Remove the last directory from directory specification. 2289079SVladimir.Kotal@Sun.COM # 2299079SVladimir.Kotal@Sun.COM typeset -r dirs_mk=${dir_spec%/*} 2309503SVladimir.Kotal@Sun.COM typeset -r batch_file_mkdir=$( $MKTEMP \ 2319503SVladimir.Kotal@Sun.COM /tmp/webrev_mkdir.XXXXXX ) 2329079SVladimir.Kotal@Sun.COM if [[ -z $batch_file_mkdir ]]; then 2339079SVladimir.Kotal@Sun.COM print "\nERROR: remote_mkdirs:" \ 2349079SVladimir.Kotal@Sun.COM "cannot create temporary file for batch file" 2359079SVladimir.Kotal@Sun.COM return 1 2369079SVladimir.Kotal@Sun.COM fi 2379079SVladimir.Kotal@Sun.COM OLDIFS=$IFS 2389079SVladimir.Kotal@Sun.COM IFS=/ 2399079SVladimir.Kotal@Sun.COM typeset dir 2409079SVladimir.Kotal@Sun.COM for dir in ${dirs_mk}; do 2419079SVladimir.Kotal@Sun.COM # 2429079SVladimir.Kotal@Sun.COM # Use the '-' prefix to ignore mkdir errors in order 2439079SVladimir.Kotal@Sun.COM # to avoid an error in case the directory already 2449079SVladimir.Kotal@Sun.COM # exists. We check the directory with chdir to be sure 2459079SVladimir.Kotal@Sun.COM # there is one. 2469079SVladimir.Kotal@Sun.COM # 2479079SVladimir.Kotal@Sun.COM print -- "-mkdir ${dir}" >> ${batch_file_mkdir} 2489079SVladimir.Kotal@Sun.COM print "chdir ${dir}" >> ${batch_file_mkdir} 2499079SVladimir.Kotal@Sun.COM done 2509079SVladimir.Kotal@Sun.COM IFS=$OLDIFS 2519503SVladimir.Kotal@Sun.COM typeset -r sftp_err_msg=$( $MKTEMP /tmp/webrev_scp_err.XXXXXX ) 2529079SVladimir.Kotal@Sun.COM if [[ -z ${sftp_err_msg} ]]; then 2539079SVladimir.Kotal@Sun.COM print "\nERROR: remote_mkdirs:" \ 2549079SVladimir.Kotal@Sun.COM "cannot create temporary file for error messages" 2559079SVladimir.Kotal@Sun.COM return 1 2569079SVladimir.Kotal@Sun.COM fi 2579079SVladimir.Kotal@Sun.COM $SFTP -b ${batch_file_mkdir} ${host_spec} 2>${sftp_err_msg} 1>&2 2589079SVladimir.Kotal@Sun.COM if (( $? != 0 )); then 2599079SVladimir.Kotal@Sun.COM print "\nERROR: failed to create remote directories" 2609079SVladimir.Kotal@Sun.COM print "error messages:" 2619079SVladimir.Kotal@Sun.COM $SED 's/^/> /' ${sftp_err_msg} 2629079SVladimir.Kotal@Sun.COM rm -f ${sftp_err_msg} ${batch_file_mkdir} 2639079SVladimir.Kotal@Sun.COM return 1 2649079SVladimir.Kotal@Sun.COM fi 2659079SVladimir.Kotal@Sun.COM rm -f ${sftp_err_msg} ${batch_file_mkdir} 2669079SVladimir.Kotal@Sun.COM fi 2679079SVladimir.Kotal@Sun.COM 2689079SVladimir.Kotal@Sun.COM return 0 2699079SVladimir.Kotal@Sun.COM} 2709079SVladimir.Kotal@Sun.COM 2719079SVladimir.Kotal@Sun.COM# 2728018SVladimir.Kotal@Sun.COM# Upload the webrev via SSH. Return 0 on success, 1 on error. 2739079SVladimir.Kotal@Sun.COM# 2748365SVladimir.Kotal@Sun.COMfunction ssh_upload 2758018SVladimir.Kotal@Sun.COM{ 2768018SVladimir.Kotal@Sun.COM if (( $# != 1 )); then 2779079SVladimir.Kotal@Sun.COM print "\nERROR: ssh_upload: wrong number of arguments" 2789079SVladimir.Kotal@Sun.COM exit 1 2798018SVladimir.Kotal@Sun.COM fi 2808018SVladimir.Kotal@Sun.COM 2818018SVladimir.Kotal@Sun.COM typeset dst=$1 2828018SVladimir.Kotal@Sun.COM typeset -r host_spec=${dst%%:*} 2838365SVladimir.Kotal@Sun.COM typeset -r dir_spec=${dst#*:} 2848365SVladimir.Kotal@Sun.COM 2859079SVladimir.Kotal@Sun.COM # 2869079SVladimir.Kotal@Sun.COM # Display the upload information before calling delete_webrev 2879079SVladimir.Kotal@Sun.COM # because it will also print its progress. 2889079SVladimir.Kotal@Sun.COM # 2899079SVladimir.Kotal@Sun.COM print_upload_header ${ssh_prefix} 2909079SVladimir.Kotal@Sun.COM 2919079SVladimir.Kotal@Sun.COM # 2929079SVladimir.Kotal@Sun.COM # If the deletion was explicitly requested there is no need 2939079SVladimir.Kotal@Sun.COM # to perform it again. 2949079SVladimir.Kotal@Sun.COM # 2958365SVladimir.Kotal@Sun.COM if [[ -z $Dflag ]]; then 2969079SVladimir.Kotal@Sun.COM # 2979079SVladimir.Kotal@Sun.COM # We do not care about return value because this might be 2989079SVladimir.Kotal@Sun.COM # the first time this directory is uploaded. 2999079SVladimir.Kotal@Sun.COM # 3008365SVladimir.Kotal@Sun.COM delete_webrev 0 3018018SVladimir.Kotal@Sun.COM fi 3028018SVladimir.Kotal@Sun.COM 3039079SVladimir.Kotal@Sun.COM # 3049079SVladimir.Kotal@Sun.COM # Create remote directories. Any error reporting will be done 3059079SVladimir.Kotal@Sun.COM # in remote_mkdirs function. 3069079SVladimir.Kotal@Sun.COM # 30711735SVladimir.Kotal@Sun.COM remote_mkdirs ${dir_spec} ${host_spec} 3088018SVladimir.Kotal@Sun.COM if (( $? != 0 )); then 3098018SVladimir.Kotal@Sun.COM return 1 3108018SVladimir.Kotal@Sun.COM fi 3118018SVladimir.Kotal@Sun.COM 3129079SVladimir.Kotal@Sun.COM print "upload ... \c" 3139503SVladimir.Kotal@Sun.COM typeset -r scp_err_msg=$( $MKTEMP /tmp/scp_err.XXXXXX ) 3149079SVladimir.Kotal@Sun.COM if [[ -z ${scp_err_msg} ]]; then 3159079SVladimir.Kotal@Sun.COM print "\nERROR: ssh_upload:" \ 3169079SVladimir.Kotal@Sun.COM "cannot create temporary file for error messages" 3179079SVladimir.Kotal@Sun.COM return 1 3189079SVladimir.Kotal@Sun.COM fi 3199079SVladimir.Kotal@Sun.COM $SCP -q -C -B -o PreferredAuthentications=publickey -r \ 3209079SVladimir.Kotal@Sun.COM $WDIR $dst 2>${scp_err_msg} 3219079SVladimir.Kotal@Sun.COM if (( $? != 0 )); then 3229079SVladimir.Kotal@Sun.COM print "Failed.\nERROR: scp failed" 3239079SVladimir.Kotal@Sun.COM print "src dir: '$WDIR'\ndst dir: '$dst'" 3249079SVladimir.Kotal@Sun.COM print "error messages:" 3259079SVladimir.Kotal@Sun.COM $SED 's/^/> /' ${scp_err_msg} 3269079SVladimir.Kotal@Sun.COM rm -f ${scp_err_msg} 3279079SVladimir.Kotal@Sun.COM return 1 3289079SVladimir.Kotal@Sun.COM fi 3299079SVladimir.Kotal@Sun.COM 3309079SVladimir.Kotal@Sun.COM rm -f ${scp_err_msg} 3318018SVladimir.Kotal@Sun.COM print "Done." 3328018SVladimir.Kotal@Sun.COM return 0 3338018SVladimir.Kotal@Sun.COM} 3348018SVladimir.Kotal@Sun.COM 3358018SVladimir.Kotal@Sun.COM# 3368365SVladimir.Kotal@Sun.COM# Delete webrev at remote site. Return 0 on success, 1 or exit code from sftp 3379079SVladimir.Kotal@Sun.COM# on failure. If first argument is 1 then perform the check of sftp return 3389079SVladimir.Kotal@Sun.COM# value otherwise ignore it. If second argument is present it means this run 3399079SVladimir.Kotal@Sun.COM# only performs deletion. 3408365SVladimir.Kotal@Sun.COM# 3418365SVladimir.Kotal@Sun.COMfunction delete_webrev 3428365SVladimir.Kotal@Sun.COM{ 3439079SVladimir.Kotal@Sun.COM if (( $# < 1 )); then 3449079SVladimir.Kotal@Sun.COM print "delete_webrev: wrong number of arguments" 3459079SVladimir.Kotal@Sun.COM exit 1 3468365SVladimir.Kotal@Sun.COM fi 3478365SVladimir.Kotal@Sun.COM 3489079SVladimir.Kotal@Sun.COM integer -r check=$1 3499079SVladimir.Kotal@Sun.COM integer delete_only=0 3509079SVladimir.Kotal@Sun.COM if (( $# == 2 )); then 3519079SVladimir.Kotal@Sun.COM delete_only=1 3529079SVladimir.Kotal@Sun.COM fi 3539079SVladimir.Kotal@Sun.COM 3549079SVladimir.Kotal@Sun.COM # 3558365SVladimir.Kotal@Sun.COM # Strip the transport specification part of remote target first. 3569079SVladimir.Kotal@Sun.COM # 3578365SVladimir.Kotal@Sun.COM typeset -r stripped_target=${remote_target##*://} 3588365SVladimir.Kotal@Sun.COM typeset -r host_spec=${stripped_target%%:*} 3598365SVladimir.Kotal@Sun.COM typeset -r dir_spec=${stripped_target#*:} 3608365SVladimir.Kotal@Sun.COM typeset dir_rm 3618365SVladimir.Kotal@Sun.COM 3629079SVladimir.Kotal@Sun.COM # 3638365SVladimir.Kotal@Sun.COM # Do not accept an absolute path. 3649079SVladimir.Kotal@Sun.COM # 3658365SVladimir.Kotal@Sun.COM if [[ ${dir_spec} == /* ]]; then 3668365SVladimir.Kotal@Sun.COM return 1 3678365SVladimir.Kotal@Sun.COM fi 3688365SVladimir.Kotal@Sun.COM 3699079SVladimir.Kotal@Sun.COM # 3708365SVladimir.Kotal@Sun.COM # Strip the ending slash. 3719079SVladimir.Kotal@Sun.COM # 3728365SVladimir.Kotal@Sun.COM if [[ ${dir_spec} == */ ]]; then 3738365SVladimir.Kotal@Sun.COM dir_rm=${dir_spec%%/} 3748365SVladimir.Kotal@Sun.COM else 3758365SVladimir.Kotal@Sun.COM dir_rm=${dir_spec} 3768365SVladimir.Kotal@Sun.COM fi 3778365SVladimir.Kotal@Sun.COM 3789079SVladimir.Kotal@Sun.COM if (( ${delete_only} > 0 )); then 3799079SVladimir.Kotal@Sun.COM print " Removing: \c" 3809079SVladimir.Kotal@Sun.COM else 3819079SVladimir.Kotal@Sun.COM print "rmdir \c" 3829079SVladimir.Kotal@Sun.COM fi 3838365SVladimir.Kotal@Sun.COM if [[ -z "$dir_rm" ]]; then 3849079SVladimir.Kotal@Sun.COM print "\nERROR: empty directory for removal" 3858365SVladimir.Kotal@Sun.COM return 1 3868365SVladimir.Kotal@Sun.COM fi 3878365SVladimir.Kotal@Sun.COM 3889079SVladimir.Kotal@Sun.COM # 3898365SVladimir.Kotal@Sun.COM # Prepare batch file. 3909079SVladimir.Kotal@Sun.COM # 3919503SVladimir.Kotal@Sun.COM typeset -r batch_file_rm=$( $MKTEMP /tmp/webrev_remove.XXXXXX ) 3928365SVladimir.Kotal@Sun.COM if [[ -z $batch_file_rm ]]; then 3939079SVladimir.Kotal@Sun.COM print "\nERROR: delete_webrev: cannot create temporary file" 3948365SVladimir.Kotal@Sun.COM return 1 3958365SVladimir.Kotal@Sun.COM fi 3968365SVladimir.Kotal@Sun.COM print "rename $dir_rm $TRASH_DIR/removed.$$" > $batch_file_rm 3978365SVladimir.Kotal@Sun.COM 3989079SVladimir.Kotal@Sun.COM # 3998365SVladimir.Kotal@Sun.COM # Perform remote deletion and remove the batch file. 4009079SVladimir.Kotal@Sun.COM # 4019503SVladimir.Kotal@Sun.COM typeset -r sftp_err_msg=$( $MKTEMP /tmp/webrev_scp_err.XXXXXX ) 4029079SVladimir.Kotal@Sun.COM if [[ -z ${sftp_err_msg} ]]; then 4039079SVladimir.Kotal@Sun.COM print "\nERROR: delete_webrev:" \ 4049079SVladimir.Kotal@Sun.COM "cannot create temporary file for error messages" 4059079SVladimir.Kotal@Sun.COM return 1 4069079SVladimir.Kotal@Sun.COM fi 4079079SVladimir.Kotal@Sun.COM $SFTP -b $batch_file_rm $host_spec 2>${sftp_err_msg} 1>&2 4088365SVladimir.Kotal@Sun.COM integer -r ret=$? 4098365SVladimir.Kotal@Sun.COM rm -f $batch_file_rm 4108365SVladimir.Kotal@Sun.COM if (( $ret != 0 && $check > 0 )); then 4119079SVladimir.Kotal@Sun.COM print "Failed.\nERROR: failed to remove remote directories" 4129079SVladimir.Kotal@Sun.COM print "error messages:" 4139079SVladimir.Kotal@Sun.COM $SED 's/^/> /' ${sftp_err_msg} 4149079SVladimir.Kotal@Sun.COM rm -f ${sftp_err_msg} 4158365SVladimir.Kotal@Sun.COM return $ret 4168365SVladimir.Kotal@Sun.COM fi 4179079SVladimir.Kotal@Sun.COM rm -f ${sftp_err_msg} 4189079SVladimir.Kotal@Sun.COM if (( ${delete_only} > 0 )); then 4199079SVladimir.Kotal@Sun.COM print "Done." 4209079SVladimir.Kotal@Sun.COM fi 4218365SVladimir.Kotal@Sun.COM 4228365SVladimir.Kotal@Sun.COM return 0 4238365SVladimir.Kotal@Sun.COM} 4248365SVladimir.Kotal@Sun.COM 4258365SVladimir.Kotal@Sun.COM# 4268018SVladimir.Kotal@Sun.COM# Upload webrev to remote site 4278018SVladimir.Kotal@Sun.COM# 4288365SVladimir.Kotal@Sun.COMfunction upload_webrev 4298018SVladimir.Kotal@Sun.COM{ 4309079SVladimir.Kotal@Sun.COM integer ret 4318018SVladimir.Kotal@Sun.COM 4328018SVladimir.Kotal@Sun.COM if [[ ! -d "$WDIR" ]]; then 4339079SVladimir.Kotal@Sun.COM print "\nERROR: webrev directory '$WDIR' does not exist" 4348018SVladimir.Kotal@Sun.COM return 1 4358018SVladimir.Kotal@Sun.COM fi 4368018SVladimir.Kotal@Sun.COM 4379079SVladimir.Kotal@Sun.COM # 4388018SVladimir.Kotal@Sun.COM # Perform a late check to make sure we do not upload closed source 4398018SVladimir.Kotal@Sun.COM # to remote target when -n is used. If the user used custom remote 4408018SVladimir.Kotal@Sun.COM # target he probably knows what he is doing. 4419079SVladimir.Kotal@Sun.COM # 4428018SVladimir.Kotal@Sun.COM if [[ -n $nflag && -z $tflag ]]; then 4438365SVladimir.Kotal@Sun.COM $FIND $WDIR -type d -name closed \ 4448018SVladimir.Kotal@Sun.COM | $GREP closed >/dev/null 4458018SVladimir.Kotal@Sun.COM if (( $? == 0 )); then 4469079SVladimir.Kotal@Sun.COM print "\nERROR: directory '$WDIR' contains" \ 4479079SVladimir.Kotal@Sun.COM "\"closed\" directory" 4488018SVladimir.Kotal@Sun.COM return 1 4498018SVladimir.Kotal@Sun.COM fi 4508018SVladimir.Kotal@Sun.COM fi 4518018SVladimir.Kotal@Sun.COM 4529079SVladimir.Kotal@Sun.COM 4539079SVladimir.Kotal@Sun.COM # 4549079SVladimir.Kotal@Sun.COM # We have the URI for remote destination now so let's start the upload. 4559079SVladimir.Kotal@Sun.COM # 4568018SVladimir.Kotal@Sun.COM if [[ -n $tflag ]]; then 4578018SVladimir.Kotal@Sun.COM if [[ "${remote_target}" == ${rsync_prefix}?* ]]; then 4589079SVladimir.Kotal@Sun.COM rsync_upload ${remote_target##$rsync_prefix} 1 4599079SVladimir.Kotal@Sun.COM ret=$? 4609079SVladimir.Kotal@Sun.COM return $ret 4618018SVladimir.Kotal@Sun.COM elif [[ "${remote_target}" == ${ssh_prefix}?* ]]; then 4628018SVladimir.Kotal@Sun.COM ssh_upload ${remote_target##$ssh_prefix} 4639079SVladimir.Kotal@Sun.COM ret=$? 4649079SVladimir.Kotal@Sun.COM return $ret 4658018SVladimir.Kotal@Sun.COM fi 4668018SVladimir.Kotal@Sun.COM else 4679079SVladimir.Kotal@Sun.COM # 4689079SVladimir.Kotal@Sun.COM # Try rsync first and fallback to SSH in case it fails. 4699079SVladimir.Kotal@Sun.COM # 4709079SVladimir.Kotal@Sun.COM rsync_upload ${remote_target} 0 4719079SVladimir.Kotal@Sun.COM ret=$? 4729079SVladimir.Kotal@Sun.COM if (( $ret != 0 )); then 4739079SVladimir.Kotal@Sun.COM print "Failed. (falling back to SSH)" 4748365SVladimir.Kotal@Sun.COM ssh_upload ${remote_target} 4759079SVladimir.Kotal@Sun.COM ret=$? 4768018SVladimir.Kotal@Sun.COM fi 4779079SVladimir.Kotal@Sun.COM return $ret 4788018SVladimir.Kotal@Sun.COM fi 4798018SVladimir.Kotal@Sun.COM} 4808018SVladimir.Kotal@Sun.COM 4813252Sdp# 4829011SLubomir.Sedlacik@Sun.COM# input_cmd | url_encode | output_cmd 4839011SLubomir.Sedlacik@Sun.COM# 4849011SLubomir.Sedlacik@Sun.COM# URL-encode (percent-encode) reserved characters as defined in RFC 3986. 4859011SLubomir.Sedlacik@Sun.COM# 4869011SLubomir.Sedlacik@Sun.COM# Reserved characters are: :/?#[]@!$&'()*+,;= 4879011SLubomir.Sedlacik@Sun.COM# 4889011SLubomir.Sedlacik@Sun.COM# While not a reserved character itself, percent '%' is reserved by definition 4899011SLubomir.Sedlacik@Sun.COM# so encode it first to avoid recursive transformation, and skip '/' which is 4909011SLubomir.Sedlacik@Sun.COM# a path delimiter. 4919011SLubomir.Sedlacik@Sun.COM# 4929561SVladimir.Kotal@Sun.COM# The quotation character is deliberately not escaped in order to make 4939561SVladimir.Kotal@Sun.COM# the substitution work with GNU sed. 4949561SVladimir.Kotal@Sun.COM# 4959011SLubomir.Sedlacik@Sun.COMfunction url_encode 4969011SLubomir.Sedlacik@Sun.COM{ 4979079SVladimir.Kotal@Sun.COM $SED -e "s|%|%25|g" -e "s|:|%3A|g" -e "s|\&|%26|g" \ 4989011SLubomir.Sedlacik@Sun.COM -e "s|?|%3F|g" -e "s|#|%23|g" -e "s|\[|%5B|g" \ 4999011SLubomir.Sedlacik@Sun.COM -e "s|*|%2A|g" -e "s|@|%40|g" -e "s|\!|%21|g" \ 5009011SLubomir.Sedlacik@Sun.COM -e "s|=|%3D|g" -e "s|;|%3B|g" -e "s|\]|%5D|g" \ 5019561SVladimir.Kotal@Sun.COM -e "s|(|%28|g" -e "s|)|%29|g" -e "s|'|%27|g" \ 5029011SLubomir.Sedlacik@Sun.COM -e "s|+|%2B|g" -e "s|\,|%2C|g" -e "s|\\\$|%24|g" 5039011SLubomir.Sedlacik@Sun.COM} 5049011SLubomir.Sedlacik@Sun.COM 5059011SLubomir.Sedlacik@Sun.COM# 5063252Sdp# input_cmd | html_quote | output_cmd 5073252Sdp# or 5083252Sdp# html_quote filename | output_cmd 5090Sstevel@tonic-gate# 5100Sstevel@tonic-gate# Make a piece of source code safe for display in an HTML <pre> block. 5110Sstevel@tonic-gate# 5120Sstevel@tonic-gatehtml_quote() 5130Sstevel@tonic-gate{ 5149079SVladimir.Kotal@Sun.COM $SED -e "s/&/\&/g" -e "s/</\</g" -e "s/>/\>/g" "$@" | expand 5150Sstevel@tonic-gate} 5160Sstevel@tonic-gate 5173252Sdp# 5189193SMark.J.Nelson@Sun.COM# input_cmd | its2url | output_cmd 5193252Sdp# 5209193SMark.J.Nelson@Sun.COM# Scan for information tracking system references and insert <a> links to the 5219193SMark.J.Nelson@Sun.COM# relevant databases. 5220Sstevel@tonic-gate# 5239193SMark.J.Nelson@Sun.COMits2url() 5243252Sdp{ 5259193SMark.J.Nelson@Sun.COM $SED -f ${its_sed_script} 5263252Sdp} 5273252Sdp 5283252Sdp# 5293252Sdp# strip_unchanged <infile> | output_cmd 5300Sstevel@tonic-gate# 5313252Sdp# Removes chunks of sdiff documents that have not changed. This makes it 5323252Sdp# easier for a code reviewer to find the bits that have changed. 5333252Sdp# 5343252Sdp# Deleted lines of text are replaced by a horizontal rule. Some 5353252Sdp# identical lines are retained before and after the changed lines to 5363252Sdp# provide some context. The number of these lines is controlled by the 5377078Smjnelson# variable C in the $AWK script below. 5383252Sdp# 5393252Sdp# The script detects changed lines as any line that has a "<span class=" 5403252Sdp# string embedded (unchanged lines have no particular class and are not 5413252Sdp# part of a <span>). Blank lines (without a sequence number) are also 5423252Sdp# detected since they flag lines that have been inserted or deleted. 5430Sstevel@tonic-gate# 5443252Sdpstrip_unchanged() 5453252Sdp{ 5467078Smjnelson $AWK ' 5473252Sdp BEGIN { C = c = 20 } 5487078Smjnelson NF == 0 || /<span class="/ { 5493252Sdp if (c > C) { 5503252Sdp c -= C 5513252Sdp inx = 0 5523252Sdp if (c > C) { 5536922Smjnelson print "\n</pre><hr></hr><pre>" 5543252Sdp inx = c % C 5553252Sdp c = C 5563252Sdp } 5573252Sdp 5583252Sdp for (i = 0; i < c; i++) 5593252Sdp print ln[(inx + i) % C] 5603252Sdp } 5613252Sdp c = 0; 5623252Sdp print 5633252Sdp next 5643252Sdp } 5653252Sdp { if (c >= C) { 5663252Sdp ln[c % C] = $0 5673252Sdp c++; 5683252Sdp next; 5693252Sdp } 5703252Sdp c++; 5713252Sdp print 5723252Sdp } 5736922Smjnelson END { if (c > (C * 2)) print "\n</pre><hr></hr>" } 5743252Sdp 5753252Sdp ' $1 5763252Sdp} 5773252Sdp 5780Sstevel@tonic-gate# 5793252Sdp# sdiff_to_html 5803252Sdp# 5813252Sdp# This function takes two files as arguments, obtains their diff, and 5823252Sdp# processes the diff output to present the files as an HTML document with 5833252Sdp# the files displayed side-by-side, differences shown in color. It also 5843252Sdp# takes a delta comment, rendered as an HTML snippet, as the third 5853252Sdp# argument. The function takes two files as arguments, then the name of 5863252Sdp# file, the path, and the comment. The HTML will be delivered on stdout, 5873252Sdp# e.g. 5880Sstevel@tonic-gate# 5893252Sdp# $ sdiff_to_html old/usr/src/tools/scripts/webrev.sh \ 5903252Sdp# new/usr/src/tools/scripts/webrev.sh \ 5913252Sdp# webrev.sh usr/src/tools/scripts \ 5923252Sdp# '<a href="http://monaco.sfbay.sun.com/detail.jsp?cr=1234567"> 5933252Sdp# 1234567</a> my bugid' > <file>.html 5943252Sdp# 5953252Sdp# framed_sdiff() is then called which creates $2.frames.html 5963252Sdp# in the webrev tree. 5973252Sdp# 5983252Sdp# FYI: This function is rather unusual in its use of awk. The initial 5993252Sdp# diff run produces conventional diff output showing changed lines mixed 6003252Sdp# with editing codes. The changed lines are ignored - we're interested in 6013252Sdp# the editing codes, e.g. 6020Sstevel@tonic-gate# 6030Sstevel@tonic-gate# 8c8 6040Sstevel@tonic-gate# 57a61 6050Sstevel@tonic-gate# 63c66,76 6060Sstevel@tonic-gate# 68,93d80 6070Sstevel@tonic-gate# 106d90 6080Sstevel@tonic-gate# 108,110d91 6090Sstevel@tonic-gate# 6103252Sdp# These editing codes are parsed by the awk script and used to generate 6113252Sdp# another awk script that generates HTML, e.g the above lines would turn 6123252Sdp# into something like this: 6130Sstevel@tonic-gate# 6140Sstevel@tonic-gate# BEGIN { printf "<pre>\n" } 6150Sstevel@tonic-gate# function sp(n) {for (i=0;i<n;i++)printf "\n"} 6163252Sdp# function wl(n) {printf "<font color=%s>%4d %s </font>\n", n, NR, $0} 6170Sstevel@tonic-gate# NR==8 {wl("#7A7ADD");next} 6180Sstevel@tonic-gate# NR==54 {wl("#7A7ADD");sp(3);next} 6190Sstevel@tonic-gate# NR==56 {wl("#7A7ADD");next} 6200Sstevel@tonic-gate# NR==57 {wl("black");printf "\n"; next} 6210Sstevel@tonic-gate# : : 6220Sstevel@tonic-gate# 6233252Sdp# This script is then run on the original source file to generate the 6243252Sdp# HTML that corresponds to the source file. 6250Sstevel@tonic-gate# 6263252Sdp# The two HTML files are then combined into a single piece of HTML that 6273252Sdp# uses an HTML table construct to present the files side by side. You'll 6283252Sdp# notice that the changes are color-coded: 6290Sstevel@tonic-gate# 6300Sstevel@tonic-gate# black - unchanged lines 6310Sstevel@tonic-gate# blue - changed lines 6320Sstevel@tonic-gate# bold blue - new lines 6330Sstevel@tonic-gate# brown - deleted lines 6340Sstevel@tonic-gate# 6353252Sdp# Blank lines are inserted in each file to keep unchanged lines in sync 6363252Sdp# (side-by-side). This format is familiar to users of sdiff(1) or 6373252Sdp# Teamware's filemerge tool. 6383252Sdp# 6393252Sdpsdiff_to_html() 6403252Sdp{ 6413252Sdp diff -b $1 $2 > /tmp/$$.diffs 6420Sstevel@tonic-gate 6433252Sdp TNAME=$3 6443252Sdp TPATH=$4 6453252Sdp COMMENT=$5 6460Sstevel@tonic-gate 6473252Sdp # 6483252Sdp # Now we have the diffs, generate the HTML for the old file. 6493252Sdp # 6507078Smjnelson $AWK ' 6513252Sdp BEGIN { 6523252Sdp printf "function sp(n) {for (i=0;i<n;i++)printf \"\\n\"}\n" 6533252Sdp printf "function removed() " 6543252Sdp printf "{printf \"<span class=\\\"removed\\\">%%4d %%s</span>\\n\", NR, $0}\n" 6553252Sdp printf "function changed() " 6563252Sdp printf "{printf \"<span class=\\\"changed\\\">%%4d %%s</span>\\n\", NR, $0}\n" 6573252Sdp printf "function bl() {printf \"%%4d %%s\\n\", NR, $0}\n" 6583252Sdp} 6593252Sdp /^</ {next} 6603252Sdp /^>/ {next} 6613252Sdp /^---/ {next} 6620Sstevel@tonic-gate 6633252Sdp { 6640Sstevel@tonic-gate split($1, a, /[cad]/) ; 6650Sstevel@tonic-gate if (index($1, "a")) { 6660Sstevel@tonic-gate if (a[1] == 0) { 6670Sstevel@tonic-gate n = split(a[2], r, /,/); 6680Sstevel@tonic-gate if (n == 1) 6690Sstevel@tonic-gate printf "BEGIN\t\t{sp(1)}\n" 6700Sstevel@tonic-gate else 6710Sstevel@tonic-gate printf "BEGIN\t\t{sp(%d)}\n",\ 6720Sstevel@tonic-gate (r[2] - r[1]) + 1 6730Sstevel@tonic-gate next 6740Sstevel@tonic-gate } 6750Sstevel@tonic-gate 6760Sstevel@tonic-gate printf "NR==%s\t\t{", a[1] 6770Sstevel@tonic-gate n = split(a[2], r, /,/); 6780Sstevel@tonic-gate s = r[1]; 6790Sstevel@tonic-gate if (n == 1) 6800Sstevel@tonic-gate printf "bl();printf \"\\n\"; next}\n" 6810Sstevel@tonic-gate else { 6820Sstevel@tonic-gate n = r[2] - r[1] 6830Sstevel@tonic-gate printf "bl();sp(%d);next}\n",\ 6840Sstevel@tonic-gate (r[2] - r[1]) + 1 6850Sstevel@tonic-gate } 6863252Sdp next 6870Sstevel@tonic-gate } 6880Sstevel@tonic-gate if (index($1, "d")) { 6890Sstevel@tonic-gate n = split(a[1], r, /,/); 6900Sstevel@tonic-gate n1 = r[1] 6910Sstevel@tonic-gate n2 = r[2] 6920Sstevel@tonic-gate if (n == 1) 6933252Sdp printf "NR==%s\t\t{removed(); next}\n" , n1 6940Sstevel@tonic-gate else 6953252Sdp printf "NR==%s,NR==%s\t{removed(); next}\n" , n1, n2 6963252Sdp next 6970Sstevel@tonic-gate } 6980Sstevel@tonic-gate if (index($1, "c")) { 6990Sstevel@tonic-gate n = split(a[1], r, /,/); 7000Sstevel@tonic-gate n1 = r[1] 7010Sstevel@tonic-gate n2 = r[2] 7020Sstevel@tonic-gate final = n2 7030Sstevel@tonic-gate d1 = 0 7040Sstevel@tonic-gate if (n == 1) 7053252Sdp printf "NR==%s\t\t{changed();" , n1 7060Sstevel@tonic-gate else { 7070Sstevel@tonic-gate d1 = n2 - n1 7083252Sdp printf "NR==%s,NR==%s\t{changed();" , n1, n2 7090Sstevel@tonic-gate } 7100Sstevel@tonic-gate m = split(a[2], r, /,/); 7110Sstevel@tonic-gate n1 = r[1] 7120Sstevel@tonic-gate n2 = r[2] 7130Sstevel@tonic-gate if (m > 1) { 7140Sstevel@tonic-gate d2 = n2 - n1 7150Sstevel@tonic-gate if (d2 > d1) { 7160Sstevel@tonic-gate if (n > 1) printf "if (NR==%d)", final 7170Sstevel@tonic-gate printf "sp(%d);", d2 - d1 7180Sstevel@tonic-gate } 7190Sstevel@tonic-gate } 7200Sstevel@tonic-gate printf "next}\n" ; 7213252Sdp 7223252Sdp next 7233252Sdp } 7240Sstevel@tonic-gate } 7250Sstevel@tonic-gate 7263252Sdp END { printf "{printf \"%%4d %%s\\n\", NR, $0 }\n" } 7273252Sdp ' /tmp/$$.diffs > /tmp/$$.file1 7280Sstevel@tonic-gate 7293252Sdp # 7303252Sdp # Now generate the HTML for the new file 7313252Sdp # 7327078Smjnelson $AWK ' 7333252Sdp BEGIN { 7343252Sdp printf "function sp(n) {for (i=0;i<n;i++)printf \"\\n\"}\n" 7353252Sdp printf "function new() " 7363252Sdp printf "{printf \"<span class=\\\"new\\\">%%4d %%s</span>\\n\", NR, $0}\n" 7373252Sdp printf "function changed() " 7383252Sdp printf "{printf \"<span class=\\\"changed\\\">%%4d %%s</span>\\n\", NR, $0}\n" 7393252Sdp printf "function bl() {printf \"%%4d %%s\\n\", NR, $0}\n" 7403252Sdp } 7410Sstevel@tonic-gate 7423252Sdp /^</ {next} 7433252Sdp /^>/ {next} 7443252Sdp /^---/ {next} 7453252Sdp 7463252Sdp { 7470Sstevel@tonic-gate split($1, a, /[cad]/) ; 7480Sstevel@tonic-gate if (index($1, "d")) { 7490Sstevel@tonic-gate if (a[2] == 0) { 7500Sstevel@tonic-gate n = split(a[1], r, /,/); 7510Sstevel@tonic-gate if (n == 1) 7520Sstevel@tonic-gate printf "BEGIN\t\t{sp(1)}\n" 7530Sstevel@tonic-gate else 7540Sstevel@tonic-gate printf "BEGIN\t\t{sp(%d)}\n",\ 7550Sstevel@tonic-gate (r[2] - r[1]) + 1 7560Sstevel@tonic-gate next 7570Sstevel@tonic-gate } 7580Sstevel@tonic-gate 7590Sstevel@tonic-gate printf "NR==%s\t\t{", a[2] 7600Sstevel@tonic-gate n = split(a[1], r, /,/); 7610Sstevel@tonic-gate s = r[1]; 7620Sstevel@tonic-gate if (n == 1) 7630Sstevel@tonic-gate printf "bl();printf \"\\n\"; next}\n" 7640Sstevel@tonic-gate else { 7650Sstevel@tonic-gate n = r[2] - r[1] 7660Sstevel@tonic-gate printf "bl();sp(%d);next}\n",\ 7670Sstevel@tonic-gate (r[2] - r[1]) + 1 7680Sstevel@tonic-gate } 7693252Sdp next 7700Sstevel@tonic-gate } 7710Sstevel@tonic-gate if (index($1, "a")) { 7720Sstevel@tonic-gate n = split(a[2], r, /,/); 7730Sstevel@tonic-gate n1 = r[1] 7740Sstevel@tonic-gate n2 = r[2] 7750Sstevel@tonic-gate if (n == 1) 7763252Sdp printf "NR==%s\t\t{new() ; next}\n" , n1 7770Sstevel@tonic-gate else 7783252Sdp printf "NR==%s,NR==%s\t{new() ; next}\n" , n1, n2 7793252Sdp next 7800Sstevel@tonic-gate } 7810Sstevel@tonic-gate if (index($1, "c")) { 7820Sstevel@tonic-gate n = split(a[2], r, /,/); 7830Sstevel@tonic-gate n1 = r[1] 7840Sstevel@tonic-gate n2 = r[2] 7850Sstevel@tonic-gate final = n2 7860Sstevel@tonic-gate d2 = 0; 7870Sstevel@tonic-gate if (n == 1) { 7880Sstevel@tonic-gate final = n1 7893252Sdp printf "NR==%s\t\t{changed();" , n1 7900Sstevel@tonic-gate } else { 7910Sstevel@tonic-gate d2 = n2 - n1 7923252Sdp printf "NR==%s,NR==%s\t{changed();" , n1, n2 7930Sstevel@tonic-gate } 7940Sstevel@tonic-gate m = split(a[1], r, /,/); 7950Sstevel@tonic-gate n1 = r[1] 7960Sstevel@tonic-gate n2 = r[2] 7970Sstevel@tonic-gate if (m > 1) { 7980Sstevel@tonic-gate d1 = n2 - n1 7990Sstevel@tonic-gate if (d1 > d2) { 8000Sstevel@tonic-gate if (n > 1) printf "if (NR==%d)", final 8010Sstevel@tonic-gate printf "sp(%d);", d1 - d2 8020Sstevel@tonic-gate } 8030Sstevel@tonic-gate } 8040Sstevel@tonic-gate printf "next}\n" ; 8053252Sdp next 8063252Sdp } 8070Sstevel@tonic-gate } 8083252Sdp END { printf "{printf \"%%4d %%s\\n\", NR, $0 }\n" } 8093252Sdp ' /tmp/$$.diffs > /tmp/$$.file2 8100Sstevel@tonic-gate 8113252Sdp # 8127078Smjnelson # Post-process the HTML files by running them back through $AWK 8133252Sdp # 8147078Smjnelson html_quote < $1 | $AWK -f /tmp/$$.file1 > /tmp/$$.file1.html 8157078Smjnelson 8167078Smjnelson html_quote < $2 | $AWK -f /tmp/$$.file2 > /tmp/$$.file2.html 8170Sstevel@tonic-gate 8183252Sdp # 8193252Sdp # Now combine into a valid HTML file and side-by-side into a table 8203252Sdp # 8213252Sdp print "$HTML<head>$STDHEAD" 8227078Smjnelson print "<title>$WNAME Sdiff $TPATH/$TNAME</title>" 8233252Sdp print "</head><body id=\"SUNWwebrev\">" 8243252Sdp print "<a class=\"print\" href=\"javascript:print()\">Print this page</a>" 8253252Sdp print "<pre>$COMMENT</pre>\n" 8263252Sdp print "<table><tr valign=\"top\">" 8273252Sdp print "<td><pre>" 8280Sstevel@tonic-gate 8293252Sdp strip_unchanged /tmp/$$.file1.html 8300Sstevel@tonic-gate 8313252Sdp print "</pre></td><td><pre>" 8323252Sdp 8333252Sdp strip_unchanged /tmp/$$.file2.html 8340Sstevel@tonic-gate 8353252Sdp print "</pre></td>" 8363252Sdp print "</tr></table>" 8373252Sdp print "</body></html>" 8380Sstevel@tonic-gate 8393252Sdp framed_sdiff $TNAME $TPATH /tmp/$$.file1.html /tmp/$$.file2.html \ 8403252Sdp "$COMMENT" 8410Sstevel@tonic-gate} 8420Sstevel@tonic-gate 8430Sstevel@tonic-gate 8443252Sdp# 8453252Sdp# framed_sdiff <filename> <filepath> <lhsfile> <rhsfile> <comment> 8463252Sdp# 8473252Sdp# Expects lefthand and righthand side html files created by sdiff_to_html. 8483252Sdp# We use insert_anchors() to augment those with HTML navigation anchors, 8493252Sdp# and then emit the main frame. Content is placed into: 8503252Sdp# 8513252Sdp# $WDIR/DIR/$TNAME.lhs.html 8523252Sdp# $WDIR/DIR/$TNAME.rhs.html 8533252Sdp# $WDIR/DIR/$TNAME.frames.html 8543252Sdp# 8553252Sdp# NOTE: We rely on standard usage of $WDIR and $DIR. 8563252Sdp# 8570Sstevel@tonic-gatefunction framed_sdiff 8580Sstevel@tonic-gate{ 8593252Sdp typeset TNAME=$1 8603252Sdp typeset TPATH=$2 8613252Sdp typeset lhsfile=$3 8623252Sdp typeset rhsfile=$4 8633252Sdp typeset comments=$5 8643252Sdp typeset RTOP 8653252Sdp 8663252Sdp # Enable html files to access WDIR via a relative path. 8673252Sdp RTOP=$(relative_dir $TPATH $WDIR) 8683252Sdp 8693252Sdp # Make the rhs/lhs files and output the frameset file. 8703252Sdp print "$HTML<head>$STDHEAD" > $WDIR/$DIR/$TNAME.lhs.html 8713252Sdp 8723252Sdp cat >> $WDIR/$DIR/$TNAME.lhs.html <<-EOF 8739191SMark.J.Nelson@Sun.COM <script type="text/javascript" src="${RTOP}ancnav.js"></script> 8743252Sdp </head> 8753252Sdp <body id="SUNWwebrev" onkeypress="keypress(event);"> 8766922Smjnelson <a name="0"></a> 8776922Smjnelson <pre>$comments</pre><hr></hr> 8783252Sdp EOF 8793252Sdp 8803252Sdp cp $WDIR/$DIR/$TNAME.lhs.html $WDIR/$DIR/$TNAME.rhs.html 8813252Sdp 8823252Sdp insert_anchors $lhsfile >> $WDIR/$DIR/$TNAME.lhs.html 8833252Sdp insert_anchors $rhsfile >> $WDIR/$DIR/$TNAME.rhs.html 8843252Sdp 8853252Sdp close='</body></html>' 8863252Sdp 8873252Sdp print $close >> $WDIR/$DIR/$TNAME.lhs.html 8883252Sdp print $close >> $WDIR/$DIR/$TNAME.rhs.html 8893252Sdp 8903252Sdp print "$FRAMEHTML<head>$STDHEAD" > $WDIR/$DIR/$TNAME.frames.html 8913252Sdp print "<title>$WNAME Framed-Sdiff " \ 8923252Sdp "$TPATH/$TNAME</title> </head>" >> $WDIR/$DIR/$TNAME.frames.html 8933252Sdp cat >> $WDIR/$DIR/$TNAME.frames.html <<-EOF 8943252Sdp <frameset rows="*,60"> 8953252Sdp <frameset cols="50%,50%"> 8966922Smjnelson <frame src="$TNAME.lhs.html" scrolling="auto" name="lhs"></frame> 8976922Smjnelson <frame src="$TNAME.rhs.html" scrolling="auto" name="rhs"></frame> 8983252Sdp </frameset> 8999191SMark.J.Nelson@Sun.COM <frame src="${RTOP}ancnav.html" scrolling="no" marginwidth="0" 9006922Smjnelson marginheight="0" name="nav"></frame> 9013252Sdp <noframes> 9023252Sdp <body id="SUNWwebrev"> 9033252Sdp Alas 'frames' webrev requires that your browser supports frames 9043252Sdp and has the feature enabled. 9053252Sdp </body> 9063252Sdp </noframes> 9073252Sdp </frameset> 9080Sstevel@tonic-gate </html> 9090Sstevel@tonic-gate EOF 9100Sstevel@tonic-gate} 9110Sstevel@tonic-gate 9120Sstevel@tonic-gate 9133252Sdp# 9143252Sdp# fix_postscript 9150Sstevel@tonic-gate# 9163252Sdp# Merge codereview output files to a single conforming postscript file, by: 91710789SEdward.Pilatowicz@Sun.COM# - removing all extraneous headers/trailers 9183252Sdp# - making the page numbers right 9193252Sdp# - removing pages devoid of contents which confuse some 9203252Sdp# postscript readers. 9213252Sdp# 9223252Sdp# From Casper. 9230Sstevel@tonic-gate# 9243252Sdpfunction fix_postscript 9253252Sdp{ 9263252Sdp infile=$1 9273252Sdp 9283252Sdp cat > /tmp/$$.crmerge.pl << \EOF 9290Sstevel@tonic-gate 9303252Sdp print scalar(<>); # %!PS-Adobe--- 9313252Sdp print "%%Orientation: Landscape\n"; 9323252Sdp 9333252Sdp $pno = 0; 9343252Sdp $doprint = 1; 9353252Sdp 9363252Sdp $page = ""; 9370Sstevel@tonic-gate 9383252Sdp while (<>) { 9393252Sdp next if (/^%%Pages:\s*\d+/); 9403252Sdp 9413252Sdp if (/^%%Page:/) { 9423252Sdp if ($pno == 0 || $page =~ /\)S/) { 9433252Sdp # Header or single page containing text 9443252Sdp print "%%Page: ? $pno\n" if ($pno > 0); 9453252Sdp print $page; 9463252Sdp $pno++; 9473252Sdp } else { 9483252Sdp # Empty page, skip it. 9493252Sdp } 9503252Sdp $page = ""; 9513252Sdp $doprint = 1; 9523252Sdp next; 9530Sstevel@tonic-gate } 9540Sstevel@tonic-gate 9553252Sdp # Skip from %%Trailer of one document to Endprolog 9563252Sdp # %%Page of the next 9573252Sdp $doprint = 0 if (/^%%Trailer/); 9583252Sdp $page .= $_ if ($doprint); 9590Sstevel@tonic-gate } 9603252Sdp 9613252Sdp if ($page =~ /\)S/) { 9623252Sdp print "%%Page: ? $pno\n"; 9633252Sdp print $page; 9643252Sdp } else { 9653252Sdp $pno--; 9660Sstevel@tonic-gate } 9673252Sdp print "%%Trailer\n%%Pages: $pno\n"; 9683252SdpEOF 9690Sstevel@tonic-gate 9703295Sdp $PERL /tmp/$$.crmerge.pl < $infile 9710Sstevel@tonic-gate} 9723252Sdp 9730Sstevel@tonic-gate 9743252Sdp# 9753252Sdp# input_cmd | insert_anchors | output_cmd 9763252Sdp# 9770Sstevel@tonic-gate# Flag blocks of difference with sequentially numbered invisible 9783252Sdp# anchors. These are used to drive the frames version of the 9790Sstevel@tonic-gate# sdiffs output. 9800Sstevel@tonic-gate# 9810Sstevel@tonic-gate# NOTE: Anchor zero flags the top of the file irrespective of changes, 9820Sstevel@tonic-gate# an additional anchor is also appended to flag the bottom. 9830Sstevel@tonic-gate# 9843252Sdp# The script detects changed lines as any line that has a "<span 9853252Sdp# class=" string embedded (unchanged lines have no class set and are 9863252Sdp# not part of a <span>. Blank lines (without a sequence number) 9870Sstevel@tonic-gate# are also detected since they flag lines that have been inserted or 9880Sstevel@tonic-gate# deleted. 9890Sstevel@tonic-gate# 9903252Sdpfunction insert_anchors 9913252Sdp{ 9927078Smjnelson $AWK ' 9933252Sdp function ia() { 9943252Sdp printf "<a name=\"%d\" id=\"anc%d\"></a>", anc, anc++; 9953252Sdp } 9960Sstevel@tonic-gate 9973252Sdp BEGIN { 9983252Sdp anc=1; 9993252Sdp inblock=1; 10003252Sdp printf "<pre>\n"; 10013252Sdp } 10023252Sdp NF == 0 || /^<span class=/ { 10033252Sdp if (inblock == 0) { 10043252Sdp ia(); 10053252Sdp inblock=1; 10063252Sdp } 10073252Sdp print; 10083252Sdp next; 10093252Sdp } 10103252Sdp { 10113252Sdp inblock=0; 10123252Sdp print; 10133252Sdp } 10143252Sdp END { 10150Sstevel@tonic-gate ia(); 10163252Sdp 10173252Sdp printf "<b style=\"font-size: large; color: red\">"; 10183252Sdp printf "--- EOF ---</b>" 101910789SEdward.Pilatowicz@Sun.COM for(i=0;i<8;i++) printf "\n\n\n\n\n\n\n\n\n\n"; 10203252Sdp printf "</pre>" 10213252Sdp printf "<form name=\"eof\">"; 10226922Smjnelson printf "<input name=\"value\" value=\"%d\" " \ 10236922Smjnelson "type=\"hidden\"></input>", anc - 1; 10243252Sdp printf "</form>"; 10250Sstevel@tonic-gate } 10263252Sdp ' $1 10270Sstevel@tonic-gate} 10280Sstevel@tonic-gate 10290Sstevel@tonic-gate 10303252Sdp# 10313252Sdp# relative_dir 10320Sstevel@tonic-gate# 10333252Sdp# Print a relative return path from $1 to $2. For example if 10343252Sdp# $1=/tmp/myreview/raw_files/usr/src/tools/scripts and $2=/tmp/myreview, 10353252Sdp# this function would print "../../../../". 10363252Sdp# 10373252Sdp# In the event that $1 is not in $2 a warning is printed to stderr, 10383252Sdp# and $2 is returned-- the result of this is that the resulting webrev 10393252Sdp# is not relocatable. 10400Sstevel@tonic-gate# 10413252Sdpfunction relative_dir 10423252Sdp{ 10439191SMark.J.Nelson@Sun.COM typeset cur="${1##$2?(/)}" 10449191SMark.J.Nelson@Sun.COM 10459191SMark.J.Nelson@Sun.COM # 10469191SMark.J.Nelson@Sun.COM # If the first path was specified absolutely, and it does 10479191SMark.J.Nelson@Sun.COM # not start with the second path, it's an error. 10489191SMark.J.Nelson@Sun.COM # 10499193SMark.J.Nelson@Sun.COM if [[ "$cur" = "/${1#/}" ]]; then 10509191SMark.J.Nelson@Sun.COM # Should never happen. 10519191SMark.J.Nelson@Sun.COM print -u2 "\nWARNING: relative_dir: \"$1\" not relative " 10529191SMark.J.Nelson@Sun.COM print -u2 "to \"$2\". Check input paths. Framed webrev " 10539191SMark.J.Nelson@Sun.COM print -u2 "will not be relocatable!" 10549191SMark.J.Nelson@Sun.COM print $2 10559191SMark.J.Nelson@Sun.COM return 10569191SMark.J.Nelson@Sun.COM fi 10579191SMark.J.Nelson@Sun.COM 10589191SMark.J.Nelson@Sun.COM # 10599191SMark.J.Nelson@Sun.COM # This is kind of ugly. The sed script will do the following: 10609191SMark.J.Nelson@Sun.COM # 10619191SMark.J.Nelson@Sun.COM # 1. Strip off a leading "." or "./": this is important to get 10629191SMark.J.Nelson@Sun.COM # the correct arcnav links for files in $WDIR. 106310789SEdward.Pilatowicz@Sun.COM # 2. Strip off a trailing "/": this is not strictly necessary, 10649191SMark.J.Nelson@Sun.COM # but is kind of nice, since it doesn't end up in "//" at 10659191SMark.J.Nelson@Sun.COM # the end of a relative path. 10669191SMark.J.Nelson@Sun.COM # 3. Replace all remaining sequences of non-"/" with "..": the 10679191SMark.J.Nelson@Sun.COM # assumption here is that each dirname represents another 10689191SMark.J.Nelson@Sun.COM # level of relative separation. 10699191SMark.J.Nelson@Sun.COM # 4. Append a trailing "/" only for non-empty paths: this way 10709191SMark.J.Nelson@Sun.COM # the caller doesn't need to duplicate this logic, and does 10719191SMark.J.Nelson@Sun.COM # not end up using $RTOP/file for files in $WDIR. 10729191SMark.J.Nelson@Sun.COM # 10739193SMark.J.Nelson@Sun.COM print $cur | $SED -e '{ 10749193SMark.J.Nelson@Sun.COM s:^\./*:: 10759193SMark.J.Nelson@Sun.COM s:/$:: 10769193SMark.J.Nelson@Sun.COM s:[^/][^/]*:..:g 10779193SMark.J.Nelson@Sun.COM s:^\(..*\)$:\1/: 10789193SMark.J.Nelson@Sun.COM }' 10790Sstevel@tonic-gate} 10800Sstevel@tonic-gate 10813252Sdp# 10823252Sdp# frame_nav_js 10833252Sdp# 10843252Sdp# Emit javascript for frame navigation 10853252Sdp# 10863252Sdpfunction frame_nav_js 10870Sstevel@tonic-gate{ 10880Sstevel@tonic-gatecat << \EOF 10890Sstevel@tonic-gatevar myInt; 10900Sstevel@tonic-gatevar scrolling=0; 10913252Sdpvar sfactor = 3; 10920Sstevel@tonic-gatevar scount=10; 10930Sstevel@tonic-gate 10940Sstevel@tonic-gatefunction scrollByPix() { 10950Sstevel@tonic-gate if (scount<=0) { 10960Sstevel@tonic-gate sfactor*=1.2; 10970Sstevel@tonic-gate scount=10; 10980Sstevel@tonic-gate } 10990Sstevel@tonic-gate parent.lhs.scrollBy(0,sfactor); 11000Sstevel@tonic-gate parent.rhs.scrollBy(0,sfactor); 11010Sstevel@tonic-gate scount--; 11020Sstevel@tonic-gate} 11030Sstevel@tonic-gate 11043252Sdpfunction scrollToAnc(num) { 11053252Sdp 11063252Sdp // Update the value of the anchor in the form which we use as 11073252Sdp // storage for this value. setAncValue() will take care of 11083252Sdp // correcting for overflow and underflow of the value and return 11093252Sdp // us the new value. 11103252Sdp num = setAncValue(num); 11113252Sdp 11123252Sdp // Set location and scroll back a little to expose previous 11133252Sdp // lines. 11143252Sdp // 11153252Sdp // Note that this could be improved: it is possible although 11163252Sdp // complex to compute the x and y position of an anchor, and to 11173252Sdp // scroll to that location directly. 11183252Sdp // 11190Sstevel@tonic-gate parent.lhs.location.replace(parent.lhs.location.pathname + "#" + num); 11200Sstevel@tonic-gate parent.rhs.location.replace(parent.rhs.location.pathname + "#" + num); 11213252Sdp 11220Sstevel@tonic-gate parent.lhs.scrollBy(0,-30); 11230Sstevel@tonic-gate parent.rhs.scrollBy(0,-30); 11240Sstevel@tonic-gate} 11250Sstevel@tonic-gate 11263252Sdpfunction getAncValue() 11273252Sdp{ 11283252Sdp return (parseInt(parent.nav.document.diff.real.value)); 11293252Sdp} 11303252Sdp 11313252Sdpfunction setAncValue(val) 11323252Sdp{ 11333252Sdp if (val <= 0) { 11343252Sdp val = 0; 11353252Sdp parent.nav.document.diff.real.value = val; 11363252Sdp parent.nav.document.diff.display.value = "BOF"; 11373252Sdp return (val); 11383252Sdp } 11393252Sdp 11403252Sdp // 11413252Sdp // The way we compute the max anchor value is to stash it 11423252Sdp // inline in the left and right hand side pages-- it's the same 11433252Sdp // on each side, so we pluck from the left. 11443252Sdp // 11453252Sdp maxval = parent.lhs.document.eof.value.value; 11463252Sdp if (val < maxval) { 11473252Sdp parent.nav.document.diff.real.value = val; 11483252Sdp parent.nav.document.diff.display.value = val.toString(); 11493252Sdp return (val); 11503252Sdp } 11513252Sdp 11523252Sdp // this must be: val >= maxval 11533252Sdp val = maxval; 11543252Sdp parent.nav.document.diff.real.value = val; 11553252Sdp parent.nav.document.diff.display.value = "EOF"; 11563252Sdp return (val); 11573252Sdp} 11583252Sdp 11590Sstevel@tonic-gatefunction stopScroll() { 11600Sstevel@tonic-gate if (scrolling==1) { 11610Sstevel@tonic-gate clearInterval(myInt); 11620Sstevel@tonic-gate scrolling=0; 11630Sstevel@tonic-gate } 11640Sstevel@tonic-gate} 11650Sstevel@tonic-gate 11660Sstevel@tonic-gatefunction startScroll() { 11670Sstevel@tonic-gate stopScroll(); 11680Sstevel@tonic-gate scrolling=1; 11690Sstevel@tonic-gate myInt=setInterval("scrollByPix()",10); 11700Sstevel@tonic-gate} 11710Sstevel@tonic-gate 11723252Sdpfunction handlePress(b) { 11733252Sdp 11740Sstevel@tonic-gate switch (b) { 11750Sstevel@tonic-gate case 1 : 11763252Sdp scrollToAnc(-1); 11770Sstevel@tonic-gate break; 11780Sstevel@tonic-gate case 2 : 11793252Sdp scrollToAnc(getAncValue() - 1); 11800Sstevel@tonic-gate break; 11810Sstevel@tonic-gate case 3 : 11820Sstevel@tonic-gate sfactor=-3; 11830Sstevel@tonic-gate startScroll(); 11840Sstevel@tonic-gate break; 11850Sstevel@tonic-gate case 4 : 11860Sstevel@tonic-gate sfactor=3; 11870Sstevel@tonic-gate startScroll(); 11880Sstevel@tonic-gate break; 11890Sstevel@tonic-gate case 5 : 11903252Sdp scrollToAnc(getAncValue() + 1); 11910Sstevel@tonic-gate break; 11920Sstevel@tonic-gate case 6 : 11933252Sdp scrollToAnc(999999); 11940Sstevel@tonic-gate break; 11950Sstevel@tonic-gate } 11960Sstevel@tonic-gate} 11970Sstevel@tonic-gate 11980Sstevel@tonic-gatefunction handleRelease(b) { 11990Sstevel@tonic-gate stopScroll(); 12000Sstevel@tonic-gate} 12010Sstevel@tonic-gate 12023252Sdpfunction keypress(ev) { 12033252Sdp var keynum; 12043252Sdp var keychar; 12053252Sdp 12063252Sdp if (window.event) { // IE 12073252Sdp keynum = ev.keyCode; 12083252Sdp } else if (ev.which) { // non-IE 12093252Sdp keynum = ev.which; 12100Sstevel@tonic-gate } 12113252Sdp 12123252Sdp keychar = String.fromCharCode(keynum); 12133252Sdp 12143252Sdp if (keychar == "k") { 12153252Sdp handlePress(2); 12163252Sdp return (0); 12173252Sdp } else if (keychar == "j" || keychar == " ") { 12183252Sdp handlePress(5); 12193252Sdp return (0); 12203252Sdp } 12213252Sdp return (1); 12220Sstevel@tonic-gate} 12230Sstevel@tonic-gate 12243252Sdpfunction ValidateDiffNum(){ 12253252Sdp val = parent.nav.document.diff.display.value; 12263252Sdp if (val == "EOF") { 12273252Sdp scrollToAnc(999999); 12283252Sdp return; 12293252Sdp } 12303252Sdp 12313252Sdp if (val == "BOF") { 12323252Sdp scrollToAnc(0); 12333252Sdp return; 12343252Sdp } 12353252Sdp 12363252Sdp i=parseInt(val); 12373252Sdp if (isNaN(i)) { 12383252Sdp parent.nav.document.diff.display.value = getAncValue(); 12393252Sdp } else { 12403252Sdp scrollToAnc(i); 12413252Sdp } 12423252Sdp return false; 12433252Sdp} 12443252Sdp 12453252SdpEOF 12463252Sdp} 12473252Sdp 12483252Sdp# 12493252Sdp# frame_navigation 12503252Sdp# 12513252Sdp# Output anchor navigation file for framed sdiffs. 12523252Sdp# 12533252Sdpfunction frame_navigation 12543252Sdp{ 12553252Sdp print "$HTML<head>$STDHEAD" 12563252Sdp 12573252Sdp cat << \EOF 12583252Sdp<title>Anchor Navigation</title> 12593252Sdp<meta http-equiv="Content-Script-Type" content="text/javascript"> 12603252Sdp<meta http-equiv="Content-Type" content="text/html"> 12613252Sdp 12623252Sdp<style type="text/css"> 12633252Sdp div.button td { padding-left: 5px; padding-right: 5px; 12643252Sdp background-color: #eee; text-align: center; 12653252Sdp border: 1px #444 outset; cursor: pointer; } 12663252Sdp div.button a { font-weight: bold; color: black } 12673252Sdp div.button td:hover { background: #ffcc99; } 12683252Sdp</style> 12693252SdpEOF 12703252Sdp 12716922Smjnelson print "<script type=\"text/javascript\" src=\"ancnav.js\"></script>" 12723252Sdp 12733252Sdp cat << \EOF 12743252Sdp</head> 12753252Sdp<body id="SUNWwebrev" bgcolor="#eeeeee" onload="document.diff.real.focus();" 12763252Sdp onkeypress="keypress(event);"> 12770Sstevel@tonic-gate <noscript lang="javascript"> 12780Sstevel@tonic-gate <center> 12796922Smjnelson <p><big>Framed Navigation controls require Javascript</big><br></br> 12800Sstevel@tonic-gate Either this browser is incompatable or javascript is not enabled</p> 12810Sstevel@tonic-gate </center> 12820Sstevel@tonic-gate </noscript> 12830Sstevel@tonic-gate <table width="100%" border="0" align="center"> 12843252Sdp <tr> 12853252Sdp <td valign="middle" width="25%">Diff navigation: 12863252Sdp Use 'j' and 'k' for next and previous diffs; or use buttons 12873252Sdp at right</td> 12883252Sdp <td align="center" valign="top" width="50%"> 12890Sstevel@tonic-gate <div class="button"> 12903252Sdp <table border="0" align="center"> 12913252Sdp <tr> 12923252Sdp <td> 12930Sstevel@tonic-gate <a onMouseDown="handlePress(1);return true;" 12940Sstevel@tonic-gate onMouseUp="handleRelease(1);return true;" 12950Sstevel@tonic-gate onMouseOut="handleRelease(1);return true;" 12960Sstevel@tonic-gate onClick="return false;" 12970Sstevel@tonic-gate title="Go to Beginning Of file">BOF</a></td> 12983252Sdp <td> 12990Sstevel@tonic-gate <a onMouseDown="handlePress(3);return true;" 13000Sstevel@tonic-gate onMouseUp="handleRelease(3);return true;" 13010Sstevel@tonic-gate onMouseOut="handleRelease(3);return true;" 13020Sstevel@tonic-gate title="Scroll Up: Press and Hold to accelerate" 13033252Sdp onClick="return false;">Scroll Up</a></td> 13043252Sdp <td> 13050Sstevel@tonic-gate <a onMouseDown="handlePress(2);return true;" 13060Sstevel@tonic-gate onMouseUp="handleRelease(2);return true;" 13073252Sdp onMouseOut="handleRelease(2);return true;" 13080Sstevel@tonic-gate title="Go to previous Diff" 13090Sstevel@tonic-gate onClick="return false;">Prev Diff</a> 13100Sstevel@tonic-gate </td></tr> 13113252Sdp 13120Sstevel@tonic-gate <tr> 13133252Sdp <td> 13143252Sdp <a onMouseDown="handlePress(6);return true;" 13153252Sdp onMouseUp="handleRelease(6);return true;" 13163252Sdp onMouseOut="handleRelease(6);return true;" 13170Sstevel@tonic-gate onClick="return false;" 13180Sstevel@tonic-gate title="Go to End Of File">EOF</a></td> 13193252Sdp <td> 13203252Sdp <a onMouseDown="handlePress(4);return true;" 13213252Sdp onMouseUp="handleRelease(4);return true;" 13223252Sdp onMouseOut="handleRelease(4);return true;" 13230Sstevel@tonic-gate title="Scroll Down: Press and Hold to accelerate" 13243252Sdp onClick="return false;">Scroll Down</a></td> 13253252Sdp <td> 13263252Sdp <a onMouseDown="handlePress(5);return true;" 13273252Sdp onMouseUp="handleRelease(5);return true;" 13283252Sdp onMouseOut="handleRelease(5);return true;" 13290Sstevel@tonic-gate title="Go to next Diff" 13300Sstevel@tonic-gate onClick="return false;">Next Diff</a></td> 13313252Sdp </tr> 13323252Sdp </table> 13333252Sdp </div> 13343252Sdp </td> 13350Sstevel@tonic-gate <th valign="middle" width="25%"> 13363252Sdp <form action="" name="diff" onsubmit="return ValidateDiffNum();"> 13376922Smjnelson <input name="display" value="BOF" size="8" type="text"></input> 13386922Smjnelson <input name="real" value="0" size="8" type="hidden"></input> 13390Sstevel@tonic-gate </form> 13400Sstevel@tonic-gate </th> 13413252Sdp </tr> 13420Sstevel@tonic-gate </table> 13430Sstevel@tonic-gate </body> 13440Sstevel@tonic-gate</html> 13450Sstevel@tonic-gateEOF 13460Sstevel@tonic-gate} 13470Sstevel@tonic-gate 13483252Sdp 13490Sstevel@tonic-gate 13503252Sdp# 13513252Sdp# diff_to_html <filename> <filepath> { U | C } <comment> 13523252Sdp# 13533252Sdp# Processes the output of diff to produce an HTML file representing either 13543252Sdp# context or unified diffs. 13553252Sdp# 13560Sstevel@tonic-gatediff_to_html() 13570Sstevel@tonic-gate{ 13583252Sdp TNAME=$1 13593252Sdp TPATH=$2 13603252Sdp DIFFTYPE=$3 13613252Sdp COMMENT=$4 13623252Sdp 13633252Sdp print "$HTML<head>$STDHEAD" 13643252Sdp print "<title>$WNAME ${DIFFTYPE}diff $TPATH</title>" 13653252Sdp 13663252Sdp if [[ $DIFFTYPE == "U" ]]; then 13673252Sdp print "$UDIFFCSS" 13683252Sdp fi 13693252Sdp 13703252Sdp cat <<-EOF 13713252Sdp </head> 13723252Sdp <body id="SUNWwebrev"> 13733252Sdp <a class="print" href="javascript:print()">Print this page</a> 13743252Sdp <pre>$COMMENT</pre> 13753252Sdp <pre> 13763252Sdp EOF 13770Sstevel@tonic-gate 13787078Smjnelson html_quote | $AWK ' 13793252Sdp /^--- new/ { next } 13803252Sdp /^\+\+\+ new/ { next } 13813252Sdp /^--- old/ { next } 13823252Sdp /^\*\*\* old/ { next } 13833252Sdp /^\*\*\*\*/ { next } 13843252Sdp /^-------/ { printf "<center><h1>%s</h1></center>\n", $0; next } 13856922Smjnelson /^\@\@.*\@\@$/ { printf "</pre><hr></hr><pre>\n"; 13863252Sdp printf "<span class=\"newmarker\">%s</span>\n", $0; 13873252Sdp next} 13883252Sdp 13896922Smjnelson /^\*\*\*/ { printf "<hr></hr><span class=\"oldmarker\">%s</span>\n", $0; 13903252Sdp next} 13913252Sdp /^---/ { printf "<span class=\"newmarker\">%s</span>\n", $0; 13923252Sdp next} 13933252Sdp /^\+/ {printf "<span class=\"new\">%s</span>\n", $0; next} 13943252Sdp /^!/ {printf "<span class=\"changed\">%s</span>\n", $0; next} 13953252Sdp /^-/ {printf "<span class=\"removed\">%s</span>\n", $0; next} 13963252Sdp {printf "%s\n", $0; next} 13973252Sdp ' 13983252Sdp 13993252Sdp print "</pre></body></html>\n" 14000Sstevel@tonic-gate} 14010Sstevel@tonic-gate 14020Sstevel@tonic-gate 14033252Sdp# 14043252Sdp# source_to_html { new | old } <filename> 14053252Sdp# 14063252Sdp# Process a plain vanilla source file to transform it into an HTML file. 14073252Sdp# 14080Sstevel@tonic-gatesource_to_html() 14090Sstevel@tonic-gate{ 14103252Sdp WHICH=$1 14113252Sdp TNAME=$2 14120Sstevel@tonic-gate 14133252Sdp print "$HTML<head>$STDHEAD" 14147078Smjnelson print "<title>$WNAME $WHICH $TNAME</title>" 14153252Sdp print "<body id=\"SUNWwebrev\">" 14163252Sdp print "<pre>" 14177078Smjnelson html_quote | $AWK '{line += 1 ; printf "%4d %s\n", line, $0 }' 14183252Sdp print "</pre></body></html>" 14190Sstevel@tonic-gate} 14200Sstevel@tonic-gate 14213252Sdp# 14227078Smjnelson# comments_from_teamware {text|html} parent-file child-file 14233252Sdp# 14243252Sdp# Find the first delta in the child that's not in the parent. Get the 14253252Sdp# newest delta from the parent, get all deltas from the child starting 14263252Sdp# with that delta, and then get all info starting with the second oldest 14273252Sdp# delta in that list (the first delta unique to the child). 14280Sstevel@tonic-gate# 14290Sstevel@tonic-gate# This code adapted from Bill Shannon's "spc" script 14303252Sdp# 14313252Sdpcomments_from_teamware() 14320Sstevel@tonic-gate{ 14333252Sdp fmt=$1 14343252Sdp pfile=$PWS/$2 14353252Sdp cfile=$CWS/$3 14360Sstevel@tonic-gate 14377078Smjnelson if [[ ! -f $PWS/${2%/*}/SCCS/s.${2##*/} && -n $RWS ]]; then 14387078Smjnelson pfile=$RWS/$2 14397078Smjnelson fi 14407078Smjnelson 14413252Sdp if [[ -f $pfile ]]; then 14427078Smjnelson psid=$($SCCS prs -d:I: $pfile 2>/dev/null) 14433252Sdp else 14443252Sdp psid=1.1 14453252Sdp fi 14460Sstevel@tonic-gate 14477078Smjnelson set -A sids $($SCCS prs -l -r$psid -d:I: $cfile 2>/dev/null) 14483252Sdp N=${#sids[@]} 14490Sstevel@tonic-gate 14503252Sdp nawkprg=' 14513252Sdp /^COMMENTS:/ {p=1; continue} 14523252Sdp /^D [0-9]+\.[0-9]+/ {printf "--- %s ---\n", $2; p=0; } 14533252Sdp NF == 0u { continue } 14543252Sdp {if (p==0) continue; print $0 }' 14553252Sdp 14563252Sdp if [[ $N -ge 2 ]]; then 14573252Sdp sid1=${sids[$((N-2))]} # Gets 2nd to last sid 14580Sstevel@tonic-gate 14593252Sdp if [[ $fmt == "text" ]]; then 14607078Smjnelson $SCCS prs -l -r$sid1 $cfile 2>/dev/null | \ 14617078Smjnelson $AWK "$nawkprg" 14623252Sdp return 14633252Sdp fi 14643252Sdp 14657078Smjnelson $SCCS prs -l -r$sid1 $cfile 2>/dev/null | \ 14669193SMark.J.Nelson@Sun.COM html_quote | its2url | $AWK "$nawkprg" 14673252Sdp fi 14680Sstevel@tonic-gate} 14690Sstevel@tonic-gate 14703252Sdp# 14717078Smjnelson# comments_from_wx {text|html} filepath 14723252Sdp# 14737078Smjnelson# Given the pathname of a file, find its location in a "wx" active 14747078Smjnelson# file list and print the following comment. Output is either text or 14757078Smjnelson# HTML; if the latter, embedded bugids (sequence of 5 or more digits) 14767078Smjnelson# are turned into URLs. 14777078Smjnelson# 14787078Smjnelson# This is also used with Mercurial and the file list provided by hg-active. 14793252Sdp# 14803252Sdpcomments_from_wx() 14813252Sdp{ 14823252Sdp typeset fmt=$1 14833252Sdp typeset p=$2 14840Sstevel@tonic-gate 14857078Smjnelson comm=`$AWK ' 14863252Sdp $1 == "'$p'" { 14870Sstevel@tonic-gate do getline ; while (NF > 0) 14880Sstevel@tonic-gate getline 14890Sstevel@tonic-gate while (NF > 0) { print ; getline } 14900Sstevel@tonic-gate exit 14913252Sdp }' < $wxfile` 14923252Sdp 14937078Smjnelson if [[ -z $comm ]]; then 14947078Smjnelson comm="*** NO COMMENTS ***" 14957078Smjnelson fi 14967078Smjnelson 14973252Sdp if [[ $fmt == "text" ]]; then 14987078Smjnelson print -- "$comm" 14993252Sdp return 15003252Sdp fi 15013252Sdp 15029193SMark.J.Nelson@Sun.COM print -- "$comm" | html_quote | its2url 15037078Smjnelson 15040Sstevel@tonic-gate} 15050Sstevel@tonic-gate 15063252Sdp# 15073252Sdp# getcomments {text|html} filepath parentpath 15083252Sdp# 15093252Sdp# Fetch the comments depending on what SCM mode we're in. 15103252Sdp# 15113252Sdpgetcomments() 15123252Sdp{ 15133252Sdp typeset fmt=$1 15143252Sdp typeset p=$2 15153252Sdp typeset pp=$3 15163252Sdp 15177310SDarren.Moffat@Sun.COM if [[ -n $Nflag ]]; then 15187310SDarren.Moffat@Sun.COM return 15197310SDarren.Moffat@Sun.COM fi 15207078Smjnelson # 15217078Smjnelson # Mercurial support uses a file list in wx format, so this 15227078Smjnelson # will be used there, too 15237078Smjnelson # 15243252Sdp if [[ -n $wxfile ]]; then 15253252Sdp comments_from_wx $fmt $p 15263252Sdp else 15273252Sdp if [[ $SCM_MODE == "teamware" ]]; then 15283252Sdp comments_from_teamware $fmt $pp $p 15293252Sdp fi 15303252Sdp fi 15313252Sdp} 15320Sstevel@tonic-gate 15333252Sdp# 15343252Sdp# printCI <total-changed> <inserted> <deleted> <modified> <unchanged> 15353252Sdp# 15363252Sdp# Print out Code Inspection figures similar to sccs-prt(1) format. 15373252Sdp# 15383252Sdpfunction printCI 15393252Sdp{ 15403252Sdp integer tot=$1 ins=$2 del=$3 mod=$4 unc=$5 15413252Sdp typeset str 15423252Sdp if (( tot == 1 )); then 15433252Sdp str="line" 15443252Sdp else 15453252Sdp str="lines" 15463252Sdp fi 15473252Sdp printf '%d %s changed: %d ins; %d del; %d mod; %d unchg\n' \ 15483252Sdp $tot $str $ins $del $mod $unc 15493252Sdp} 15503252Sdp 15513252Sdp 15523252Sdp# 15533252Sdp# difflines <oldfile> <newfile> 15543252Sdp# 15553252Sdp# Calculate and emit number of added, removed, modified and unchanged lines, 15563252Sdp# and total lines changed, the sum of added + removed + modified. 15573252Sdp# 15580Sstevel@tonic-gatefunction difflines 15590Sstevel@tonic-gate{ 15603252Sdp integer tot mod del ins unc err 15613252Sdp typeset filename 15623252Sdp 15637078Smjnelson eval $( diff -e $1 $2 | $AWK ' 15643252Sdp # Change range of lines: N,Nc 15653252Sdp /^[0-9]*,[0-9]*c$/ { 15663252Sdp n=split(substr($1,1,length($1)-1), counts, ","); 15673252Sdp if (n != 2) { 15683252Sdp error=2 15693252Sdp exit; 15703252Sdp } 15713252Sdp # 15723252Sdp # 3,5c means lines 3 , 4 and 5 are changed, a total of 3 lines. 15733252Sdp # following would be 5 - 3 = 2! Hence +1 for correction. 15743252Sdp # 15753252Sdp r=(counts[2]-counts[1])+1; 15760Sstevel@tonic-gate 15773252Sdp # 15783252Sdp # Now count replacement lines: each represents a change instead 15793252Sdp # of a delete, so increment c and decrement r. 15803252Sdp # 15813252Sdp while (getline != /^\.$/) { 15823252Sdp c++; 15833252Sdp r--; 15843252Sdp } 15853252Sdp # 15863252Sdp # If there were more replacement lines than original lines, 15873252Sdp # then r will be negative; in this case there are no deletions, 15883252Sdp # but there are r changes that should be counted as adds, and 15893252Sdp # since r is negative, subtract it from a and add it to c. 15903252Sdp # 15913252Sdp if (r < 0) { 15923252Sdp a-=r; 15933252Sdp c+=r; 15943252Sdp } 15950Sstevel@tonic-gate 15963252Sdp # 15973252Sdp # If there were more original lines than replacement lines, then 15983252Sdp # r will be positive; in this case, increment d by that much. 15993252Sdp # 16003252Sdp if (r > 0) { 16013252Sdp d+=r; 16023252Sdp } 16033252Sdp next; 16040Sstevel@tonic-gate } 16050Sstevel@tonic-gate 16063252Sdp # Change lines: Nc 16073252Sdp /^[0-9].*c$/ { 16083252Sdp # The first line is a replacement; any more are additions. 16093252Sdp if (getline != /^\.$/) { 16103252Sdp c++; 16113252Sdp while (getline != /^\.$/) a++; 16123252Sdp } 16133252Sdp next; 16143252Sdp } 16150Sstevel@tonic-gate 16163252Sdp # Add lines: both Na and N,Na 16173252Sdp /^[0-9].*a$/ { 16183252Sdp while (getline != /^\.$/) a++; 16193252Sdp next; 16200Sstevel@tonic-gate } 16210Sstevel@tonic-gate 16223252Sdp # Delete range of lines: N,Nd 16233252Sdp /^[0-9]*,[0-9]*d$/ { 16243252Sdp n=split(substr($1,1,length($1)-1), counts, ","); 16253252Sdp if (n != 2) { 16263252Sdp error=2 16273252Sdp exit; 16283252Sdp } 16293252Sdp # 16303252Sdp # 3,5d means lines 3 , 4 and 5 are deleted, a total of 3 lines. 16313252Sdp # following would be 5 - 3 = 2! Hence +1 for correction. 16323252Sdp # 16333252Sdp r=(counts[2]-counts[1])+1; 16343252Sdp d+=r; 16353252Sdp next; 16363252Sdp } 16373252Sdp 16383252Sdp # Delete line: Nd. For example 10d says line 10 is deleted. 16393252Sdp /^[0-9]*d$/ {d++; next} 16400Sstevel@tonic-gate 16413252Sdp # Should not get here! 16423252Sdp { 16433252Sdp error=1; 16443252Sdp exit; 16453252Sdp } 16460Sstevel@tonic-gate 16473252Sdp # Finish off - print results 16483252Sdp END { 16493252Sdp printf("tot=%d;mod=%d;del=%d;ins=%d;err=%d\n", 16503252Sdp (c+d+a), c, d, a, error); 16513252Sdp }' ) 16520Sstevel@tonic-gate 16537078Smjnelson # End of $AWK, Check to see if any trouble occurred. 16543252Sdp if (( $? > 0 || err > 0 )); then 16553252Sdp print "Unexpected Error occurred reading" \ 16563252Sdp "\`diff -e $1 $2\`: \$?=$?, err=" $err 16573252Sdp return 16583252Sdp fi 16593252Sdp 16600Sstevel@tonic-gate # Accumulate totals 16610Sstevel@tonic-gate (( TOTL += tot )) 16623252Sdp (( TMOD += mod )) 16633252Sdp (( TDEL += del )) 16640Sstevel@tonic-gate (( TINS += ins )) 16650Sstevel@tonic-gate # Calculate unchanged lines 16667078Smjnelson unc=`wc -l < $1` 16670Sstevel@tonic-gate if (( unc > 0 )); then 16683252Sdp (( unc -= del + mod )) 16693252Sdp (( TUNC += unc )) 16700Sstevel@tonic-gate fi 16710Sstevel@tonic-gate # print summary 16723252Sdp print "<span class=\"lineschanged\">" 16733252Sdp printCI $tot $ins $del $mod $unc 16743252Sdp print "</span>" 16753252Sdp} 16763252Sdp 16773252Sdp 16783252Sdp# 16793252Sdp# flist_from_wx 16803252Sdp# 16813252Sdp# Sets up webrev to source its information from a wx-formatted file. 16823252Sdp# Sets the global 'wxfile' variable. 16833252Sdp# 16843252Sdpfunction flist_from_wx 16853252Sdp{ 16863252Sdp typeset argfile=$1 16873252Sdp if [[ -n ${argfile%%/*} ]]; then 16883252Sdp # 16893252Sdp # If the wx file pathname is relative then make it absolute 16903252Sdp # because the webrev does a "cd" later on. 16913252Sdp # 16923252Sdp wxfile=$PWD/$argfile 16933252Sdp else 16943252Sdp wxfile=$argfile 16953252Sdp fi 16963252Sdp 16977078Smjnelson $AWK '{ c = 1; print; 16983252Sdp while (getline) { 16993252Sdp if (NF == 0) { c = -c; continue } 17003252Sdp if (c > 0) print 17013252Sdp } 17023252Sdp }' $wxfile > $FLIST 17033252Sdp 17043252Sdp print " Done." 17053252Sdp} 17063252Sdp 17073252Sdp# 17083252Sdp# flist_from_teamware [ <args-to-putback-n> ] 17093252Sdp# 17103252Sdp# Generate the file list by extracting file names from a putback -n. Some 17113252Sdp# names may come from the "update/create" messages and others from the 17123252Sdp# "currently checked out" warning. Renames are detected here too. Extract 17133252Sdp# values for CODEMGR_WS and CODEMGR_PARENT from the output of the putback 17143252Sdp# -n as well, but remove them if they are already defined. 17153252Sdp# 17163252Sdpfunction flist_from_teamware 17173252Sdp{ 17187078Smjnelson if [[ -n $codemgr_parent && -z $parent_webrev ]]; then 17193252Sdp if [[ ! -d $codemgr_parent/Codemgr_wsdata ]]; then 17203252Sdp print -u2 "parent $codemgr_parent doesn't look like a" \ 17213252Sdp "valid teamware workspace" 17223252Sdp exit 1 17233252Sdp fi 17243252Sdp parent_args="-p $codemgr_parent" 17253252Sdp fi 17263252Sdp 17273252Sdp print " File list from: 'putback -n $parent_args $*' ... \c" 17283252Sdp 17293252Sdp putback -n $parent_args $* 2>&1 | 17307078Smjnelson $AWK ' 17313252Sdp /^update:|^create:/ {print $2} 17323252Sdp /^Parent workspace:/ {printf("CODEMGR_PARENT=%s\n",$3)} 17333252Sdp /^Child workspace:/ {printf("CODEMGR_WS=%s\n",$3)} 17343252Sdp /^The following files are currently checked out/ {p = 1; continue} 17353252Sdp NF == 0 {p=0 ; continue} 17363252Sdp /^rename/ {old=$3} 17373252Sdp $1 == "to:" {print $2, old} 17383252Sdp /^"/ {continue} 17393252Sdp p == 1 {print $1}' | 17403252Sdp sort -r -k 1,1 -u | sort > $FLIST 17413252Sdp 17423252Sdp print " Done." 17430Sstevel@tonic-gate} 17440Sstevel@tonic-gate 17457078Smjnelson# 17467078Smjnelson# Call hg-active to get the active list output in the wx active list format 17477078Smjnelson# 17487078Smjnelsonfunction hg_active_wxfile 17497078Smjnelson{ 17507078Smjnelson typeset child=$1 17517078Smjnelson typeset parent=$2 17527078Smjnelson 17537078Smjnelson TMPFLIST=/tmp/$$.active 17547298SMark.J.Nelson@Sun.COM $HG_ACTIVE -w $child -p $parent -o $TMPFLIST 17557078Smjnelson wxfile=$TMPFLIST 17567078Smjnelson} 17577078Smjnelson 17587078Smjnelson# 17597078Smjnelson# flist_from_mercurial 17607078Smjnelson# Call hg-active to get a wx-style active list, and hand it off to 17617078Smjnelson# flist_from_wx 17627078Smjnelson# 176310789SEdward.Pilatowicz@Sun.COMfunction flist_from_mercurial 17647078Smjnelson{ 17657078Smjnelson typeset child=$1 17667078Smjnelson typeset parent=$2 17677078Smjnelson 17687078Smjnelson print " File list from: hg-active -p $parent ...\c" 17697078Smjnelson if [[ ! -x $HG_ACTIVE ]]; then 17707078Smjnelson print # Blank line for the \c above 17717078Smjnelson print -u2 "Error: hg-active tool not found. Exiting" 17727078Smjnelson exit 1 17737078Smjnelson fi 17747078Smjnelson hg_active_wxfile $child $parent 177510789SEdward.Pilatowicz@Sun.COM 17767078Smjnelson # flist_from_wx prints the Done, so we don't have to. 17777078Smjnelson flist_from_wx $TMPFLIST 17787078Smjnelson} 17797078Smjnelson 17807078Smjnelson# 17817078Smjnelson# flist_from_subversion 17827078Smjnelson# 17837078Smjnelson# Generate the file list by extracting file names from svn status. 17847078Smjnelson# 17857078Smjnelsonfunction flist_from_subversion 17867078Smjnelson{ 17877078Smjnelson CWS=$1 17887078Smjnelson OLDPWD=$2 17897078Smjnelson 17907078Smjnelson cd $CWS 17917078Smjnelson print -u2 " File list from: svn status ... \c" 17927078Smjnelson svn status | $AWK '/^[ACDMR]/ { print $NF }' > $FLIST 17937078Smjnelson print -u2 " Done." 17947078Smjnelson cd $OLDPWD 17957078Smjnelson} 17967078Smjnelson 17973252Sdpfunction env_from_flist 17980Sstevel@tonic-gate{ 17993252Sdp [[ -r $FLIST ]] || return 18003252Sdp 18013252Sdp # 18023252Sdp # Use "eval" to set env variables that are listed in the file 18033252Sdp # list. Then copy those into our local versions of those 18043252Sdp # variables if they have not been set already. 18053252Sdp # 18069079SVladimir.Kotal@Sun.COM eval `$SED -e "s/#.*$//" $FLIST | $GREP = ` 18073252Sdp 18087078Smjnelson if [[ -z $codemgr_ws && -n $CODEMGR_WS ]]; then 18097078Smjnelson codemgr_ws=$CODEMGR_WS 18107078Smjnelson export CODEMGR_WS 18117078Smjnelson fi 18123252Sdp 18133252Sdp # 18143252Sdp # Check to see if CODEMGR_PARENT is set in the flist file. 18153252Sdp # 18167078Smjnelson if [[ -z $codemgr_parent && -n $CODEMGR_PARENT ]]; then 18177078Smjnelson codemgr_parent=$CODEMGR_PARENT 18187078Smjnelson export CODEMGR_PARENT 18193252Sdp fi 18203252Sdp} 18213252Sdp 18223295Sdpfunction look_for_prog 18233295Sdp{ 18243295Sdp typeset path 18253295Sdp typeset ppath 18263295Sdp typeset progname=$1 18273295Sdp 18283295Sdp ppath=$PATH 18293295Sdp ppath=$ppath:/usr/sfw/bin:/usr/bin:/usr/sbin 18303295Sdp ppath=$ppath:/opt/teamware/bin:/opt/onbld/bin 18317078Smjnelson ppath=$ppath:/opt/onbld/bin/`uname -p` 18323295Sdp 18333295Sdp PATH=$ppath prog=`whence $progname` 18343295Sdp if [[ -n $prog ]]; then 18353295Sdp print $prog 18363295Sdp fi 18373295Sdp} 18383295Sdp 18397078Smjnelsonfunction get_file_mode 18407078Smjnelson{ 18417078Smjnelson $PERL -e ' 18427078Smjnelson if (@stat = stat($ARGV[0])) { 18437078Smjnelson $mode = $stat[2] & 0777; 18447078Smjnelson printf "%03o\n", $mode; 18457078Smjnelson exit 0; 18467078Smjnelson } else { 18477078Smjnelson exit 1; 18487078Smjnelson } 18497078Smjnelson ' $1 18507078Smjnelson} 18517078Smjnelson 18527078Smjnelsonfunction build_old_new_teamware 18537078Smjnelson{ 18547078Smjnelson typeset olddir="$1" 18557078Smjnelson typeset newdir="$2" 18567078Smjnelson 18577078Smjnelson # If the child's version doesn't exist then 18587078Smjnelson # get a readonly copy. 18597078Smjnelson 18607078Smjnelson if [[ ! -f $CWS/$DIR/$F && -f $CWS/$DIR/SCCS/s.$F ]]; then 18617078Smjnelson $SCCS get -s -p $CWS/$DIR/$F > $CWS/$DIR/$F 18627078Smjnelson fi 18637078Smjnelson 18647078Smjnelson # The following two sections propagate file permissions the 18657078Smjnelson # same way SCCS does. If the file is already under version 18667078Smjnelson # control, always use permissions from the SCCS/s.file. If 18677078Smjnelson # the file is not under SCCS control, use permissions from the 18687078Smjnelson # working copy. In all cases, the file copied to the webrev 18697078Smjnelson # is set to read only, and group/other permissions are set to 18707078Smjnelson # match those of the file owner. This way, even if the file 18717078Smjnelson # is currently checked out, the webrev will display the final 18727078Smjnelson # permissions that would result after check in. 18737078Smjnelson 18747078Smjnelson # 18757078Smjnelson # Snag new version of file. 18767078Smjnelson # 18777078Smjnelson rm -f $newdir/$DIR/$F 18787078Smjnelson cp $CWS/$DIR/$F $newdir/$DIR/$F 18797078Smjnelson if [[ -f $CWS/$DIR/SCCS/s.$F ]]; then 18807078Smjnelson chmod `get_file_mode $CWS/$DIR/SCCS/s.$F` \ 18817078Smjnelson $newdir/$DIR/$F 18827078Smjnelson fi 18837078Smjnelson chmod u-w,go=u $newdir/$DIR/$F 18847078Smjnelson 18857078Smjnelson # 18867078Smjnelson # Get the parent's version of the file. First see whether the 18877078Smjnelson # child's version is checked out and get the parent's version 18887078Smjnelson # with keywords expanded or unexpanded as appropriate. 18897078Smjnelson # 18907078Smjnelson if [[ -f $PWS/$PDIR/$PF && ! -f $PWS/$PDIR/SCCS/s.$PF && \ 18917078Smjnelson ! -f $PWS/$PDIR/SCCS/p.$PF ]]; then 18927078Smjnelson # Parent is not a real workspace, but just a raw 18937078Smjnelson # directory tree - use the file that's there as 18947078Smjnelson # the old file. 18957078Smjnelson 18967078Smjnelson rm -f $olddir/$PDIR/$PF 18977078Smjnelson cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF 18987078Smjnelson else 18997078Smjnelson if [[ -f $PWS/$PDIR/SCCS/s.$PF ]]; then 19007078Smjnelson real_parent=$PWS 19017078Smjnelson else 19027078Smjnelson real_parent=$RWS 19037078Smjnelson fi 19047078Smjnelson 19057078Smjnelson rm -f $olddir/$PDIR/$PF 19067078Smjnelson 19077078Smjnelson if [[ -f $real_parent/$PDIR/$PF ]]; then 19087078Smjnelson if [ -f $CWS/$DIR/SCCS/p.$F ]; then 19097078Smjnelson $SCCS get -s -p -k $real_parent/$PDIR/$PF > \ 19107078Smjnelson $olddir/$PDIR/$PF 19117078Smjnelson else 19127078Smjnelson $SCCS get -s -p $real_parent/$PDIR/$PF > \ 19137078Smjnelson $olddir/$PDIR/$PF 19147078Smjnelson fi 19157078Smjnelson chmod `get_file_mode $real_parent/$PDIR/SCCS/s.$PF` \ 19167078Smjnelson $olddir/$PDIR/$PF 19177078Smjnelson fi 19187078Smjnelson fi 19197078Smjnelson if [[ -f $olddir/$PDIR/$PF ]]; then 19207078Smjnelson chmod u-w,go=u $olddir/$PDIR/$PF 19217078Smjnelson fi 19227078Smjnelson} 19237078Smjnelson 19247078Smjnelsonfunction build_old_new_mercurial 19257078Smjnelson{ 19267078Smjnelson typeset olddir="$1" 19277078Smjnelson typeset newdir="$2" 19287078Smjnelson typeset old_mode= 19297078Smjnelson typeset new_mode= 19307078Smjnelson typeset file 19317078Smjnelson 19327078Smjnelson # 19337078Smjnelson # Get old file mode, from the parent revision manifest entry. 19347078Smjnelson # Mercurial only stores a "file is executable" flag, but the 19357078Smjnelson # manifest will display an octal mode "644" or "755". 19367078Smjnelson # 19377078Smjnelson if [[ "$PDIR" == "." ]]; then 19387078Smjnelson file="$PF" 19397078Smjnelson else 19407078Smjnelson file="$PDIR/$PF" 19417078Smjnelson fi 19429079SVladimir.Kotal@Sun.COM file=`echo $file | $SED 's#/#\\\/#g'` 19437078Smjnelson # match the exact filename, and return only the permission digits 19449079SVladimir.Kotal@Sun.COM old_mode=`$SED -n -e "/^\\(...\\) . ${file}$/s//\\1/p" \ 19457078Smjnelson < $HG_PARENT_MANIFEST` 19467078Smjnelson 19477078Smjnelson # 19487078Smjnelson # Get new file mode, directly from the filesystem. 19497078Smjnelson # Normalize the mode to match Mercurial's behavior. 19507078Smjnelson # 19517078Smjnelson new_mode=`get_file_mode $CWS/$DIR/$F` 19527078Smjnelson if [[ -n "$new_mode" ]]; then 19537078Smjnelson if [[ "$new_mode" = *[1357]* ]]; then 19547078Smjnelson new_mode=755 19557078Smjnelson else 19567078Smjnelson new_mode=644 19577078Smjnelson fi 19587078Smjnelson fi 19597078Smjnelson 19607078Smjnelson # 19617078Smjnelson # new version of the file. 19627078Smjnelson # 19637078Smjnelson rm -rf $newdir/$DIR/$F 19647078Smjnelson if [[ -e $CWS/$DIR/$F ]]; then 19657078Smjnelson cp $CWS/$DIR/$F $newdir/$DIR/$F 19667078Smjnelson if [[ -n $new_mode ]]; then 19677078Smjnelson chmod $new_mode $newdir/$DIR/$F 19687078Smjnelson else 19697078Smjnelson # should never happen 19707078Smjnelson print -u2 "ERROR: set mode of $newdir/$DIR/$F" 19717078Smjnelson fi 19727078Smjnelson fi 19737078Smjnelson 19747078Smjnelson # 19757078Smjnelson # parent's version of the file 19767078Smjnelson # 19777078Smjnelson # Note that we get this from the last version common to both 19787078Smjnelson # ourselves and the parent. References are via $CWS since we have no 19797078Smjnelson # guarantee that the parent workspace is reachable via the filesystem. 19807078Smjnelson # 19817078Smjnelson if [[ -n $parent_webrev && -e $PWS/$PDIR/$PF ]]; then 19827078Smjnelson cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF 19837078Smjnelson elif [[ -n $HG_PARENT ]]; then 19847078Smjnelson hg cat -R $CWS -r $HG_PARENT $CWS/$PDIR/$PF > \ 19857078Smjnelson $olddir/$PDIR/$PF 2>/dev/null 19867078Smjnelson 19878018SVladimir.Kotal@Sun.COM if (( $? != 0 )); then 19887078Smjnelson rm -f $olddir/$PDIR/$PF 19897078Smjnelson else 19907078Smjnelson if [[ -n $old_mode ]]; then 19917078Smjnelson chmod $old_mode $olddir/$PDIR/$PF 19927078Smjnelson else 19937078Smjnelson # should never happen 19947078Smjnelson print -u2 "ERROR: set mode of $olddir/$PDIR/$PF" 19957078Smjnelson fi 19967078Smjnelson fi 19977078Smjnelson fi 19987078Smjnelson} 19997078Smjnelson 20007078Smjnelsonfunction build_old_new_subversion 20017078Smjnelson{ 20027078Smjnelson typeset olddir="$1" 20037078Smjnelson typeset newdir="$2" 20047078Smjnelson 20057078Smjnelson # Snag new version of file. 20067078Smjnelson rm -f $newdir/$DIR/$F 20077078Smjnelson [[ -e $CWS/$DIR/$F ]] && cp $CWS/$DIR/$F $newdir/$DIR/$F 20087078Smjnelson 20097078Smjnelson if [[ -n $PWS && -e $PWS/$PDIR/$PF ]]; then 20107078Smjnelson cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF 20117078Smjnelson else 20127078Smjnelson # Get the parent's version of the file. 20137078Smjnelson svn status $CWS/$DIR/$F | read stat file 20147078Smjnelson if [[ $stat != "A" ]]; then 20157078Smjnelson svn cat -r BASE $CWS/$DIR/$F > $olddir/$PDIR/$PF 20167078Smjnelson fi 20177078Smjnelson fi 20187078Smjnelson} 20197078Smjnelson 20207078Smjnelsonfunction build_old_new_unknown 20217078Smjnelson{ 20227078Smjnelson typeset olddir="$1" 20237078Smjnelson typeset newdir="$2" 20247078Smjnelson 20257078Smjnelson # 20267078Smjnelson # Snag new version of file. 20277078Smjnelson # 20287078Smjnelson rm -f $newdir/$DIR/$F 20297078Smjnelson [[ -e $CWS/$DIR/$F ]] && cp $CWS/$DIR/$F $newdir/$DIR/$F 20307078Smjnelson 20317078Smjnelson # 20327078Smjnelson # Snag the parent's version of the file. 203310789SEdward.Pilatowicz@Sun.COM # 20347078Smjnelson if [[ -f $PWS/$PDIR/$PF ]]; then 20357078Smjnelson rm -f $olddir/$PDIR/$PF 20367078Smjnelson cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF 20377078Smjnelson fi 20387078Smjnelson} 20397078Smjnelson 20407078Smjnelsonfunction build_old_new 20417078Smjnelson{ 20427078Smjnelson typeset WDIR=$1 20437078Smjnelson typeset PWS=$2 20447078Smjnelson typeset PDIR=$3 20457078Smjnelson typeset PF=$4 20467078Smjnelson typeset CWS=$5 20477078Smjnelson typeset DIR=$6 20487078Smjnelson typeset F=$7 20497078Smjnelson 20507078Smjnelson typeset olddir="$WDIR/raw_files/old" 20517078Smjnelson typeset newdir="$WDIR/raw_files/new" 20527078Smjnelson 20537078Smjnelson mkdir -p $olddir/$PDIR 20547078Smjnelson mkdir -p $newdir/$DIR 20557078Smjnelson 20567078Smjnelson if [[ $SCM_MODE == "teamware" ]]; then 20577078Smjnelson build_old_new_teamware "$olddir" "$newdir" 20587078Smjnelson elif [[ $SCM_MODE == "mercurial" ]]; then 20597078Smjnelson build_old_new_mercurial "$olddir" "$newdir" 20607078Smjnelson elif [[ $SCM_MODE == "subversion" ]]; then 20617078Smjnelson build_old_new_subversion "$olddir" "$newdir" 20627078Smjnelson elif [[ $SCM_MODE == "unknown" ]]; then 20637078Smjnelson build_old_new_unknown "$olddir" "$newdir" 20647078Smjnelson fi 20657078Smjnelson 20667078Smjnelson if [[ ! -f $olddir/$PDIR/$PF && ! -f $newdir/$DIR/$F ]]; then 20677078Smjnelson print "*** Error: file not in parent or child" 20687078Smjnelson return 1 20697078Smjnelson fi 20707078Smjnelson return 0 20717078Smjnelson} 20727078Smjnelson 20737078Smjnelson 20743252Sdp# 20753252Sdp# Usage message. 20760Sstevel@tonic-gate# 20773252Sdpfunction usage 20783252Sdp{ 20793252Sdp print 'Usage:\twebrev [common-options] 20803252Sdp webrev [common-options] ( <file> | - ) 20813252Sdp webrev [common-options] -w <wx file> 20823252Sdp 20833252SdpOptions: 20849193SMark.J.Nelson@Sun.COM -C <filename>: Use <filename> for the information tracking configuration. 20858365SVladimir.Kotal@Sun.COM -D: delete remote webrev 20868365SVladimir.Kotal@Sun.COM -i <filename>: Include <filename> in the index.html file. 20879193SMark.J.Nelson@Sun.COM -I <filename>: Use <filename> for the information tracking registry. 20888365SVladimir.Kotal@Sun.COM -n: do not generate the webrev (useful with -U) 20893252Sdp -O: Print bugids/arc cases suitable for OpenSolaris. 20903252Sdp -o <outdir>: Output webrev to specified directory. 20913252Sdp -p <compare-against>: Use specified parent wkspc or basis for comparison 20928018SVladimir.Kotal@Sun.COM -t <remote_target>: Specify remote destination for webrev upload 20938018SVladimir.Kotal@Sun.COM -U: upload the webrev to remote destination 20943252Sdp -w <wxfile>: Use specified wx active file. 20953252Sdp 20963252SdpEnvironment: 20973252Sdp WDIR: Control the output directory. 20988365SVladimir.Kotal@Sun.COM WEBREV_TRASH_DIR: Set directory for webrev delete. 20993252Sdp 21007078SmjnelsonSCM Specific Options: 21017078Smjnelson TeamWare: webrev [common-options] -l [arguments to 'putback'] 21027078Smjnelson 21033252SdpSCM Environment: 21047078Smjnelson CODEMGR_WS: Workspace location. 21057078Smjnelson CODEMGR_PARENT: Parent workspace location. 21063252Sdp' 21073252Sdp 21083252Sdp exit 2 21093252Sdp} 21103252Sdp 21110Sstevel@tonic-gate# 21123252Sdp# 21133252Sdp# Main program starts here 21143252Sdp# 21153252Sdp# 21160Sstevel@tonic-gate 21170Sstevel@tonic-gatetrap "rm -f /tmp/$$.* ; exit" 0 1 2 3 15 21180Sstevel@tonic-gate 21190Sstevel@tonic-gateset +o noclobber 21200Sstevel@tonic-gate 21217078SmjnelsonPATH=$(dirname $(whence $0)):$PATH 21227078Smjnelson 21233295Sdp[[ -z $WDIFF ]] && WDIFF=`look_for_prog wdiff` 21243295Sdp[[ -z $WX ]] && WX=`look_for_prog wx` 21257078Smjnelson[[ -z $HG_ACTIVE ]] && HG_ACTIVE=`look_for_prog hg-active` 21267078Smjnelson[[ -z $WHICH_SCM ]] && WHICH_SCM=`look_for_prog which_scm` 21273295Sdp[[ -z $CODEREVIEW ]] && CODEREVIEW=`look_for_prog codereview` 21283295Sdp[[ -z $PS2PDF ]] && PS2PDF=`look_for_prog ps2pdf` 21293295Sdp[[ -z $PERL ]] && PERL=`look_for_prog perl` 21308018SVladimir.Kotal@Sun.COM[[ -z $RSYNC ]] && RSYNC=`look_for_prog rsync` 21317078Smjnelson[[ -z $SCCS ]] && SCCS=`look_for_prog sccs` 21327078Smjnelson[[ -z $AWK ]] && AWK=`look_for_prog nawk` 21337078Smjnelson[[ -z $AWK ]] && AWK=`look_for_prog gawk` 21347078Smjnelson[[ -z $AWK ]] && AWK=`look_for_prog awk` 21358018SVladimir.Kotal@Sun.COM[[ -z $SCP ]] && SCP=`look_for_prog scp` 21369079SVladimir.Kotal@Sun.COM[[ -z $SED ]] && SED=`look_for_prog sed` 21378018SVladimir.Kotal@Sun.COM[[ -z $SFTP ]] && SFTP=`look_for_prog sftp` 213810789SEdward.Pilatowicz@Sun.COM[[ -z $SORT ]] && SORT=`look_for_prog sort` 21398018SVladimir.Kotal@Sun.COM[[ -z $MKTEMP ]] && MKTEMP=`look_for_prog mktemp` 21408018SVladimir.Kotal@Sun.COM[[ -z $GREP ]] && GREP=`look_for_prog grep` 21418365SVladimir.Kotal@Sun.COM[[ -z $FIND ]] && FIND=`look_for_prog find` 21428365SVladimir.Kotal@Sun.COM 21438365SVladimir.Kotal@Sun.COM# set name of trash directory for remote webrev deletion 21448365SVladimir.Kotal@Sun.COMTRASH_DIR=".trash" 21458365SVladimir.Kotal@Sun.COM[[ -n $WEBREV_TRASH_DIR ]] && TRASH_DIR=$WEBREV_TRASH_DIR 21463295Sdp 21473295Sdpif [[ ! -x $PERL ]]; then 21483295Sdp print -u2 "Error: No perl interpreter found. Exiting." 21493295Sdp exit 1 21500Sstevel@tonic-gatefi 21510Sstevel@tonic-gate 21527078Smjnelsonif [[ ! -x $WHICH_SCM ]]; then 21537078Smjnelson print -u2 "Error: Could not find which_scm. Exiting." 21547078Smjnelson exit 1 21557078Smjnelsonfi 21567078Smjnelson 21573295Sdp# 21583295Sdp# These aren't fatal, but we want to note them to the user. 21593295Sdp# We don't warn on the absence of 'wx' until later when we've 21603295Sdp# determined that we actually need to try to invoke it. 21613295Sdp# 21623295Sdp[[ ! -x $CODEREVIEW ]] && print -u2 "WARNING: codereview(1) not found." 21633295Sdp[[ ! -x $PS2PDF ]] && print -u2 "WARNING: ps2pdf(1) not found." 21643295Sdp[[ ! -x $WDIFF ]] && print -u2 "WARNING: wdiff not found." 21653295Sdp 21663252Sdp# Declare global total counters. 21673252Sdpinteger TOTL TINS TDEL TMOD TUNC 21680Sstevel@tonic-gate 21698365SVladimir.Kotal@Sun.COM# default remote host for upload/delete 21708365SVladimir.Kotal@Sun.COMtypeset -r DEFAULT_REMOTE_HOST="cr.opensolaris.org" 21719079SVladimir.Kotal@Sun.COM# prefixes for upload targets 21729079SVladimir.Kotal@Sun.COMtypeset -r rsync_prefix="rsync://" 21739079SVladimir.Kotal@Sun.COMtypeset -r ssh_prefix="ssh://" 21748365SVladimir.Kotal@Sun.COM 21759193SMark.J.Nelson@Sun.COMCflag= 21768365SVladimir.Kotal@Sun.COMDflag= 21773295Sdpflist_mode= 21783295Sdpflist_file= 21793252Sdpiflag= 21809193SMark.J.Nelson@Sun.COMIflag= 21818018SVladimir.Kotal@Sun.COMlflag= 21828018SVladimir.Kotal@Sun.COMNflag= 21838018SVladimir.Kotal@Sun.COMnflag= 21848018SVladimir.Kotal@Sun.COMOflag= 21853252Sdpoflag= 21863252Sdppflag= 21878018SVladimir.Kotal@Sun.COMtflag= 21888018SVladimir.Kotal@Sun.COMuflag= 21898018SVladimir.Kotal@Sun.COMUflag= 21903252Sdpwflag= 21918018SVladimir.Kotal@Sun.COMremote_target= 21928365SVladimir.Kotal@Sun.COM 21938365SVladimir.Kotal@Sun.COM# 21948365SVladimir.Kotal@Sun.COM# NOTE: when adding/removing options it is necessary to sync the list 219510789SEdward.Pilatowicz@Sun.COM# with usr/src/tools/onbld/hgext/cdm.py 21968365SVladimir.Kotal@Sun.COM# 21979561SVladimir.Kotal@Sun.COMwhile getopts "C:Di:I:lnNo:Op:t:Uw" opt 21983252Sdpdo 21993252Sdp case $opt in 22009193SMark.J.Nelson@Sun.COM C) Cflag=1 22019193SMark.J.Nelson@Sun.COM ITSCONF=$OPTARG;; 22029193SMark.J.Nelson@Sun.COM 22038365SVladimir.Kotal@Sun.COM D) Dflag=1;; 22048365SVladimir.Kotal@Sun.COM 22053252Sdp i) iflag=1 22063252Sdp INCLUDE_FILE=$OPTARG;; 22073252Sdp 22089193SMark.J.Nelson@Sun.COM I) Iflag=1 22099193SMark.J.Nelson@Sun.COM ITSREG=$OPTARG;; 22109193SMark.J.Nelson@Sun.COM 22113252Sdp # 22123252Sdp # If -l has been specified, we need to abort further options 22133252Sdp # processing, because subsequent arguments are going to be 22143252Sdp # arguments to 'putback -n'. 22153252Sdp # 22163252Sdp l) lflag=1 22173252Sdp break;; 22180Sstevel@tonic-gate 22198018SVladimir.Kotal@Sun.COM N) Nflag=1;; 22208018SVladimir.Kotal@Sun.COM 22218018SVladimir.Kotal@Sun.COM n) nflag=1;; 22223252Sdp 22233252Sdp O) Oflag=1;; 22240Sstevel@tonic-gate 22258018SVladimir.Kotal@Sun.COM o) oflag=1 222611735SVladimir.Kotal@Sun.COM # Strip the trailing slash to correctly form remote target. 222711735SVladimir.Kotal@Sun.COM WDIR=${OPTARG%/};; 22288018SVladimir.Kotal@Sun.COM 22298018SVladimir.Kotal@Sun.COM p) pflag=1 22308018SVladimir.Kotal@Sun.COM codemgr_parent=$OPTARG;; 22318018SVladimir.Kotal@Sun.COM 22328018SVladimir.Kotal@Sun.COM t) tflag=1 22338018SVladimir.Kotal@Sun.COM remote_target=$OPTARG;; 22348018SVladimir.Kotal@Sun.COM 22358018SVladimir.Kotal@Sun.COM U) Uflag=1;; 22368018SVladimir.Kotal@Sun.COM 22378018SVladimir.Kotal@Sun.COM w) wflag=1;; 22387310SDarren.Moffat@Sun.COM 22393252Sdp ?) usage;; 22403252Sdp esac 22413252Sdpdone 22423252Sdp 22433252SdpFLIST=/tmp/$$.flist 22443252Sdp 22453252Sdpif [[ -n $wflag && -n $lflag ]]; then 22463252Sdp usage 22470Sstevel@tonic-gatefi 22480Sstevel@tonic-gate 22498018SVladimir.Kotal@Sun.COM# more sanity checking 22508018SVladimir.Kotal@Sun.COMif [[ -n $nflag && -z $Uflag ]]; then 22518365SVladimir.Kotal@Sun.COM print "it does not make sense to skip webrev generation" \ 22528365SVladimir.Kotal@Sun.COM "without -U" 22538018SVladimir.Kotal@Sun.COM exit 1 22548018SVladimir.Kotal@Sun.COMfi 22558018SVladimir.Kotal@Sun.COM 22568365SVladimir.Kotal@Sun.COMif [[ -n $tflag && -z $Uflag && -z $Dflag ]]; then 22578365SVladimir.Kotal@Sun.COM echo "remote target has to be used only for upload or delete" 22588018SVladimir.Kotal@Sun.COM exit 1 22598018SVladimir.Kotal@Sun.COMfi 22608018SVladimir.Kotal@Sun.COM 22613252Sdp# 22629420SMark.J.Nelson@Sun.COM# For the invocation "webrev -n -U" with no other options, webrev will assume 22639420SMark.J.Nelson@Sun.COM# that the webrev exists in ${CWS}/webrev, but will upload it using the name 22649420SMark.J.Nelson@Sun.COM# $(basename ${CWS}). So we need to get CWS set before we skip any remaining 22659420SMark.J.Nelson@Sun.COM# logic. 22669420SMark.J.Nelson@Sun.COM# 22679420SMark.J.Nelson@Sun.COM$WHICH_SCM | read SCM_MODE junk || exit 1 22689420SMark.J.Nelson@Sun.COMif [[ $SCM_MODE == "teamware" ]]; then 22699420SMark.J.Nelson@Sun.COM # 22709420SMark.J.Nelson@Sun.COM # Teamware priorities: 22719420SMark.J.Nelson@Sun.COM # 1. CODEMGR_WS from the environment 22729420SMark.J.Nelson@Sun.COM # 2. workspace name 22739420SMark.J.Nelson@Sun.COM # 22749420SMark.J.Nelson@Sun.COM [[ -z $codemgr_ws && -n $CODEMGR_WS ]] && codemgr_ws=$CODEMGR_WS 22759420SMark.J.Nelson@Sun.COM if [[ -n $codemgr_ws && ! -d $codemgr_ws ]]; then 22769420SMark.J.Nelson@Sun.COM print -u2 "$codemgr_ws: no such workspace" 22779420SMark.J.Nelson@Sun.COM exit 1 22789420SMark.J.Nelson@Sun.COM fi 22799420SMark.J.Nelson@Sun.COM [[ -z $codemgr_ws ]] && codemgr_ws=$(workspace name) 22809420SMark.J.Nelson@Sun.COM codemgr_ws=$(cd $codemgr_ws;print $PWD) 22819420SMark.J.Nelson@Sun.COM CODEMGR_WS=$codemgr_ws 22829420SMark.J.Nelson@Sun.COM CWS=$codemgr_ws 22839420SMark.J.Nelson@Sun.COMelif [[ $SCM_MODE == "mercurial" ]]; then 22849420SMark.J.Nelson@Sun.COM # 22859420SMark.J.Nelson@Sun.COM # Mercurial priorities: 22869420SMark.J.Nelson@Sun.COM # 1. hg root from CODEMGR_WS environment variable 2287*12776SJames.McPherson@Sun.COM # 1a. hg root from CODEMGR_WS/usr/closed if we're somewhere under 2288*12776SJames.McPherson@Sun.COM # usr/closed when we run webrev 22899420SMark.J.Nelson@Sun.COM # 2. hg root from directory of invocation 22909420SMark.J.Nelson@Sun.COM # 2291*12776SJames.McPherson@Sun.COM if [[ ${PWD} =~ "usr/closed" ]]; then 2292*12776SJames.McPherson@Sun.COM testparent=${CODEMGR_WS}/usr/closed 2293*12776SJames.McPherson@Sun.COM # If we're in OpenSolaris mode, we enforce a minor policy: 2294*12776SJames.McPherson@Sun.COM # help to make sure the reviewer doesn't accidentally publish 2295*12776SJames.McPherson@Sun.COM # source which is under usr/closed 2296*12776SJames.McPherson@Sun.COM if [[ -n "$Oflag" ]]; then 2297*12776SJames.McPherson@Sun.COM print -u2 "OpenSolaris output not permitted with" \ 2298*12776SJames.McPherson@Sun.COM "usr/closed changes" 2299*12776SJames.McPherson@Sun.COM exit 1 2300*12776SJames.McPherson@Sun.COM fi 2301*12776SJames.McPherson@Sun.COM else 2302*12776SJames.McPherson@Sun.COM testparent=${CODEMGR_WS} 2303*12776SJames.McPherson@Sun.COM fi 2304*12776SJames.McPherson@Sun.COM [[ -z $codemgr_ws && -n $testparent ]] && \ 2305*12776SJames.McPherson@Sun.COM codemgr_ws=$(hg root -R $testparent 2>/dev/null) 23069420SMark.J.Nelson@Sun.COM [[ -z $codemgr_ws ]] && codemgr_ws=$(hg root 2>/dev/null) 23079420SMark.J.Nelson@Sun.COM CWS=$codemgr_ws 23089420SMark.J.Nelson@Sun.COMelif [[ $SCM_MODE == "subversion" ]]; then 23099420SMark.J.Nelson@Sun.COM # 23109420SMark.J.Nelson@Sun.COM # Subversion priorities: 23119420SMark.J.Nelson@Sun.COM # 1. CODEMGR_WS from environment 23129420SMark.J.Nelson@Sun.COM # 2. Relative path from current directory to SVN repository root 23139420SMark.J.Nelson@Sun.COM # 23149420SMark.J.Nelson@Sun.COM if [[ -n $CODEMGR_WS && -d $CODEMGR_WS/.svn ]]; then 23159420SMark.J.Nelson@Sun.COM CWS=$CODEMGR_WS 23169420SMark.J.Nelson@Sun.COM else 23179420SMark.J.Nelson@Sun.COM svn info | while read line; do 23189420SMark.J.Nelson@Sun.COM if [[ $line == "URL: "* ]]; then 23199420SMark.J.Nelson@Sun.COM url=${line#URL: } 23209420SMark.J.Nelson@Sun.COM elif [[ $line == "Repository Root: "* ]]; then 23219420SMark.J.Nelson@Sun.COM repo=${line#Repository Root: } 23229420SMark.J.Nelson@Sun.COM fi 23239420SMark.J.Nelson@Sun.COM done 23249420SMark.J.Nelson@Sun.COM 232510789SEdward.Pilatowicz@Sun.COM rel=${url#$repo} 23269420SMark.J.Nelson@Sun.COM CWS=${PWD%$rel} 23279420SMark.J.Nelson@Sun.COM fi 23289420SMark.J.Nelson@Sun.COMfi 23299420SMark.J.Nelson@Sun.COM 23309420SMark.J.Nelson@Sun.COM# 23319420SMark.J.Nelson@Sun.COM# If no SCM has been determined, take either the environment setting 23329420SMark.J.Nelson@Sun.COM# setting for CODEMGR_WS, or the current directory if that wasn't set. 23339420SMark.J.Nelson@Sun.COM# 23349420SMark.J.Nelson@Sun.COMif [[ -z ${CWS} ]]; then 23359420SMark.J.Nelson@Sun.COM CWS=${CODEMGR_WS:-.} 23369420SMark.J.Nelson@Sun.COMfi 23379420SMark.J.Nelson@Sun.COM 23389420SMark.J.Nelson@Sun.COM# 23399193SMark.J.Nelson@Sun.COM# If the command line options indicate no webrev generation, either 23409193SMark.J.Nelson@Sun.COM# explicitly (-n) or implicitly (-D but not -U), then there's a whole 23419193SMark.J.Nelson@Sun.COM# ton of logic we can skip. 23429193SMark.J.Nelson@Sun.COM# 23439193SMark.J.Nelson@Sun.COM# Instead of increasing indentation, we intentionally leave this loop 23449193SMark.J.Nelson@Sun.COM# body open here, and exit via break from multiple points within. 23459193SMark.J.Nelson@Sun.COM# Search for DO_EVERYTHING below to find the break points and closure. 23469193SMark.J.Nelson@Sun.COM# 23479193SMark.J.Nelson@Sun.COMfor do_everything in 1; do 23489193SMark.J.Nelson@Sun.COM 23499193SMark.J.Nelson@Sun.COM# DO_EVERYTHING: break point 23509193SMark.J.Nelson@Sun.COMif [[ -n $nflag || ( -z $Uflag && -n $Dflag ) ]]; then 23519193SMark.J.Nelson@Sun.COM break 23529193SMark.J.Nelson@Sun.COMfi 23539193SMark.J.Nelson@Sun.COM 23549193SMark.J.Nelson@Sun.COM# 23553252Sdp# If this manually set as the parent, and it appears to be an earlier webrev, 23563252Sdp# then note that fact and set the parent to the raw_files/new subdirectory. 23573252Sdp# 23583252Sdpif [[ -n $pflag && -d $codemgr_parent/raw_files/new ]]; then 23593252Sdp parent_webrev="$codemgr_parent" 23603252Sdp codemgr_parent="$codemgr_parent/raw_files/new" 23610Sstevel@tonic-gatefi 23620Sstevel@tonic-gate 23633252Sdpif [[ -z $wflag && -z $lflag ]]; then 23643252Sdp shift $(($OPTIND - 1)) 23650Sstevel@tonic-gate 23663252Sdp if [[ $1 == "-" ]]; then 23673252Sdp cat > $FLIST 23683295Sdp flist_mode="stdin" 23693295Sdp flist_done=1 23703295Sdp shift 23713252Sdp elif [[ -n $1 ]]; then 23723295Sdp if [[ ! -r $1 ]]; then 23733252Sdp print -u2 "$1: no such file or not readable" 23743252Sdp usage 23753252Sdp fi 23763252Sdp cat $1 > $FLIST 23773295Sdp flist_mode="file" 23783295Sdp flist_file=$1 23793295Sdp flist_done=1 23803295Sdp shift 23813252Sdp else 23823295Sdp flist_mode="auto" 23833252Sdp fi 23843252Sdpfi 23853252Sdp 23863252Sdp# 23873252Sdp# Before we go on to further consider -l and -w, work out which SCM we think 23883252Sdp# is in use. 23893252Sdp# 23907078Smjnelsoncase "$SCM_MODE" in 23917078Smjnelsonteamware|mercurial|subversion) 23927078Smjnelson ;; 23937078Smjnelsonunknown) 23947078Smjnelson if [[ $flist_mode == "auto" ]]; then 23957078Smjnelson print -u2 "Unable to determine SCM in use and file list not specified" 23967078Smjnelson print -u2 "See which_scm(1) for SCM detection information." 23977078Smjnelson exit 1 23987078Smjnelson fi 23997078Smjnelson ;; 24007078Smjnelson*) 24017078Smjnelson if [[ $flist_mode == "auto" ]]; then 24027078Smjnelson print -u2 "Unsupported SCM in use ($SCM_MODE) and file list not specified" 24037078Smjnelson exit 1 24047078Smjnelson fi 24057078Smjnelson ;; 24067078Smjnelsonesac 24070Sstevel@tonic-gate 24083252Sdpprint -u2 " SCM detected: $SCM_MODE" 24090Sstevel@tonic-gate 24103252Sdpif [[ -n $lflag ]]; then 24113252Sdp # 24123252Sdp # If the -l flag is given instead of the name of a file list, 24133252Sdp # then generate the file list by extracting file names from a 24143252Sdp # putback -n. 24153252Sdp # 24163252Sdp shift $(($OPTIND - 1)) 24177078Smjnelson if [[ $SCM_MODE == "teamware" ]]; then 24187078Smjnelson flist_from_teamware "$*" 24197078Smjnelson else 24207078Smjnelson print -u2 -- "Error: -l option only applies to TeamWare" 24217078Smjnelson exit 1 24227078Smjnelson fi 24233252Sdp flist_done=1 24243252Sdp shift $# 24253252Sdpelif [[ -n $wflag ]]; then 24263252Sdp # 24273252Sdp # If the -w is given then assume the file list is in Bonwick's "wx" 24283252Sdp # command format, i.e. pathname lines alternating with SCCS comment 24293252Sdp # lines with blank lines as separators. Use the SCCS comments later 24303252Sdp # in building the index.html file. 24313252Sdp # 24323252Sdp shift $(($OPTIND - 1)) 24333252Sdp wxfile=$1 24343252Sdp if [[ -z $wxfile && -n $CODEMGR_WS ]]; then 24353252Sdp if [[ -r $CODEMGR_WS/wx/active ]]; then 24363252Sdp wxfile=$CODEMGR_WS/wx/active 24373252Sdp fi 24383252Sdp fi 24393252Sdp 24403252Sdp [[ -z $wxfile ]] && print -u2 "wx file not specified, and could not " \ 24413252Sdp "be auto-detected (check \$CODEMGR_WS)" && exit 1 24423252Sdp 24437078Smjnelson if [[ ! -r $wxfile ]]; then 24447078Smjnelson print -u2 "$wxfile: no such file or not readable" 24457078Smjnelson usage 24467078Smjnelson fi 24477078Smjnelson 24483252Sdp print -u2 " File list from: wx 'active' file '$wxfile' ... \c" 24493252Sdp flist_from_wx $wxfile 24503252Sdp flist_done=1 24513252Sdp if [[ -n "$*" ]]; then 24523252Sdp shift 24533252Sdp fi 24543295Sdpelif [[ $flist_mode == "stdin" ]]; then 24553295Sdp print -u2 " File list from: standard input" 24563295Sdpelif [[ $flist_mode == "file" ]]; then 24573295Sdp print -u2 " File list from: $flist_file" 24580Sstevel@tonic-gatefi 24593252Sdp 24603252Sdpif [[ $# -gt 0 ]]; then 24613295Sdp print -u2 "WARNING: unused arguments: $*" 24620Sstevel@tonic-gatefi 24630Sstevel@tonic-gate 24649420SMark.J.Nelson@Sun.COM# 24659420SMark.J.Nelson@Sun.COM# Before we entered the DO_EVERYTHING loop, we should have already set CWS 24669420SMark.J.Nelson@Sun.COM# and CODEMGR_WS as needed. Here, we set the parent workspace. 24679420SMark.J.Nelson@Sun.COM# 24689420SMark.J.Nelson@Sun.COM 24693252Sdpif [[ $SCM_MODE == "teamware" ]]; then 24709420SMark.J.Nelson@Sun.COM 24713252Sdp # 24729420SMark.J.Nelson@Sun.COM # Teamware priorities: 24733252Sdp # 24749420SMark.J.Nelson@Sun.COM # 1) via -p command line option 24753252Sdp # 2) in the user environment 24763252Sdp # 3) in the flist 24779420SMark.J.Nelson@Sun.COM # 4) automatically based on the workspace 24783252Sdp # 24790Sstevel@tonic-gate 24803252Sdp # 24819420SMark.J.Nelson@Sun.COM # For 1, codemgr_parent will already be set. Here's 2: 24823252Sdp # 24833252Sdp [[ -z $codemgr_parent && -n $CODEMGR_PARENT ]] && \ 24843252Sdp codemgr_parent=$CODEMGR_PARENT 24853252Sdp if [[ -n $codemgr_parent && ! -d $codemgr_parent ]]; then 24863252Sdp print -u2 "$codemgr_parent: no such directory" 24873252Sdp exit 1 24883252Sdp fi 24890Sstevel@tonic-gate 24903252Sdp # 24913252Sdp # If we're in auto-detect mode and we haven't already gotten the file 24923252Sdp # list, then see if we can get it by probing for wx. 24933252Sdp # 24943295Sdp if [[ -z $flist_done && $flist_mode == "auto" && -n $codemgr_ws ]]; then 24953295Sdp if [[ ! -x $WX ]]; then 24963295Sdp print -u2 "WARNING: wx not found!" 24973252Sdp fi 24980Sstevel@tonic-gate 24993252Sdp # 25003252Sdp # We need to use wx list -w so that we get renamed files, etc. 25013252Sdp # but only if a wx active file exists-- otherwise wx will 25023252Sdp # hang asking us to initialize our wx information. 25033252Sdp # 25043295Sdp if [[ -x $WX && -f $codemgr_ws/wx/active ]]; then 25053252Sdp print -u2 " File list from: 'wx list -w' ... \c" 25063252Sdp $WX list -w > $FLIST 25073252Sdp $WX comments > /tmp/$$.wx_comments 25083252Sdp wxfile=/tmp/$$.wx_comments 25093252Sdp print -u2 "done" 25103252Sdp flist_done=1 25113252Sdp fi 25123252Sdp fi 25133252Sdp 25143252Sdp # 25153252Sdp # If by hook or by crook we've gotten a file list by now (perhaps 25163252Sdp # from the command line), eval it to extract environment variables from 25179420SMark.J.Nelson@Sun.COM # it: This is method 3 for finding the parent. 25183252Sdp # 25193252Sdp if [[ -z $flist_done ]]; then 25203252Sdp flist_from_teamware 25213252Sdp fi 25229420SMark.J.Nelson@Sun.COM env_from_flist 25233252Sdp 25243252Sdp # 25253252Sdp # (4) If we still don't have a value for codemgr_parent, get it 25263252Sdp # from workspace. 25273252Sdp # 25283252Sdp [[ -z $codemgr_parent ]] && codemgr_parent=`workspace parent` 25293252Sdp if [[ ! -d $codemgr_parent ]]; then 25303252Sdp print -u2 "$CODEMGR_PARENT: no such parent workspace" 25313252Sdp exit 1 25323252Sdp fi 25333252Sdp 25343252Sdp PWS=$codemgr_parent 25357078Smjnelson 25367078Smjnelson [[ -n $parent_webrev ]] && RWS=$(workspace parent $CWS) 25377078Smjnelson 25387078Smjnelsonelif [[ $SCM_MODE == "mercurial" ]]; then 25397078Smjnelson # 25407078Smjnelson # Parent can either be specified with -p 25417078Smjnelson # Specified with CODEMGR_PARENT in the environment 25427078Smjnelson # or taken from hg's default path. 25437078Smjnelson # 25447078Smjnelson 25457078Smjnelson if [[ -z $codemgr_parent && -n $CODEMGR_PARENT ]]; then 25467078Smjnelson codemgr_parent=$CODEMGR_PARENT 25477078Smjnelson fi 25487078Smjnelson 25497078Smjnelson if [[ -z $codemgr_parent ]]; then 25507078Smjnelson codemgr_parent=`hg path -R $codemgr_ws default 2>/dev/null` 25517078Smjnelson fi 25527078Smjnelson 25537078Smjnelson CWS_REV=`hg parent -R $codemgr_ws --template '{node|short}' 2>/dev/null` 25547078Smjnelson PWS=$codemgr_parent 25557078Smjnelson 255610789SEdward.Pilatowicz@Sun.COM # 25577078Smjnelson # If the parent is a webrev, we want to do some things against 25587078Smjnelson # the natural workspace parent (file list, comments, etc) 25597078Smjnelson # 25607078Smjnelson if [[ -n $parent_webrev ]]; then 25617078Smjnelson real_parent=$(hg path -R $codemgr_ws default 2>/dev/null) 25627078Smjnelson else 25637078Smjnelson real_parent=$PWS 25647078Smjnelson fi 25657078Smjnelson 25667078Smjnelson # 25677078Smjnelson # If hg-active exists, then we run it. In the case of no explicit 25687078Smjnelson # flist given, we'll use it for our comments. In the case of an 25697078Smjnelson # explicit flist given we'll try to use it for comments for any 25707078Smjnelson # files mentioned in the flist. 25717078Smjnelson # 25727078Smjnelson if [[ -z $flist_done ]]; then 25737078Smjnelson flist_from_mercurial $CWS $real_parent 25747078Smjnelson flist_done=1 25757078Smjnelson fi 25767078Smjnelson 25777078Smjnelson # 25787078Smjnelson # If we have a file list now, pull out any variables set 25797078Smjnelson # therein. We do this now (rather than when we possibly use 25807078Smjnelson # hg-active to find comments) to avoid stomping specifications 25817078Smjnelson # in the user-specified flist. 258210789SEdward.Pilatowicz@Sun.COM # 25837078Smjnelson if [[ -n $flist_done ]]; then 25847078Smjnelson env_from_flist 25857078Smjnelson fi 25867078Smjnelson 25877078Smjnelson # 25887078Smjnelson # Only call hg-active if we don't have a wx formatted file already 25897078Smjnelson # 25907078Smjnelson if [[ -x $HG_ACTIVE && -z $wxfile ]]; then 25917078Smjnelson print " Comments from: hg-active -p $real_parent ...\c" 25927078Smjnelson hg_active_wxfile $CWS $real_parent 25937078Smjnelson print " Done." 25947078Smjnelson fi 259510789SEdward.Pilatowicz@Sun.COM 25967078Smjnelson # 25977078Smjnelson # At this point we must have a wx flist either from hg-active, 25987078Smjnelson # or in general. Use it to try and find our parent revision, 25997078Smjnelson # if we don't have one. 26007078Smjnelson # 26017078Smjnelson if [[ -z $HG_PARENT ]]; then 26029079SVladimir.Kotal@Sun.COM eval `$SED -e "s/#.*$//" $wxfile | $GREP HG_PARENT=` 26037078Smjnelson fi 26047078Smjnelson 26057078Smjnelson # 26067078Smjnelson # If we still don't have a parent, we must have been given a 26077078Smjnelson # wx-style active list with no HG_PARENT specification, run 26087078Smjnelson # hg-active and pull an HG_PARENT out of it, ignore the rest. 26097078Smjnelson # 26107078Smjnelson if [[ -z $HG_PARENT && -x $HG_ACTIVE ]]; then 26117078Smjnelson $HG_ACTIVE -w $codemgr_ws -p $real_parent | \ 26129079SVladimir.Kotal@Sun.COM eval `$SED -e "s/#.*$//" | $GREP HG_PARENT=` 26137078Smjnelson elif [[ -z $HG_PARENT ]]; then 26147078Smjnelson print -u2 "Error: Cannot discover parent revision" 26157078Smjnelson exit 1 26167078Smjnelson fi 26177078Smjnelsonelif [[ $SCM_MODE == "subversion" ]]; then 26187078Smjnelson 26197078Smjnelson # 26207078Smjnelson # We only will have a real parent workspace in the case one 26217078Smjnelson # was specified (be it an older webrev, or another checkout). 26227078Smjnelson # 26237078Smjnelson [[ -n $codemgr_parent ]] && PWS=$codemgr_parent 26247078Smjnelson 26257078Smjnelson if [[ -z $flist_done && $flist_mode == "auto" ]]; then 26267078Smjnelson flist_from_subversion $CWS $OLDPWD 26277078Smjnelson fi 26287078Smjnelsonelse 26297078Smjnelson if [[ $SCM_MODE == "unknown" ]]; then 26307078Smjnelson print -u2 " Unknown type of SCM in use" 26317078Smjnelson else 26327078Smjnelson print -u2 " Unsupported SCM in use: $SCM_MODE" 26337078Smjnelson fi 26347078Smjnelson 26357078Smjnelson env_from_flist 26367078Smjnelson 26377078Smjnelson if [[ -z $CODEMGR_WS ]]; then 26387078Smjnelson print -u2 "SCM not detected/supported and CODEMGR_WS not specified" 26397078Smjnelson exit 1 26407078Smjnelson fi 26417078Smjnelson 26427078Smjnelson if [[ -z $CODEMGR_PARENT ]]; then 26437078Smjnelson print -u2 "SCM not detected/supported and CODEMGR_PARENT not specified" 26447078Smjnelson exit 1 26457078Smjnelson fi 26467078Smjnelson 26477078Smjnelson CWS=$CODEMGR_WS 26487078Smjnelson PWS=$CODEMGR_PARENT 26490Sstevel@tonic-gatefi 26500Sstevel@tonic-gate 26513252Sdp# 26523252Sdp# If the user didn't specify a -i option, check to see if there is a 26533252Sdp# webrev-info file in the workspace directory. 26543252Sdp# 26553252Sdpif [[ -z $iflag && -r "$CWS/webrev-info" ]]; then 26563252Sdp iflag=1 26573252Sdp INCLUDE_FILE="$CWS/webrev-info" 26580Sstevel@tonic-gatefi 26590Sstevel@tonic-gate 26603252Sdpif [[ -n $iflag ]]; then 26613252Sdp if [[ ! -r $INCLUDE_FILE ]]; then 26623252Sdp print -u2 "include file '$INCLUDE_FILE' does not exist or is" \ 26633252Sdp "not readable." 26643252Sdp exit 1 26653252Sdp else 26663252Sdp # 26673252Sdp # $INCLUDE_FILE may be a relative path, and the script alters 26683252Sdp # PWD, so we just stash a copy in /tmp. 26693252Sdp # 26703252Sdp cp $INCLUDE_FILE /tmp/$$.include 26713252Sdp fi 26720Sstevel@tonic-gatefi 26730Sstevel@tonic-gate 26749193SMark.J.Nelson@Sun.COM# DO_EVERYTHING: break point 26759193SMark.J.Nelson@Sun.COMif [[ -n $Nflag ]]; then 26769193SMark.J.Nelson@Sun.COM break 26779193SMark.J.Nelson@Sun.COMfi 26789193SMark.J.Nelson@Sun.COM 26799193SMark.J.Nelson@Sun.COMtypeset -A itsinfo 26809193SMark.J.Nelson@Sun.COMtypeset -r its_sed_script=/tmp/$$.its_sed 26819193SMark.J.Nelson@Sun.COMvalid_prefixes= 26829193SMark.J.Nelson@Sun.COMif [[ -z $nflag ]]; then 26839193SMark.J.Nelson@Sun.COM DEFREGFILE="$(dirname $(whence $0))/../etc/its.reg" 26849193SMark.J.Nelson@Sun.COM if [[ -n $Iflag ]]; then 26859193SMark.J.Nelson@Sun.COM REGFILE=$ITSREG 26869193SMark.J.Nelson@Sun.COM elif [[ -r $HOME/.its.reg ]]; then 26879193SMark.J.Nelson@Sun.COM REGFILE=$HOME/.its.reg 26889193SMark.J.Nelson@Sun.COM else 26899193SMark.J.Nelson@Sun.COM REGFILE=$DEFREGFILE 26909193SMark.J.Nelson@Sun.COM fi 26919193SMark.J.Nelson@Sun.COM if [[ ! -r $REGFILE ]]; then 26929193SMark.J.Nelson@Sun.COM print "ERROR: Unable to read database registry file $REGFILE" 26939193SMark.J.Nelson@Sun.COM exit 1 26949193SMark.J.Nelson@Sun.COM elif [[ $REGFILE != $DEFREGFILE ]]; then 26959193SMark.J.Nelson@Sun.COM print " its.reg from: $REGFILE" 26969193SMark.J.Nelson@Sun.COM fi 26979193SMark.J.Nelson@Sun.COM 26989193SMark.J.Nelson@Sun.COM $SED -e '/^#/d' -e '/^[ ]*$/d' $REGFILE | while read LINE; do 269910789SEdward.Pilatowicz@Sun.COM 27009193SMark.J.Nelson@Sun.COM name=${LINE%%=*} 27019193SMark.J.Nelson@Sun.COM value="${LINE#*=}" 27029193SMark.J.Nelson@Sun.COM 27039193SMark.J.Nelson@Sun.COM if [[ $name == PREFIX ]]; then 27049193SMark.J.Nelson@Sun.COM p=${value} 27059193SMark.J.Nelson@Sun.COM valid_prefixes="${p} ${valid_prefixes}" 27069193SMark.J.Nelson@Sun.COM else 27079193SMark.J.Nelson@Sun.COM itsinfo["${p}_${name}"]="${value}" 27089193SMark.J.Nelson@Sun.COM fi 27099193SMark.J.Nelson@Sun.COM done 27109193SMark.J.Nelson@Sun.COM 27119193SMark.J.Nelson@Sun.COM 27129193SMark.J.Nelson@Sun.COM DEFCONFFILE="$(dirname $(whence $0))/../etc/its.conf" 27139193SMark.J.Nelson@Sun.COM CONFFILES=$DEFCONFFILE 27149193SMark.J.Nelson@Sun.COM if [[ -r $HOME/.its.conf ]]; then 27159193SMark.J.Nelson@Sun.COM CONFFILES="${CONFFILES} $HOME/.its.conf" 27169193SMark.J.Nelson@Sun.COM fi 27179193SMark.J.Nelson@Sun.COM if [[ -n $Cflag ]]; then 27189193SMark.J.Nelson@Sun.COM CONFFILES="${CONFFILES} ${ITSCONF}" 27199193SMark.J.Nelson@Sun.COM fi 27209193SMark.J.Nelson@Sun.COM its_domain= 27219193SMark.J.Nelson@Sun.COM its_priority= 27229193SMark.J.Nelson@Sun.COM for cf in ${CONFFILES}; do 27239193SMark.J.Nelson@Sun.COM if [[ ! -r $cf ]]; then 27249193SMark.J.Nelson@Sun.COM print "ERROR: Unable to read database configuration file $cf" 27259193SMark.J.Nelson@Sun.COM exit 1 27269193SMark.J.Nelson@Sun.COM elif [[ $cf != $DEFCONFFILE ]]; then 27279193SMark.J.Nelson@Sun.COM print " its.conf: reading $cf" 27289193SMark.J.Nelson@Sun.COM fi 27299193SMark.J.Nelson@Sun.COM $SED -e '/^#/d' -e '/^[ ]*$/d' $cf | while read LINE; do 27309193SMark.J.Nelson@Sun.COM eval "${LINE}" 27319193SMark.J.Nelson@Sun.COM done 27329193SMark.J.Nelson@Sun.COM done 27339193SMark.J.Nelson@Sun.COM 27349193SMark.J.Nelson@Sun.COM # 27359193SMark.J.Nelson@Sun.COM # If an information tracking system is explicitly identified by prefix, 27369193SMark.J.Nelson@Sun.COM # we want to disregard the specified priorities and resolve it accordingly. 27379193SMark.J.Nelson@Sun.COM # 27389193SMark.J.Nelson@Sun.COM # To that end, we'll build a sed script to do each valid prefix in turn. 27399193SMark.J.Nelson@Sun.COM # 27409193SMark.J.Nelson@Sun.COM for p in ${valid_prefixes}; do 27419193SMark.J.Nelson@Sun.COM # 27429193SMark.J.Nelson@Sun.COM # When an informational URL was provided, translate it to a 27439193SMark.J.Nelson@Sun.COM # hyperlink. When omitted, simply use the prefix text. 27449193SMark.J.Nelson@Sun.COM # 27459193SMark.J.Nelson@Sun.COM if [[ -z ${itsinfo["${p}_INFO"]} ]]; then 27469193SMark.J.Nelson@Sun.COM itsinfo["${p}_INFO"]=${p} 27479193SMark.J.Nelson@Sun.COM else 27489193SMark.J.Nelson@Sun.COM itsinfo["${p}_INFO"]="<a href=\\\"${itsinfo["${p}_INFO"]}\\\">${p}</a>" 27499193SMark.J.Nelson@Sun.COM fi 27509193SMark.J.Nelson@Sun.COM 27519193SMark.J.Nelson@Sun.COM # 27529193SMark.J.Nelson@Sun.COM # Assume that, for this invocation of webrev, all references 27539193SMark.J.Nelson@Sun.COM # to this information tracking system should resolve through 27549193SMark.J.Nelson@Sun.COM # the same URL. 27559193SMark.J.Nelson@Sun.COM # 27569193SMark.J.Nelson@Sun.COM # If the caller specified -O, then always use EXTERNAL_URL. 27579193SMark.J.Nelson@Sun.COM # 27589193SMark.J.Nelson@Sun.COM # Otherwise, look in the list of domains for a matching 27599193SMark.J.Nelson@Sun.COM # INTERNAL_URL. 27609193SMark.J.Nelson@Sun.COM # 27619193SMark.J.Nelson@Sun.COM [[ -z $Oflag ]] && for d in ${its_domain}; do 27629193SMark.J.Nelson@Sun.COM if [[ -n ${itsinfo["${p}_INTERNAL_URL_${d}"]} ]]; then 27639193SMark.J.Nelson@Sun.COM itsinfo["${p}_URL"]="${itsinfo[${p}_INTERNAL_URL_${d}]}" 27649193SMark.J.Nelson@Sun.COM break 27659193SMark.J.Nelson@Sun.COM fi 27669193SMark.J.Nelson@Sun.COM done 27679193SMark.J.Nelson@Sun.COM if [[ -z ${itsinfo["${p}_URL"]} ]]; then 27689193SMark.J.Nelson@Sun.COM itsinfo["${p}_URL"]="${itsinfo[${p}_EXTERNAL_URL]}" 27699193SMark.J.Nelson@Sun.COM fi 27709193SMark.J.Nelson@Sun.COM 27719193SMark.J.Nelson@Sun.COM # 27729193SMark.J.Nelson@Sun.COM # Turn the destination URL into a hyperlink 27739193SMark.J.Nelson@Sun.COM # 27749193SMark.J.Nelson@Sun.COM itsinfo["${p}_URL"]="<a href=\\\"${itsinfo[${p}_URL]}\\\">&</a>" 27759193SMark.J.Nelson@Sun.COM 27769193SMark.J.Nelson@Sun.COM print "/^${p}[ ]/ { 27779193SMark.J.Nelson@Sun.COM s;${itsinfo[${p}_REGEX]};${itsinfo[${p}_URL]};g 27789193SMark.J.Nelson@Sun.COM s;^${p};${itsinfo[${p}_INFO]}; 27799193SMark.J.Nelson@Sun.COM }" >> ${its_sed_script} 27809193SMark.J.Nelson@Sun.COM done 27819193SMark.J.Nelson@Sun.COM 27829193SMark.J.Nelson@Sun.COM # 27839193SMark.J.Nelson@Sun.COM # The previous loop took care of explicit specification. Now use 27849193SMark.J.Nelson@Sun.COM # the configured priorities to attempt implicit translations. 27859193SMark.J.Nelson@Sun.COM # 27869193SMark.J.Nelson@Sun.COM for p in ${its_priority}; do 27879193SMark.J.Nelson@Sun.COM print "/^${itsinfo[${p}_REGEX]}[ ]/ { 27889193SMark.J.Nelson@Sun.COM s;${itsinfo[${p}_REGEX]};${itsinfo[${p}_URL]};g 27899193SMark.J.Nelson@Sun.COM }" >> ${its_sed_script} 27909193SMark.J.Nelson@Sun.COM done 27919193SMark.J.Nelson@Sun.COMfi 27929193SMark.J.Nelson@Sun.COM 27939193SMark.J.Nelson@Sun.COM# 27949193SMark.J.Nelson@Sun.COM# Search for DO_EVERYTHING above for matching "for" statement 27959193SMark.J.Nelson@Sun.COM# and explanation of this terminator. 27969193SMark.J.Nelson@Sun.COM# 27979193SMark.J.Nelson@Sun.COMdone 27989193SMark.J.Nelson@Sun.COM 27993252Sdp# 28003252Sdp# Output directory. 28013252Sdp# 28023252SdpWDIR=${WDIR:-$CWS/webrev} 28030Sstevel@tonic-gate 28043252Sdp# 28058018SVladimir.Kotal@Sun.COM# Name of the webrev, derived from the workspace name or output directory; 28068018SVladimir.Kotal@Sun.COM# in the future this could potentially be an option. 28073252Sdp# 28088018SVladimir.Kotal@Sun.COMif [[ -n $oflag ]]; then 28098018SVladimir.Kotal@Sun.COM WNAME=${WDIR##*/} 28108018SVladimir.Kotal@Sun.COMelse 28118018SVladimir.Kotal@Sun.COM WNAME=${CWS##*/} 28128018SVladimir.Kotal@Sun.COMfi 28138018SVladimir.Kotal@Sun.COM 28148365SVladimir.Kotal@Sun.COM# Make sure remote target is well formed for remote upload/delete. 28158365SVladimir.Kotal@Sun.COMif [[ -n $Dflag || -n $Uflag ]]; then 28169079SVladimir.Kotal@Sun.COM # 28178365SVladimir.Kotal@Sun.COM # If remote target is not specified, build it from scratch using 28188365SVladimir.Kotal@Sun.COM # the default values. 28199079SVladimir.Kotal@Sun.COM # 28208365SVladimir.Kotal@Sun.COM if [[ -z $tflag ]]; then 28218365SVladimir.Kotal@Sun.COM remote_target=${DEFAULT_REMOTE_HOST}:${WNAME} 28228365SVladimir.Kotal@Sun.COM else 28239079SVladimir.Kotal@Sun.COM # 28249079SVladimir.Kotal@Sun.COM # Check upload target prefix first. 28259079SVladimir.Kotal@Sun.COM # 28269079SVladimir.Kotal@Sun.COM if [[ "${remote_target}" != ${rsync_prefix}* && 28279079SVladimir.Kotal@Sun.COM "${remote_target}" != ${ssh_prefix}* ]]; then 28289079SVladimir.Kotal@Sun.COM print "ERROR: invalid prefix of upload URI" \ 28299079SVladimir.Kotal@Sun.COM "($remote_target)" 28309079SVladimir.Kotal@Sun.COM exit 1 28319079SVladimir.Kotal@Sun.COM fi 28329079SVladimir.Kotal@Sun.COM # 28338365SVladimir.Kotal@Sun.COM # If destination specification is not in the form of 28348365SVladimir.Kotal@Sun.COM # host_spec:remote_dir then assume it is just remote hostname 28358365SVladimir.Kotal@Sun.COM # and append a colon and destination directory formed from 28368365SVladimir.Kotal@Sun.COM # local webrev directory name. 28379079SVladimir.Kotal@Sun.COM # 28389079SVladimir.Kotal@Sun.COM typeset target_no_prefix=${remote_target##*://} 28399079SVladimir.Kotal@Sun.COM if [[ ${target_no_prefix} == *:* ]]; then 28408365SVladimir.Kotal@Sun.COM if [[ "${remote_target}" == *: ]]; then 28419079SVladimir.Kotal@Sun.COM remote_target=${remote_target}${WNAME} 28429079SVladimir.Kotal@Sun.COM fi 28439079SVladimir.Kotal@Sun.COM else 28449079SVladimir.Kotal@Sun.COM if [[ ${target_no_prefix} == */* ]]; then 28459079SVladimir.Kotal@Sun.COM print "ERROR: badly formed upload URI" \ 28469079SVladimir.Kotal@Sun.COM "($remote_target)" 28479079SVladimir.Kotal@Sun.COM exit 1 28488365SVladimir.Kotal@Sun.COM else 28499079SVladimir.Kotal@Sun.COM remote_target=${remote_target}:${WNAME} 28508365SVladimir.Kotal@Sun.COM fi 28518365SVladimir.Kotal@Sun.COM fi 28528365SVladimir.Kotal@Sun.COM fi 28539079SVladimir.Kotal@Sun.COM 28549079SVladimir.Kotal@Sun.COM # 28559079SVladimir.Kotal@Sun.COM # Strip trailing slash. Each upload method will deal with directory 28569079SVladimir.Kotal@Sun.COM # specification separately. 28579079SVladimir.Kotal@Sun.COM # 28589079SVladimir.Kotal@Sun.COM remote_target=${remote_target%/} 28598365SVladimir.Kotal@Sun.COMfi 28608365SVladimir.Kotal@Sun.COM 28619079SVladimir.Kotal@Sun.COM# 28628365SVladimir.Kotal@Sun.COM# Option -D by itself (option -U not present) implies no webrev generation. 28639079SVladimir.Kotal@Sun.COM# 28648365SVladimir.Kotal@Sun.COMif [[ -z $Uflag && -n $Dflag ]]; then 28659079SVladimir.Kotal@Sun.COM delete_webrev 1 1 28668018SVladimir.Kotal@Sun.COM exit $? 28678018SVladimir.Kotal@Sun.COMfi 28683252Sdp 28699079SVladimir.Kotal@Sun.COM# 28708365SVladimir.Kotal@Sun.COM# Do not generate the webrev, just upload it or delete it. 28719079SVladimir.Kotal@Sun.COM# 28728365SVladimir.Kotal@Sun.COMif [[ -n $nflag ]]; then 28738365SVladimir.Kotal@Sun.COM if [[ -n $Dflag ]]; then 28749079SVladimir.Kotal@Sun.COM delete_webrev 1 1 28758365SVladimir.Kotal@Sun.COM (( $? == 0 )) || exit $? 28768365SVladimir.Kotal@Sun.COM fi 28778365SVladimir.Kotal@Sun.COM if [[ -n $Uflag ]]; then 28788365SVladimir.Kotal@Sun.COM upload_webrev 28798365SVladimir.Kotal@Sun.COM exit $? 28808365SVladimir.Kotal@Sun.COM fi 28818365SVladimir.Kotal@Sun.COMfi 28828365SVladimir.Kotal@Sun.COM 28835175Sjmcpif [ "${WDIR%%/*}" ]; then 28840Sstevel@tonic-gate WDIR=$PWD/$WDIR 28850Sstevel@tonic-gatefi 28863252Sdp 28873252Sdpif [[ ! -d $WDIR ]]; then 28883252Sdp mkdir -p $WDIR 28898365SVladimir.Kotal@Sun.COM (( $? != 0 )) && exit 1 28903252Sdpfi 28913252Sdp 28923252Sdp# 28933252Sdp# Summarize what we're going to do. 28943252Sdp# 28957078Smjnelsonif [[ -n $CWS_REV ]]; then 28967078Smjnelson print " Workspace: $CWS (at $CWS_REV)" 28977078Smjnelsonelse 28987078Smjnelson print " Workspace: $CWS" 28997078Smjnelsonfi 29003252Sdpif [[ -n $parent_webrev ]]; then 29013252Sdp print "Compare against: webrev at $parent_webrev" 29023252Sdpelse 29037078Smjnelson if [[ -n $HG_PARENT ]]; then 29047078Smjnelson hg_parent_short=`echo $HG_PARENT \ 29059079SVladimir.Kotal@Sun.COM | $SED -e 's/\([0-9a-f]\{12\}\).*/\1/'` 29067078Smjnelson print "Compare against: $PWS (at $hg_parent_short)" 29077078Smjnelson else 29087078Smjnelson print "Compare against: $PWS" 29097078Smjnelson fi 29100Sstevel@tonic-gatefi 29110Sstevel@tonic-gate 29123252Sdp[[ -n $INCLUDE_FILE ]] && print " Including: $INCLUDE_FILE" 29133252Sdpprint " Output to: $WDIR" 29143252Sdp 29153252Sdp# 29160Sstevel@tonic-gate# Save the file list in the webrev dir 29173252Sdp# 29183252Sdp[[ ! $FLIST -ef $WDIR/file.list ]] && cp $FLIST $WDIR/file.list 29190Sstevel@tonic-gate 29203252Sdprm -f $WDIR/$WNAME.patch 29213252Sdprm -f $WDIR/$WNAME.ps 29223252Sdprm -f $WDIR/$WNAME.pdf 29230Sstevel@tonic-gate 29243252Sdptouch $WDIR/$WNAME.patch 29253252Sdp 29263252Sdpprint " Output Files:" 29270Sstevel@tonic-gate 29283252Sdp# 29293252Sdp# Clean up the file list: Remove comments, blank lines and env variables. 29303252Sdp# 29319079SVladimir.Kotal@Sun.COM$SED -e "s/#.*$//" -e "/=/d" -e "/^[ ]*$/d" $FLIST > /tmp/$$.flist.clean 29323252SdpFLIST=/tmp/$$.flist.clean 29333252Sdp 29343252Sdp# 29357078Smjnelson# For Mercurial, create a cache of manifest entries. 29367078Smjnelson# 29377078Smjnelsonif [[ $SCM_MODE == "mercurial" ]]; then 29387078Smjnelson # 29397078Smjnelson # Transform the FLIST into a temporary sed script that matches 29407078Smjnelson # relevant entries in the Mercurial manifest as follows: 29417078Smjnelson # 1) The script will be used against the parent revision manifest, 29427078Smjnelson # so for FLIST lines that have two filenames (a renamed file) 29437078Smjnelson # keep only the old name. 29447078Smjnelson # 2) Escape all forward slashes the filename. 29457078Smjnelson # 3) Change the filename into another sed command that matches 29467078Smjnelson # that file in "hg manifest -v" output: start of line, three 29477078Smjnelson # octal digits for file permissions, space, a file type flag 29487078Smjnelson # character, space, the filename, end of line. 294910789SEdward.Pilatowicz@Sun.COM # 4) Eliminate any duplicate entries. (This can occur if a 295010789SEdward.Pilatowicz@Sun.COM # file has been used as the source of an hg cp and it's 295110789SEdward.Pilatowicz@Sun.COM # also been modified in the same changeset.) 29527078Smjnelson # 29537078Smjnelson SEDFILE=/tmp/$$.manifest.sed 29549079SVladimir.Kotal@Sun.COM $SED ' 29557078Smjnelson s#^[^ ]* ## 29567078Smjnelson s#/#\\\/#g 29577078Smjnelson s#^.*$#/^... . &$/p# 295810789SEdward.Pilatowicz@Sun.COM ' < $FLIST | $SORT -u > $SEDFILE 29597078Smjnelson 29607078Smjnelson # 29617078Smjnelson # Apply the generated script to the output of "hg manifest -v" 29627078Smjnelson # to get the relevant subset for this webrev. 29637078Smjnelson # 29647078Smjnelson HG_PARENT_MANIFEST=/tmp/$$.manifest 29657078Smjnelson hg -R $CWS manifest -v -r $HG_PARENT | 29669079SVladimir.Kotal@Sun.COM $SED -n -f $SEDFILE > $HG_PARENT_MANIFEST 29677078Smjnelsonfi 29687078Smjnelson 29697078Smjnelson# 29703252Sdp# First pass through the files: generate the per-file webrev HTML-files. 29713252Sdp# 29723252Sdpcat $FLIST | while read LINE 29730Sstevel@tonic-gatedo 29740Sstevel@tonic-gate set - $LINE 29750Sstevel@tonic-gate P=$1 29760Sstevel@tonic-gate 29773252Sdp # 29783252Sdp # Normally, each line in the file list is just a pathname of a 29793252Sdp # file that has been modified or created in the child. A file 29803252Sdp # that is renamed in the child workspace has two names on the 29813252Sdp # line: new name followed by the old name. 29823252Sdp # 29833252Sdp oldname="" 29843252Sdp oldpath="" 29853252Sdp rename= 29863252Sdp if [[ $# -eq 2 ]]; then 29870Sstevel@tonic-gate PP=$2 # old filename 298810789SEdward.Pilatowicz@Sun.COM if [[ -f $PP ]]; then 298910789SEdward.Pilatowicz@Sun.COM oldname=" (copied from $PP)" 299010789SEdward.Pilatowicz@Sun.COM else 299110789SEdward.Pilatowicz@Sun.COM oldname=" (renamed from $PP)" 299210789SEdward.Pilatowicz@Sun.COM fi 29933252Sdp oldpath="$PP" 29943252Sdp rename=1 299510789SEdward.Pilatowicz@Sun.COM PDIR=${PP%/*} 299610789SEdward.Pilatowicz@Sun.COM if [[ $PDIR == $PP ]]; then 29970Sstevel@tonic-gate PDIR="." # File at root of workspace 29980Sstevel@tonic-gate fi 29990Sstevel@tonic-gate 30000Sstevel@tonic-gate PF=${PP##*/} 30010Sstevel@tonic-gate 300210789SEdward.Pilatowicz@Sun.COM DIR=${P%/*} 300310789SEdward.Pilatowicz@Sun.COM if [[ $DIR == $P ]]; then 30040Sstevel@tonic-gate DIR="." # File at root of workspace 30050Sstevel@tonic-gate fi 30063252Sdp 30070Sstevel@tonic-gate F=${P##*/} 30083252Sdp 30090Sstevel@tonic-gate else 301010789SEdward.Pilatowicz@Sun.COM DIR=${P%/*} 301110789SEdward.Pilatowicz@Sun.COM if [[ "$DIR" == "$P" ]]; then 30120Sstevel@tonic-gate DIR="." # File at root of workspace 30130Sstevel@tonic-gate fi 30143252Sdp 30150Sstevel@tonic-gate F=${P##*/} 30160Sstevel@tonic-gate 30170Sstevel@tonic-gate PP=$P 30180Sstevel@tonic-gate PDIR=$DIR 30190Sstevel@tonic-gate PF=$F 30200Sstevel@tonic-gate fi 30210Sstevel@tonic-gate 30223252Sdp COMM=`getcomments html $P $PP` 30230Sstevel@tonic-gate 30243252Sdp print "\t$P$oldname\n\t\t\c" 30250Sstevel@tonic-gate 30260Sstevel@tonic-gate # Make the webrev mirror directory if necessary 30273252Sdp mkdir -p $WDIR/$DIR 30280Sstevel@tonic-gate 30293252Sdp # 30307078Smjnelson # We stash old and new files into parallel directories in $WDIR 30313252Sdp # and do our diffs there. This makes it possible to generate 30323252Sdp # clean looking diffs which don't have absolute paths present. 30333252Sdp # 30347078Smjnelson 30357078Smjnelson build_old_new "$WDIR" "$PWS" "$PDIR" "$PF" "$CWS" "$DIR" "$F" || \ 30367078Smjnelson continue 30377078Smjnelson 30387078Smjnelson # 30397078Smjnelson # Keep the old PWD around, so we can safely switch back after 30407078Smjnelson # diff generation, such that build_old_new runs in a 30417078Smjnelson # consistent environment. 30427078Smjnelson # 30437078Smjnelson OWD=$PWD 30443252Sdp cd $WDIR/raw_files 30453252Sdp ofile=old/$PDIR/$PF 30463252Sdp nfile=new/$DIR/$F 30473252Sdp 30483252Sdp mv_but_nodiff= 30493252Sdp cmp $ofile $nfile > /dev/null 2>&1 30503252Sdp if [[ $? == 0 && $rename == 1 ]]; then 30513252Sdp mv_but_nodiff=1 30523252Sdp fi 30533252Sdp 30543252Sdp # 30553252Sdp # If we have old and new versions of the file then run the appropriate 30563252Sdp # diffs. This is complicated by a couple of factors: 30573252Sdp # 30583252Sdp # - renames must be handled specially: we emit a 'remove' 30593252Sdp # diff and an 'add' diff 30603252Sdp # - new files and deleted files must be handled specially 30613252Sdp # - Solaris patch(1m) can't cope with file creation 30623252Sdp # (and hence renames) as of this writing. 30633252Sdp # - To make matters worse, gnu patch doesn't interpret the 30643252Sdp # output of Solaris diff properly when it comes to 30653252Sdp # adds and deletes. We need to do some "cleansing" 30663252Sdp # transformations: 306710789SEdward.Pilatowicz@Sun.COM # [to add a file] @@ -1,0 +X,Y @@ --> @@ -0,0 +X,Y @@ 30683252Sdp # [to del a file] @@ -X,Y +1,0 @@ --> @@ -X,Y +0,0 @@ 30693252Sdp # 30709079SVladimir.Kotal@Sun.COM cleanse_rmfile="$SED 's/^\(@@ [0-9+,-]*\) [0-9+,-]* @@$/\1 +0,0 @@/'" 30719079SVladimir.Kotal@Sun.COM cleanse_newfile="$SED 's/^@@ [0-9+,-]* \([0-9+,-]* @@\)$/@@ -0,0 \1/'" 30720Sstevel@tonic-gate 30733252Sdp rm -f $WDIR/$DIR/$F.patch 30743252Sdp if [[ -z $rename ]]; then 30755175Sjmcp if [ ! -f "$ofile" ]; then 30763252Sdp diff -u /dev/null $nfile | sh -c "$cleanse_newfile" \ 30773252Sdp > $WDIR/$DIR/$F.patch 30785175Sjmcp elif [ ! -f "$nfile" ]; then 30793252Sdp diff -u $ofile /dev/null | sh -c "$cleanse_rmfile" \ 30803252Sdp > $WDIR/$DIR/$F.patch 30813252Sdp else 30823252Sdp diff -u $ofile $nfile > $WDIR/$DIR/$F.patch 30833252Sdp fi 30843252Sdp else 30853252Sdp diff -u $ofile /dev/null | sh -c "$cleanse_rmfile" \ 30863252Sdp > $WDIR/$DIR/$F.patch 30873252Sdp 30883252Sdp diff -u /dev/null $nfile | sh -c "$cleanse_newfile" \ 30893252Sdp >> $WDIR/$DIR/$F.patch 30903252Sdp fi 30913252Sdp 30923252Sdp # 30933252Sdp # Tack the patch we just made onto the accumulated patch for the 30943252Sdp # whole wad. 30953252Sdp # 30963252Sdp cat $WDIR/$DIR/$F.patch >> $WDIR/$WNAME.patch 30973252Sdp 30983252Sdp print " patch\c" 30993252Sdp 31003252Sdp if [[ -f $ofile && -f $nfile && -z $mv_but_nodiff ]]; then 31013252Sdp 31023252Sdp ${CDIFFCMD:-diff -bt -C 5} $ofile $nfile > $WDIR/$DIR/$F.cdiff 31033252Sdp diff_to_html $F $DIR/$F "C" "$COMM" < $WDIR/$DIR/$F.cdiff \ 31043252Sdp > $WDIR/$DIR/$F.cdiff.html 31050Sstevel@tonic-gate print " cdiffs\c" 31060Sstevel@tonic-gate 31073252Sdp ${UDIFFCMD:-diff -bt -U 5} $ofile $nfile > $WDIR/$DIR/$F.udiff 31083252Sdp diff_to_html $F $DIR/$F "U" "$COMM" < $WDIR/$DIR/$F.udiff \ 31093252Sdp > $WDIR/$DIR/$F.udiff.html 31103252Sdp 31110Sstevel@tonic-gate print " udiffs\c" 31120Sstevel@tonic-gate 31130Sstevel@tonic-gate if [[ -x $WDIFF ]]; then 31143252Sdp $WDIFF -c "$COMM" \ 31153252Sdp -t "$WNAME Wdiff $DIR/$F" $ofile $nfile > \ 31163252Sdp $WDIR/$DIR/$F.wdiff.html 2>/dev/null 31173252Sdp if [[ $? -eq 0 ]]; then 31183252Sdp print " wdiffs\c" 31193252Sdp else 31203252Sdp print " wdiffs[fail]\c" 31213252Sdp fi 31220Sstevel@tonic-gate fi 31230Sstevel@tonic-gate 31243252Sdp sdiff_to_html $ofile $nfile $F $DIR "$COMM" \ 31253252Sdp > $WDIR/$DIR/$F.sdiff.html 31260Sstevel@tonic-gate print " sdiffs\c" 31270Sstevel@tonic-gate 31283252Sdp print " frames\c" 31290Sstevel@tonic-gate 31300Sstevel@tonic-gate rm -f $WDIR/$DIR/$F.cdiff $WDIR/$DIR/$F.udiff 31310Sstevel@tonic-gate 31323252Sdp difflines $ofile $nfile > $WDIR/$DIR/$F.count 31333252Sdp 31343252Sdp elif [[ -f $ofile && -f $nfile && -n $mv_but_nodiff ]]; then 31353252Sdp # renamed file: may also have differences 31363252Sdp difflines $ofile $nfile > $WDIR/$DIR/$F.count 31373252Sdp elif [[ -f $nfile ]]; then 31380Sstevel@tonic-gate # new file: count added lines 31393252Sdp difflines /dev/null $nfile > $WDIR/$DIR/$F.count 31403252Sdp elif [[ -f $ofile ]]; then 31410Sstevel@tonic-gate # old file: count deleted lines 31423252Sdp difflines $ofile /dev/null > $WDIR/$DIR/$F.count 31430Sstevel@tonic-gate fi 31440Sstevel@tonic-gate 31453252Sdp # 31463252Sdp # Now we generate the postscript for this file. We generate diffs 31473252Sdp # only in the event that there is delta, or the file is new (it seems 31483252Sdp # tree-killing to print out the contents of deleted files). 31493252Sdp # 31503252Sdp if [[ -f $nfile ]]; then 31513252Sdp ocr=$ofile 31523252Sdp [[ ! -f $ofile ]] && ocr=/dev/null 31533252Sdp 31543252Sdp if [[ -z $mv_but_nodiff ]]; then 31553252Sdp textcomm=`getcomments text $P $PP` 31563295Sdp if [[ -x $CODEREVIEW ]]; then 31573295Sdp $CODEREVIEW -y "$textcomm" \ 31583295Sdp -e $ocr $nfile \ 31593295Sdp > /tmp/$$.psfile 2>/dev/null && 31603295Sdp cat /tmp/$$.psfile >> $WDIR/$WNAME.ps 31613295Sdp if [[ $? -eq 0 ]]; then 31623295Sdp print " ps\c" 31633295Sdp else 31643295Sdp print " ps[fail]\c" 31653295Sdp fi 31663252Sdp fi 31673252Sdp fi 31683252Sdp fi 31693252Sdp 31707078Smjnelson if [[ -f $ofile ]]; then 31717078Smjnelson source_to_html Old $PP < $ofile > $WDIR/$DIR/$F-.html 31720Sstevel@tonic-gate print " old\c" 31730Sstevel@tonic-gate fi 31740Sstevel@tonic-gate 31753252Sdp if [[ -f $nfile ]]; then 31763252Sdp source_to_html New $P < $nfile > $WDIR/$DIR/$F.html 31770Sstevel@tonic-gate print " new\c" 31780Sstevel@tonic-gate fi 31790Sstevel@tonic-gate 31807078Smjnelson cd $OWD 31817078Smjnelson 31823252Sdp print 31830Sstevel@tonic-gatedone 31840Sstevel@tonic-gate 31853252Sdpframe_nav_js > $WDIR/ancnav.js 31863252Sdpframe_navigation > $WDIR/ancnav.html 31873252Sdp 31883295Sdpif [[ ! -f $WDIR/$WNAME.ps ]]; then 31893295Sdp print " Generating PDF: Skipped: no output available" 31903295Sdpelif [[ -x $CODEREVIEW && -x $PS2PDF ]]; then 31913295Sdp print " Generating PDF: \c" 31923295Sdp fix_postscript $WDIR/$WNAME.ps | $PS2PDF - > $WDIR/$WNAME.pdf 31933295Sdp print "Done." 31943295Sdpelse 31953295Sdp print " Generating PDF: Skipped: missing 'ps2pdf' or 'codereview'" 31963295Sdpfi 31970Sstevel@tonic-gate 31985175Sjmcp# If we're in OpenSolaris mode and there's a closed dir under $WDIR, 31995175Sjmcp# delete it - prevent accidental publishing of closed source 32005175Sjmcp 32015175Sjmcpif [[ -n "$Oflag" ]]; then 32028365SVladimir.Kotal@Sun.COM $FIND $WDIR -type d -name closed -exec /bin/rm -rf {} \; 32035175Sjmcpfi 32045175Sjmcp 32050Sstevel@tonic-gate# Now build the index.html file that contains 32060Sstevel@tonic-gate# links to the source files and their diffs. 32070Sstevel@tonic-gate 32080Sstevel@tonic-gatecd $CWS 32090Sstevel@tonic-gate 32100Sstevel@tonic-gate# Save total changed lines for Code Inspection. 32113252Sdpprint "$TOTL" > $WDIR/TotalChangedLines 32120Sstevel@tonic-gate 32133252Sdpprint " index.html: \c" 32140Sstevel@tonic-gateINDEXFILE=$WDIR/index.html 32150Sstevel@tonic-gateexec 3<&1 # duplicate stdout to FD3. 32160Sstevel@tonic-gateexec 1<&- # Close stdout. 32170Sstevel@tonic-gateexec > $INDEXFILE # Open stdout to index file. 32180Sstevel@tonic-gate 32193252Sdpprint "$HTML<head>$STDHEAD" 32203252Sdpprint "<title>$WNAME</title>" 32213252Sdpprint "</head>" 32223252Sdpprint "<body id=\"SUNWwebrev\">" 32233252Sdpprint "<div class=\"summary\">" 32243252Sdpprint "<h2>Code Review for $WNAME</h2>" 32253252Sdp 32263252Sdpprint "<table>" 32273252Sdp 32283252Sdp# 32297078Smjnelson# Get the preparer's name: 32307078Smjnelson# 32317078Smjnelson# If the SCM detected is Mercurial, and the configuration property 32327078Smjnelson# ui.username is available, use that, but be careful to properly escape 32337078Smjnelson# angle brackets (HTML syntax characters) in the email address. 32347078Smjnelson# 32357078Smjnelson# Otherwise, use the current userid in the form "John Doe (jdoe)", but 32367078Smjnelson# to maintain compatibility with passwd(4), we must support '&' substitutions. 32373252Sdp# 32387078Smjnelsonpreparer= 32397078Smjnelsonif [[ "$SCM_MODE" == mercurial ]]; then 32407078Smjnelson preparer=`hg showconfig ui.username 2>/dev/null` 32417078Smjnelson if [[ -n "$preparer" ]]; then 32427078Smjnelson preparer="$(echo "$preparer" | html_quote)" 32437078Smjnelson fi 32443252Sdpfi 32457078Smjnelsonif [[ -z "$preparer" ]]; then 32467078Smjnelson preparer=$( 32477078Smjnelson $PERL -e ' 32487078Smjnelson ($login, $pw, $uid, $gid, $quota, $cmt, $gcos) = getpwuid($<); 32497078Smjnelson if ($login) { 32507078Smjnelson $gcos =~ s/\&/ucfirst($login)/e; 32517078Smjnelson printf "%s (%s)\n", $gcos, $login; 32527078Smjnelson } else { 32537078Smjnelson printf "(unknown)\n"; 32547078Smjnelson } 32557078Smjnelson ') 32567078Smjnelsonfi 32577078Smjnelson 325810738SJames.McPherson@Sun.COMPREPDATE=$(LC_ALL=C /usr/bin/date +%Y-%b-%d\ %R\ %z\ %Z) 325910738SJames.McPherson@Sun.COMprint "<tr><th>Prepared by:</th><td>$preparer on $PREPDATE</td></tr>" 32607078Smjnelsonprint "<tr><th>Workspace:</th><td>$CWS" 32617078Smjnelsonif [[ -n $CWS_REV ]]; then 32627078Smjnelson print "(at $CWS_REV)" 32637078Smjnelsonfi 32647078Smjnelsonprint "</td></tr>" 32653252Sdpprint "<tr><th>Compare against:</th><td>" 32663252Sdpif [[ -n $parent_webrev ]]; then 32673252Sdp print "webrev at $parent_webrev" 32683252Sdpelse 32693252Sdp print "$PWS" 32707078Smjnelson if [[ -n $hg_parent_short ]]; then 32717078Smjnelson print "(at $hg_parent_short)" 32727078Smjnelson fi 32733252Sdpfi 32743252Sdpprint "</td></tr>" 32753252Sdpprint "<tr><th>Summary of changes:</th><td>" 32763252SdpprintCI $TOTL $TINS $TDEL $TMOD $TUNC 32773252Sdpprint "</td></tr>" 32780Sstevel@tonic-gate 32793252Sdpif [[ -f $WDIR/$WNAME.patch ]]; then 32809011SLubomir.Sedlacik@Sun.COM wpatch_url="$(print $WNAME.patch | url_encode)" 32813252Sdp print "<tr><th>Patch of changes:</th><td>" 32829011SLubomir.Sedlacik@Sun.COM print "<a href=\"$wpatch_url\">$WNAME.patch</a></td></tr>" 32833252Sdpfi 32843252Sdpif [[ -f $WDIR/$WNAME.pdf ]]; then 32859011SLubomir.Sedlacik@Sun.COM wpdf_url="$(print $WNAME.pdf | url_encode)" 32863252Sdp print "<tr><th>Printable review:</th><td>" 32879011SLubomir.Sedlacik@Sun.COM print "<a href=\"$wpdf_url\">$WNAME.pdf</a></td></tr>" 32883252Sdpfi 32890Sstevel@tonic-gate 32903252Sdpif [[ -n "$iflag" ]]; then 32913252Sdp print "<tr><th>Author comments:</th><td><div>" 32923252Sdp cat /tmp/$$.include 32933252Sdp print "</div></td></tr>" 32943252Sdpfi 32953252Sdpprint "</table>" 32963252Sdpprint "</div>" 32973252Sdp 32983252Sdp# 32993252Sdp# Second pass through the files: generate the rest of the index file 33003252Sdp# 33013252Sdpcat $FLIST | while read LINE 33020Sstevel@tonic-gatedo 33030Sstevel@tonic-gate set - $LINE 33040Sstevel@tonic-gate P=$1 33050Sstevel@tonic-gate 33063252Sdp if [[ $# == 2 ]]; then 33070Sstevel@tonic-gate PP=$2 33087078Smjnelson oldname="$PP" 33090Sstevel@tonic-gate else 33100Sstevel@tonic-gate PP=$P 33113252Sdp oldname="" 33123252Sdp fi 33133252Sdp 33147078Smjnelson mv_but_nodiff= 33157078Smjnelson cmp $WDIR/raw_files/old/$PP $WDIR/raw_files/new/$P > /dev/null 2>&1 33167078Smjnelson if [[ $? == 0 && -n "$oldname" ]]; then 33177078Smjnelson mv_but_nodiff=1 33187078Smjnelson fi 33197078Smjnelson 33203252Sdp DIR=${P%/*} 33213252Sdp if [[ $DIR == $P ]]; then 33223252Sdp DIR="." # File at root of workspace 33230Sstevel@tonic-gate fi 33240Sstevel@tonic-gate 33250Sstevel@tonic-gate # Avoid processing the same file twice. 33260Sstevel@tonic-gate # It's possible for renamed files to 33270Sstevel@tonic-gate # appear twice in the file list 33280Sstevel@tonic-gate 33290Sstevel@tonic-gate F=$WDIR/$P 33300Sstevel@tonic-gate 33313252Sdp print "<p>" 33320Sstevel@tonic-gate 33330Sstevel@tonic-gate # If there's a diffs file, make diffs links 33340Sstevel@tonic-gate 33353252Sdp if [[ -f $F.cdiff.html ]]; then 33369011SLubomir.Sedlacik@Sun.COM cdiff_url="$(print $P.cdiff.html | url_encode)" 33379011SLubomir.Sedlacik@Sun.COM udiff_url="$(print $P.udiff.html | url_encode)" 33389011SLubomir.Sedlacik@Sun.COM print "<a href=\"$cdiff_url\">Cdiffs</a>" 33399011SLubomir.Sedlacik@Sun.COM print "<a href=\"$udiff_url\">Udiffs</a>" 33403252Sdp 33413252Sdp if [[ -f $F.wdiff.html && -x $WDIFF ]]; then 33429011SLubomir.Sedlacik@Sun.COM wdiff_url="$(print $P.wdiff.html | url_encode)" 33439011SLubomir.Sedlacik@Sun.COM print "<a href=\"$wdiff_url\">Wdiffs</a>" 33443252Sdp fi 33450Sstevel@tonic-gate 33469011SLubomir.Sedlacik@Sun.COM sdiff_url="$(print $P.sdiff.html | url_encode)" 33479011SLubomir.Sedlacik@Sun.COM print "<a href=\"$sdiff_url\">Sdiffs</a>" 33489011SLubomir.Sedlacik@Sun.COM 33499011SLubomir.Sedlacik@Sun.COM frames_url="$(print $P.frames.html | url_encode)" 33509011SLubomir.Sedlacik@Sun.COM print "<a href=\"$frames_url\">Frames</a>" 33513252Sdp else 33523252Sdp print " ------ ------ ------" 33533252Sdp 33543252Sdp if [[ -x $WDIFF ]]; then 33553252Sdp print " ------" 33560Sstevel@tonic-gate fi 33570Sstevel@tonic-gate 33583252Sdp print " ------" 33593252Sdp fi 33603252Sdp 33613252Sdp # If there's an old file, make the link 33620Sstevel@tonic-gate 33633252Sdp if [[ -f $F-.html ]]; then 33649011SLubomir.Sedlacik@Sun.COM oldfile_url="$(print $P-.html | url_encode)" 33659011SLubomir.Sedlacik@Sun.COM print "<a href=\"$oldfile_url\">Old</a>" 33663252Sdp else 33673252Sdp print " ---" 33683252Sdp fi 33693252Sdp 33703252Sdp # If there's an new file, make the link 33713252Sdp 33723252Sdp if [[ -f $F.html ]]; then 33739011SLubomir.Sedlacik@Sun.COM newfile_url="$(print $P.html | url_encode)" 33749011SLubomir.Sedlacik@Sun.COM print "<a href=\"$newfile_url\">New</a>" 33750Sstevel@tonic-gate else 33763252Sdp print " ---" 33773252Sdp fi 33783252Sdp 33793252Sdp if [[ -f $F.patch ]]; then 33809011SLubomir.Sedlacik@Sun.COM patch_url="$(print $P.patch | url_encode)" 33819011SLubomir.Sedlacik@Sun.COM print "<a href=\"$patch_url\">Patch</a>" 33823252Sdp else 33833252Sdp print " -----" 33843252Sdp fi 33850Sstevel@tonic-gate 33863252Sdp if [[ -f $WDIR/raw_files/new/$P ]]; then 33879011SLubomir.Sedlacik@Sun.COM rawfiles_url="$(print raw_files/new/$P | url_encode)" 33889011SLubomir.Sedlacik@Sun.COM print "<a href=\"$rawfiles_url\">Raw</a>" 33893252Sdp else 33903252Sdp print " ---" 33913252Sdp fi 33923252Sdp 33937078Smjnelson print "<b>$P</b>" 33947078Smjnelson 33957078Smjnelson # For renamed files, clearly state whether or not they are modified 339610789SEdward.Pilatowicz@Sun.COM if [[ -f "$oldname" ]]; then 33977078Smjnelson if [[ -n "$mv_but_nodiff" ]]; then 339810789SEdward.Pilatowicz@Sun.COM print "<i>(copied from $oldname)</i>" 33997078Smjnelson else 340010789SEdward.Pilatowicz@Sun.COM print "<i>(copied and modified from $oldname)</i>" 340110789SEdward.Pilatowicz@Sun.COM fi 340210789SEdward.Pilatowicz@Sun.COM elif [[ -n "$oldname" ]]; then 340310789SEdward.Pilatowicz@Sun.COM if [[ -n "$mv_but_nodiff" ]]; then 340410789SEdward.Pilatowicz@Sun.COM print "<i>(renamed from $oldname)</i>" 340510789SEdward.Pilatowicz@Sun.COM else 340610789SEdward.Pilatowicz@Sun.COM print "<i>(renamed and modified from $oldname)</i>" 34077078Smjnelson fi 34087078Smjnelson fi 34097078Smjnelson 34107078Smjnelson # If there's an old file, but no new file, the file was deleted 34117078Smjnelson if [[ -f $F-.html && ! -f $F.html ]]; then 34127078Smjnelson print " <i>(deleted)</i>" 34137078Smjnelson fi 34140Sstevel@tonic-gate 34153252Sdp # 34165175Sjmcp # Check for usr/closed and deleted_files/usr/closed 34173252Sdp # 34183252Sdp if [ ! -z "$Oflag" ]; then 34195175Sjmcp if [[ $P == usr/closed/* || \ 34205175Sjmcp $P == deleted_files/usr/closed/* ]]; then 34213252Sdp print " <i>Closed source: omitted from" \ 34223252Sdp "this review</i>" 34230Sstevel@tonic-gate fi 34240Sstevel@tonic-gate fi 34250Sstevel@tonic-gate 34263252Sdp print "</p>" 34270Sstevel@tonic-gate # Insert delta comments 34280Sstevel@tonic-gate 34293252Sdp print "<blockquote><pre>" 34303252Sdp getcomments html $P $PP 34313252Sdp print "</pre>" 34320Sstevel@tonic-gate 34330Sstevel@tonic-gate # Add additional comments comment 34340Sstevel@tonic-gate 34353252Sdp print "<!-- Add comments to explain changes in $P here -->" 34360Sstevel@tonic-gate 34370Sstevel@tonic-gate # Add count of changes. 34380Sstevel@tonic-gate 34393252Sdp if [[ -f $F.count ]]; then 34400Sstevel@tonic-gate cat $F.count 34410Sstevel@tonic-gate rm $F.count 34420Sstevel@tonic-gate fi 34437078Smjnelson 34447078Smjnelson if [[ $SCM_MODE == "teamware" || 34457078Smjnelson $SCM_MODE == "mercurial" || 34467078Smjnelson $SCM_MODE == "unknown" ]]; then 34477078Smjnelson 34487078Smjnelson # Include warnings for important file mode situations: 34497078Smjnelson # 1) New executable files 34507078Smjnelson # 2) Permission changes of any kind 34517078Smjnelson # 3) Existing executable files 34527078Smjnelson 34537078Smjnelson old_mode= 34547078Smjnelson if [[ -f $WDIR/raw_files/old/$PP ]]; then 34557078Smjnelson old_mode=`get_file_mode $WDIR/raw_files/old/$PP` 34567078Smjnelson fi 34577078Smjnelson 34587078Smjnelson new_mode= 34597078Smjnelson if [[ -f $WDIR/raw_files/new/$P ]]; then 34607078Smjnelson new_mode=`get_file_mode $WDIR/raw_files/new/$P` 34617078Smjnelson fi 34627078Smjnelson 34637078Smjnelson if [[ -z "$old_mode" && "$new_mode" = *[1357]* ]]; then 34647078Smjnelson print "<span class=\"chmod\">" 34657078Smjnelson print "<p>new executable file: mode $new_mode</p>" 34667078Smjnelson print "</span>" 34677078Smjnelson elif [[ -n "$old_mode" && -n "$new_mode" && 34687078Smjnelson "$old_mode" != "$new_mode" ]]; then 34697078Smjnelson print "<span class=\"chmod\">" 34707078Smjnelson print "<p>mode change: $old_mode to $new_mode</p>" 34717078Smjnelson print "</span>" 34727078Smjnelson elif [[ "$new_mode" = *[1357]* ]]; then 34737078Smjnelson print "<span class=\"chmod\">" 34747078Smjnelson print "<p>executable file: mode $new_mode</p>" 34757078Smjnelson print "</span>" 34767078Smjnelson fi 34777078Smjnelson fi 34787078Smjnelson 34793252Sdp print "</blockquote>" 34800Sstevel@tonic-gatedone 34810Sstevel@tonic-gate 34823252Sdpprint 34833252Sdpprint 34846922Smjnelsonprint "<hr></hr>" 34853252Sdpprint "<p style=\"font-size: small\">" 34867298SMark.J.Nelson@Sun.COMprint "This code review page was prepared using <b>$0</b>." 34873252Sdpprint "Webrev is maintained by the <a href=\"http://www.opensolaris.org\">" 34883252Sdpprint "OpenSolaris</a> project. The latest version may be obtained" 34893696Sfr80241print "<a href=\"http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/tools/scripts/webrev.sh\">here</a>.</p>" 34903252Sdpprint "</body>" 34913252Sdpprint "</html>" 34920Sstevel@tonic-gate 34930Sstevel@tonic-gateexec 1<&- # Close FD 1. 34940Sstevel@tonic-gateexec 1<&3 # dup FD 3 to restore stdout. 34950Sstevel@tonic-gateexec 3<&- # close FD 3. 34960Sstevel@tonic-gate 34973252Sdpprint "Done." 34988018SVladimir.Kotal@Sun.COM 34999079SVladimir.Kotal@Sun.COM# 35008365SVladimir.Kotal@Sun.COM# If remote deletion was specified and fails do not continue. 35019079SVladimir.Kotal@Sun.COM# 35028365SVladimir.Kotal@Sun.COMif [[ -n $Dflag ]]; then 35039079SVladimir.Kotal@Sun.COM delete_webrev 1 1 35048365SVladimir.Kotal@Sun.COM (( $? == 0 )) || exit $? 35058365SVladimir.Kotal@Sun.COMfi 35068365SVladimir.Kotal@Sun.COM 35078018SVladimir.Kotal@Sun.COMif [[ -n $Uflag ]]; then 35088018SVladimir.Kotal@Sun.COM upload_webrev 35098018SVladimir.Kotal@Sun.COM exit $? 35108018SVladimir.Kotal@Sun.COMfi 3511