summaryrefslogtreecommitdiff
path: root/usr/src/tools/scripts/webrev.sh
diff options
context:
space:
mode:
authormjnelson <none@none>2008-07-10 19:11:48 -0700
committermjnelson <none@none>2008-07-10 19:11:48 -0700
commitcdf0c1d55d9b3b6beaf994835440dfb01aef5cf0 (patch)
treec1b10cec006b1a248eca473c6dddc63d5c720208 /usr/src/tools/scripts/webrev.sh
parent84db2a68825c1a672f664432101f6f0b443679e3 (diff)
downloadillumos-gate-cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0.tar.gz
6538468 add Mercurial support to ON developer tools
6658967 /etc/publickey entries get removed on upgrade Portions of 6538468 contributed by Rich Lowe. Portions of 6538468 contributed by Mike Gerdts. --HG-- rename : usr/src/pkgdefs/common_files/i.confupdate => deleted_files/usr/src/pkgdefs/common_files/i.confupdate rename : usr/src/pkgdefs/common_files/i.pcicconf => deleted_files/usr/src/pkgdefs/common_files/i.pcicconf rename : usr/src/tools/scripts/cddlchk.pl => deleted_files/usr/src/tools/scripts/cddlchk.pl rename : usr/src/tools/scripts/hdrchk.pl => deleted_files/usr/src/tools/scripts/hdrchk.pl rename : usr/src/tools/findunref/exception_list => usr/src/tools/findunref/exception_list.open
Diffstat (limited to 'usr/src/tools/scripts/webrev.sh')
-rw-r--r--usr/src/tools/scripts/webrev.sh857
1 files changed, 689 insertions, 168 deletions
diff --git a/usr/src/tools/scripts/webrev.sh b/usr/src/tools/scripts/webrev.sh
index 2b47e4518b..c0c4cc0a45 100644
--- a/usr/src/tools/scripts/webrev.sh
+++ b/usr/src/tools/scripts/webrev.sh
@@ -19,12 +19,13 @@
#
# CDDL HEADER END
#
-#
# ident "%Z%%M% %I% %E% SMI"
#
# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
+
+#
# This script takes a file list and a workspace and builds a set of html files
# suitable for doing a code review of source changes via a web page.
# Documentation is available via the manual page, webrev.1, or just
@@ -114,6 +115,10 @@ span.new {
color: blue;
font-weight: bold;
}
+span.chmod {
+ font-size: 0.7em;
+ color: #db7800;
+}
a.print { font-size: x-small; }
a:hover { background-color: #ffcc99; }
</style>
@@ -191,7 +196,7 @@ sac2url()
# Deleted lines of text are replaced by a horizontal rule. Some
# identical lines are retained before and after the changed lines to
# provide some context. The number of these lines is controlled by the
-# variable C in the nawk script below.
+# variable C in the $AWK script below.
#
# The script detects changed lines as any line that has a "<span class="
# string embedded (unchanged lines have no particular class and are not
@@ -200,9 +205,9 @@ sac2url()
#
strip_unchanged()
{
- nawk '
+ $AWK '
BEGIN { C = c = 20 }
- NF == 0 || /span class=/ {
+ NF == 0 || /<span class="/ {
if (c > C) {
c -= C
inx = 0
@@ -304,7 +309,7 @@ sdiff_to_html()
#
# Now we have the diffs, generate the HTML for the old file.
#
- nawk '
+ $AWK '
BEGIN {
printf "function sp(n) {for (i=0;i<n;i++)printf \"\\n\"}\n"
printf "function removed() "
@@ -386,7 +391,7 @@ sdiff_to_html()
#
# Now generate the HTML for the new file
#
- nawk '
+ $AWK '
BEGIN {
printf "function sp(n) {for (i=0;i<n;i++)printf \"\\n\"}\n"
printf "function new() "
@@ -466,17 +471,17 @@ sdiff_to_html()
' /tmp/$$.diffs > /tmp/$$.file2
#
- # Post-process the HTML files by running them back through nawk
+ # Post-process the HTML files by running them back through $AWK
#
- html_quote < $1 | nawk -f /tmp/$$.file1 > /tmp/$$.file1.html
+ html_quote < $1 | $AWK -f /tmp/$$.file1 > /tmp/$$.file1.html
- html_quote < $2 | nawk -f /tmp/$$.file2 > /tmp/$$.file2.html
+ html_quote < $2 | $AWK -f /tmp/$$.file2 > /tmp/$$.file2.html
#
# Now combine into a valid HTML file and side-by-side into a table
#
print "$HTML<head>$STDHEAD"
- print "<title>$WNAME Sdiff $TPATH </title>"
+ print "<title>$WNAME Sdiff $TPATH/$TNAME</title>"
print "</head><body id=\"SUNWwebrev\">"
print "<a class=\"print\" href=\"javascript:print()\">Print this page</a>"
print "<pre>$COMMENT</pre>\n"
@@ -646,7 +651,7 @@ EOF
#
function insert_anchors
{
- nawk '
+ $AWK '
function ia() {
printf "<a name=\"%d\" id=\"anc%d\"></a>", anc, anc++;
}
@@ -1018,7 +1023,7 @@ diff_to_html()
<pre>
EOF
- html_quote | nawk '
+ html_quote | $AWK '
/^--- new/ { next }
/^\+\+\+ new/ { next }
/^--- old/ { next }
@@ -1054,15 +1059,15 @@ source_to_html()
TNAME=$2
print "$HTML<head>$STDHEAD"
- print "<title>$WHICH $TNAME</title>"
+ print "<title>$WNAME $WHICH $TNAME</title>"
print "<body id=\"SUNWwebrev\">"
print "<pre>"
- html_quote | nawk '{line += 1 ; printf "%4d %s\n", line, $0 }'
+ html_quote | $AWK '{line += 1 ; printf "%4d %s\n", line, $0 }'
print "</pre></body></html>"
}
#
-# teamwarecomments {text|html} parent-file child-file
+# comments_from_teamware {text|html} parent-file child-file
#
# Find the first delta in the child that's not in the parent. Get the
# newest delta from the parent, get all deltas from the child starting
@@ -1077,13 +1082,17 @@ comments_from_teamware()
pfile=$PWS/$2
cfile=$CWS/$3
+ if [[ ! -f $PWS/${2%/*}/SCCS/s.${2##*/} && -n $RWS ]]; then
+ pfile=$RWS/$2
+ fi
+
if [[ -f $pfile ]]; then
- psid=$(sccs prs -d:I: $pfile 2>/dev/null)
+ psid=$($SCCS prs -d:I: $pfile 2>/dev/null)
else
psid=1.1
fi
- set -A sids $(sccs prs -l -r$psid -d:I: $cfile 2>/dev/null)
+ set -A sids $($SCCS prs -l -r$psid -d:I: $cfile 2>/dev/null)
N=${#sids[@]}
nawkprg='
@@ -1096,30 +1105,32 @@ comments_from_teamware()
sid1=${sids[$((N-2))]} # Gets 2nd to last sid
if [[ $fmt == "text" ]]; then
- sccs prs -l -r$sid1 $cfile 2>/dev/null | \
- nawk "$nawkprg"
+ $SCCS prs -l -r$sid1 $cfile 2>/dev/null | \
+ $AWK "$nawkprg"
return
fi
- sccs prs -l -r$sid1 $cfile 2>/dev/null | \
- html_quote | bug2url | sac2url | nawk "$nawkprg"
+ $SCCS prs -l -r$sid1 $cfile 2>/dev/null | \
+ html_quote | bug2url | sac2url | $AWK "$nawkprg"
fi
}
#
-# wxcomments {text|html} filepath
+# comments_from_wx {text|html} filepath
+#
+# Given the pathname of a file, find its location in a "wx" active
+# file list and print the following comment. Output is either text or
+# HTML; if the latter, embedded bugids (sequence of 5 or more digits)
+# are turned into URLs.
#
-# Given the pathname of a file, find its location in a "wx" active file
-# list and print the following sccs comment. Output is either text or
-# HTML; if the latter, embedded bugids (sequence of 5 or more digits) are
-# turned into URLs.
+# This is also used with Mercurial and the file list provided by hg-active.
#
comments_from_wx()
{
typeset fmt=$1
typeset p=$2
- comm=`nawk '
+ comm=`$AWK '
$1 == "'$p'" {
do getline ; while (NF > 0)
getline
@@ -1127,12 +1138,17 @@ comments_from_wx()
exit
}' < $wxfile`
+ if [[ -z $comm ]]; then
+ comm="*** NO COMMENTS ***"
+ fi
+
if [[ $fmt == "text" ]]; then
- print "$comm"
+ print -- "$comm"
return
fi
- print "$comm" | html_quote | bug2url | sac2url
+ print -- "$comm" | html_quote | bug2url | sac2url
+
}
#
@@ -1146,6 +1162,10 @@ getcomments()
typeset p=$2
typeset pp=$3
+ #
+ # Mercurial support uses a file list in wx format, so this
+ # will be used there, too
+ #
if [[ -n $wxfile ]]; then
comments_from_wx $fmt $p
else
@@ -1185,7 +1205,7 @@ function difflines
integer tot mod del ins unc err
typeset filename
- diff -e $1 $2 | eval $( nawk '
+ eval $( diff -e $1 $2 | $AWK '
# Change range of lines: N,Nc
/^[0-9]*,[0-9]*c$/ {
n=split(substr($1,1,length($1)-1), counts, ",");
@@ -1275,7 +1295,7 @@ function difflines
(c+d+a), c, d, a, error);
}' )
- # End of nawk, Check to see if any trouble occurred.
+ # End of $AWK, Check to see if any trouble occurred.
if (( $? > 0 || err > 0 )); then
print "Unexpected Error occurred reading" \
"\`diff -e $1 $2\`: \$?=$?, err=" $err
@@ -1288,7 +1308,7 @@ function difflines
(( TDEL += del ))
(( TINS += ins ))
# Calculate unchanged lines
- wc -l $1 | read unc filename
+ unc=`wc -l < $1`
if (( unc > 0 )); then
(( unc -= del + mod ))
(( TUNC += unc ))
@@ -1319,7 +1339,7 @@ function flist_from_wx
wxfile=$argfile
fi
- nawk '{ c = 1; print;
+ $AWK '{ c = 1; print;
while (getline) {
if (NF == 0) { c = -c; continue }
if (c > 0) print
@@ -1340,7 +1360,7 @@ function flist_from_wx
#
function flist_from_teamware
{
- if [[ -n $codemgr_parent ]]; then
+ if [[ -n $codemgr_parent && -z $parent_webrev ]]; then
if [[ ! -d $codemgr_parent/Codemgr_wsdata ]]; then
print -u2 "parent $codemgr_parent doesn't look like a" \
"valid teamware workspace"
@@ -1352,7 +1372,7 @@ function flist_from_teamware
print " File list from: 'putback -n $parent_args $*' ... \c"
putback -n $parent_args $* 2>&1 |
- nawk '
+ $AWK '
/^update:|^create:/ {print $2}
/^Parent workspace:/ {printf("CODEMGR_PARENT=%s\n",$3)}
/^Child workspace:/ {printf("CODEMGR_WS=%s\n",$3)}
@@ -1367,53 +1387,81 @@ function flist_from_teamware
print " Done."
}
-function env_from_flist
+#
+# Call hg-active to get the active list output in the wx active list format
+#
+function hg_active_wxfile
{
- [[ -r $FLIST ]] || return
+ typeset child=$1
+ typeset parent=$2
- #
- # Use "eval" to set env variables that are listed in the file
- # list. Then copy those into our local versions of those
- # variables if they have not been set already.
- #
- eval `sed -e "s/#.*$//" $FLIST | grep = `
+ TMPFLIST=/tmp/$$.active
+ $HG_ACTIVE -w $child -p $parent > $TMPFLIST
+ wxfile=$TMPFLIST
+}
- [[ -z $codemgr_ws && -n $CODEMGR_WS ]] && codemgr_ws=$CODEMGR_WS
+#
+# flist_from_mercurial
+# Call hg-active to get a wx-style active list, and hand it off to
+# flist_from_wx
+#
+function flist_from_mercurial
+{
+ typeset child=$1
+ typeset parent=$2
- #
- # Check to see if CODEMGR_PARENT is set in the flist file.
- #
- [[ -z $codemgr_parent && -n $CODEMGR_PARENT ]] && \
- codemgr_parent=$CODEMGR_PARENT
+ print " File list from: hg-active -p $parent ...\c"
+
+ if [[ ! -x $HG_ACTIVE ]]; then
+ print # Blank line for the \c above
+ print -u2 "Error: hg-active tool not found. Exiting"
+ exit 1
+ fi
+ hg_active_wxfile $child $parent
+
+ # flist_from_wx prints the Done, so we don't have to.
+ flist_from_wx $TMPFLIST
}
#
-# detect_scm
+# flist_from_subversion
#
-# We dynamically test the SCM type; this allows future extensions to
-# new SCM types
+# Generate the file list by extracting file names from svn status.
#
-function detect_scm
+function flist_from_subversion
{
+ CWS=$1
+ OLDPWD=$2
+
+ cd $CWS
+ print -u2 " File list from: svn status ... \c"
+ svn status | $AWK '/^[ACDMR]/ { print $NF }' > $FLIST
+ print -u2 " Done."
+ cd $OLDPWD
+}
+
+function env_from_flist
+{
+ [[ -r $FLIST ]] || return
+
#
- # If CODEMGR_WS is specified in the flist file, we assume teamware.
+ # Use "eval" to set env variables that are listed in the file
+ # list. Then copy those into our local versions of those
+ # variables if they have not been set already.
#
- if [[ -r $FLIST ]]; then
- egrep '^CODEMGR_WS=' $FLIST > /dev/null 2>&1
- if [[ $? -eq 0 ]]; then
- print "teamware"
- return
- fi
+ eval `sed -e "s/#.*$//" $FLIST | grep = `
+
+ if [[ -z $codemgr_ws && -n $CODEMGR_WS ]]; then
+ codemgr_ws=$CODEMGR_WS
+ export CODEMGR_WS
fi
#
- # The presence of $CODEMGR_WS and a Codemgr_wsdata directory
- # is our clue that this is a teamware workspace.
+ # Check to see if CODEMGR_PARENT is set in the flist file.
#
- if [[ -n $CODEMGR_WS && -d "$CODEMGR_WS/Codemgr_wsdata" ]]; then
- print "teamware"
- else
- print "unknown"
+ if [[ -z $codemgr_parent && -n $CODEMGR_PARENT ]]; then
+ codemgr_parent=$CODEMGR_PARENT
+ export CODEMGR_PARENT
fi
}
@@ -1426,7 +1474,7 @@ function look_for_prog
ppath=$PATH
ppath=$ppath:/usr/sfw/bin:/usr/bin:/usr/sbin
ppath=$ppath:/opt/teamware/bin:/opt/onbld/bin
- ppath=$ppath:/opt/onbld/bin/`/usr/bin/uname -p`
+ ppath=$ppath:/opt/onbld/bin/`uname -p`
PATH=$ppath prog=`whence $progname`
if [[ -n $prog ]]; then
@@ -1434,6 +1482,241 @@ function look_for_prog
fi
}
+function get_file_mode
+{
+ $PERL -e '
+ if (@stat = stat($ARGV[0])) {
+ $mode = $stat[2] & 0777;
+ printf "%03o\n", $mode;
+ exit 0;
+ } else {
+ exit 1;
+ }
+ ' $1
+}
+
+function build_old_new_teamware
+{
+ typeset olddir="$1"
+ typeset newdir="$2"
+
+ # If the child's version doesn't exist then
+ # get a readonly copy.
+
+ if [[ ! -f $CWS/$DIR/$F && -f $CWS/$DIR/SCCS/s.$F ]]; then
+ $SCCS get -s -p $CWS/$DIR/$F > $CWS/$DIR/$F
+ fi
+
+ # The following two sections propagate file permissions the
+ # same way SCCS does. If the file is already under version
+ # control, always use permissions from the SCCS/s.file. If
+ # the file is not under SCCS control, use permissions from the
+ # working copy. In all cases, the file copied to the webrev
+ # is set to read only, and group/other permissions are set to
+ # match those of the file owner. This way, even if the file
+ # is currently checked out, the webrev will display the final
+ # permissions that would result after check in.
+
+ #
+ # Snag new version of file.
+ #
+ rm -f $newdir/$DIR/$F
+ cp $CWS/$DIR/$F $newdir/$DIR/$F
+ if [[ -f $CWS/$DIR/SCCS/s.$F ]]; then
+ chmod `get_file_mode $CWS/$DIR/SCCS/s.$F` \
+ $newdir/$DIR/$F
+ fi
+ chmod u-w,go=u $newdir/$DIR/$F
+
+ #
+ # Get the parent's version of the file. First see whether the
+ # child's version is checked out and get the parent's version
+ # with keywords expanded or unexpanded as appropriate.
+ #
+ if [[ -f $PWS/$PDIR/$PF && ! -f $PWS/$PDIR/SCCS/s.$PF && \
+ ! -f $PWS/$PDIR/SCCS/p.$PF ]]; then
+ # Parent is not a real workspace, but just a raw
+ # directory tree - use the file that's there as
+ # the old file.
+
+ rm -f $olddir/$PDIR/$PF
+ cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF
+ else
+ if [[ -f $PWS/$PDIR/SCCS/s.$PF ]]; then
+ real_parent=$PWS
+ else
+ real_parent=$RWS
+ fi
+
+ rm -f $olddir/$PDIR/$PF
+
+ if [[ -f $real_parent/$PDIR/$PF ]]; then
+ if [ -f $CWS/$DIR/SCCS/p.$F ]; then
+ $SCCS get -s -p -k $real_parent/$PDIR/$PF > \
+ $olddir/$PDIR/$PF
+ else
+ $SCCS get -s -p $real_parent/$PDIR/$PF > \
+ $olddir/$PDIR/$PF
+ fi
+ chmod `get_file_mode $real_parent/$PDIR/SCCS/s.$PF` \
+ $olddir/$PDIR/$PF
+ fi
+ fi
+ if [[ -f $olddir/$PDIR/$PF ]]; then
+ chmod u-w,go=u $olddir/$PDIR/$PF
+ fi
+}
+
+function build_old_new_mercurial
+{
+ typeset olddir="$1"
+ typeset newdir="$2"
+ typeset old_mode=
+ typeset new_mode=
+ typeset file
+
+ #
+ # Get old file mode, from the parent revision manifest entry.
+ # Mercurial only stores a "file is executable" flag, but the
+ # manifest will display an octal mode "644" or "755".
+ #
+ if [[ "$PDIR" == "." ]]; then
+ file="$PF"
+ else
+ file="$PDIR/$PF"
+ fi
+ file=`echo $file | sed 's#/#\\\/#g'`
+ # match the exact filename, and return only the permission digits
+ old_mode=`sed -n -e "/^\\(...\\) . ${file}$/s//\\1/p" \
+ < $HG_PARENT_MANIFEST`
+
+ #
+ # Get new file mode, directly from the filesystem.
+ # Normalize the mode to match Mercurial's behavior.
+ #
+ new_mode=`get_file_mode $CWS/$DIR/$F`
+ if [[ -n "$new_mode" ]]; then
+ if [[ "$new_mode" = *[1357]* ]]; then
+ new_mode=755
+ else
+ new_mode=644
+ fi
+ fi
+
+ #
+ # new version of the file.
+ #
+ rm -rf $newdir/$DIR/$F
+ if [[ -e $CWS/$DIR/$F ]]; then
+ cp $CWS/$DIR/$F $newdir/$DIR/$F
+ if [[ -n $new_mode ]]; then
+ chmod $new_mode $newdir/$DIR/$F
+ else
+ # should never happen
+ print -u2 "ERROR: set mode of $newdir/$DIR/$F"
+ fi
+ fi
+
+ #
+ # parent's version of the file
+ #
+ # Note that we get this from the last version common to both
+ # ourselves and the parent. References are via $CWS since we have no
+ # guarantee that the parent workspace is reachable via the filesystem.
+ #
+ if [[ -n $parent_webrev && -e $PWS/$PDIR/$PF ]]; then
+ cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF
+ elif [[ -n $HG_PARENT ]]; then
+ hg cat -R $CWS -r $HG_PARENT $CWS/$PDIR/$PF > \
+ $olddir/$PDIR/$PF 2>/dev/null
+
+ if [ $? -ne 0 ]; then
+ rm -f $olddir/$PDIR/$PF
+ else
+ if [[ -n $old_mode ]]; then
+ chmod $old_mode $olddir/$PDIR/$PF
+ else
+ # should never happen
+ print -u2 "ERROR: set mode of $olddir/$PDIR/$PF"
+ fi
+ fi
+ fi
+}
+
+function build_old_new_subversion
+{
+ typeset olddir="$1"
+ typeset newdir="$2"
+
+ # Snag new version of file.
+ rm -f $newdir/$DIR/$F
+ [[ -e $CWS/$DIR/$F ]] && cp $CWS/$DIR/$F $newdir/$DIR/$F
+
+ if [[ -n $PWS && -e $PWS/$PDIR/$PF ]]; then
+ cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF
+ else
+ # Get the parent's version of the file.
+ svn status $CWS/$DIR/$F | read stat file
+ if [[ $stat != "A" ]]; then
+ svn cat -r BASE $CWS/$DIR/$F > $olddir/$PDIR/$PF
+ fi
+ fi
+}
+
+function build_old_new_unknown
+{
+ typeset olddir="$1"
+ typeset newdir="$2"
+
+ #
+ # Snag new version of file.
+ #
+ rm -f $newdir/$DIR/$F
+ [[ -e $CWS/$DIR/$F ]] && cp $CWS/$DIR/$F $newdir/$DIR/$F
+
+ #
+ # Snag the parent's version of the file.
+ #
+ if [[ -f $PWS/$PDIR/$PF ]]; then
+ rm -f $olddir/$PDIR/$PF
+ cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF
+ fi
+}
+
+function build_old_new
+{
+ typeset WDIR=$1
+ typeset PWS=$2
+ typeset PDIR=$3
+ typeset PF=$4
+ typeset CWS=$5
+ typeset DIR=$6
+ typeset F=$7
+
+ typeset olddir="$WDIR/raw_files/old"
+ typeset newdir="$WDIR/raw_files/new"
+
+ mkdir -p $olddir/$PDIR
+ mkdir -p $newdir/$DIR
+
+ if [[ $SCM_MODE == "teamware" ]]; then
+ build_old_new_teamware "$olddir" "$newdir"
+ elif [[ $SCM_MODE == "mercurial" ]]; then
+ build_old_new_mercurial "$olddir" "$newdir"
+ elif [[ $SCM_MODE == "subversion" ]]; then
+ build_old_new_subversion "$olddir" "$newdir"
+ elif [[ $SCM_MODE == "unknown" ]]; then
+ build_old_new_unknown "$olddir" "$newdir"
+ fi
+
+ if [[ ! -f $olddir/$PDIR/$PF && ! -f $newdir/$DIR/$F ]]; then
+ print "*** Error: file not in parent or child"
+ return 1
+ fi
+ return 0
+}
+
+
#
# Usage message.
#
@@ -1442,7 +1725,6 @@ function usage
print 'Usage:\twebrev [common-options]
webrev [common-options] ( <file> | - )
webrev [common-options] -w <wx file>
- webrev [common-options] -l [arguments to 'putback']
Options:
-O: Print bugids/arc cases suitable for OpenSolaris.
@@ -1456,9 +1738,12 @@ Environment:
WEBREV_BUGURL: Control the URL prefix for bugids.
WEBREV_SACURL: Control the URL prefix for ARC cases.
+SCM Specific Options:
+ TeamWare: webrev [common-options] -l [arguments to 'putback']
+
SCM Environment:
- Teamware: CODEMGR_WS: Workspace location.
- Teamware: CODEMGR_PARENT: Parent workspace location.
+ CODEMGR_WS: Workspace location.
+ CODEMGR_PARENT: Parent workspace location.
'
exit 2
@@ -1474,17 +1759,31 @@ trap "rm -f /tmp/$$.* ; exit" 0 1 2 3 15
set +o noclobber
+PATH=$(dirname $(whence $0)):$PATH
+
[[ -z $WDIFF ]] && WDIFF=`look_for_prog wdiff`
[[ -z $WX ]] && WX=`look_for_prog wx`
+[[ -z $HG_ACTIVE ]] && HG_ACTIVE=`look_for_prog hg-active`
+[[ -z $WHICH_SCM ]] && WHICH_SCM=`look_for_prog which_scm`
[[ -z $CODEREVIEW ]] && CODEREVIEW=`look_for_prog codereview`
[[ -z $PS2PDF ]] && PS2PDF=`look_for_prog ps2pdf`
[[ -z $PERL ]] && PERL=`look_for_prog perl`
+[[ -z $SCCS ]] && SCCS=`look_for_prog sccs`
+[[ -z $AWK ]] && AWK=`look_for_prog nawk`
+[[ -z $AWK ]] && AWK=`look_for_prog gawk`
+[[ -z $AWK ]] && AWK=`look_for_prog awk`
+
if [[ ! -x $PERL ]]; then
print -u2 "Error: No perl interpreter found. Exiting."
exit 1
fi
+if [[ ! -x $WHICH_SCM ]]; then
+ print -u2 "Error: Could not find which_scm. Exiting."
+ exit 1
+fi
+
#
# These aren't fatal, but we want to note them to the user.
# We don't warn on the absence of 'wx' until later when we've
@@ -1575,13 +1874,24 @@ fi
# Before we go on to further consider -l and -w, work out which SCM we think
# is in use.
#
-SCM_MODE=`detect_scm $FLIST`
-if [[ $SCM_MODE == "unknown" ]]; then
- print -u2 "Unable to determine SCM type currently in use."
- print -u2 "For teamware: webrev looks for \$CODEMGR_WS either in"
- print -u2 " the environment or in the file list."
- exit 1
-fi
+$WHICH_SCM | read SCM_MODE junk || exit 1
+case "$SCM_MODE" in
+teamware|mercurial|subversion)
+ ;;
+unknown)
+ if [[ $flist_mode == "auto" ]]; then
+ print -u2 "Unable to determine SCM in use and file list not specified"
+ print -u2 "See which_scm(1) for SCM detection information."
+ exit 1
+ fi
+ ;;
+*)
+ if [[ $flist_mode == "auto" ]]; then
+ print -u2 "Unsupported SCM in use ($SCM_MODE) and file list not specified"
+ exit 1
+ fi
+ ;;
+esac
print -u2 " SCM detected: $SCM_MODE"
@@ -1592,10 +1902,14 @@ if [[ -n $lflag ]]; then
# putback -n.
#
shift $(($OPTIND - 1))
- flist_from_teamware "$*"
+ if [[ $SCM_MODE == "teamware" ]]; then
+ flist_from_teamware "$*"
+ else
+ print -u2 -- "Error: -l option only applies to TeamWare"
+ exit 1
+ fi
flist_done=1
shift $#
-
elif [[ -n $wflag ]]; then
#
# If the -w is given then assume the file list is in Bonwick's "wx"
@@ -1614,6 +1928,11 @@ elif [[ -n $wflag ]]; then
[[ -z $wxfile ]] && print -u2 "wx file not specified, and could not " \
"be auto-detected (check \$CODEMGR_WS)" && exit 1
+ if [[ ! -r $wxfile ]]; then
+ print -u2 "$wxfile: no such file or not readable"
+ usage
+ fi
+
print -u2 " File list from: wx 'active' file '$wxfile' ... \c"
flist_from_wx $wxfile
flist_done=1
@@ -1698,15 +2017,10 @@ if [[ $SCM_MODE == "teamware" ]]; then
fi
#
- # Observe true directory name of CODEMGR_WS, as used later in
- # webrev title.
- #
- codemgr_ws=$(cd $codemgr_ws;print $PWD)
-
- #
# (4) If we still don't have a value for codemgr_parent, get it
# from workspace.
#
+ [[ -z $codemgr_ws ]] && codemgr_ws=`workspace name`
[[ -z $codemgr_parent ]] && codemgr_parent=`workspace parent`
if [[ ! -d $codemgr_parent ]]; then
print -u2 "$CODEMGR_PARENT: no such parent workspace"
@@ -1714,11 +2028,151 @@ if [[ $SCM_MODE == "teamware" ]]; then
fi
#
+ # Observe true directory name of CODEMGR_WS, as used later in
+ # webrev title.
+ #
+ codemgr_ws=$(cd $codemgr_ws;print $PWD)
+
+ #
# Reset CODEMGR_WS to make sure teamware commands are happy.
#
CODEMGR_WS=$codemgr_ws
CWS=$codemgr_ws
PWS=$codemgr_parent
+
+ [[ -n $parent_webrev ]] && RWS=$(workspace parent $CWS)
+
+elif [[ $SCM_MODE == "mercurial" ]]; then
+ [[ -z $codemgr_ws && -n $CODEMGR_WS ]] && \
+ codemgr_ws=`hg root -R $CODEMGR_WS 2>/dev/null`
+
+ [[ -z $codemgr_ws ]] && codemgr_ws=`hg root 2>/dev/null`
+
+ #
+ # Parent can either be specified with -p
+ # Specified with CODEMGR_PARENT in the environment
+ # or taken from hg's default path.
+ #
+
+ if [[ -z $codemgr_parent && -n $CODEMGR_PARENT ]]; then
+ codemgr_parent=$CODEMGR_PARENT
+ fi
+
+ if [[ -z $codemgr_parent ]]; then
+ codemgr_parent=`hg path -R $codemgr_ws default 2>/dev/null`
+ fi
+
+ CWS_REV=`hg parent -R $codemgr_ws --template '{node|short}' 2>/dev/null`
+ CWS=$codemgr_ws
+ PWS=$codemgr_parent
+
+ #
+ # If the parent is a webrev, we want to do some things against
+ # the natural workspace parent (file list, comments, etc)
+ #
+ if [[ -n $parent_webrev ]]; then
+ real_parent=$(hg path -R $codemgr_ws default 2>/dev/null)
+ else
+ real_parent=$PWS
+ fi
+
+ #
+ # If hg-active exists, then we run it. In the case of no explicit
+ # flist given, we'll use it for our comments. In the case of an
+ # explicit flist given we'll try to use it for comments for any
+ # files mentioned in the flist.
+ #
+ if [[ -z $flist_done ]]; then
+ flist_from_mercurial $CWS $real_parent
+ flist_done=1
+ fi
+
+ #
+ # If we have a file list now, pull out any variables set
+ # therein. We do this now (rather than when we possibly use
+ # hg-active to find comments) to avoid stomping specifications
+ # in the user-specified flist.
+ #
+ if [[ -n $flist_done ]]; then
+ env_from_flist
+ fi
+
+ #
+ # Only call hg-active if we don't have a wx formatted file already
+ #
+ if [[ -x $HG_ACTIVE && -z $wxfile ]]; then
+ print " Comments from: hg-active -p $real_parent ...\c"
+ hg_active_wxfile $CWS $real_parent
+ print " Done."
+ fi
+
+ #
+ # At this point we must have a wx flist either from hg-active,
+ # or in general. Use it to try and find our parent revision,
+ # if we don't have one.
+ #
+ if [[ -z $HG_PARENT ]]; then
+ eval `sed -e "s/#.*$//" $wxfile | grep HG_PARENT=`
+ fi
+
+ #
+ # If we still don't have a parent, we must have been given a
+ # wx-style active list with no HG_PARENT specification, run
+ # hg-active and pull an HG_PARENT out of it, ignore the rest.
+ #
+ if [[ -z $HG_PARENT && -x $HG_ACTIVE ]]; then
+ $HG_ACTIVE -w $codemgr_ws -p $real_parent | \
+ eval `sed -e "s/#.*$//" | grep HG_PARENT=`
+ elif [[ -z $HG_PARENT ]]; then
+ print -u2 "Error: Cannot discover parent revision"
+ exit 1
+ fi
+elif [[ $SCM_MODE == "subversion" ]]; then
+ if [[ -n $CODEMGR_WS && -d $CODEMGR_WS/.svn ]]; then
+ CWS=$CODEMGR_WS
+ else
+ svn info | while read line; do
+ if [[ $line == "URL: "* ]]; then
+ url=${line#URL: }
+ elif [[ $line == "Repository Root: "* ]]; then
+ repo=${line#Repository Root: }
+ fi
+ done
+
+ rel=${url#$repo}
+ CWS=${PWD%$rel}
+ fi
+
+ #
+ # We only will have a real parent workspace in the case one
+ # was specified (be it an older webrev, or another checkout).
+ #
+ [[ -n $codemgr_parent ]] && PWS=$codemgr_parent
+
+ if [[ -z $flist_done && $flist_mode == "auto" ]]; then
+ flist_from_subversion $CWS $OLDPWD
+ fi
+else
+ if [[ $SCM_MODE == "unknown" ]]; then
+ print -u2 " Unknown type of SCM in use"
+ else
+ print -u2 " Unsupported SCM in use: $SCM_MODE"
+ fi
+
+ env_from_flist
+
+ if [[ -z $CODEMGR_WS ]]; then
+ print -u2 "SCM not detected/supported and CODEMGR_WS not specified"
+ exit 1
+ fi
+
+ if [[ -z $CODEMGR_PARENT ]]; then
+ print -u2 "SCM not detected/supported and CODEMGR_PARENT not specified"
+ exit 1
+ fi
+
+ CWS=$CODEMGR_WS
+ PWS=$CODEMGR_PARENT
fi
#
@@ -1767,11 +2221,21 @@ fi
#
# Summarize what we're going to do.
#
-print " Workspace: $CWS"
+if [[ -n $CWS_REV ]]; then
+ print " Workspace: $CWS (at $CWS_REV)"
+else
+ print " Workspace: $CWS"
+fi
if [[ -n $parent_webrev ]]; then
print "Compare against: webrev at $parent_webrev"
else
- print "Compare against: $PWS"
+ if [[ -n $HG_PARENT ]]; then
+ hg_parent_short=`echo $HG_PARENT \
+ | sed -e 's/\([0-9a-f]\{12\}\).*/\1/'`
+ print "Compare against: $PWS (at $hg_parent_short)"
+ else
+ print "Compare against: $PWS"
+ fi
fi
[[ -n $INCLUDE_FILE ]] && print " Including: $INCLUDE_FILE"
@@ -1818,6 +2282,38 @@ sed -e "s/#.*$//" -e "/=/d" -e "/^[ ]*$/d" $FLIST > /tmp/$$.flist.clean
FLIST=/tmp/$$.flist.clean
#
+# For Mercurial, create a cache of manifest entries.
+#
+if [[ $SCM_MODE == "mercurial" ]]; then
+ #
+ # Transform the FLIST into a temporary sed script that matches
+ # relevant entries in the Mercurial manifest as follows:
+ # 1) The script will be used against the parent revision manifest,
+ # so for FLIST lines that have two filenames (a renamed file)
+ # keep only the old name.
+ # 2) Escape all forward slashes the filename.
+ # 3) Change the filename into another sed command that matches
+ # that file in "hg manifest -v" output: start of line, three
+ # octal digits for file permissions, space, a file type flag
+ # character, space, the filename, end of line.
+ #
+ SEDFILE=/tmp/$$.manifest.sed
+ sed '
+ s#^[^ ]* ##
+ s#/#\\\/#g
+ s#^.*$#/^... . &$/p#
+ ' < $FLIST > $SEDFILE
+
+ #
+ # Apply the generated script to the output of "hg manifest -v"
+ # to get the relevant subset for this webrev.
+ #
+ HG_PARENT_MANIFEST=/tmp/$$.manifest
+ hg -R $CWS manifest -v -r $HG_PARENT |
+ sed -n -f $SEDFILE > $HG_PARENT_MANIFEST
+fi
+
+#
# First pass through the files: generate the per-file webrev HTML-files.
#
cat $FLIST | while read LINE
@@ -1868,19 +2364,11 @@ do
COMM=`getcomments html $P $PP`
- if [[ ! -d $CWS/$DIR ]]; then
- print " $CWS/$DIR: no such directory"
- continue
- fi
-
print "\t$P$oldname\n\t\t\c"
# Make the webrev mirror directory if necessary
mkdir -p $WDIR/$DIR
- # cd to the directory so the names are short
- cd $CWS/$DIR
-
#
# If we're in OpenSolaris mode, we enforce a minor policy:
# help to make sure the reviewer doesn't accidentally publish
@@ -1897,63 +2385,20 @@ do
fi
#
- # We stash old and new files into parallel directories in /tmp
+ # We stash old and new files into parallel directories in $WDIR
# and do our diffs there. This makes it possible to generate
# clean looking diffs which don't have absolute paths present.
#
- olddir=$WDIR/raw_files/old
- newdir=$WDIR/raw_files/new
- mkdir -p $olddir
- mkdir -p $newdir
- mkdir -p $olddir/$PDIR
- mkdir -p $newdir/$DIR
-
- if [[ $SCM_MODE == "teamware" ]]; then
- # If the child's version doesn't exist then
- # get a readonly copy.
- if [[ ! -f $F && -f SCCS/s.$F ]]; then
- sccs get -s $F
- fi
-
- #
- # Snag new version of file.
- #
- rm -f $newdir/$DIR/$F
- cp $F $newdir/$DIR/$F
-
- #
- # Get the parent's version of the file. First see whether the
- # child's version is checked out and get the parent's version
- # with keywords expanded or unexpanded as appropriate.
- #
- if [ -f "$PWS/$PDIR/SCCS/s.$PF" -o \
- -f "$PWS/$PDIR/SCCS/p.$PF" ]; then
- rm -f $olddir/$PDIR/$PF
- if [ -f "SCCS/p.$F" ]; then
- sccs get -s -p -k $PWS/$PDIR/$PF \
- > $olddir/$PDIR/$PF
- else
- sccs get -s -p $PWS/$PDIR/$PF \
- > $olddir/$PDIR/$PF
- fi
- else
- if [[ -f $PWS/$PDIR/$PF ]]; then
- # Parent is not a real workspace, but just a raw
- # directory tree - use the file that's there as
- # the old file.
-
- rm -f $olddir/$DIR/$F
- cp $PWS/$PDIR/$PF $olddir/$DIR/$F
- fi
- fi
- fi
-
- if [[ ! -f $F && ! -f $olddir/$DIR/$F ]]; then
- print "*** Error: file not in parent or child"
- continue
- fi
+ build_old_new "$WDIR" "$PWS" "$PDIR" "$PF" "$CWS" "$DIR" "$F" || \
+ continue
+ #
+ # Keep the old PWD around, so we can safely switch back after
+ # diff generation, such that build_old_new runs in a
+ # consistent environment.
+ #
+ OWD=$PWD
cd $WDIR/raw_files
ofile=old/$PDIR/$PF
nfile=new/$DIR/$F
@@ -2081,8 +2526,8 @@ do
fi
fi
- if [[ -f $ofile && -z $mv_but_nodiff ]]; then
- source_to_html Old $P < $ofile > $WDIR/$DIR/$F-.html
+ if [[ -f $ofile ]]; then
+ source_to_html Old $PP < $ofile > $WDIR/$DIR/$F-.html
print " old\c"
fi
@@ -2091,6 +2536,8 @@ do
print " new\c"
fi
+ cd $OWD
+
print
done
@@ -2102,7 +2549,6 @@ if [[ ! -f $WDIR/$WNAME.ps ]]; then
elif [[ -x $CODEREVIEW && -x $PS2PDF ]]; then
print " Generating PDF: \c"
fix_postscript $WDIR/$WNAME.ps | $PS2PDF - > $WDIR/$WNAME.pdf
- rm -f $WDIR/$WNAME.ps
print "Done."
else
print " Generating PDF: Skipped: missing 'ps2pdf' or 'codereview'"
@@ -2139,28 +2585,49 @@ print "<h2>Code Review for $WNAME</h2>"
print "<table>"
#
-# Figure out the username and gcos name. To maintain compatibility
-# with passwd(4), we must support '&' substitutions.
+# Get the preparer's name:
#
-username=`id | cut -d '(' -f 2 | cut -d ')' -f 1`
-realname=`getent passwd $username | cut -d':' -f 5`
-userupper=`$PERL -e "print ucfirst $username"`
-realname=`print $realname | sed s/\&/$userupper/`
-date="on `date`"
-
-if [[ -n "$username" && -n "$realname" ]]; then
- print "<tr><th>Prepared by:</th>"
- print "<td>$realname ($username) $date</td></tr>"
-elif [[ -n "$username" ]]; then
- print "<tr><th>Prepared by:</th><td>$username $date</td></tr>"
+# If the SCM detected is Mercurial, and the configuration property
+# ui.username is available, use that, but be careful to properly escape
+# angle brackets (HTML syntax characters) in the email address.
+#
+# Otherwise, use the current userid in the form "John Doe (jdoe)", but
+# to maintain compatibility with passwd(4), we must support '&' substitutions.
+#
+preparer=
+if [[ "$SCM_MODE" == mercurial ]]; then
+ preparer=`hg showconfig ui.username 2>/dev/null`
+ if [[ -n "$preparer" ]]; then
+ preparer="$(echo "$preparer" | html_quote)"
+ fi
+fi
+if [[ -z "$preparer" ]]; then
+ preparer=$(
+ $PERL -e '
+ ($login, $pw, $uid, $gid, $quota, $cmt, $gcos) = getpwuid($<);
+ if ($login) {
+ $gcos =~ s/\&/ucfirst($login)/e;
+ printf "%s (%s)\n", $gcos, $login;
+ } else {
+ printf "(unknown)\n";
+ }
+ ')
fi
-print "<tr><th>Workspace:</th><td>$CWS</td></tr>"
+print "<tr><th>Prepared by:</th><td>$preparer on `date`</td></tr>"
+print "<tr><th>Workspace:</th><td>$CWS"
+if [[ -n $CWS_REV ]]; then
+ print "(at $CWS_REV)"
+fi
+print "</td></tr>"
print "<tr><th>Compare against:</th><td>"
if [[ -n $parent_webrev ]]; then
print "webrev at $parent_webrev"
else
print "$PWS"
+ if [[ -n $hg_parent_short ]]; then
+ print "(at $hg_parent_short)"
+ fi
fi
print "</td></tr>"
print "<tr><th>Summary of changes:</th><td>"
@@ -2184,7 +2651,6 @@ fi
print "</table>"
print "</div>"
-
#
# Second pass through the files: generate the rest of the index file
#
@@ -2195,13 +2661,18 @@ do
if [[ $# == 2 ]]; then
PP=$2
- oldname=" <i>(was $PP)</i>"
-
+ oldname="$PP"
else
PP=$P
oldname=""
fi
+ mv_but_nodiff=
+ cmp $WDIR/raw_files/old/$PP $WDIR/raw_files/new/$P > /dev/null 2>&1
+ if [[ $? == 0 && -n "$oldname" ]]; then
+ mv_but_nodiff=1
+ fi
+
DIR=${P%/*}
if [[ $DIR == $P ]]; then
DIR="." # File at root of workspace
@@ -2266,7 +2737,21 @@ do
print " ---"
fi
- print "<b>$P</b> $oldname"
+ print "<b>$P</b>"
+
+ # For renamed files, clearly state whether or not they are modified
+ if [[ -n "$oldname" ]]; then
+ if [[ -n "$mv_but_nodiff" ]]; then
+ print "<i>(renamed only, was $oldname)</i>"
+ else
+ print "<i>(modified and renamed, was $oldname)</i>"
+ fi
+ fi
+
+ # If there's an old file, but no new file, the file was deleted
+ if [[ -f $F-.html && ! -f $F.html ]]; then
+ print " <i>(deleted)</i>"
+ fi
#
# Check for usr/closed and deleted_files/usr/closed
@@ -2296,6 +2781,42 @@ do
cat $F.count
rm $F.count
fi
+
+ if [[ $SCM_MODE == "teamware" ||
+ $SCM_MODE == "mercurial" ||
+ $SCM_MODE == "unknown" ]]; then
+
+ # Include warnings for important file mode situations:
+ # 1) New executable files
+ # 2) Permission changes of any kind
+ # 3) Existing executable files
+
+ old_mode=
+ if [[ -f $WDIR/raw_files/old/$PP ]]; then
+ old_mode=`get_file_mode $WDIR/raw_files/old/$PP`
+ fi
+
+ new_mode=
+ if [[ -f $WDIR/raw_files/new/$P ]]; then
+ new_mode=`get_file_mode $WDIR/raw_files/new/$P`
+ fi
+
+ if [[ -z "$old_mode" && "$new_mode" = *[1357]* ]]; then
+ print "<span class=\"chmod\">"
+ print "<p>new executable file: mode $new_mode</p>"
+ print "</span>"
+ elif [[ -n "$old_mode" && -n "$new_mode" &&
+ "$old_mode" != "$new_mode" ]]; then
+ print "<span class=\"chmod\">"
+ print "<p>mode change: $old_mode to $new_mode</p>"
+ print "</span>"
+ elif [[ "$new_mode" = *[1357]* ]]; then
+ print "<span class=\"chmod\">"
+ print "<p>executable file: mode $new_mode</p>"
+ print "</span>"
+ fi
+ fi
+
print "</blockquote>"
done