629 # function wl(n) {printf "<font color=%s>%4d %s </font>\n", n, NR, $0}
630 # NR==8 {wl("#7A7ADD");next}
631 # NR==54 {wl("#7A7ADD");sp(3);next}
632 # NR==56 {wl("#7A7ADD");next}
633 # NR==57 {wl("black");printf "\n"; next}
634 # : :
635 #
636 # This script is then run on the original source file to generate the
637 # HTML that corresponds to the source file.
638 #
639 # The two HTML files are then combined into a single piece of HTML that
640 # uses an HTML table construct to present the files side by side. You'll
641 # notice that the changes are color-coded:
642 #
643 # black - unchanged lines
644 # blue - changed lines
645 # bold blue - new lines
646 # brown - deleted lines
647 #
648 # Blank lines are inserted in each file to keep unchanged lines in sync
649 # (side-by-side). This format is familiar to users of sdiff(1) or
650 # Teamware's filemerge tool.
651 #
652 sdiff_to_html()
653 {
654 diff -b $1 $2 > /tmp/$$.diffs
655
656 TNAME=$3
657 TPATH=$4
658 COMMENT=$5
659
660 #
661 # Now we have the diffs, generate the HTML for the old file.
662 #
663 $AWK '
664 BEGIN {
665 printf "function sp(n) {for (i=0;i<n;i++)printf \"\\n\"}\n"
666 printf "function removed() "
667 printf "{printf \"<span class=\\\"removed\\\">%%4d %%s</span>\\n\", NR, $0}\n"
668 printf "function changed() "
669 printf "{printf \"<span class=\\\"changed\\\">%%4d %%s</span>\\n\", NR, $0}\n"
670 printf "function bl() {printf \"%%4d %%s\\n\", NR, $0}\n"
1415
1416 #
1417 # source_to_html { new | old } <filename>
1418 #
1419 # Process a plain vanilla source file to transform it into an HTML file.
1420 #
1421 source_to_html()
1422 {
1423 WHICH=$1
1424 TNAME=$2
1425
1426 print "$HTML<head>$STDHEAD"
1427 print "<title>$WNAME $WHICH $TNAME</title>"
1428 print "<body id=\"SUNWwebrev\">"
1429 print "<pre>"
1430 html_quote | $AWK '{line += 1 ; printf "%4d %s\n", line, $0 }'
1431 print "</pre></body></html>"
1432 }
1433
1434 #
1435 # comments_from_teamware {text|html} parent-file child-file
1436 #
1437 # Find the first delta in the child that's not in the parent. Get the
1438 # newest delta from the parent, get all deltas from the child starting
1439 # with that delta, and then get all info starting with the second oldest
1440 # delta in that list (the first delta unique to the child).
1441 #
1442 # This code adapted from Bill Shannon's "spc" script
1443 #
1444 comments_from_teamware()
1445 {
1446 fmt=$1
1447 pfile=$PWS/$2
1448 cfile=$CWS/$3
1449
1450 if [[ ! -f $PWS/${2%/*}/SCCS/s.${2##*/} && -n $RWS ]]; then
1451 pfile=$RWS/$2
1452 fi
1453
1454 if [[ -f $pfile ]]; then
1455 psid=$($SCCS prs -d:I: $pfile 2>/dev/null)
1456 else
1457 psid=1.1
1458 fi
1459
1460 set -A sids $($SCCS prs -l -r$psid -d:I: $cfile 2>/dev/null)
1461 N=${#sids[@]}
1462
1463 nawkprg='
1464 /^COMMENTS:/ {p=1; continue}
1465 /^D [0-9]+\.[0-9]+/ {printf "--- %s ---\n", $2; p=0; }
1466 NF == 0u { continue }
1467 {if (p==0) continue; print $0 }'
1468
1469 if [[ $N -ge 2 ]]; then
1470 sid1=${sids[$((N-2))]} # Gets 2nd to last sid
1471
1472 if [[ $fmt == "text" ]]; then
1473 $SCCS prs -l -r$sid1 $cfile 2>/dev/null | \
1474 $AWK "$nawkprg"
1475 return
1476 fi
1477
1478 $SCCS prs -l -r$sid1 $cfile 2>/dev/null | \
1479 html_quote | its2url | $AWK "$nawkprg"
1480 fi
1481 }
1482
1483 #
1484 # comments_from_wx {text|html} filepath
1485 #
1486 # Given the pathname of a file, find its location in a "wx" active
1487 # file list and print the following comment. Output is either text or
1488 # HTML; if the latter, embedded bugids (sequence of 5 or more digits)
1489 # are turned into URLs.
1490 #
1491 # This is also used with Mercurial and the file list provided by hg-active.
1492 #
1493 comments_from_wx()
1494 {
1495 typeset fmt=$1
1496 typeset p=$2
1497
1498 comm=`$AWK '
1499 $1 == "'$p'" {
1500 do getline ; while (NF > 0)
1501 getline
1502 while (NF > 0) { print ; getline }
1503 exit
1519 #
1520 # getcomments {text|html} filepath parentpath
1521 #
1522 # Fetch the comments depending on what SCM mode we're in.
1523 #
1524 getcomments()
1525 {
1526 typeset fmt=$1
1527 typeset p=$2
1528 typeset pp=$3
1529
1530 if [[ -n $Nflag ]]; then
1531 return
1532 fi
1533 #
1534 # Mercurial support uses a file list in wx format, so this
1535 # will be used there, too
1536 #
1537 if [[ -n $wxfile ]]; then
1538 comments_from_wx $fmt $p
1539 else
1540 if [[ $SCM_MODE == "teamware" ]]; then
1541 comments_from_teamware $fmt $pp $p
1542 fi
1543 fi
1544 }
1545
1546 #
1547 # printCI <total-changed> <inserted> <deleted> <modified> <unchanged>
1548 #
1549 # Print out Code Inspection figures similar to sccs-prt(1) format.
1550 #
1551 function printCI
1552 {
1553 integer tot=$1 ins=$2 del=$3 mod=$4 unc=$5
1554 typeset str
1555 if (( tot == 1 )); then
1556 str="line"
1557 else
1558 str="lines"
1559 fi
1560 printf '%d %s changed: %d ins; %d del; %d mod; %d unchg\n' \
1561 $tot $str $ins $del $mod $unc
1562 }
1701 #
1702 # If the wx file pathname is relative then make it absolute
1703 # because the webrev does a "cd" later on.
1704 #
1705 wxfile=$PWD/$argfile
1706 else
1707 wxfile=$argfile
1708 fi
1709
1710 $AWK '{ c = 1; print;
1711 while (getline) {
1712 if (NF == 0) { c = -c; continue }
1713 if (c > 0) print
1714 }
1715 }' $wxfile > $FLIST
1716
1717 print " Done."
1718 }
1719
1720 #
1721 # flist_from_teamware [ <args-to-putback-n> ]
1722 #
1723 # Generate the file list by extracting file names from a putback -n. Some
1724 # names may come from the "update/create" messages and others from the
1725 # "currently checked out" warning. Renames are detected here too. Extract
1726 # values for CODEMGR_WS and CODEMGR_PARENT from the output of the putback
1727 # -n as well, but remove them if they are already defined.
1728 #
1729 function flist_from_teamware
1730 {
1731 if [[ -n $codemgr_parent && -z $parent_webrev ]]; then
1732 if [[ ! -d $codemgr_parent/Codemgr_wsdata ]]; then
1733 print -u2 "parent $codemgr_parent doesn't look like a" \
1734 "valid teamware workspace"
1735 exit 1
1736 fi
1737 parent_args="-p $codemgr_parent"
1738 fi
1739
1740 print " File list from: 'putback -n $parent_args $*' ... \c"
1741
1742 putback -n $parent_args $* 2>&1 |
1743 $AWK '
1744 /^update:|^create:/ {print $2}
1745 /^Parent workspace:/ {printf("CODEMGR_PARENT=%s\n",$3)}
1746 /^Child workspace:/ {printf("CODEMGR_WS=%s\n",$3)}
1747 /^The following files are currently checked out/ {p = 1; continue}
1748 NF == 0 {p=0 ; continue}
1749 /^rename/ {old=$3}
1750 $1 == "to:" {print $2, old}
1751 /^"/ {continue}
1752 p == 1 {print $1}' |
1753 sort -r -k 1,1 -u | sort > $FLIST
1754
1755 print " Done."
1756 }
1757
1758 #
1759 # Call hg-active to get the active list output in the wx active list format
1760 #
1761 function hg_active_wxfile
1762 {
1763 typeset child=$1
1764 typeset parent=$2
1765
1766 TMPFLIST=/tmp/$$.active
1767 $HG_ACTIVE -w $child -p $parent -o $TMPFLIST
1768 wxfile=$TMPFLIST
1769 }
1770
1771 #
1772 # flist_from_mercurial
1773 # Call hg-active to get a wx-style active list, and hand it off to
1774 # flist_from_wx
1775 #
1776 function flist_from_mercurial
1777 {
1778 typeset child=$1
1899 export CODEMGR_WS
1900 fi
1901
1902 #
1903 # Check to see if CODEMGR_PARENT is set in the flist file.
1904 #
1905 if [[ -z $codemgr_parent && -n $CODEMGR_PARENT ]]; then
1906 codemgr_parent=$CODEMGR_PARENT
1907 export CODEMGR_PARENT
1908 fi
1909 }
1910
1911 function look_for_prog
1912 {
1913 typeset path
1914 typeset ppath
1915 typeset progname=$1
1916
1917 ppath=$PATH
1918 ppath=$ppath:/usr/sfw/bin:/usr/bin:/usr/sbin
1919 ppath=$ppath:/opt/teamware/bin:/opt/onbld/bin
1920 ppath=$ppath:/opt/onbld/bin/`uname -p`
1921
1922 PATH=$ppath prog=`whence $progname`
1923 if [[ -n $prog ]]; then
1924 print $prog
1925 fi
1926 }
1927
1928 function get_file_mode
1929 {
1930 $PERL -e '
1931 if (@stat = stat($ARGV[0])) {
1932 $mode = $stat[2] & 0777;
1933 printf "%03o\n", $mode;
1934 exit 0;
1935 } else {
1936 exit 1;
1937 }
1938 ' $1
1939 }
1940
1941 function build_old_new_teamware
1942 {
1943 typeset olddir="$1"
1944 typeset newdir="$2"
1945
1946 # If the child's version doesn't exist then
1947 # get a readonly copy.
1948
1949 if [[ ! -f $CWS/$DIR/$F && -f $CWS/$DIR/SCCS/s.$F ]]; then
1950 $SCCS get -s -p $CWS/$DIR/$F > $CWS/$DIR/$F
1951 fi
1952
1953 # The following two sections propagate file permissions the
1954 # same way SCCS does. If the file is already under version
1955 # control, always use permissions from the SCCS/s.file. If
1956 # the file is not under SCCS control, use permissions from the
1957 # working copy. In all cases, the file copied to the webrev
1958 # is set to read only, and group/other permissions are set to
1959 # match those of the file owner. This way, even if the file
1960 # is currently checked out, the webrev will display the final
1961 # permissions that would result after check in.
1962
1963 #
1964 # Snag new version of file.
1965 #
1966 rm -f $newdir/$DIR/$F
1967 cp $CWS/$DIR/$F $newdir/$DIR/$F
1968 if [[ -f $CWS/$DIR/SCCS/s.$F ]]; then
1969 chmod `get_file_mode $CWS/$DIR/SCCS/s.$F` \
1970 $newdir/$DIR/$F
1971 fi
1972 chmod u-w,go=u $newdir/$DIR/$F
1973
1974 #
1975 # Get the parent's version of the file. First see whether the
1976 # child's version is checked out and get the parent's version
1977 # with keywords expanded or unexpanded as appropriate.
1978 #
1979 if [[ -f $PWS/$PDIR/$PF && ! -f $PWS/$PDIR/SCCS/s.$PF && \
1980 ! -f $PWS/$PDIR/SCCS/p.$PF ]]; then
1981 # Parent is not a real workspace, but just a raw
1982 # directory tree - use the file that's there as
1983 # the old file.
1984
1985 rm -f $olddir/$PDIR/$PF
1986 cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF
1987 else
1988 if [[ -f $PWS/$PDIR/SCCS/s.$PF ]]; then
1989 real_parent=$PWS
1990 else
1991 real_parent=$RWS
1992 fi
1993
1994 rm -f $olddir/$PDIR/$PF
1995
1996 if [[ -f $real_parent/$PDIR/$PF ]]; then
1997 if [ -f $CWS/$DIR/SCCS/p.$F ]; then
1998 $SCCS get -s -p -k $real_parent/$PDIR/$PF > \
1999 $olddir/$PDIR/$PF
2000 else
2001 $SCCS get -s -p $real_parent/$PDIR/$PF > \
2002 $olddir/$PDIR/$PF
2003 fi
2004 chmod `get_file_mode $real_parent/$PDIR/SCCS/s.$PF` \
2005 $olddir/$PDIR/$PF
2006 fi
2007 fi
2008 if [[ -f $olddir/$PDIR/$PF ]]; then
2009 chmod u-w,go=u $olddir/$PDIR/$PF
2010 fi
2011 }
2012
2013 function build_old_new_mercurial
2014 {
2015 typeset olddir="$1"
2016 typeset newdir="$2"
2017 typeset old_mode=
2018 typeset new_mode=
2019 typeset file
2020
2021 #
2022 # Get old file mode, from the parent revision manifest entry.
2023 # Mercurial only stores a "file is executable" flag, but the
2024 # manifest will display an octal mode "644" or "755".
2025 #
2026 if [[ "$PDIR" == "." ]]; then
2027 file="$PF"
2028 else
2029 file="$PDIR/$PF"
2030 fi
2031 file=`echo $file | $SED 's#/#\\\/#g'`
2032 # match the exact filename, and return only the permission digits
2183 cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF
2184 fi
2185 }
2186
2187 function build_old_new
2188 {
2189 typeset WDIR=$1
2190 typeset PWS=$2
2191 typeset PDIR=$3
2192 typeset PF=$4
2193 typeset CWS=$5
2194 typeset DIR=$6
2195 typeset F=$7
2196
2197 typeset olddir="$WDIR/raw_files/old"
2198 typeset newdir="$WDIR/raw_files/new"
2199
2200 mkdir -p $olddir/$PDIR
2201 mkdir -p $newdir/$DIR
2202
2203 if [[ $SCM_MODE == "teamware" ]]; then
2204 build_old_new_teamware "$olddir" "$newdir"
2205 elif [[ $SCM_MODE == "mercurial" ]]; then
2206 build_old_new_mercurial "$olddir" "$newdir"
2207 elif [[ $SCM_MODE == "git" ]]; then
2208 build_old_new_git "$olddir" "$newdir"
2209 elif [[ $SCM_MODE == "subversion" ]]; then
2210 build_old_new_subversion "$olddir" "$newdir"
2211 elif [[ $SCM_MODE == "unknown" ]]; then
2212 build_old_new_unknown "$olddir" "$newdir"
2213 fi
2214
2215 if [[ ! -f $olddir/$PDIR/$PF && ! -f $newdir/$DIR/$F ]]; then
2216 print "*** Error: file not in parent or child"
2217 return 1
2218 fi
2219 return 0
2220 }
2221
2222
2223 #
2224 # Usage message.
2225 #
2229 webrev [common-options] ( <file> | - )
2230 webrev [common-options] -w <wx file>
2231
2232 Options:
2233 -C <filename>: Use <filename> for the information tracking configuration.
2234 -D: delete remote webrev
2235 -i <filename>: Include <filename> in the index.html file.
2236 -I <filename>: Use <filename> for the information tracking registry.
2237 -n: do not generate the webrev (useful with -U)
2238 -O: Print bugids/arc cases suitable for OpenSolaris.
2239 -o <outdir>: Output webrev to specified directory.
2240 -p <compare-against>: Use specified parent wkspc or basis for comparison
2241 -t <remote_target>: Specify remote destination for webrev upload
2242 -U: upload the webrev to remote destination
2243 -w <wxfile>: Use specified wx active file.
2244
2245 Environment:
2246 WDIR: Control the output directory.
2247 WEBREV_TRASH_DIR: Set directory for webrev delete.
2248
2249 SCM Specific Options:
2250 TeamWare: webrev [common-options] -l [arguments to 'putback']
2251
2252 SCM Environment:
2253 CODEMGR_WS: Workspace location.
2254 CODEMGR_PARENT: Parent workspace location.
2255 '
2256
2257 exit 2
2258 }
2259
2260 #
2261 #
2262 # Main program starts here
2263 #
2264 #
2265
2266 trap "rm -f /tmp/$$.* ; exit" 0 1 2 3 15
2267
2268 set +o noclobber
2269
2270 PATH=$(/bin/dirname "$(whence $0)"):$PATH
2271
2272 [[ -z $WDIFF ]] && WDIFF=`look_for_prog wdiff`
2273 [[ -z $WX ]] && WX=`look_for_prog wx`
2274 [[ -z $HG_ACTIVE ]] && HG_ACTIVE=`look_for_prog hg-active`
2275 [[ -z $GIT ]] && GIT=`look_for_prog git`
2276 [[ -z $WHICH_SCM ]] && WHICH_SCM=`look_for_prog which_scm`
2398
2399 # more sanity checking
2400 if [[ -n $nflag && -z $Uflag ]]; then
2401 print "it does not make sense to skip webrev generation" \
2402 "without -U"
2403 exit 1
2404 fi
2405
2406 if [[ -n $tflag && -z $Uflag && -z $Dflag ]]; then
2407 echo "remote target has to be used only for upload or delete"
2408 exit 1
2409 fi
2410
2411 #
2412 # For the invocation "webrev -n -U" with no other options, webrev will assume
2413 # that the webrev exists in ${CWS}/webrev, but will upload it using the name
2414 # $(basename ${CWS}). So we need to get CWS set before we skip any remaining
2415 # logic.
2416 #
2417 $WHICH_SCM | read SCM_MODE junk || exit 1
2418 if [[ $SCM_MODE == "teamware" ]]; then
2419 #
2420 # Teamware priorities:
2421 # 1. CODEMGR_WS from the environment
2422 # 2. workspace name
2423 #
2424 [[ -z $codemgr_ws && -n $CODEMGR_WS ]] && codemgr_ws=$CODEMGR_WS
2425 if [[ -n $codemgr_ws && ! -d $codemgr_ws ]]; then
2426 print -u2 "$codemgr_ws: no such workspace"
2427 exit 1
2428 fi
2429 [[ -z $codemgr_ws ]] && codemgr_ws=$(workspace name)
2430 codemgr_ws=$(cd $codemgr_ws;print $PWD)
2431 CODEMGR_WS=$codemgr_ws
2432 CWS=$codemgr_ws
2433 elif [[ $SCM_MODE == "mercurial" ]]; then
2434 #
2435 # Mercurial priorities:
2436 # 1. hg root from CODEMGR_WS environment variable
2437 # 1a. hg root from CODEMGR_WS/usr/closed if we're somewhere under
2438 # usr/closed when we run webrev
2439 # 2. hg root from directory of invocation
2440 #
2441 if [[ ${PWD} =~ "usr/closed" ]]; then
2442 testparent=${CODEMGR_WS}/usr/closed
2443 # If we're in OpenSolaris mode, we enforce a minor policy:
2444 # help to make sure the reviewer doesn't accidentally publish
2445 # source which is under usr/closed
2446 if [[ -n "$Oflag" ]]; then
2447 print -u2 "OpenSolaris output not permitted with" \
2448 "usr/closed changes"
2449 exit 1
2450 fi
2451 else
2452 testparent=${CODEMGR_WS}
2453 fi
2539 elif [[ -n $1 ]]; then
2540 if [[ ! -r $1 ]]; then
2541 print -u2 "$1: no such file or not readable"
2542 usage
2543 fi
2544 cat $1 > $FLIST
2545 flist_mode="file"
2546 flist_file=$1
2547 flist_done=1
2548 shift
2549 else
2550 flist_mode="auto"
2551 fi
2552 fi
2553
2554 #
2555 # Before we go on to further consider -l and -w, work out which SCM we think
2556 # is in use.
2557 #
2558 case "$SCM_MODE" in
2559 teamware|mercurial|git|subversion)
2560 ;;
2561 unknown)
2562 if [[ $flist_mode == "auto" ]]; then
2563 print -u2 "Unable to determine SCM in use and file list not specified"
2564 print -u2 "See which_scm(1) for SCM detection information."
2565 exit 1
2566 fi
2567 ;;
2568 *)
2569 if [[ $flist_mode == "auto" ]]; then
2570 print -u2 "Unsupported SCM in use ($SCM_MODE) and file list not specified"
2571 exit 1
2572 fi
2573 ;;
2574 esac
2575
2576 print -u2 " SCM detected: $SCM_MODE"
2577
2578 if [[ -n $lflag ]]; then
2579 #
2580 # If the -l flag is given instead of the name of a file list,
2581 # then generate the file list by extracting file names from a
2582 # putback -n.
2583 #
2584 shift $(($OPTIND - 1))
2585 if [[ $SCM_MODE == "teamware" ]]; then
2586 flist_from_teamware "$*"
2587 else
2588 print -u2 -- "Error: -l option only applies to TeamWare"
2589 exit 1
2590 fi
2591 flist_done=1
2592 shift $#
2593 elif [[ -n $wflag ]]; then
2594 #
2595 # If the -w is given then assume the file list is in Bonwick's "wx"
2596 # command format, i.e. pathname lines alternating with SCCS comment
2597 # lines with blank lines as separators. Use the SCCS comments later
2598 # in building the index.html file.
2599 #
2600 shift $(($OPTIND - 1))
2601 wxfile=$1
2602 if [[ -z $wxfile && -n $CODEMGR_WS ]]; then
2603 if [[ -r $CODEMGR_WS/wx/active ]]; then
2604 wxfile=$CODEMGR_WS/wx/active
2605 fi
2606 fi
2607
2608 [[ -z $wxfile ]] && print -u2 "wx file not specified, and could not " \
2609 "be auto-detected (check \$CODEMGR_WS)" && exit 1
2610
2611 if [[ ! -r $wxfile ]]; then
2612 print -u2 "$wxfile: no such file or not readable"
2613 usage
2617 flist_from_wx $wxfile
2618 flist_done=1
2619 if [[ -n "$*" ]]; then
2620 shift
2621 fi
2622 elif [[ $flist_mode == "stdin" ]]; then
2623 print -u2 " File list from: standard input"
2624 elif [[ $flist_mode == "file" ]]; then
2625 print -u2 " File list from: $flist_file"
2626 fi
2627
2628 if [[ $# -gt 0 ]]; then
2629 print -u2 "WARNING: unused arguments: $*"
2630 fi
2631
2632 #
2633 # Before we entered the DO_EVERYTHING loop, we should have already set CWS
2634 # and CODEMGR_WS as needed. Here, we set the parent workspace.
2635 #
2636
2637 if [[ $SCM_MODE == "teamware" ]]; then
2638
2639 #
2640 # Teamware priorities:
2641 #
2642 # 1) via -p command line option
2643 # 2) in the user environment
2644 # 3) in the flist
2645 # 4) automatically based on the workspace
2646 #
2647
2648 #
2649 # For 1, codemgr_parent will already be set. Here's 2:
2650 #
2651 [[ -z $codemgr_parent && -n $CODEMGR_PARENT ]] && \
2652 codemgr_parent=$CODEMGR_PARENT
2653 if [[ -n $codemgr_parent && ! -d $codemgr_parent ]]; then
2654 print -u2 "$codemgr_parent: no such directory"
2655 exit 1
2656 fi
2657
2658 #
2659 # If we're in auto-detect mode and we haven't already gotten the file
2660 # list, then see if we can get it by probing for wx.
2661 #
2662 if [[ -z $flist_done && $flist_mode == "auto" && -n $codemgr_ws ]]; then
2663 if [[ ! -x $WX ]]; then
2664 print -u2 "WARNING: wx not found!"
2665 fi
2666
2667 #
2668 # We need to use wx list -w so that we get renamed files, etc.
2669 # but only if a wx active file exists-- otherwise wx will
2670 # hang asking us to initialize our wx information.
2671 #
2672 if [[ -x $WX && -f $codemgr_ws/wx/active ]]; then
2673 print -u2 " File list from: 'wx list -w' ... \c"
2674 $WX list -w > $FLIST
2675 $WX comments > /tmp/$$.wx_comments
2676 wxfile=/tmp/$$.wx_comments
2677 print -u2 "done"
2678 flist_done=1
2679 fi
2680 fi
2681
2682 #
2683 # If by hook or by crook we've gotten a file list by now (perhaps
2684 # from the command line), eval it to extract environment variables from
2685 # it: This is method 3 for finding the parent.
2686 #
2687 if [[ -z $flist_done ]]; then
2688 flist_from_teamware
2689 fi
2690 env_from_flist
2691
2692 #
2693 # (4) If we still don't have a value for codemgr_parent, get it
2694 # from workspace.
2695 #
2696 [[ -z $codemgr_parent ]] && codemgr_parent=`workspace parent`
2697 if [[ ! -d $codemgr_parent ]]; then
2698 print -u2 "$CODEMGR_PARENT: no such parent workspace"
2699 exit 1
2700 fi
2701
2702 PWS=$codemgr_parent
2703
2704 [[ -n $parent_webrev ]] && RWS=$(workspace parent $CWS)
2705
2706 elif [[ $SCM_MODE == "mercurial" ]]; then
2707 #
2708 # Parent can either be specified with -p
2709 # Specified with CODEMGR_PARENT in the environment
2710 # or taken from hg's default path.
2711 #
2712
2713 if [[ -z $codemgr_parent && -n $CODEMGR_PARENT ]]; then
2714 codemgr_parent=$CODEMGR_PARENT
2715 fi
2716
2717 if [[ -z $codemgr_parent ]]; then
2718 codemgr_parent=`hg path -R $codemgr_ws default 2>/dev/null`
2719 fi
2720
2721 PWS=$codemgr_parent
2722
2723 #
2724 # If the parent is a webrev, we want to do some things against
2725 # the natural workspace parent (file list, comments, etc)
2726 #
3666 fi
3667
3668 print "</p>"
3669 # Insert delta comments
3670
3671 print "<blockquote><pre>"
3672 getcomments html $P $PP
3673 print "</pre>"
3674
3675 # Add additional comments comment
3676
3677 print "<!-- Add comments to explain changes in $P here -->"
3678
3679 # Add count of changes.
3680
3681 if [[ -f $F.count ]]; then
3682 cat $F.count
3683 rm $F.count
3684 fi
3685
3686 if [[ $SCM_MODE == "teamware" ||
3687 $SCM_MODE == "mercurial" ||
3688 $SCM_MODE == "unknown" ]]; then
3689
3690 # Include warnings for important file mode situations:
3691 # 1) New executable files
3692 # 2) Permission changes of any kind
3693 # 3) Existing executable files
3694
3695 old_mode=
3696 if [[ -f $WDIR/raw_files/old/$PP ]]; then
3697 old_mode=`get_file_mode $WDIR/raw_files/old/$PP`
3698 fi
3699
3700 new_mode=
3701 if [[ -f $WDIR/raw_files/new/$P ]]; then
3702 new_mode=`get_file_mode $WDIR/raw_files/new/$P`
3703 fi
3704
3705 if [[ -z "$old_mode" && "$new_mode" = *[1357]* ]]; then
3706 print "<span class=\"chmod\">"
3707 print "<p>new executable file: mode $new_mode</p>"
|
629 # function wl(n) {printf "<font color=%s>%4d %s </font>\n", n, NR, $0}
630 # NR==8 {wl("#7A7ADD");next}
631 # NR==54 {wl("#7A7ADD");sp(3);next}
632 # NR==56 {wl("#7A7ADD");next}
633 # NR==57 {wl("black");printf "\n"; next}
634 # : :
635 #
636 # This script is then run on the original source file to generate the
637 # HTML that corresponds to the source file.
638 #
639 # The two HTML files are then combined into a single piece of HTML that
640 # uses an HTML table construct to present the files side by side. You'll
641 # notice that the changes are color-coded:
642 #
643 # black - unchanged lines
644 # blue - changed lines
645 # bold blue - new lines
646 # brown - deleted lines
647 #
648 # Blank lines are inserted in each file to keep unchanged lines in sync
649 # (side-by-side). This format is familiar to users of sdiff(1).
650 #
651 sdiff_to_html()
652 {
653 diff -b $1 $2 > /tmp/$$.diffs
654
655 TNAME=$3
656 TPATH=$4
657 COMMENT=$5
658
659 #
660 # Now we have the diffs, generate the HTML for the old file.
661 #
662 $AWK '
663 BEGIN {
664 printf "function sp(n) {for (i=0;i<n;i++)printf \"\\n\"}\n"
665 printf "function removed() "
666 printf "{printf \"<span class=\\\"removed\\\">%%4d %%s</span>\\n\", NR, $0}\n"
667 printf "function changed() "
668 printf "{printf \"<span class=\\\"changed\\\">%%4d %%s</span>\\n\", NR, $0}\n"
669 printf "function bl() {printf \"%%4d %%s\\n\", NR, $0}\n"
1414
1415 #
1416 # source_to_html { new | old } <filename>
1417 #
1418 # Process a plain vanilla source file to transform it into an HTML file.
1419 #
1420 source_to_html()
1421 {
1422 WHICH=$1
1423 TNAME=$2
1424
1425 print "$HTML<head>$STDHEAD"
1426 print "<title>$WNAME $WHICH $TNAME</title>"
1427 print "<body id=\"SUNWwebrev\">"
1428 print "<pre>"
1429 html_quote | $AWK '{line += 1 ; printf "%4d %s\n", line, $0 }'
1430 print "</pre></body></html>"
1431 }
1432
1433 #
1434 # comments_from_wx {text|html} filepath
1435 #
1436 # Given the pathname of a file, find its location in a "wx" active
1437 # file list and print the following comment. Output is either text or
1438 # HTML; if the latter, embedded bugids (sequence of 5 or more digits)
1439 # are turned into URLs.
1440 #
1441 # This is also used with Mercurial and the file list provided by hg-active.
1442 #
1443 comments_from_wx()
1444 {
1445 typeset fmt=$1
1446 typeset p=$2
1447
1448 comm=`$AWK '
1449 $1 == "'$p'" {
1450 do getline ; while (NF > 0)
1451 getline
1452 while (NF > 0) { print ; getline }
1453 exit
1469 #
1470 # getcomments {text|html} filepath parentpath
1471 #
1472 # Fetch the comments depending on what SCM mode we're in.
1473 #
1474 getcomments()
1475 {
1476 typeset fmt=$1
1477 typeset p=$2
1478 typeset pp=$3
1479
1480 if [[ -n $Nflag ]]; then
1481 return
1482 fi
1483 #
1484 # Mercurial support uses a file list in wx format, so this
1485 # will be used there, too
1486 #
1487 if [[ -n $wxfile ]]; then
1488 comments_from_wx $fmt $p
1489 fi
1490 }
1491
1492 #
1493 # printCI <total-changed> <inserted> <deleted> <modified> <unchanged>
1494 #
1495 # Print out Code Inspection figures similar to sccs-prt(1) format.
1496 #
1497 function printCI
1498 {
1499 integer tot=$1 ins=$2 del=$3 mod=$4 unc=$5
1500 typeset str
1501 if (( tot == 1 )); then
1502 str="line"
1503 else
1504 str="lines"
1505 fi
1506 printf '%d %s changed: %d ins; %d del; %d mod; %d unchg\n' \
1507 $tot $str $ins $del $mod $unc
1508 }
1647 #
1648 # If the wx file pathname is relative then make it absolute
1649 # because the webrev does a "cd" later on.
1650 #
1651 wxfile=$PWD/$argfile
1652 else
1653 wxfile=$argfile
1654 fi
1655
1656 $AWK '{ c = 1; print;
1657 while (getline) {
1658 if (NF == 0) { c = -c; continue }
1659 if (c > 0) print
1660 }
1661 }' $wxfile > $FLIST
1662
1663 print " Done."
1664 }
1665
1666 #
1667 # Call hg-active to get the active list output in the wx active list format
1668 #
1669 function hg_active_wxfile
1670 {
1671 typeset child=$1
1672 typeset parent=$2
1673
1674 TMPFLIST=/tmp/$$.active
1675 $HG_ACTIVE -w $child -p $parent -o $TMPFLIST
1676 wxfile=$TMPFLIST
1677 }
1678
1679 #
1680 # flist_from_mercurial
1681 # Call hg-active to get a wx-style active list, and hand it off to
1682 # flist_from_wx
1683 #
1684 function flist_from_mercurial
1685 {
1686 typeset child=$1
1807 export CODEMGR_WS
1808 fi
1809
1810 #
1811 # Check to see if CODEMGR_PARENT is set in the flist file.
1812 #
1813 if [[ -z $codemgr_parent && -n $CODEMGR_PARENT ]]; then
1814 codemgr_parent=$CODEMGR_PARENT
1815 export CODEMGR_PARENT
1816 fi
1817 }
1818
1819 function look_for_prog
1820 {
1821 typeset path
1822 typeset ppath
1823 typeset progname=$1
1824
1825 ppath=$PATH
1826 ppath=$ppath:/usr/sfw/bin:/usr/bin:/usr/sbin
1827 ppath=$ppath:/opt/onbld/bin:/opt/onbld/bin/`uname -p`
1828
1829 PATH=$ppath prog=`whence $progname`
1830 if [[ -n $prog ]]; then
1831 print $prog
1832 fi
1833 }
1834
1835 function get_file_mode
1836 {
1837 $PERL -e '
1838 if (@stat = stat($ARGV[0])) {
1839 $mode = $stat[2] & 0777;
1840 printf "%03o\n", $mode;
1841 exit 0;
1842 } else {
1843 exit 1;
1844 }
1845 ' $1
1846 }
1847
1848 function build_old_new_mercurial
1849 {
1850 typeset olddir="$1"
1851 typeset newdir="$2"
1852 typeset old_mode=
1853 typeset new_mode=
1854 typeset file
1855
1856 #
1857 # Get old file mode, from the parent revision manifest entry.
1858 # Mercurial only stores a "file is executable" flag, but the
1859 # manifest will display an octal mode "644" or "755".
1860 #
1861 if [[ "$PDIR" == "." ]]; then
1862 file="$PF"
1863 else
1864 file="$PDIR/$PF"
1865 fi
1866 file=`echo $file | $SED 's#/#\\\/#g'`
1867 # match the exact filename, and return only the permission digits
2018 cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF
2019 fi
2020 }
2021
2022 function build_old_new
2023 {
2024 typeset WDIR=$1
2025 typeset PWS=$2
2026 typeset PDIR=$3
2027 typeset PF=$4
2028 typeset CWS=$5
2029 typeset DIR=$6
2030 typeset F=$7
2031
2032 typeset olddir="$WDIR/raw_files/old"
2033 typeset newdir="$WDIR/raw_files/new"
2034
2035 mkdir -p $olddir/$PDIR
2036 mkdir -p $newdir/$DIR
2037
2038 if [[ $SCM_MODE == "mercurial" ]]; then
2039 build_old_new_mercurial "$olddir" "$newdir"
2040 elif [[ $SCM_MODE == "git" ]]; then
2041 build_old_new_git "$olddir" "$newdir"
2042 elif [[ $SCM_MODE == "subversion" ]]; then
2043 build_old_new_subversion "$olddir" "$newdir"
2044 elif [[ $SCM_MODE == "unknown" ]]; then
2045 build_old_new_unknown "$olddir" "$newdir"
2046 fi
2047
2048 if [[ ! -f $olddir/$PDIR/$PF && ! -f $newdir/$DIR/$F ]]; then
2049 print "*** Error: file not in parent or child"
2050 return 1
2051 fi
2052 return 0
2053 }
2054
2055
2056 #
2057 # Usage message.
2058 #
2062 webrev [common-options] ( <file> | - )
2063 webrev [common-options] -w <wx file>
2064
2065 Options:
2066 -C <filename>: Use <filename> for the information tracking configuration.
2067 -D: delete remote webrev
2068 -i <filename>: Include <filename> in the index.html file.
2069 -I <filename>: Use <filename> for the information tracking registry.
2070 -n: do not generate the webrev (useful with -U)
2071 -O: Print bugids/arc cases suitable for OpenSolaris.
2072 -o <outdir>: Output webrev to specified directory.
2073 -p <compare-against>: Use specified parent wkspc or basis for comparison
2074 -t <remote_target>: Specify remote destination for webrev upload
2075 -U: upload the webrev to remote destination
2076 -w <wxfile>: Use specified wx active file.
2077
2078 Environment:
2079 WDIR: Control the output directory.
2080 WEBREV_TRASH_DIR: Set directory for webrev delete.
2081
2082 SCM Environment:
2083 CODEMGR_WS: Workspace location.
2084 CODEMGR_PARENT: Parent workspace location.
2085 '
2086 exit 2
2087 }
2088
2089 #
2090 #
2091 # Main program starts here
2092 #
2093 #
2094
2095 trap "rm -f /tmp/$$.* ; exit" 0 1 2 3 15
2096
2097 set +o noclobber
2098
2099 PATH=$(/bin/dirname "$(whence $0)"):$PATH
2100
2101 [[ -z $WDIFF ]] && WDIFF=`look_for_prog wdiff`
2102 [[ -z $WX ]] && WX=`look_for_prog wx`
2103 [[ -z $HG_ACTIVE ]] && HG_ACTIVE=`look_for_prog hg-active`
2104 [[ -z $GIT ]] && GIT=`look_for_prog git`
2105 [[ -z $WHICH_SCM ]] && WHICH_SCM=`look_for_prog which_scm`
2227
2228 # more sanity checking
2229 if [[ -n $nflag && -z $Uflag ]]; then
2230 print "it does not make sense to skip webrev generation" \
2231 "without -U"
2232 exit 1
2233 fi
2234
2235 if [[ -n $tflag && -z $Uflag && -z $Dflag ]]; then
2236 echo "remote target has to be used only for upload or delete"
2237 exit 1
2238 fi
2239
2240 #
2241 # For the invocation "webrev -n -U" with no other options, webrev will assume
2242 # that the webrev exists in ${CWS}/webrev, but will upload it using the name
2243 # $(basename ${CWS}). So we need to get CWS set before we skip any remaining
2244 # logic.
2245 #
2246 $WHICH_SCM | read SCM_MODE junk || exit 1
2247 if [[ $SCM_MODE == "mercurial" ]]; then
2248 #
2249 # Mercurial priorities:
2250 # 1. hg root from CODEMGR_WS environment variable
2251 # 1a. hg root from CODEMGR_WS/usr/closed if we're somewhere under
2252 # usr/closed when we run webrev
2253 # 2. hg root from directory of invocation
2254 #
2255 if [[ ${PWD} =~ "usr/closed" ]]; then
2256 testparent=${CODEMGR_WS}/usr/closed
2257 # If we're in OpenSolaris mode, we enforce a minor policy:
2258 # help to make sure the reviewer doesn't accidentally publish
2259 # source which is under usr/closed
2260 if [[ -n "$Oflag" ]]; then
2261 print -u2 "OpenSolaris output not permitted with" \
2262 "usr/closed changes"
2263 exit 1
2264 fi
2265 else
2266 testparent=${CODEMGR_WS}
2267 fi
2353 elif [[ -n $1 ]]; then
2354 if [[ ! -r $1 ]]; then
2355 print -u2 "$1: no such file or not readable"
2356 usage
2357 fi
2358 cat $1 > $FLIST
2359 flist_mode="file"
2360 flist_file=$1
2361 flist_done=1
2362 shift
2363 else
2364 flist_mode="auto"
2365 fi
2366 fi
2367
2368 #
2369 # Before we go on to further consider -l and -w, work out which SCM we think
2370 # is in use.
2371 #
2372 case "$SCM_MODE" in
2373 mercurial|git|subversion)
2374 ;;
2375 unknown)
2376 if [[ $flist_mode == "auto" ]]; then
2377 print -u2 "Unable to determine SCM in use and file list not specified"
2378 print -u2 "See which_scm(1) for SCM detection information."
2379 exit 1
2380 fi
2381 ;;
2382 *)
2383 if [[ $flist_mode == "auto" ]]; then
2384 print -u2 "Unsupported SCM in use ($SCM_MODE) and file list not specified"
2385 exit 1
2386 fi
2387 ;;
2388 esac
2389
2390 print -u2 " SCM detected: $SCM_MODE"
2391
2392 if [[ -n $wflag ]]; then
2393 #
2394 # If the -w is given then assume the file list is in Bonwick's "wx"
2395 # command format, i.e. pathname lines alternating with SCCS comment
2396 # lines with blank lines as separators. Use the SCCS comments later
2397 # in building the index.html file.
2398 #
2399 shift $(($OPTIND - 1))
2400 wxfile=$1
2401 if [[ -z $wxfile && -n $CODEMGR_WS ]]; then
2402 if [[ -r $CODEMGR_WS/wx/active ]]; then
2403 wxfile=$CODEMGR_WS/wx/active
2404 fi
2405 fi
2406
2407 [[ -z $wxfile ]] && print -u2 "wx file not specified, and could not " \
2408 "be auto-detected (check \$CODEMGR_WS)" && exit 1
2409
2410 if [[ ! -r $wxfile ]]; then
2411 print -u2 "$wxfile: no such file or not readable"
2412 usage
2416 flist_from_wx $wxfile
2417 flist_done=1
2418 if [[ -n "$*" ]]; then
2419 shift
2420 fi
2421 elif [[ $flist_mode == "stdin" ]]; then
2422 print -u2 " File list from: standard input"
2423 elif [[ $flist_mode == "file" ]]; then
2424 print -u2 " File list from: $flist_file"
2425 fi
2426
2427 if [[ $# -gt 0 ]]; then
2428 print -u2 "WARNING: unused arguments: $*"
2429 fi
2430
2431 #
2432 # Before we entered the DO_EVERYTHING loop, we should have already set CWS
2433 # and CODEMGR_WS as needed. Here, we set the parent workspace.
2434 #
2435
2436 if [[ $SCM_MODE == "mercurial" ]]; then
2437 #
2438 # Parent can either be specified with -p
2439 # Specified with CODEMGR_PARENT in the environment
2440 # or taken from hg's default path.
2441 #
2442
2443 if [[ -z $codemgr_parent && -n $CODEMGR_PARENT ]]; then
2444 codemgr_parent=$CODEMGR_PARENT
2445 fi
2446
2447 if [[ -z $codemgr_parent ]]; then
2448 codemgr_parent=`hg path -R $codemgr_ws default 2>/dev/null`
2449 fi
2450
2451 PWS=$codemgr_parent
2452
2453 #
2454 # If the parent is a webrev, we want to do some things against
2455 # the natural workspace parent (file list, comments, etc)
2456 #
3396 fi
3397
3398 print "</p>"
3399 # Insert delta comments
3400
3401 print "<blockquote><pre>"
3402 getcomments html $P $PP
3403 print "</pre>"
3404
3405 # Add additional comments comment
3406
3407 print "<!-- Add comments to explain changes in $P here -->"
3408
3409 # Add count of changes.
3410
3411 if [[ -f $F.count ]]; then
3412 cat $F.count
3413 rm $F.count
3414 fi
3415
3416 if [[ $SCM_MODE == "mercurial" ||
3417 $SCM_MODE == "unknown" ]]; then
3418
3419 # Include warnings for important file mode situations:
3420 # 1) New executable files
3421 # 2) Permission changes of any kind
3422 # 3) Existing executable files
3423
3424 old_mode=
3425 if [[ -f $WDIR/raw_files/old/$PP ]]; then
3426 old_mode=`get_file_mode $WDIR/raw_files/old/$PP`
3427 fi
3428
3429 new_mode=
3430 if [[ -f $WDIR/raw_files/new/$P ]]; then
3431 new_mode=`get_file_mode $WDIR/raw_files/new/$P`
3432 fi
3433
3434 if [[ -z "$old_mode" && "$new_mode" = *[1357]* ]]; then
3435 print "<span class=\"chmod\">"
3436 print "<p>new executable file: mode $new_mode</p>"
|