make/scripts/webrev.ksh

Tue, 26 Mar 2013 13:41:36 -0400

author
jgish
date
Tue, 26 Mar 2013 13:41:36 -0400
changeset 678
26a4456cb19e
parent 643
c641268c4532
child 690
b95c5c8ee60a
permissions
-rw-r--r--

8009824: webrev.ksh generated jdk.patch files do not handle renames, copies, and shouldn't be applied
Summary: use hg export --git to produce proper patch file
Reviewed-by: mduigou

ohair@314 1 #!/bin/ksh -p
ohair@314 2 #
ohair@314 3 # CDDL HEADER START
ohair@314 4 #
ohair@314 5 # The contents of this file are subject to the terms of the
ohair@314 6 # Common Development and Distribution License (the "License").
ohair@314 7 # You may not use this file except in compliance with the License.
ohair@314 8 #
ohair@314 9 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
ohair@314 10 # or http://www.opensolaris.org/os/licensing.
ohair@314 11 # See the License for the specific language governing permissions
ohair@314 12 # and limitations under the License.
ohair@314 13 #
ohair@314 14 # When distributing Covered Code, include this CDDL HEADER in each
ohair@314 15 # file and include the License file at usr/src/OPENSOLARIS.LICENSE.
ohair@314 16 # If applicable, add the following below this CDDL HEADER, with the
ohair@314 17 # fields enclosed by brackets "[]" replaced with your own identifying
ohair@314 18 # information: Portions Copyright [yyyy] [name of copyright owner]
ohair@314 19 #
ohair@314 20 # CDDL HEADER END
ohair@314 21 #
mduigou@616 22 # Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
ohair@314 23 # Use is subject to license terms.
ohair@314 24 #
ohair@314 25 # This script takes a file list and a workspace and builds a set of html files
ohair@314 26 # suitable for doing a code review of source changes via a web page.
ohair@314 27 # Documentation is available via 'webrev -h'.
ohair@314 28 #
ohair@314 29
mduigou@616 30 WEBREV_UPDATED=23.18-hg+jbs
ohair@314 31
ohair@314 32 HTML='<?xml version="1.0"?>
ohair@314 33 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
ohair@314 34 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
ohair@314 35 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">\n'
ohair@314 36
ohair@314 37 FRAMEHTML='<?xml version="1.0"?>
ohair@314 38 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"
ohair@314 39 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
ohair@314 40 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">\n'
ohair@314 41
ohair@314 42 STDHEAD='<meta http-equiv="cache-control" content="no-cache" />
ohair@314 43 <meta http-equiv="Pragma" content="no-cache" />
ohair@314 44 <meta http-equiv="Expires" content="-1" />
ohair@314 45 <!--
ohair@314 46 Note to customizers: the body of the webrev is IDed as SUNWwebrev
ohair@314 47 to allow easy overriding by users of webrev via the userContent.css
ohair@314 48 mechanism available in some browsers.
ohair@314 49
ohair@314 50 For example, to have all "removed" information be red instead of
ohair@314 51 brown, set a rule in your userContent.css file like:
ohair@314 52
ohair@314 53 body#SUNWwebrev span.removed { color: red ! important; }
ohair@314 54 -->
ohair@314 55 <style type="text/css" media="screen">
ohair@314 56 body {
ohair@314 57 background-color: #eeeeee;
ohair@314 58 }
ohair@314 59 hr {
ohair@314 60 border: none 0;
ohair@314 61 border-top: 1px solid #aaa;
ohair@314 62 height: 1px;
ohair@314 63 }
ohair@314 64 div.summary {
ohair@314 65 font-size: .8em;
ohair@314 66 border-bottom: 1px solid #aaa;
ohair@314 67 padding-left: 1em;
ohair@314 68 padding-right: 1em;
ohair@314 69 }
ohair@314 70 div.summary h2 {
ohair@314 71 margin-bottom: 0.3em;
ohair@314 72 }
ohair@314 73 div.summary table th {
ohair@314 74 text-align: right;
ohair@314 75 vertical-align: top;
ohair@314 76 white-space: nowrap;
ohair@314 77 }
ohair@314 78 span.lineschanged {
ohair@314 79 font-size: 0.7em;
ohair@314 80 }
ohair@314 81 span.oldmarker {
ohair@314 82 color: red;
ohair@314 83 font-size: large;
ohair@314 84 font-weight: bold;
ohair@314 85 }
ohair@314 86 span.newmarker {
ohair@314 87 color: green;
ohair@314 88 font-size: large;
ohair@314 89 font-weight: bold;
ohair@314 90 }
ohair@314 91 span.removed {
ohair@314 92 color: brown;
ohair@314 93 }
ohair@314 94 span.changed {
ohair@314 95 color: blue;
ohair@314 96 }
ohair@314 97 span.new {
ohair@314 98 color: blue;
ohair@314 99 font-weight: bold;
ohair@314 100 }
ohair@314 101 a.print { font-size: x-small; }
ohair@314 102
ohair@314 103 </style>
ohair@314 104
ohair@314 105 <style type="text/css" media="print">
ohair@314 106 pre { font-size: 0.8em; font-family: courier, monospace; }
ohair@314 107 span.removed { color: #444; font-style: italic }
ohair@314 108 span.changed { font-weight: bold; }
ohair@314 109 span.new { font-weight: bold; }
ohair@314 110 span.newmarker { font-size: 1.2em; font-weight: bold; }
ohair@314 111 span.oldmarker { font-size: 1.2em; font-weight: bold; }
ohair@314 112 a.print {display: none}
ohair@314 113 hr { border: none 0; border-top: 1px solid #aaa; height: 1px; }
ohair@314 114 </style>
ohair@314 115 '
ohair@314 116
ohair@314 117 #
ohair@314 118 # UDiffs need a slightly different CSS rule for 'new' items (we don't
ohair@314 119 # want them to be bolded as we do in cdiffs or sdiffs).
ohair@314 120 #
ohair@314 121 UDIFFCSS='
ohair@314 122 <style type="text/css" media="screen">
ohair@314 123 span.new {
ohair@314 124 color: blue;
ohair@314 125 font-weight: normal;
ohair@314 126 }
ohair@314 127 </style>
ohair@314 128 '
ohair@314 129
ohair@314 130 #
ohair@314 131 # input_cmd | html_quote | output_cmd
ohair@314 132 # or
ohair@314 133 # html_quote filename | output_cmd
ohair@314 134 #
ohair@314 135 # Make a piece of source code safe for display in an HTML <pre> block.
ohair@314 136 #
ohair@314 137 html_quote()
ohair@314 138 {
ohair@314 139 sed -e "s/&/\&amp;/g" -e "s/</\&lt;/g" -e "s/>/\&gt;/g" "$@" | expand
ohair@314 140 }
ohair@314 141
ohair@314 142 #
ohair@314 143 # input_cmd | bug2url | output_cmd
ohair@314 144 #
ohair@314 145 # Scan for bugids and insert <a> links to the relevent bug database.
ohair@314 146 #
ohair@314 147 bug2url()
ohair@314 148 {
mduigou@616 149 sed -e 's|[0-9]\{5,\}|<a href=\"'$BUGURL$IDPREFIX'&\">&</a>|g'
ohair@314 150 }
ohair@314 151
ohair@314 152 #
ohair@314 153 # input_cmd | sac2url | output_cmd
ohair@314 154 #
ohair@314 155 # Scan for ARC cases and insert <a> links to the relevent SAC database.
ohair@314 156 # This is slightly complicated because inside the SWAN, SAC cases are
ohair@314 157 # grouped by ARC: PSARC/2006/123. But on OpenSolaris.org, they are
ohair@314 158 # referenced as 2006/123 (without labelling the ARC).
ohair@314 159 #
ohair@314 160 sac2url()
ohair@314 161 {
ohair@314 162 if [[ -z $Oflag ]]; then
ohair@314 163 sed -e 's|\([A-Z]\{1,2\}ARC\)[ /]\([0-9]\{4\}\)/\([0-9]\{3\}\)|<a href=\"'$SACURL'\1/\2/\3\">\1 \2/\3</a>|g'
ohair@314 164 else
ohair@314 165 sed -e 's|\([A-Z]\{1,2\}ARC\)[ /]\([0-9]\{4\}\)/\([0-9]\{3\}\)|<a href=\"'$SACURL'/\2/\3\">\1 \2/\3</a>|g'
ohair@314 166 fi
ohair@314 167 }
ohair@314 168
ohair@314 169 #
ohair@314 170 # strip_unchanged <infile> | output_cmd
ohair@314 171 #
ohair@314 172 # Removes chunks of sdiff documents that have not changed. This makes it
ohair@314 173 # easier for a code reviewer to find the bits that have changed.
ohair@314 174 #
ohair@314 175 # Deleted lines of text are replaced by a horizontal rule. Some
ohair@314 176 # identical lines are retained before and after the changed lines to
ohair@314 177 # provide some context. The number of these lines is controlled by the
ohair@314 178 # variable C in the $AWK script below.
ohair@314 179 #
ohair@314 180 # The script detects changed lines as any line that has a "<span class="
ohair@314 181 # string embedded (unchanged lines have no particular class and are not
ohair@314 182 # part of a <span>). Blank lines (without a sequence number) are also
ohair@314 183 # detected since they flag lines that have been inserted or deleted.
ohair@314 184 #
ohair@314 185 strip_unchanged()
ohair@314 186 {
ohair@314 187 $AWK '
ohair@314 188 BEGIN { C = c = 20 }
ohair@314 189 NF == 0 || /span class=/ {
ohair@314 190 if (c > C) {
ohair@314 191 c -= C
ohair@314 192 inx = 0
ohair@314 193 if (c > C) {
ohair@314 194 print "\n</pre><hr></hr><pre>"
ohair@314 195 inx = c % C
ohair@314 196 c = C
ohair@314 197 }
ohair@314 198
ohair@314 199 for (i = 0; i < c; i++)
ohair@314 200 print ln[(inx + i) % C]
ohair@314 201 }
ohair@314 202 c = 0;
ohair@314 203 print
ohair@314 204 next
ohair@314 205 }
ohair@314 206 { if (c >= C) {
ohair@314 207 ln[c % C] = $0
ohair@314 208 c++;
ohair@314 209 next;
ohair@314 210 }
ohair@314 211 c++;
ohair@314 212 print
ohair@314 213 }
ohair@314 214 END { if (c > (C * 2)) print "\n</pre><hr></hr>" }
ohair@314 215
ohair@314 216 ' $1
ohair@314 217 }
ohair@314 218
ohair@314 219 #
ohair@314 220 # sdiff_to_html
ohair@314 221 #
ohair@314 222 # This function takes two files as arguments, obtains their diff, and
ohair@314 223 # processes the diff output to present the files as an HTML document with
ohair@314 224 # the files displayed side-by-side, differences shown in color. It also
ohair@314 225 # takes a delta comment, rendered as an HTML snippet, as the third
ohair@314 226 # argument. The function takes two files as arguments, then the name of
ohair@314 227 # file, the path, and the comment. The HTML will be delivered on stdout,
ohair@314 228 # e.g.
ohair@314 229 #
ohair@314 230 # $ sdiff_to_html old/usr/src/tools/scripts/webrev.sh \
ohair@314 231 # new/usr/src/tools/scripts/webrev.sh \
ohair@314 232 # webrev.sh usr/src/tools/scripts \
mduigou@616 233 # '<a href="https://jbs.oracle.com/bugs/browse/JDK-1234567">
mduigou@616 234 # JDK-1234567</a> my bugid' > <file>.html
ohair@314 235 #
ohair@314 236 # framed_sdiff() is then called which creates $2.frames.html
ohair@314 237 # in the webrev tree.
ohair@314 238 #
ohair@314 239 # FYI: This function is rather unusual in its use of awk. The initial
ohair@314 240 # diff run produces conventional diff output showing changed lines mixed
ohair@314 241 # with editing codes. The changed lines are ignored - we're interested in
ohair@314 242 # the editing codes, e.g.
ohair@314 243 #
ohair@314 244 # 8c8
ohair@314 245 # 57a61
ohair@314 246 # 63c66,76
ohair@314 247 # 68,93d80
ohair@314 248 # 106d90
ohair@314 249 # 108,110d91
ohair@314 250 #
ohair@314 251 # These editing codes are parsed by the awk script and used to generate
ohair@314 252 # another awk script that generates HTML, e.g the above lines would turn
ohair@314 253 # into something like this:
ohair@314 254 #
ohair@314 255 # BEGIN { printf "<pre>\n" }
ohair@314 256 # function sp(n) {for (i=0;i<n;i++)printf "\n"}
ohair@314 257 # function wl(n) {printf "<font color=%s>%4d %s </font>\n", n, NR, $0}
ohair@314 258 # NR==8 {wl("#7A7ADD");next}
ohair@314 259 # NR==54 {wl("#7A7ADD");sp(3);next}
ohair@314 260 # NR==56 {wl("#7A7ADD");next}
ohair@314 261 # NR==57 {wl("black");printf "\n"; next}
ohair@314 262 # : :
ohair@314 263 #
ohair@314 264 # This script is then run on the original source file to generate the
ohair@314 265 # HTML that corresponds to the source file.
ohair@314 266 #
ohair@314 267 # The two HTML files are then combined into a single piece of HTML that
ohair@314 268 # uses an HTML table construct to present the files side by side. You'll
ohair@314 269 # notice that the changes are color-coded:
ohair@314 270 #
ohair@314 271 # black - unchanged lines
ohair@314 272 # blue - changed lines
ohair@314 273 # bold blue - new lines
ohair@314 274 # brown - deleted lines
ohair@314 275 #
ohair@314 276 # Blank lines are inserted in each file to keep unchanged lines in sync
ohair@314 277 # (side-by-side). This format is familiar to users of sdiff(1) or
ohair@314 278 # Teamware's filemerge tool.
ohair@314 279 #
ohair@314 280 sdiff_to_html()
ohair@314 281 {
ohair@314 282 diff -b $1 $2 > /tmp/$$.diffs
ohair@314 283
ohair@314 284 TNAME=$3
ohair@314 285 TPATH=$4
ohair@314 286 COMMENT=$5
ohair@314 287
ohair@314 288 #
ohair@314 289 # Now we have the diffs, generate the HTML for the old file.
ohair@314 290 #
ohair@314 291 $AWK '
ohair@314 292 BEGIN {
ohair@314 293 printf "function sp(n) {for (i=0;i<n;i++)printf \"\\n\"}\n"
ohair@314 294 printf "function removed() "
ohair@314 295 printf "{printf \"<span class=\\\"removed\\\">%%4d %%s</span>\\n\", NR, $0}\n"
ohair@314 296 printf "function changed() "
ohair@314 297 printf "{printf \"<span class=\\\"changed\\\">%%4d %%s</span>\\n\", NR, $0}\n"
ohair@314 298 printf "function bl() {printf \"%%4d %%s\\n\", NR, $0}\n"
ohair@314 299 }
ohair@314 300 /^</ {next}
ohair@314 301 /^>/ {next}
ohair@314 302 /^---/ {next}
ohair@314 303
ohair@314 304 {
ohair@314 305 split($1, a, /[cad]/) ;
ohair@314 306 if (index($1, "a")) {
ohair@314 307 if (a[1] == 0) {
ohair@314 308 n = split(a[2], r, /,/);
ohair@314 309 if (n == 1)
ohair@314 310 printf "BEGIN\t\t{sp(1)}\n"
ohair@314 311 else
ohair@314 312 printf "BEGIN\t\t{sp(%d)}\n",\
ohair@314 313 (r[2] - r[1]) + 1
ohair@314 314 next
ohair@314 315 }
ohair@314 316
ohair@314 317 printf "NR==%s\t\t{", a[1]
ohair@314 318 n = split(a[2], r, /,/);
ohair@314 319 s = r[1];
ohair@314 320 if (n == 1)
ohair@314 321 printf "bl();printf \"\\n\"; next}\n"
ohair@314 322 else {
ohair@314 323 n = r[2] - r[1]
ohair@314 324 printf "bl();sp(%d);next}\n",\
ohair@314 325 (r[2] - r[1]) + 1
ohair@314 326 }
ohair@314 327 next
ohair@314 328 }
ohair@314 329 if (index($1, "d")) {
ohair@314 330 n = split(a[1], r, /,/);
ohair@314 331 n1 = r[1]
ohair@314 332 n2 = r[2]
ohair@314 333 if (n == 1)
ohair@314 334 printf "NR==%s\t\t{removed(); next}\n" , n1
ohair@314 335 else
ohair@314 336 printf "NR==%s,NR==%s\t{removed(); next}\n" , n1, n2
ohair@314 337 next
ohair@314 338 }
ohair@314 339 if (index($1, "c")) {
ohair@314 340 n = split(a[1], r, /,/);
ohair@314 341 n1 = r[1]
ohair@314 342 n2 = r[2]
ohair@314 343 final = n2
ohair@314 344 d1 = 0
ohair@314 345 if (n == 1)
ohair@314 346 printf "NR==%s\t\t{changed();" , n1
ohair@314 347 else {
ohair@314 348 d1 = n2 - n1
ohair@314 349 printf "NR==%s,NR==%s\t{changed();" , n1, n2
ohair@314 350 }
ohair@314 351 m = split(a[2], r, /,/);
ohair@314 352 n1 = r[1]
ohair@314 353 n2 = r[2]
ohair@314 354 if (m > 1) {
ohair@314 355 d2 = n2 - n1
ohair@314 356 if (d2 > d1) {
ohair@314 357 if (n > 1) printf "if (NR==%d)", final
ohair@314 358 printf "sp(%d);", d2 - d1
ohair@314 359 }
ohair@314 360 }
ohair@314 361 printf "next}\n" ;
ohair@314 362
ohair@314 363 next
ohair@314 364 }
ohair@314 365 }
ohair@314 366
ohair@314 367 END { printf "{printf \"%%4d %%s\\n\", NR, $0 }\n" }
ohair@314 368 ' /tmp/$$.diffs > /tmp/$$.file1
ohair@314 369
ohair@314 370 #
ohair@314 371 # Now generate the HTML for the new file
ohair@314 372 #
ohair@314 373 $AWK '
ohair@314 374 BEGIN {
ohair@314 375 printf "function sp(n) {for (i=0;i<n;i++)printf \"\\n\"}\n"
ohair@314 376 printf "function new() "
ohair@314 377 printf "{printf \"<span class=\\\"new\\\">%%4d %%s</span>\\n\", NR, $0}\n"
ohair@314 378 printf "function changed() "
ohair@314 379 printf "{printf \"<span class=\\\"changed\\\">%%4d %%s</span>\\n\", NR, $0}\n"
ohair@314 380 printf "function bl() {printf \"%%4d %%s\\n\", NR, $0}\n"
ohair@314 381 }
ohair@314 382
ohair@314 383 /^</ {next}
ohair@314 384 /^>/ {next}
ohair@314 385 /^---/ {next}
ohair@314 386
ohair@314 387 {
ohair@314 388 split($1, a, /[cad]/) ;
ohair@314 389 if (index($1, "d")) {
ohair@314 390 if (a[2] == 0) {
ohair@314 391 n = split(a[1], r, /,/);
ohair@314 392 if (n == 1)
ohair@314 393 printf "BEGIN\t\t{sp(1)}\n"
ohair@314 394 else
ohair@314 395 printf "BEGIN\t\t{sp(%d)}\n",\
ohair@314 396 (r[2] - r[1]) + 1
ohair@314 397 next
ohair@314 398 }
ohair@314 399
ohair@314 400 printf "NR==%s\t\t{", a[2]
ohair@314 401 n = split(a[1], r, /,/);
ohair@314 402 s = r[1];
ohair@314 403 if (n == 1)
ohair@314 404 printf "bl();printf \"\\n\"; next}\n"
ohair@314 405 else {
ohair@314 406 n = r[2] - r[1]
ohair@314 407 printf "bl();sp(%d);next}\n",\
ohair@314 408 (r[2] - r[1]) + 1
ohair@314 409 }
ohair@314 410 next
ohair@314 411 }
ohair@314 412 if (index($1, "a")) {
ohair@314 413 n = split(a[2], r, /,/);
ohair@314 414 n1 = r[1]
ohair@314 415 n2 = r[2]
ohair@314 416 if (n == 1)
ohair@314 417 printf "NR==%s\t\t{new() ; next}\n" , n1
ohair@314 418 else
ohair@314 419 printf "NR==%s,NR==%s\t{new() ; next}\n" , n1, n2
ohair@314 420 next
ohair@314 421 }
ohair@314 422 if (index($1, "c")) {
ohair@314 423 n = split(a[2], r, /,/);
ohair@314 424 n1 = r[1]
ohair@314 425 n2 = r[2]
ohair@314 426 final = n2
ohair@314 427 d2 = 0;
ohair@314 428 if (n == 1) {
ohair@314 429 final = n1
ohair@314 430 printf "NR==%s\t\t{changed();" , n1
ohair@314 431 } else {
ohair@314 432 d2 = n2 - n1
ohair@314 433 printf "NR==%s,NR==%s\t{changed();" , n1, n2
ohair@314 434 }
ohair@314 435 m = split(a[1], r, /,/);
ohair@314 436 n1 = r[1]
ohair@314 437 n2 = r[2]
ohair@314 438 if (m > 1) {
ohair@314 439 d1 = n2 - n1
ohair@314 440 if (d1 > d2) {
ohair@314 441 if (n > 1) printf "if (NR==%d)", final
ohair@314 442 printf "sp(%d);", d1 - d2
ohair@314 443 }
ohair@314 444 }
ohair@314 445 printf "next}\n" ;
ohair@314 446 next
ohair@314 447 }
ohair@314 448 }
ohair@314 449 END { printf "{printf \"%%4d %%s\\n\", NR, $0 }\n" }
ohair@314 450 ' /tmp/$$.diffs > /tmp/$$.file2
ohair@314 451
ohair@314 452 #
ohair@314 453 # Post-process the HTML files by running them back through $AWK
ohair@314 454 #
ohair@314 455 html_quote < $1 | $AWK -f /tmp/$$.file1 > /tmp/$$.file1.html
ohair@314 456
ohair@314 457 html_quote < $2 | $AWK -f /tmp/$$.file2 > /tmp/$$.file2.html
ohair@314 458
ohair@314 459 #
ohair@314 460 # Now combine into a valid HTML file and side-by-side into a table
ohair@314 461 #
ohair@314 462 print "$HTML<head>$STDHEAD"
ohair@314 463 print "<title>$WNAME Sdiff $TPATH </title>"
ohair@314 464 print "</head><body id=\"SUNWwebrev\">"
ohair@314 465 print "<h2>$TPATH/$TNAME</h2>"
ohair@314 466 print "<a class=\"print\" href=\"javascript:print()\">Print this page</a>"
ohair@314 467 print "<pre>$COMMENT</pre>\n"
ohair@314 468 print "<table><tr valign=\"top\">"
ohair@314 469 print "<td><pre>"
ohair@314 470
ohair@314 471 strip_unchanged /tmp/$$.file1.html
ohair@314 472
ohair@314 473 print "</pre></td><td><pre>"
ohair@314 474
ohair@314 475 strip_unchanged /tmp/$$.file2.html
ohair@314 476
ohair@314 477 print "</pre></td>"
ohair@314 478 print "</tr></table>"
ohair@314 479 print "</body></html>"
ohair@314 480
ohair@314 481 framed_sdiff $TNAME $TPATH /tmp/$$.file1.html /tmp/$$.file2.html \
ohair@314 482 "$COMMENT"
ohair@314 483 }
ohair@314 484
ohair@314 485
ohair@314 486 #
ohair@314 487 # framed_sdiff <filename> <filepath> <lhsfile> <rhsfile> <comment>
ohair@314 488 #
ohair@314 489 # Expects lefthand and righthand side html files created by sdiff_to_html.
ohair@314 490 # We use insert_anchors() to augment those with HTML navigation anchors,
ohair@314 491 # and then emit the main frame. Content is placed into:
ohair@314 492 #
ohair@314 493 # $WDIR/DIR/$TNAME.lhs.html
ohair@314 494 # $WDIR/DIR/$TNAME.rhs.html
ohair@314 495 # $WDIR/DIR/$TNAME.frames.html
ohair@314 496 #
ohair@314 497 # NOTE: We rely on standard usage of $WDIR and $DIR.
ohair@314 498 #
ohair@314 499 function framed_sdiff
ohair@314 500 {
ohair@314 501 typeset TNAME=$1
ohair@314 502 typeset TPATH=$2
ohair@314 503 typeset lhsfile=$3
ohair@314 504 typeset rhsfile=$4
ohair@314 505 typeset comments=$5
ohair@314 506 typeset RTOP
ohair@314 507
ohair@314 508 # Enable html files to access WDIR via a relative path.
ohair@314 509 RTOP=$(relative_dir $TPATH $WDIR)
ohair@314 510
ohair@314 511 # Make the rhs/lhs files and output the frameset file.
ohair@314 512 print "$HTML<head>$STDHEAD" > $WDIR/$DIR/$TNAME.lhs.html
ohair@314 513
ohair@314 514 cat >> $WDIR/$DIR/$TNAME.lhs.html <<-EOF
ohair@314 515 <script type="text/javascript" src="$RTOP/ancnav.js"></script>
ohair@314 516 </head>
ohair@314 517 <body id="SUNWwebrev" onkeypress="keypress(event);">
ohair@314 518 <a name="0"></a>
ohair@314 519 <pre>$comments</pre><hr></hr>
ohair@314 520 EOF
ohair@314 521
ohair@314 522 cp $WDIR/$DIR/$TNAME.lhs.html $WDIR/$DIR/$TNAME.rhs.html
ohair@314 523
ohair@314 524 insert_anchors $lhsfile >> $WDIR/$DIR/$TNAME.lhs.html
ohair@314 525 insert_anchors $rhsfile >> $WDIR/$DIR/$TNAME.rhs.html
ohair@314 526
ohair@314 527 close='</body></html>'
ohair@314 528
ohair@314 529 print $close >> $WDIR/$DIR/$TNAME.lhs.html
ohair@314 530 print $close >> $WDIR/$DIR/$TNAME.rhs.html
ohair@314 531
ohair@314 532 print "$FRAMEHTML<head>$STDHEAD" > $WDIR/$DIR/$TNAME.frames.html
ohair@314 533 print "<title>$WNAME Framed-Sdiff " \
ohair@314 534 "$TPATH/$TNAME</title> </head>" >> $WDIR/$DIR/$TNAME.frames.html
ohair@314 535 cat >> $WDIR/$DIR/$TNAME.frames.html <<-EOF
ohair@314 536 <frameset rows="*,60">
ohair@314 537 <frameset cols="50%,50%">
ohair@314 538 <frame src="$TNAME.lhs.html" scrolling="auto" name="lhs" />
ohair@314 539 <frame src="$TNAME.rhs.html" scrolling="auto" name="rhs" />
ohair@314 540 </frameset>
ohair@314 541 <frame src="$RTOP/ancnav.html" scrolling="no" marginwidth="0"
ohair@314 542 marginheight="0" name="nav" />
ohair@314 543 <noframes>
ohair@314 544 <body id="SUNWwebrev">
ohair@314 545 Alas 'frames' webrev requires that your browser supports frames
ohair@314 546 and has the feature enabled.
ohair@314 547 </body>
ohair@314 548 </noframes>
ohair@314 549 </frameset>
ohair@314 550 </html>
ohair@314 551 EOF
ohair@314 552 }
ohair@314 553
ohair@314 554
ohair@314 555 #
ohair@314 556 # fix_postscript
ohair@314 557 #
ohair@314 558 # Merge codereview output files to a single conforming postscript file, by:
ohair@314 559 # - removing all extraneous headers/trailers
ohair@314 560 # - making the page numbers right
ohair@314 561 # - removing pages devoid of contents which confuse some
ohair@314 562 # postscript readers.
ohair@314 563 #
ohair@314 564 # From Casper.
ohair@314 565 #
ohair@314 566 function fix_postscript
ohair@314 567 {
ohair@314 568 infile=$1
ohair@314 569
ohair@314 570 cat > /tmp/$$.crmerge.pl << \EOF
ohair@314 571
ohair@314 572 print scalar(<>); # %!PS-Adobe---
ohair@314 573 print "%%Orientation: Landscape\n";
ohair@314 574
ohair@314 575 $pno = 0;
ohair@314 576 $doprint = 1;
ohair@314 577
ohair@314 578 $page = "";
ohair@314 579
ohair@314 580 while (<>) {
ohair@314 581 next if (/^%%Pages:\s*\d+/);
ohair@314 582
ohair@314 583 if (/^%%Page:/) {
ohair@314 584 if ($pno == 0 || $page =~ /\)S/) {
ohair@314 585 # Header or single page containing text
ohair@314 586 print "%%Page: ? $pno\n" if ($pno > 0);
ohair@314 587 print $page;
ohair@314 588 $pno++;
ohair@314 589 } else {
ohair@314 590 # Empty page, skip it.
ohair@314 591 }
ohair@314 592 $page = "";
ohair@314 593 $doprint = 1;
ohair@314 594 next;
ohair@314 595 }
ohair@314 596
ohair@314 597 # Skip from %%Trailer of one document to Endprolog
ohair@314 598 # %%Page of the next
ohair@314 599 $doprint = 0 if (/^%%Trailer/);
ohair@314 600 $page .= $_ if ($doprint);
ohair@314 601 }
ohair@314 602
ohair@314 603 if ($page =~ /\)S/) {
ohair@314 604 print "%%Page: ? $pno\n";
ohair@314 605 print $page;
ohair@314 606 } else {
ohair@314 607 $pno--;
ohair@314 608 }
ohair@314 609 print "%%Trailer\n%%Pages: $pno\n";
ohair@314 610 EOF
ohair@314 611
ohair@314 612 $PERL /tmp/$$.crmerge.pl < $infile
ohair@314 613 }
ohair@314 614
ohair@314 615
ohair@314 616 #
ohair@314 617 # input_cmd | insert_anchors | output_cmd
ohair@314 618 #
ohair@314 619 # Flag blocks of difference with sequentially numbered invisible
ohair@314 620 # anchors. These are used to drive the frames version of the
ohair@314 621 # sdiffs output.
ohair@314 622 #
ohair@314 623 # NOTE: Anchor zero flags the top of the file irrespective of changes,
ohair@314 624 # an additional anchor is also appended to flag the bottom.
ohair@314 625 #
ohair@314 626 # The script detects changed lines as any line that has a "<span
ohair@314 627 # class=" string embedded (unchanged lines have no class set and are
ohair@314 628 # not part of a <span>. Blank lines (without a sequence number)
ohair@314 629 # are also detected since they flag lines that have been inserted or
ohair@314 630 # deleted.
ohair@314 631 #
ohair@314 632 function insert_anchors
ohair@314 633 {
ohair@314 634 $AWK '
ohair@314 635 function ia() {
ohair@314 636 # This should be able to be a singleton <a /> but that
ohair@314 637 # seems to trigger a bug in firefox a:hover rule processing
ohair@314 638 printf "<a name=\"%d\" id=\"anc%d\"></a>", anc, anc++;
ohair@314 639 }
ohair@314 640
ohair@314 641 BEGIN {
ohair@314 642 anc=1;
ohair@314 643 inblock=1;
ohair@314 644 printf "<pre>\n";
ohair@314 645 }
ohair@314 646 NF == 0 || /^<span class=/ {
ohair@314 647 if (inblock == 0) {
ohair@314 648 ia();
ohair@314 649 inblock=1;
ohair@314 650 }
ohair@314 651 print;
ohair@314 652 next;
ohair@314 653 }
ohair@314 654 {
ohair@314 655 inblock=0;
ohair@314 656 print;
ohair@314 657 }
ohair@314 658 END {
ohair@314 659 ia();
ohair@314 660
ohair@314 661 printf "<b style=\"font-size: large; color: red\">";
ohair@314 662 printf "--- EOF ---</b>"
ohair@314 663 for(i=0;i<8;i++) printf "\n\n\n\n\n\n\n\n\n\n";
ohair@314 664 printf "</pre>"
ohair@314 665 printf "<form name=\"eof\">";
ohair@314 666 printf "<input name=\"value\" value=\"%d\" type=\"hidden\" />",
ohair@314 667 anc - 1;
ohair@314 668 printf "</form>";
ohair@314 669 }
ohair@314 670 ' $1
ohair@314 671 }
ohair@314 672
ohair@314 673
ohair@314 674 #
ohair@314 675 # relative_dir
ohair@314 676 #
ohair@314 677 # Print a relative return path from $1 to $2. For example if
ohair@314 678 # $1=/tmp/myreview/raw_files/usr/src/tools/scripts and $2=/tmp/myreview,
ohair@314 679 # this function would print "../../../../".
ohair@314 680 #
ohair@314 681 # In the event that $1 is not in $2 a warning is printed to stderr,
ohair@314 682 # and $2 is returned-- the result of this is that the resulting webrev
ohair@314 683 # is not relocatable.
ohair@314 684 #
ohair@314 685 function relative_dir
ohair@314 686 {
ohair@314 687 d1=$1
ohair@314 688 d2=$2
ohair@314 689 if [[ "$d1" == "." ]]; then
ohair@314 690 print "."
ohair@314 691 else
ohair@314 692 typeset cur="${d1##$d2?(/)}"
ohair@314 693 typeset ret=""
ohair@314 694 if [[ $d2 == $cur ]]; then # Should never happen.
ohair@314 695 # Should never happen.
ohair@314 696 print -u2 "\nWARNING: relative_dir: \"$1\" not relative "
ohair@314 697 print -u2 "to \"$2\". Check input paths. Framed webrev "
ohair@314 698 print -u2 "will not be relocatable!"
ohair@314 699 print $2
ohair@314 700 return
ohair@314 701 fi
ohair@314 702
ohair@314 703 while [[ -n ${cur} ]];
ohair@314 704 do
ohair@314 705 cur=${cur%%*(/)*([!/])}
ohair@314 706 if [[ -z $ret ]]; then
ohair@314 707 ret=".."
ohair@314 708 else
ohair@314 709 ret="../$ret"
ohair@314 710 fi
ohair@314 711 done
ohair@314 712 print $ret
ohair@314 713 fi
ohair@314 714 }
ohair@314 715
ohair@314 716
ohair@314 717 #
ohair@314 718 # frame_nav_js
ohair@314 719 #
ohair@314 720 # Emit javascript for frame navigation
ohair@314 721 #
ohair@314 722 function frame_nav_js
ohair@314 723 {
ohair@314 724 cat << \EOF
ohair@314 725 var myInt;
ohair@314 726 var scrolling=0;
ohair@314 727 var sfactor = 3;
ohair@314 728 var scount=10;
ohair@314 729
ohair@314 730 function scrollByPix() {
ohair@314 731 if (scount<=0) {
ohair@314 732 sfactor*=1.2;
ohair@314 733 scount=10;
ohair@314 734 }
ohair@314 735 parent.lhs.scrollBy(0,sfactor);
ohair@314 736 parent.rhs.scrollBy(0,sfactor);
ohair@314 737 scount--;
ohair@314 738 }
ohair@314 739
ohair@314 740 function scrollToAnc(num) {
ohair@314 741
ohair@314 742 // Update the value of the anchor in the form which we use as
ohair@314 743 // storage for this value. setAncValue() will take care of
ohair@314 744 // correcting for overflow and underflow of the value and return
ohair@314 745 // us the new value.
ohair@314 746 num = setAncValue(num);
ohair@314 747
ohair@314 748 // Set location and scroll back a little to expose previous
ohair@314 749 // lines.
ohair@314 750 //
ohair@314 751 // Note that this could be improved: it is possible although
ohair@314 752 // complex to compute the x and y position of an anchor, and to
ohair@314 753 // scroll to that location directly.
ohair@314 754 //
ohair@314 755 parent.lhs.location.replace(parent.lhs.location.pathname + "#" + num);
ohair@314 756 parent.rhs.location.replace(parent.rhs.location.pathname + "#" + num);
ohair@314 757
ohair@314 758 parent.lhs.scrollBy(0,-30);
ohair@314 759 parent.rhs.scrollBy(0,-30);
ohair@314 760 }
ohair@314 761
ohair@314 762 function getAncValue()
ohair@314 763 {
ohair@314 764 return (parseInt(parent.nav.document.diff.real.value));
ohair@314 765 }
ohair@314 766
ohair@314 767 function setAncValue(val)
ohair@314 768 {
ohair@314 769 if (val <= 0) {
ohair@314 770 val = 0;
ohair@314 771 parent.nav.document.diff.real.value = val;
ohair@314 772 parent.nav.document.diff.display.value = "BOF";
ohair@314 773 return (val);
ohair@314 774 }
ohair@314 775
ohair@314 776 //
ohair@314 777 // The way we compute the max anchor value is to stash it
ohair@314 778 // inline in the left and right hand side pages-- it's the same
ohair@314 779 // on each side, so we pluck from the left.
ohair@314 780 //
ohair@314 781 maxval = parent.lhs.document.eof.value.value;
ohair@314 782 if (val < maxval) {
ohair@314 783 parent.nav.document.diff.real.value = val;
ohair@314 784 parent.nav.document.diff.display.value = val.toString();
ohair@314 785 return (val);
ohair@314 786 }
ohair@314 787
ohair@314 788 // this must be: val >= maxval
ohair@314 789 val = maxval;
ohair@314 790 parent.nav.document.diff.real.value = val;
ohair@314 791 parent.nav.document.diff.display.value = "EOF";
ohair@314 792 return (val);
ohair@314 793 }
ohair@314 794
ohair@314 795 function stopScroll() {
ohair@314 796 if (scrolling==1) {
ohair@314 797 clearInterval(myInt);
ohair@314 798 scrolling=0;
ohair@314 799 }
ohair@314 800 }
ohair@314 801
ohair@314 802 function startScroll() {
ohair@314 803 stopScroll();
ohair@314 804 scrolling=1;
ohair@314 805 myInt=setInterval("scrollByPix()",10);
ohair@314 806 }
ohair@314 807
ohair@314 808 function handlePress(b) {
ohair@314 809
ohair@314 810 switch (b) {
ohair@314 811 case 1 :
ohair@314 812 scrollToAnc(-1);
ohair@314 813 break;
ohair@314 814 case 2 :
ohair@314 815 scrollToAnc(getAncValue() - 1);
ohair@314 816 break;
ohair@314 817 case 3 :
ohair@314 818 sfactor=-3;
ohair@314 819 startScroll();
ohair@314 820 break;
ohair@314 821 case 4 :
ohair@314 822 sfactor=3;
ohair@314 823 startScroll();
ohair@314 824 break;
ohair@314 825 case 5 :
ohair@314 826 scrollToAnc(getAncValue() + 1);
ohair@314 827 break;
ohair@314 828 case 6 :
ohair@314 829 scrollToAnc(999999);
ohair@314 830 break;
ohair@314 831 }
ohair@314 832 }
ohair@314 833
ohair@314 834 function handleRelease(b) {
ohair@314 835 stopScroll();
ohair@314 836 }
ohair@314 837
ohair@314 838 function keypress(ev) {
ohair@314 839 var keynum;
ohair@314 840 var keychar;
ohair@314 841
ohair@314 842 if (window.event) { // IE
ohair@314 843 keynum = ev.keyCode;
ohair@314 844 } else if (ev.which) { // non-IE
ohair@314 845 keynum = ev.which;
ohair@314 846 }
ohair@314 847
ohair@314 848 keychar = String.fromCharCode(keynum);
ohair@314 849
ohair@314 850 if (keychar == "k") {
ohair@314 851 handlePress(2);
ohair@314 852 return (0);
ohair@314 853 } else if (keychar == "j" || keychar == " ") {
ohair@314 854 handlePress(5);
ohair@314 855 return (0);
ohair@314 856 }
ohair@314 857 return (1);
ohair@314 858 }
ohair@314 859
ohair@314 860 function ValidateDiffNum(){
ohair@314 861 val = parent.nav.document.diff.display.value;
ohair@314 862 if (val == "EOF") {
ohair@314 863 scrollToAnc(999999);
ohair@314 864 return;
ohair@314 865 }
ohair@314 866
ohair@314 867 if (val == "BOF") {
ohair@314 868 scrollToAnc(0);
ohair@314 869 return;
ohair@314 870 }
ohair@314 871
ohair@314 872 i=parseInt(val);
ohair@314 873 if (isNaN(i)) {
ohair@314 874 parent.nav.document.diff.display.value = getAncValue();
ohair@314 875 } else {
ohair@314 876 scrollToAnc(i);
ohair@314 877 }
ohair@314 878 return false;
ohair@314 879 }
ohair@314 880
ohair@314 881 EOF
ohair@314 882 }
ohair@314 883
ohair@314 884 #
ohair@314 885 # frame_navigation
ohair@314 886 #
ohair@314 887 # Output anchor navigation file for framed sdiffs.
ohair@314 888 #
ohair@314 889 function frame_navigation
ohair@314 890 {
ohair@314 891 print "$HTML<head>$STDHEAD"
ohair@314 892
ohair@314 893 cat << \EOF
ohair@314 894 <title>Anchor Navigation</title>
ohair@314 895 <meta http-equiv="Content-Script-Type" content="text/javascript" />
ohair@314 896 <meta http-equiv="Content-Type" content="text/html" />
ohair@314 897
ohair@314 898 <style type="text/css">
ohair@314 899 div.button td { padding-left: 5px; padding-right: 5px;
ohair@314 900 background-color: #eee; text-align: center;
ohair@314 901 border: 1px #444 outset; cursor: pointer; }
ohair@314 902 div.button a { font-weight: bold; color: black }
ohair@314 903 div.button td:hover { background: #ffcc99; }
ohair@314 904 </style>
ohair@314 905 EOF
ohair@314 906
ohair@314 907 print "<script type=\"text/javascript\" src=\"ancnav.js\"></script>"
ohair@314 908
ohair@314 909 cat << \EOF
ohair@314 910 </head>
ohair@314 911 <body id="SUNWwebrev" bgcolor="#eeeeee" onload="document.diff.real.focus();"
ohair@314 912 onkeypress="keypress(event);">
ohair@314 913 <noscript lang="javascript">
ohair@314 914 <center>
ohair@314 915 <p><big>Framed Navigation controls require Javascript</big><br />
ohair@314 916 Either this browser is incompatable or javascript is not enabled</p>
ohair@314 917 </center>
ohair@314 918 </noscript>
ohair@314 919 <table width="100%" border="0" align="center">
ohair@314 920 <tr>
ohair@314 921 <td valign="middle" width="25%">Diff navigation:
ohair@314 922 Use 'j' and 'k' for next and previous diffs; or use buttons
ohair@314 923 at right</td>
ohair@314 924 <td align="center" valign="top" width="50%">
ohair@314 925 <div class="button">
ohair@314 926 <table border="0" align="center">
ohair@314 927 <tr>
ohair@314 928 <td>
ohair@314 929 <a onMouseDown="handlePress(1);return true;"
ohair@314 930 onMouseUp="handleRelease(1);return true;"
ohair@314 931 onMouseOut="handleRelease(1);return true;"
ohair@314 932 onClick="return false;"
ohair@314 933 title="Go to Beginning Of file">BOF</a></td>
ohair@314 934 <td>
ohair@314 935 <a onMouseDown="handlePress(3);return true;"
ohair@314 936 onMouseUp="handleRelease(3);return true;"
ohair@314 937 onMouseOut="handleRelease(3);return true;"
ohair@314 938 title="Scroll Up: Press and Hold to accelerate"
ohair@314 939 onClick="return false;">Scroll Up</a></td>
ohair@314 940 <td>
ohair@314 941 <a onMouseDown="handlePress(2);return true;"
ohair@314 942 onMouseUp="handleRelease(2);return true;"
ohair@314 943 onMouseOut="handleRelease(2);return true;"
ohair@314 944 title="Go to previous Diff"
ohair@314 945 onClick="return false;">Prev Diff</a>
ohair@314 946 </td></tr>
ohair@314 947
ohair@314 948 <tr>
ohair@314 949 <td>
ohair@314 950 <a onMouseDown="handlePress(6);return true;"
ohair@314 951 onMouseUp="handleRelease(6);return true;"
ohair@314 952 onMouseOut="handleRelease(6);return true;"
ohair@314 953 onClick="return false;"
ohair@314 954 title="Go to End Of File">EOF</a></td>
ohair@314 955 <td>
ohair@314 956 <a onMouseDown="handlePress(4);return true;"
ohair@314 957 onMouseUp="handleRelease(4);return true;"
ohair@314 958 onMouseOut="handleRelease(4);return true;"
ohair@314 959 title="Scroll Down: Press and Hold to accelerate"
ohair@314 960 onClick="return false;">Scroll Down</a></td>
ohair@314 961 <td>
ohair@314 962 <a onMouseDown="handlePress(5);return true;"
ohair@314 963 onMouseUp="handleRelease(5);return true;"
ohair@314 964 onMouseOut="handleRelease(5);return true;"
ohair@314 965 title="Go to next Diff"
ohair@314 966 onClick="return false;">Next Diff</a></td>
ohair@314 967 </tr>
ohair@314 968 </table>
ohair@314 969 </div>
ohair@314 970 </td>
ohair@314 971 <th valign="middle" width="25%">
ohair@314 972 <form action="" name="diff" onsubmit="return ValidateDiffNum();">
ohair@314 973 <input name="display" value="BOF" size="8" type="text" />
ohair@314 974 <input name="real" value="0" size="8" type="hidden" />
ohair@314 975 </form>
ohair@314 976 </th>
ohair@314 977 </tr>
ohair@314 978 </table>
ohair@314 979 </body>
ohair@314 980 </html>
ohair@314 981 EOF
ohair@314 982 }
ohair@314 983
ohair@314 984
ohair@314 985
ohair@314 986 #
ohair@314 987 # diff_to_html <filename> <filepath> { U | C } <comment>
ohair@314 988 #
ohair@314 989 # Processes the output of diff to produce an HTML file representing either
ohair@314 990 # context or unified diffs.
ohair@314 991 #
ohair@314 992 diff_to_html()
ohair@314 993 {
ohair@314 994 TNAME=$1
ohair@314 995 TPATH=$2
ohair@314 996 DIFFTYPE=$3
ohair@314 997 COMMENT=$4
ohair@314 998
ohair@314 999 print "$HTML<head>$STDHEAD"
ohair@314 1000 print "<title>$WNAME ${DIFFTYPE}diff $TPATH</title>"
ohair@314 1001
ohair@314 1002 if [[ $DIFFTYPE == "U" ]]; then
ohair@314 1003 print "$UDIFFCSS"
ohair@314 1004 fi
ohair@314 1005
ohair@314 1006 cat <<-EOF
ohair@314 1007 </head>
ohair@314 1008 <body id="SUNWwebrev">
ohair@314 1009 <h2>$TPATH</h2>
ohair@314 1010 <a class="print" href="javascript:print()">Print this page</a>
ohair@314 1011 <pre>$COMMENT</pre>
ohair@314 1012 <pre>
ohair@314 1013 EOF
ohair@314 1014
ohair@314 1015 html_quote | $AWK '
ohair@314 1016 /^--- new/ { next }
ohair@314 1017 /^\+\+\+ new/ { next }
ohair@314 1018 /^--- old/ { next }
ohair@314 1019 /^\*\*\* old/ { next }
ohair@314 1020 /^\*\*\*\*/ { next }
ohair@314 1021 /^-------/ { printf "<center><h1>%s</h1></center>\n", $0; next }
ohair@314 1022 /^\@\@.*\@\@$/ { printf "</pre><hr /><pre>\n";
ohair@314 1023 printf "<span class=\"newmarker\">%s</span>\n", $0;
ohair@314 1024 next}
ohair@314 1025
ohair@314 1026 /^\*\*\*/ { printf "<hr /><span class=\"oldmarker\">%s</span>\n", $0;
ohair@314 1027 next}
ohair@314 1028 /^---/ { printf "<span class=\"newmarker\">%s</span>\n", $0;
ohair@314 1029 next}
ohair@314 1030 /^\+/ {printf "<span class=\"new\">%s</span>\n", $0; next}
ohair@314 1031 /^!/ {printf "<span class=\"changed\">%s</span>\n", $0; next}
ohair@314 1032 /^-/ {printf "<span class=\"removed\">%s</span>\n", $0; next}
ohair@314 1033 {printf "%s\n", $0; next}
ohair@314 1034 '
ohair@314 1035
ohair@314 1036 print "</pre></body></html>\n"
ohair@314 1037 }
ohair@314 1038
ohair@314 1039
ohair@314 1040 #
ohair@314 1041 # source_to_html { new | old } <filename>
ohair@314 1042 #
ohair@314 1043 # Process a plain vanilla source file to transform it into an HTML file.
ohair@314 1044 #
ohair@314 1045 source_to_html()
ohair@314 1046 {
ohair@314 1047 WHICH=$1
ohair@314 1048 TNAME=$2
ohair@314 1049
ohair@314 1050 print "$HTML<head>$STDHEAD"
ohair@314 1051 print "<title>$WHICH $TNAME</title>"
ohair@314 1052 print "<body id=\"SUNWwebrev\">"
ohair@314 1053 print "<pre>"
ohair@314 1054 html_quote | $AWK '{line += 1 ; printf "%4d %s\n", line, $0 }'
ohair@314 1055 print "</pre></body></html>"
ohair@314 1056 }
ohair@314 1057
ohair@314 1058 #
ohair@314 1059 # teamwarecomments {text|html} parent-file child-file
ohair@314 1060 #
ohair@314 1061 # Find the first delta in the child that's not in the parent. Get the
ohair@314 1062 # newest delta from the parent, get all deltas from the child starting
ohair@314 1063 # with that delta, and then get all info starting with the second oldest
ohair@314 1064 # delta in that list (the first delta unique to the child).
ohair@314 1065 #
ohair@314 1066 # This code adapted from Bill Shannon's "spc" script
ohair@314 1067 #
ohair@314 1068 comments_from_teamware()
ohair@314 1069 {
ohair@314 1070 fmt=$1
ohair@314 1071 pfile=$PWS/$2
ohair@314 1072 cfile=$CWS/$3
ohair@314 1073
ohair@314 1074 psid=$($SCCS prs -d:I: $pfile 2>/dev/null)
ohair@314 1075 if [[ -z "$psid" ]]; then
ohair@314 1076 psid=1.1
ohair@314 1077 fi
ohair@314 1078
ohair@314 1079 set -A sids $($SCCS prs -l -r$psid -d:I: $cfile 2>/dev/null)
ohair@314 1080 N=${#sids[@]}
ohair@314 1081
ohair@314 1082 nawkprg='
ohair@314 1083 /^COMMENTS:/ {p=1; next}
ohair@314 1084 /^D [0-9]+\.[0-9]+/ {printf "--- %s ---\n", $2; p=0; }
ohair@314 1085 NF == 0u { next }
ohair@314 1086 {if (p==0) next; print $0 }'
ohair@314 1087
ohair@314 1088 if [[ $N -ge 2 ]]; then
ohair@314 1089 sid1=${sids[$((N-2))]} # Gets 2nd to last sid
ohair@314 1090
ohair@314 1091 if [[ $fmt == "text" ]]; then
ohair@314 1092 $SCCS prs -l -r$sid1 $cfile 2>/dev/null | \
ohair@314 1093 $AWK "$nawkprg"
ohair@314 1094 return
ohair@314 1095 fi
ohair@314 1096
ohair@314 1097 $SCCS prs -l -r$sid1 $cfile 2>/dev/null | \
ohair@314 1098 html_quote | bug2url | sac2url | $AWK "$nawkprg"
ohair@314 1099 fi
ohair@314 1100 }
ohair@314 1101
ohair@314 1102 #
ohair@314 1103 # wxcomments {text|html} filepath
ohair@314 1104 #
ohair@314 1105 # Given the pathname of a file, find its location in a "wx" active file
ohair@314 1106 # list and print the following sccs comment. Output is either text or
ohair@314 1107 # HTML; if the latter, embedded bugids (sequence of 5 or more digits) are
ohair@314 1108 # turned into URLs.
ohair@314 1109 #
ohair@314 1110 comments_from_wx()
ohair@314 1111 {
ohair@314 1112 typeset fmt=$1
ohair@314 1113 typeset p=$2
ohair@314 1114
ohair@314 1115 comm=`$AWK '
ohair@314 1116 $1 == "'$p'" {
ohair@314 1117 do getline ; while (NF > 0)
ohair@314 1118 getline
ohair@314 1119 while (NF > 0) { print ; getline }
ohair@314 1120 exit
ohair@314 1121 }' < $wxfile`
ohair@314 1122
ohair@314 1123 if [[ $fmt == "text" ]]; then
ohair@314 1124 print "$comm"
ohair@314 1125 return
ohair@314 1126 fi
ohair@314 1127
ohair@314 1128 print "$comm" | html_quote | bug2url | sac2url
ohair@314 1129 }
ohair@314 1130
ohair@314 1131 comments_from_mercurial()
ohair@314 1132 {
ohair@314 1133 fmt=$1
ohair@314 1134 pfile=$PWS/$2
ohair@314 1135 cfile=$CWS/$3
ohair@314 1136
ohair@314 1137 logdir=`dirname $cfile`
ohair@314 1138 logf=`basename $cfile`
ohair@314 1139 if [ -d $logdir ]; then
ohair@314 1140 ( cd $logdir;
ohair@314 1141 active=`hg status $logf 2>/dev/null`
ohair@314 1142 # If the output from 'hg status' is not empty, it means the file
ohair@314 1143 # hasn't been committed, so don't fetch comments.
ohair@314 1144 if [[ -z $active ]] ; then
ohair@314 1145 if [[ -n $ALL_CREV ]]; then
ohair@314 1146 rev_opt=
ohair@314 1147 for rev in $ALL_CREV; do
ohair@314 1148 rev_opt="$rev_opt --rev $rev"
ohair@314 1149 done
ohair@314 1150 comm=`hg log $rev_opt --follow --template 'rev {rev} : {desc}\n' $logf`
ohair@314 1151 elif [[ -n $FIRST_CREV ]]; then
ohair@314 1152 comm=`hg log --rev $FIRST_CREV:tip --follow --template 'rev {rev} : {desc}\n' $logf`
ohair@314 1153 else
ohair@314 1154 comm=`hg log -l1 --follow --template 'rev {rev} : {desc}\n' $logf`
ohair@314 1155 fi
ohair@314 1156 else
ohair@314 1157 comm=""
ohair@314 1158 fi
ohair@314 1159 if [[ $fmt == "text" ]]; then
ohair@314 1160 print "$comm"
ohair@314 1161 return
ohair@314 1162 fi
mduigou@616 1163
ohair@314 1164 print "$comm" | html_quote | bug2url | sac2url
ohair@314 1165 )
ohair@314 1166 fi
ohair@314 1167 }
ohair@314 1168
ohair@314 1169
ohair@314 1170 #
ohair@314 1171 # getcomments {text|html} filepath parentpath
ohair@314 1172 #
ohair@314 1173 # Fetch the comments depending on what SCM mode we're in.
ohair@314 1174 #
ohair@314 1175 getcomments()
ohair@314 1176 {
ohair@314 1177 typeset fmt=$1
ohair@314 1178 typeset p=$2
ohair@314 1179 typeset pp=$3
ohair@314 1180
ohair@314 1181 if [[ -n $wxfile ]]; then
ohair@314 1182 comments_from_wx $fmt $p
ohair@314 1183 else
ohair@314 1184 if [[ $SCM_MODE == "teamware" ]]; then
ohair@314 1185 comments_from_teamware $fmt $pp $p
ohair@314 1186 elif [[ $SCM_MODE == "mercurial" ]]; then
ohair@314 1187 comments_from_mercurial $fmt $pp $p
ohair@314 1188 fi
ohair@314 1189 fi
ohair@314 1190 }
ohair@314 1191
ohair@314 1192 #
ohair@314 1193 # printCI <total-changed> <inserted> <deleted> <modified> <unchanged>
ohair@314 1194 #
ohair@314 1195 # Print out Code Inspection figures similar to sccs-prt(1) format.
ohair@314 1196 #
ohair@314 1197 function printCI
ohair@314 1198 {
ohair@314 1199 integer tot=$1 ins=$2 del=$3 mod=$4 unc=$5
ohair@314 1200 typeset str
ohair@314 1201 if (( tot == 1 )); then
ohair@314 1202 str="line"
ohair@314 1203 else
ohair@314 1204 str="lines"
ohair@314 1205 fi
ohair@314 1206 printf '%d %s changed: %d ins; %d del; %d mod; %d unchg' \
ohair@314 1207 $tot $str $ins $del $mod $unc
ohair@314 1208 }
ohair@314 1209
ohair@314 1210
ohair@314 1211 #
ohair@314 1212 # difflines <oldfile> <newfile>
ohair@314 1213 #
ohair@314 1214 # Calculate and emit number of added, removed, modified and unchanged lines,
ohair@314 1215 # and total lines changed, the sum of added + removed + modified.
ohair@314 1216 #
ohair@314 1217 function difflines
ohair@314 1218 {
ohair@314 1219 integer tot mod del ins unc err
ohair@314 1220 typeset filename
ohair@314 1221
ohair@314 1222 eval $( diff -e $1 $2 | $AWK '
ohair@314 1223 # Change range of lines: N,Nc
ohair@314 1224 /^[0-9]*,[0-9]*c$/ {
ohair@314 1225 n=split(substr($1,1,length($1)-1), counts, ",");
ohair@314 1226 if (n != 2) {
ohair@314 1227 error=2
ohair@314 1228 exit;
ohair@314 1229 }
ohair@314 1230 #
ohair@314 1231 # 3,5c means lines 3 , 4 and 5 are changed, a total of 3 lines.
ohair@314 1232 # following would be 5 - 3 = 2! Hence +1 for correction.
ohair@314 1233 #
ohair@314 1234 r=(counts[2]-counts[1])+1;
ohair@314 1235
ohair@314 1236 #
ohair@314 1237 # Now count replacement lines: each represents a change instead
ohair@314 1238 # of a delete, so increment c and decrement r.
ohair@314 1239 #
ohair@314 1240 while (getline != /^\.$/) {
ohair@314 1241 c++;
ohair@314 1242 r--;
ohair@314 1243 }
ohair@314 1244 #
ohair@314 1245 # If there were more replacement lines than original lines,
ohair@314 1246 # then r will be negative; in this case there are no deletions,
ohair@314 1247 # but there are r changes that should be counted as adds, and
ohair@314 1248 # since r is negative, subtract it from a and add it to c.
ohair@314 1249 #
ohair@314 1250 if (r < 0) {
ohair@314 1251 a-=r;
ohair@314 1252 c+=r;
ohair@314 1253 }
ohair@314 1254
ohair@314 1255 #
ohair@314 1256 # If there were more original lines than replacement lines, then
ohair@314 1257 # r will be positive; in this case, increment d by that much.
ohair@314 1258 #
ohair@314 1259 if (r > 0) {
ohair@314 1260 d+=r;
ohair@314 1261 }
ohair@314 1262 next;
ohair@314 1263 }
ohair@314 1264
ohair@314 1265 # Change lines: Nc
ohair@314 1266 /^[0-9].*c$/ {
ohair@314 1267 # The first line is a replacement; any more are additions.
ohair@314 1268 if (getline != /^\.$/) {
ohair@314 1269 c++;
ohair@314 1270 while (getline != /^\.$/) a++;
ohair@314 1271 }
ohair@314 1272 next;
ohair@314 1273 }
ohair@314 1274
ohair@314 1275 # Add lines: both Na and N,Na
ohair@314 1276 /^[0-9].*a$/ {
ohair@314 1277 while (getline != /^\.$/) a++;
ohair@314 1278 next;
ohair@314 1279 }
ohair@314 1280
ohair@314 1281 # Delete range of lines: N,Nd
ohair@314 1282 /^[0-9]*,[0-9]*d$/ {
ohair@314 1283 n=split(substr($1,1,length($1)-1), counts, ",");
ohair@314 1284 if (n != 2) {
ohair@314 1285 error=2
ohair@314 1286 exit;
ohair@314 1287 }
ohair@314 1288 #
ohair@314 1289 # 3,5d means lines 3 , 4 and 5 are deleted, a total of 3 lines.
ohair@314 1290 # following would be 5 - 3 = 2! Hence +1 for correction.
ohair@314 1291 #
ohair@314 1292 r=(counts[2]-counts[1])+1;
ohair@314 1293 d+=r;
ohair@314 1294 next;
ohair@314 1295 }
ohair@314 1296
ohair@314 1297 # Delete line: Nd. For example 10d says line 10 is deleted.
ohair@314 1298 /^[0-9]*d$/ {d++; next}
ohair@314 1299
ohair@314 1300 # Should not get here!
ohair@314 1301 {
ohair@314 1302 error=1;
ohair@314 1303 exit;
ohair@314 1304 }
ohair@314 1305
ohair@314 1306 # Finish off - print results
ohair@314 1307 END {
ohair@314 1308 printf("tot=%d;mod=%d;del=%d;ins=%d;err=%d\n",
ohair@314 1309 (c+d+a), c, d, a, error);
ohair@314 1310 }' )
ohair@314 1311
ohair@314 1312 # End of $AWK, Check to see if any trouble occurred.
ohair@314 1313 if (( $? > 0 || err > 0 )); then
ohair@314 1314 print "Unexpected Error occurred reading" \
ohair@314 1315 "\`diff -e $1 $2\`: \$?=$?, err=" $err
ohair@314 1316 return
ohair@314 1317 fi
ohair@314 1318
ohair@314 1319 # Accumulate totals
ohair@314 1320 (( TOTL += tot ))
ohair@314 1321 (( TMOD += mod ))
ohair@314 1322 (( TDEL += del ))
ohair@314 1323 (( TINS += ins ))
ohair@314 1324 # Calculate unchanged lines
ohair@314 1325 unc=`wc -l < $1`
ohair@314 1326 if (( unc > 0 )); then
ohair@314 1327 (( unc -= del + mod ))
ohair@314 1328 (( TUNC += unc ))
ohair@314 1329 fi
ohair@314 1330 # print summary
ohair@314 1331 print "<span class=\"lineschanged\">\c"
ohair@314 1332 printCI $tot $ins $del $mod $unc
ohair@314 1333 print "</span>"
ohair@314 1334 }
ohair@314 1335
ohair@314 1336
ohair@314 1337 #
ohair@314 1338 # flist_from_wx
ohair@314 1339 #
ohair@314 1340 # Sets up webrev to source its information from a wx-formatted file.
ohair@314 1341 # Sets the global 'wxfile' variable.
ohair@314 1342 #
ohair@314 1343 function flist_from_wx
ohair@314 1344 {
ohair@314 1345 typeset argfile=$1
ohair@314 1346 if [[ -n ${argfile%%/*} ]]; then
ohair@314 1347 #
ohair@314 1348 # If the wx file pathname is relative then make it absolute
ohair@314 1349 # because the webrev does a "cd" later on.
ohair@314 1350 #
ohair@314 1351 wxfile=$PWD/$argfile
ohair@314 1352 else
ohair@314 1353 wxfile=$argfile
ohair@314 1354 fi
ohair@314 1355
ohair@314 1356 $AWK '{ c = 1; print;
ohair@314 1357 while (getline) {
ohair@314 1358 if (NF == 0) { c = -c; continue }
ohair@314 1359 if (c > 0) print
ohair@314 1360 }
ohair@314 1361 }' $wxfile > $FLIST
ohair@314 1362
ohair@314 1363 print " Done."
ohair@314 1364 }
ohair@314 1365
ohair@314 1366 #
ohair@314 1367 # flist_from_teamware [ <args-to-putback-n> ]
ohair@314 1368 #
ohair@314 1369 # Generate the file list by extracting file names from a putback -n. Some
ohair@314 1370 # names may come from the "update/create" messages and others from the
ohair@314 1371 # "currently checked out" warning. Renames are detected here too. Extract
ohair@314 1372 # values for CODEMGR_WS and CODEMGR_PARENT from the output of the putback
ohair@314 1373 # -n as well, but remove them if they are already defined.
ohair@314 1374 #
ohair@314 1375 function flist_from_teamware
ohair@314 1376 {
ohair@314 1377 if [[ -n $codemgr_parent ]]; then
ohair@314 1378 if [[ ! -d $codemgr_parent/Codemgr_wsdata ]]; then
ohair@314 1379 print -u2 "parent $codemgr_parent doesn't look like a" \
ohair@314 1380 "valid teamware workspace"
ohair@314 1381 exit 1
ohair@314 1382 fi
ohair@314 1383 parent_args="-p $codemgr_parent"
ohair@314 1384 fi
ohair@314 1385
ohair@314 1386 print " File list from: 'putback -n $parent_args $*' ... \c"
ohair@314 1387
ohair@314 1388 putback -n $parent_args $* 2>&1 |
ohair@314 1389 $AWK '
ohair@314 1390 /^update:|^create:/ {print $2}
ohair@314 1391 /^Parent workspace:/ {printf("CODEMGR_PARENT=%s\n",$3)}
ohair@314 1392 /^Child workspace:/ {printf("CODEMGR_WS=%s\n",$3)}
ohair@314 1393 /^The following files are currently checked out/ {p = 1; next}
ohair@314 1394 NF == 0 {p=0 ; next}
ohair@314 1395 /^rename/ {old=$3}
ohair@314 1396 $1 == "to:" {print $2, old}
ohair@314 1397 /^"/ {next}
ohair@314 1398 p == 1 {print $1}' |
ohair@314 1399 sort -r -k 1,1 -u | sort > $FLIST
ohair@314 1400
ohair@314 1401 print " Done."
ohair@314 1402 }
ohair@314 1403
ohair@314 1404 function outgoing_from_mercurial_forest
ohair@314 1405 {
ohair@314 1406 hg foutgoing --template 'rev: {rev}\n' $OUTPWS | $FILTER | $AWK '
ohair@314 1407 BEGIN {ntree=0}
ohair@314 1408 /^comparing/ {next}
ohair@314 1409 /^no changes/ {next}
ohair@314 1410 /^searching/ {next}
ohair@314 1411 /^\[.*\]$/ {tree=substr($1,2,length($1)-2);
ohair@314 1412 trees[ntree++] = tree;
ohair@314 1413 revs[tree]=-1;
ohair@314 1414 next}
ohair@314 1415 /^rev:/ {rev=$2+0;
ohair@314 1416 if (revs[tree] == -1 || rev < revs[tree])
ohair@314 1417 { revs[tree] = rev; };
ohair@314 1418 next;}
ohair@314 1419 END {for (tree in trees)
ohair@314 1420 { rev=revs[trees[tree]];
mduigou@616 1421 if (rev > 0)
ohair@314 1422 {printf("%s %d\n",trees[tree],rev-1)}
ohair@314 1423 }}' | while read LINE
ohair@314 1424 do
ohair@314 1425 set - $LINE
ohair@314 1426 TREE=$1
ohair@314 1427 REV=$2
ohair@314 1428 A=`hg -R $CWS/$TREE log --rev $REV --template '{node}'`
ohair@314 1429 FSTAT_OPT="--rev $A"
ohair@314 1430 print "Revision: $A $REV" >> $FLIST
ohair@314 1431 treestatus $TREE
ohair@314 1432 done
ohair@314 1433 }
ohair@314 1434
ohair@314 1435 function flist_from_mercurial_forest
ohair@314 1436 {
ohair@314 1437 rm -f $FLIST
ohair@314 1438 if [ -z "$Nflag" ]; then
jgish@678 1439 print " File list from hg foutgoing $PWS ..."
ohair@314 1440 outgoing_from_mercurial_forest
ohair@314 1441 HG_LIST_FROM_COMMIT=1
ohair@314 1442 fi
ohair@314 1443 if [ ! -f $FLIST ]; then
ohair@314 1444 # hg commit hasn't been run see what is lying around
jgish@678 1445 print "\n No outgoing, perhaps you haven't commited."
jgish@678 1446 NO_OUTGOING=
jgish@678 1447 print " File list from hg fstatus -mard ...\c"
ohair@314 1448 FSTAT_OPT=
ohair@314 1449 fstatus
ohair@314 1450 HG_LIST_FROM_COMMIT=0
ohair@314 1451 fi
ohair@314 1452 print " Done."
ohair@314 1453 }
ohair@314 1454
ohair@314 1455 #
ohair@314 1456 # Used when dealing with the result of 'hg foutgoing'
ohair@314 1457 # When now go down the tree and generate the change list
ohair@314 1458 #
ohair@314 1459 function treestatus
ohair@314 1460 {
ohair@314 1461 TREE=$1
ohair@314 1462 HGCMD="hg -R $CWS/$TREE status $FSTAT_OPT"
mduigou@616 1463
ohair@314 1464 $HGCMD -mdn 2>/dev/null | $FILTER | while read F
ohair@314 1465 do
ohair@314 1466 echo $TREE/$F
ohair@314 1467 done >> $FLIST
ohair@314 1468
ohair@314 1469 # Then all the added files
jgish@678 1470 # But some of these could have been "moved" or renamed ones or copied ones
ohair@314 1471 # so let's make sure we get the proper info
ohair@314 1472 # hg status -aC will produce something like:
ohair@314 1473 # A subdir/File3
ohair@314 1474 # A subdir/File4
ohair@314 1475 # File4
ohair@314 1476 # A subdir/File5
ohair@314 1477 # The first and last are simple addition while the middle one
jgish@678 1478 # is a move/rename or a copy. We can't distinguish from a rename vs a copy
jgish@678 1479 # without also getting the status of removed files. The middle case above
jgish@678 1480 # is a rename if File4 is also shown a being removed. If File4 is not a
jgish@678 1481 # removed file, then the middle case is a copy from File4 to subdir/File4
jgish@678 1482 # FIXME - we're not distinguishing copy from rename
ohair@314 1483 $HGCMD -aC | $FILTER | while read LINE; do
ohair@314 1484 ldone=""
ohair@314 1485 while [ -z "$ldone" ]; do
ohair@314 1486 ldone="1"
ohair@314 1487 set - $LINE
ohair@314 1488 if [ $# -eq 2 -a "$1" == "A" ]; then
ohair@314 1489 AFILE=$2
ohair@314 1490 if read LINE2; then
ohair@314 1491 set - $LINE2
ohair@314 1492 if [ $# -eq 1 ]; then
ohair@314 1493 echo $TREE/$AFILE $TREE/$1 >>$FLIST
ohair@314 1494 elif [ $# -eq 2 ]; then
ohair@314 1495 echo $TREE/$AFILE >>$FLIST
ohair@314 1496 LINE=$LINE2
ohair@314 1497 ldone=""
ohair@314 1498 fi
ohair@314 1499 else
ohair@314 1500 echo $TREE/$AFILE >>$FLIST
ohair@314 1501 fi
ohair@314 1502 fi
ohair@314 1503 done
ohair@314 1504 done
ohair@314 1505 $HGCMD -rn | $FILTER | while read RFILE; do
ohair@314 1506 grep "$TREE/$RFILE" $FLIST >/dev/null
ohair@314 1507 if [ $? -eq 1 ]; then
ohair@314 1508 echo $TREE/$RFILE >>$FLIST
ohair@314 1509 fi
ohair@314 1510 done
ohair@314 1511 }
ohair@314 1512
ohair@314 1513 function fstatus
ohair@314 1514 {
ohair@314 1515 #
ohair@314 1516 # forest extension is still being changed. For instance the output
ohair@314 1517 # of fstatus used to no prepend the tree path to filenames, but
ohair@314 1518 # this has changed recently. AWK code below does try to handle both
ohair@314 1519 # cases
ohair@314 1520 #
ohair@314 1521 hg fstatus -mdn $FSTAT_OPT 2>/dev/null | $FILTER | $AWK '
ohair@314 1522 /^\[.*\]$/ {tree=substr($1,2,length($1)-2); next}
ohair@314 1523 $1 != "" {n=index($1,tree);
ohair@314 1524 if (n == 0)
ohair@314 1525 { printf("%s/%s\n",tree,$1)}
ohair@314 1526 else
ohair@314 1527 { printf("%s\n",$1)}}' >> $FLIST
ohair@314 1528
ohair@314 1529 #
ohair@314 1530 # There is a bug in the output of fstatus -aC on recent versions: it
ohair@314 1531 # inserts a space between the name of the tree and the filename of the
ohair@314 1532 # old file. e.g.:
ohair@314 1533 #
ohair@314 1534 # $ hg fstatus -aC
ohair@314 1535 # [.]
ohair@314 1536 #
ohair@314 1537 # [MyWS]
ohair@314 1538 # A MyWS/subdir/File2
ohair@314 1539 # MyWS/ File2
ohair@314 1540 #
ohair@314 1541 # [MyWS2]
ohair@314 1542 #
ohair@314 1543
ohair@314 1544 hg fstatus -aC $FSTAT_OPT 2>/dev/null | $FILTER | $AWK '
ohair@314 1545 /^\[.*\]$/ {tree=substr($1,2,length($1)-2); next}
ohair@314 1546 /^A .*/ {n=index($2,tree);
ohair@314 1547 if (n == 0)
ohair@314 1548 { printf("A %s/%s\n",tree,$2)}
ohair@314 1549 else
mduigou@616 1550 { printf("A %s\n",$2)};
ohair@314 1551 next}
ohair@314 1552 /^ / {n=index($1,tree);
ohair@314 1553 if (n == 0)
ohair@314 1554 { printf("%s/%s\n",tree,$1)}
ohair@314 1555 else
ohair@314 1556 { if (NF == 2)
ohair@314 1557 printf("%s/%s\n",tree,$2)
ohair@314 1558 else
ohair@314 1559 printf("%s\n",$1)
ohair@314 1560 };
ohair@314 1561 next}
ohair@314 1562 ' | while read LINE; do
ohair@314 1563 ldone=""
ohair@314 1564 while [ -z "$ldone" ]; do
ohair@314 1565 ldone="1"
ohair@314 1566 set - $LINE
ohair@314 1567 if [ $# -eq 2 -a "$1" == "A" ]; then
ohair@314 1568 AFILE=$2
ohair@314 1569 if read LINE2; then
ohair@314 1570 set - $LINE2
ohair@314 1571 if [ $# -eq 1 ]; then
ohair@314 1572 echo $AFILE $1 >>$FLIST
ohair@314 1573 elif [ $# -eq 2 ]; then
ohair@314 1574 echo $AFILE >>$FLIST
ohair@314 1575 LINE=$LINE2
ohair@314 1576 ldone=""
ohair@314 1577 fi
ohair@314 1578 else
ohair@314 1579 echo $AFILE >>$FLIST
ohair@314 1580 fi
ohair@314 1581 fi
ohair@314 1582 done
ohair@314 1583 done
ohair@314 1584 hg fstatus -rn $FSTAT_OPT 2>/dev/null | $FILTER | $AWK '
ohair@314 1585 /^\[.*\]$/ {tree=substr($1,2,length($1)-2); next}
ohair@314 1586 $1 != "" {n=index($1,tree);
ohair@314 1587 if (n == 0)
ohair@314 1588 { printf("%s/%s\n",tree,$1)}
ohair@314 1589 else
ohair@314 1590 { printf("%s\n",$1)}}' | while read RFILE; do
ohair@314 1591 grep "$RFILE" $FLIST >/dev/null
ohair@314 1592 if [ $? -eq 1 ]; then
ohair@314 1593 echo $RFILE >>$FLIST
ohair@314 1594 fi
ohair@314 1595 done
ohair@314 1596 }
ohair@314 1597
ohair@314 1598 #
ohair@314 1599 # flist_from_mercurial $PWS
ohair@314 1600 #
ohair@314 1601 # Only local file based repositories are supported at present
ohair@314 1602 # since even though we can determine the list from the parent finding
ohair@314 1603 # the changes is harder.
ohair@314 1604 #
ohair@314 1605 # We first look for any outgoing files, this is for when the user has
ohair@314 1606 # run hg commit. If we don't find any then we look with hg status.
ohair@314 1607 #
ohair@314 1608 # We need at least one of default-push or default paths set in .hg/hgrc
ohair@314 1609 # If neither are set we don't know who to compare with.
ohair@314 1610
mduigou@616 1611 function flist_from_mercurial
ohair@314 1612 {
ohair@314 1613 # if [ "${PWS##ssh://}" != "$PWS" -o \
ohair@314 1614 # "${PWS##http://}" != "$PWS" -o \
ohair@314 1615 # "${PWS##https://}" != "$PWS" ]; then
ohair@314 1616 # print "Remote Mercurial repositories not currently supported."
ohair@314 1617 # print "Set default and/or default-push to a local repository"
ohair@314 1618 # exit
ohair@314 1619 # fi
ohair@314 1620 if [[ -n $forestflag ]]; then
ohair@314 1621 HG_LIST_FROM_COMMIT=
ohair@314 1622 flist_from_mercurial_forest
ohair@314 1623 else
ohair@314 1624 STATUS_REV=
ohair@314 1625 if [[ -n $rflag ]]; then
ohair@314 1626 STATUS_REV="--rev $PARENT_REV"
ohair@314 1627 elif [[ -n $OUTREV ]]; then
ohair@314 1628 STATUS_REV="--rev $OUTREV"
ohair@314 1629 else
ohair@314 1630 # hg commit hasn't been run see what is lying around
ohair@314 1631 print "\n No outgoing, perhaps you haven't commited."
jgish@678 1632 NO_OUTGOING=
ohair@314 1633 fi
ohair@314 1634 # First let's list all the modified or deleted files
ohair@314 1635
ohair@314 1636 hg status $STATUS_REV -mdn | $FILTER > $FLIST
ohair@314 1637
ohair@314 1638 # Then all the added files
ohair@314 1639 # But some of these could have been "moved" or renamed ones
ohair@314 1640 # so let's make sure we get the proper info
ohair@314 1641 # hg status -aC will produce something like:
ohair@314 1642 # A subdir/File3
ohair@314 1643 # A subdir/File4
ohair@314 1644 # File4
ohair@314 1645 # A subdir/File5
jgish@678 1646 # The first and last are simple addition while the middle one
jgish@678 1647 # is a move/rename or a copy. We can't distinguish from a rename vs a copy
jgish@678 1648 # without also getting the status of removed files. The middle case above
jgish@678 1649 # is a rename if File4 is also shown a being removed. If File4 is not a
jgish@678 1650 # removed file, then the middle case is a copy from File4 to subdir/File4
jgish@678 1651 # FIXME - we're not distinguishing copy from rename
ohair@314 1652
ohair@314 1653 hg status $STATUS_REV -aC | $FILTER >$FLIST.temp
ohair@314 1654 while read LINE; do
ohair@314 1655 ldone=""
ohair@314 1656 while [ -z "$ldone" ]; do
ohair@314 1657 ldone="1"
ohair@314 1658 set - $LINE
ohair@314 1659 if [ $# -eq 2 -a "$1" == "A" ]; then
ohair@314 1660 AFILE=$2
ohair@314 1661 if read LINE2; then
ohair@314 1662 set - $LINE2
ohair@314 1663 if [ $# -eq 1 ]; then
ohair@314 1664 echo $AFILE $1 >>$FLIST
ohair@314 1665 elif [ $# -eq 2 ]; then
ohair@314 1666 echo $AFILE >>$FLIST
ohair@314 1667 LINE=$LINE2
ohair@314 1668 ldone=""
ohair@314 1669 fi
ohair@314 1670 else
ohair@314 1671 echo $AFILE >>$FLIST
ohair@314 1672 fi
ohair@314 1673 fi
ohair@314 1674 done
ohair@314 1675 done < $FLIST.temp
ohair@314 1676 hg status $STATUS_REV -rn | $FILTER > $FLIST.temp
ohair@314 1677 while read RFILE; do
ohair@314 1678 grep "$RFILE" $FLIST >/dev/null
ohair@314 1679 if [ $? -eq 1 ]; then
ohair@314 1680 echo $RFILE >>$FLIST
ohair@314 1681 fi
ohair@314 1682 done < $FLIST.temp
ohair@314 1683 rm -f $FLIST.temp
ohair@314 1684 fi
ohair@314 1685 }
ohair@314 1686
ohair@314 1687 function env_from_flist
ohair@314 1688 {
ohair@314 1689 [[ -r $FLIST ]] || return
ohair@314 1690
ohair@314 1691 #
ohair@314 1692 # Use "eval" to set env variables that are listed in the file
ohair@314 1693 # list. Then copy those into our local versions of those
ohair@314 1694 # variables if they have not been set already.
ohair@314 1695 #
ohair@314 1696 eval `sed -e "s/#.*$//" $FLIST | grep = `
ohair@314 1697
ohair@314 1698 [[ -z $codemgr_ws && -n $CODEMGR_WS ]] && codemgr_ws=$CODEMGR_WS
ohair@314 1699
ohair@314 1700 #
ohair@314 1701 # Check to see if CODEMGR_PARENT is set in the flist file.
ohair@314 1702 #
ohair@314 1703 [[ -z $codemgr_parent && -n $CODEMGR_PARENT ]] && \
ohair@314 1704 codemgr_parent=$CODEMGR_PARENT
ohair@314 1705 }
ohair@314 1706
ohair@314 1707 #
ohair@314 1708 # detect_scm
ohair@314 1709 #
ohair@314 1710 # We dynamically test the SCM type; this allows future extensions to
ohair@314 1711 # new SCM types
ohair@314 1712 #
ohair@314 1713 function detect_scm
ohair@314 1714 {
ohair@314 1715 #
ohair@314 1716 # If CODEMGR_WS is specified in the flist file, we assume teamware.
ohair@314 1717 #
ohair@314 1718 if [[ -r $FLIST ]]; then
ohair@314 1719 egrep '^CODEMGR_WS=' $FLIST > /dev/null 2>&1
ohair@314 1720 if [[ $? -eq 0 ]]; then
ohair@314 1721 print "teamware"
ohair@314 1722 return
ohair@314 1723 fi
ohair@314 1724 fi
ohair@314 1725
ohair@314 1726 #
ohair@314 1727 # The presence of $CODEMGR_WS and a Codemgr_wsdata directory
ohair@314 1728 # is our clue that this is a teamware workspace.
ohair@314 1729 # Same if true if current directory has a Codemgr_wsdata sub-dir
ohair@314 1730 #
ohair@314 1731 if [[ -z "$CODEMGR_WS" ]]; then
ohair@314 1732 CODEMGR_WS=`workspace name 2>/dev/null`
ohair@314 1733 fi
ohair@314 1734
ohair@314 1735 if [[ -n $CODEMGR_WS && -d "$CODEMGR_WS/Codemgr_wsdata" ]]; then
ohair@314 1736 print "teamware"
ohair@314 1737 elif [[ -d $PWD/Codemgr_wsdata ]]; then
ohair@314 1738 print "teamware"
ohair@314 1739 elif hg root >/dev/null ; then
ohair@314 1740 print "mercurial"
ohair@314 1741 else
ohair@314 1742 print "unknown"
ohair@314 1743 fi
ohair@314 1744 }
ohair@314 1745
ohair@314 1746 #
ohair@314 1747 # Extract the parent workspace from the Codemgr_wsdata/parent file
ohair@314 1748 #
ohair@314 1749 function parent_from_teamware
ohair@314 1750 {
ohair@314 1751 if [[ -f "$1/Codemgr_wsdata/parent" ]]; then
ohair@314 1752 tail -1 "$1/Codemgr_wsdata/parent"
ohair@314 1753 fi
ohair@314 1754 }
ohair@314 1755
ohair@314 1756 function look_for_prog
ohair@314 1757 {
ohair@314 1758 typeset path
ohair@314 1759 typeset ppath
ohair@314 1760 typeset progname=$1
ohair@314 1761
ohair@314 1762 DEVTOOLS=
ohair@314 1763 OS=`uname`
ohair@314 1764 if [[ "$OS" == "SunOS" ]]; then
ohair@314 1765 DEVTOOLS="/java/devtools/`uname -p`/bin"
ohair@314 1766 elif [[ "$OS" == "Linux" ]]; then
ohair@314 1767 DEVTOOLS="/java/devtools/linux/bin"
ohair@314 1768 fi
mduigou@616 1769
ohair@314 1770 ppath=$PATH
ohair@314 1771 ppath=$ppath:/usr/sfw/bin:/usr/bin:/usr/sbin
ohair@314 1772 ppath=$ppath:/opt/teamware/bin:/opt/onbld/bin
ohair@314 1773 ppath=$ppath:/opt/onbld/bin/`uname -p`
ohair@314 1774 ppath=$ppath:/java/devtools/share/bin:$DEVTOOLS
ohair@314 1775
ohair@314 1776 PATH=$ppath prog=`whence $progname`
ohair@314 1777 if [[ -n $prog ]]; then
ohair@314 1778 print $prog
ohair@314 1779 fi
ohair@314 1780 }
ohair@314 1781
ohair@314 1782 function build_old_new_teamware
ohair@314 1783 {
ohair@314 1784 # If the child's version doesn't exist then
ohair@314 1785 # get a readonly copy.
ohair@314 1786
ohair@314 1787 if [[ ! -f $F && -f SCCS/s.$F ]]; then
ohair@314 1788 $SCCS get -s $F
ohair@314 1789 fi
ohair@314 1790
ohair@314 1791 #
ohair@314 1792 # Snag new version of file.
ohair@314 1793 #
ohair@314 1794 rm -f $newdir/$DIR/$F
ohair@314 1795 cp $F $newdir/$DIR/$F
ohair@314 1796
ohair@314 1797 #
ohair@314 1798 # Get the parent's version of the file. First see whether the
ohair@314 1799 # child's version is checked out and get the parent's version
ohair@314 1800 # with keywords expanded or unexpanded as appropriate.
ohair@314 1801 #
ohair@314 1802 if [ -f $PWS/$PDIR/SCCS/s.$PF -o \
ohair@314 1803 -f $PWS/$PDIR/SCCS/p.$PF ]; then
ohair@314 1804 rm -f $olddir/$PDIR/$PF
ohair@314 1805 if [ -f SCCS/p.$F ]; then
ohair@314 1806 $SCCS get -s -p -k $PWS/$PDIR/$PF \
ohair@314 1807 > $olddir/$PDIR/$PF
ohair@314 1808 else
ohair@314 1809 $SCCS get -s -p $PWS/$PDIR/$PF \
ohair@314 1810 > $olddir/$PDIR/$PF
ohair@314 1811 fi
ohair@314 1812 else
ohair@314 1813 if [[ -f $PWS/$PDIR/$PF ]]; then
ohair@314 1814 # Parent is not a real workspace, but just a raw
ohair@314 1815 # directory tree - use the file that's there as
ohair@314 1816 # the old file.
ohair@314 1817
ohair@314 1818 rm -f $olddir/$DIR/$F
ohair@314 1819 cp $PWS/$PDIR/$PF $olddir/$DIR/$F
ohair@314 1820 fi
ohair@314 1821 fi
ohair@314 1822 }
ohair@314 1823
ohair@314 1824 #
ohair@314 1825 # Find the parent for $1
ohair@314 1826 #
ohair@314 1827 function find_outrev
ohair@314 1828 {
ohair@314 1829 crev=$1
ohair@314 1830 prev=`hg log -r $crev --template '{parents}\n'`
ohair@314 1831 if [[ -z "$prev" ]]
ohair@314 1832 then
ohair@314 1833 # No specific parent means previous changeset is parent
ohair@314 1834 prev=`expr $crev - 1`
ohair@314 1835 else
ohair@314 1836 # Format is either of the following two:
ohair@314 1837 # 546:7df6fcf1183b
ohair@314 1838 # 548:16f1915bb5cd 547:ffaa4e775815
ohair@314 1839 prev=`echo $prev | sed -e 's/\([0-9]*\):.*/\1/'`
ohair@314 1840 fi
ohair@314 1841 print $prev
ohair@314 1842 }
ohair@314 1843
ohair@314 1844 function extract_ssh_infos
ohair@314 1845 {
ohair@314 1846 CMD=$1
ohair@314 1847 if expr "$CMD" : 'ssh://[^/]*@' >/dev/null; then
ohair@314 1848 ssh_user=`echo $CMD | sed -e 's/ssh:\/\/\(.*\)@.*/\1/'`
ohair@314 1849 ssh_host=`echo $CMD | sed -e 's/ssh:\/\/.*@\([^/]*\)\/.*/\1/'`
ohair@314 1850 ssh_dir=`echo $CMD | sed -e 's/ssh:\/\/.*@[^/]*\/\(.*\)/\1/'`
ohair@314 1851 else
ohair@314 1852 ssh_user=
ohair@314 1853 ssh_host=`echo $CMD | sed -e 's/ssh:\/\/\([^/]*\)\/.*/\1/'`
ohair@314 1854 ssh_dir=`echo $CMD | sed -e 's/ssh:\/\/[^/]*\/\(.*\)/\1/'`
ohair@314 1855 fi
mduigou@616 1856
ohair@314 1857 }
ohair@314 1858
ohair@314 1859 function build_old_new_mercurial
ohair@314 1860 {
ohair@314 1861 olddir=$1
ohair@314 1862 newdir=$2
ohair@314 1863 DIR=$3
ohair@314 1864 F=$4
ohair@314 1865 #
ohair@314 1866 # new version of the file.
ohair@314 1867 #
ohair@314 1868 rm -rf $newdir/$DIR/$F
ohair@314 1869 if [ -f $F ]; then
ohair@314 1870 cp $F $newdir/$DIR/$F
ohair@314 1871 fi
ohair@314 1872
ohair@314 1873 #
ohair@314 1874 # Old version of the file.
ohair@314 1875 #
ohair@314 1876 rm -rf $olddir/$DIR/$F
ohair@314 1877
ohair@314 1878 if [ -n "$PWS" ]; then
ohair@314 1879 if expr "$PWS" : 'ssh://' >/dev/null
ohair@314 1880 then
ohair@314 1881 extract_ssh_infos $PWS
ohair@314 1882 if [ -n "$ssh_user" ]; then
ohair@314 1883 parent="ssh -l $ssh_user $ssh_host hg -R $ssh_dir --cwd $ssh_dir"
ohair@314 1884 else
ohair@314 1885 parent="ssh $ssh_host hg -R $ssh_dir --cwd $ssh_dir"
ohair@314 1886 fi
ohair@314 1887 else
ohair@314 1888 parent="hg -R $PWS --cwd $PWS"
ohair@314 1889 fi
ohair@314 1890 else
ohair@314 1891 parent=""
ohair@314 1892 fi
ohair@314 1893
ohair@314 1894 if [ -z "$rename" ]; then
ohair@314 1895 if [ -n "$rflag" ]; then
ohair@314 1896 parentrev=$PARENT_REV
ohair@314 1897 elif [ "$HG_LIST_FROM_COMMIT" -eq 1 ]; then
ohair@314 1898 parentrev=$OUTREV
ohair@314 1899 else
ohair@314 1900 if [[ -n $HG_BRANCH ]]; then
ohair@314 1901 parentrev=$HG_BRANCH
ohair@314 1902 else
ohair@314 1903 parentrev="tip"
ohair@314 1904 fi
ohair@314 1905 fi
ohair@314 1906
ohair@314 1907 if [ -n "$parentrev" ]; then
ohair@314 1908 if [ -z "$parent" ]; then
ohair@314 1909 hg cat --rev $parentrev --output $olddir/$DIR/$F $F 2>/dev/null
ohair@314 1910 else
ohair@314 1911 # when specifying a workspace we have to provide
ohair@314 1912 # the full path
ohair@314 1913 $parent cat --rev $parentrev --output $olddir/$DIR/$F $DIR/$F 2>/dev/null
ohair@314 1914 fi
ohair@314 1915 fi
ohair@314 1916 else
jgish@678 1917 # It's a rename (or a move), or a copy, so let's make sure we move
ohair@314 1918 # to the right directory first, then restore it once done
ohair@314 1919 current_dir=`pwd`
ohair@314 1920 cd $CWS/$PDIR
ohair@314 1921 if [ -n "$rflag" ]; then
ohair@314 1922 parentrev=$PARENT_REV
ohair@314 1923 elif [ "$HG_LIST_FROM_COMMIT" -eq 1 ]; then
ohair@314 1924 parentrev=$OUTREV
ohair@314 1925 fi
ohair@314 1926 if [ -z "$parentrev" ]; then
ohair@314 1927 parentrev=`hg log -l1 $PF | $AWK -F: '/changeset/ {print $2}'`
ohair@314 1928 fi
ohair@314 1929 if [ -n "$parentrev" ]; then
ohair@314 1930 mkdir -p $olddir/$PDIR
ohair@314 1931 if [ -z "$parent" ]; then
ohair@314 1932 hg cat --rev $parentrev --output $olddir/$PDIR/$PF $PF 2>/dev/null
ohair@314 1933 else
ohair@314 1934 $parent cat --rev $parentrev --output $olddir/$PDIR/$PF $PDIR/$PF 2>/dev/null
ohair@314 1935 fi
ohair@314 1936 fi
ohair@314 1937 cd $current_dir
ohair@314 1938 fi
ohair@314 1939 }
ohair@314 1940
ohair@314 1941 function build_old_new
ohair@314 1942 {
ohair@314 1943 if [[ $SCM_MODE == "teamware" ]]; then
ohair@314 1944 build_old_new_teamware $@
ohair@314 1945 fi
ohair@314 1946
ohair@314 1947 if [[ $SCM_MODE == "mercurial" ]]; then
ohair@314 1948 build_old_new_mercurial $@
ohair@314 1949 fi
ohair@314 1950 }
ohair@314 1951
ohair@314 1952
ohair@314 1953 #
ohair@314 1954 # Usage message.
ohair@314 1955 #
ohair@314 1956 function usage
ohair@314 1957 {
ohair@314 1958 print "Usage:\twebrev [common-options]
ohair@314 1959 webrev [common-options] ( <file> | - )
ohair@314 1960 webrev [common-options] -w <wx file>
ohair@314 1961 webrev [common-options] -l [arguments to 'putback']
ohair@314 1962
ohair@314 1963 Options:
ohair@314 1964 -v: Print the version of this tool.
ohair@314 1965 -b: Do not ignore changes in the amount of white space.
ohair@314 1966 -c <CR#>: Include link to CR (aka bugid) in the main page.
ohair@314 1967 -O: Print bugids/arc cases suitable for OpenJDK.
ohair@314 1968 -i <filename>: Include <filename> in the index.html file.
ohair@314 1969 -o <outdir>: Output webrev to specified directory.
ohair@314 1970 -p <compare-against>: Use specified parent wkspc or basis for comparison
ohair@314 1971 -w <wxfile>: Use specified wx active file.
ohair@314 1972 -u <username>: Use that username instead of 'guessing' one.
ohair@314 1973 -m: Forces the use of Mercurial
ohair@314 1974 -t: Forces the use of Teamware
ohair@314 1975
ohair@314 1976 Mercurial only options:
ohair@314 1977 -r rev: Compare against a specified revision
ohair@314 1978 -N: Skip 'hg outgoing', use only 'hg status'
ohair@314 1979 -f: Use the forest extension
ohair@314 1980
ohair@314 1981 Environment:
ohair@314 1982 WDIR: Control the output directory.
ohair@314 1983 WEBREV_BUGURL: Control the URL prefix for bugids.
ohair@314 1984 WEBREV_SACURL: Control the URL prefix for ARC cases.
ohair@314 1985
ohair@314 1986 SCM Environment:
ohair@314 1987 Teamware: CODEMGR_WS: Workspace location.
ohair@314 1988 Teamware: CODEMGR_PARENT: Parent workspace location.
ohair@314 1989
ohair@314 1990 "
ohair@314 1991
ohair@314 1992 exit 2
ohair@314 1993 }
ohair@314 1994
ohair@314 1995 #
ohair@314 1996 #
ohair@314 1997 # Main program starts here
ohair@314 1998 #
ohair@314 1999 #
ohair@314 2000 LANG="C"
ohair@314 2001 LC_ALL="C"
ohair@314 2002 export LANG LC_ALL
ohair@314 2003 trap "rm -f /tmp/$$.* ; exit" 0 1 2 3 15
ohair@314 2004
ohair@314 2005 set +o noclobber
ohair@314 2006
ohair@314 2007 [[ -z $WDIFF ]] && WDIFF=`look_for_prog wdiff`
ohair@314 2008 [[ -z $WX ]] && WX=`look_for_prog wx`
ohair@314 2009 [[ -z $CODEREVIEW ]] && CODEREVIEW=`look_for_prog codereview`
ohair@314 2010 [[ -z $PS2PDF ]] && PS2PDF=`look_for_prog ps2pdf`
ohair@314 2011 [[ -z $PERL ]] && PERL=`look_for_prog perl`
ohair@314 2012 [[ -z $SCCS ]] && SCCS=`look_for_prog sccs`
ohair@314 2013 [[ -z $AWK ]] && AWK=`look_for_prog nawk`
ohair@314 2014 [[ -z $AWK ]] && AWK=`look_for_prog gawk`
ohair@314 2015 [[ -z $AWK ]] && AWK=`look_for_prog awk`
ohair@314 2016 [[ -z $WSPACE ]] && WSPACE=`look_for_prog workspace`
ohair@314 2017 [[ -z $JAR ]] && JAR=`look_for_prog jar`
ohair@314 2018 [[ -z $ZIP ]] && ZIP=`look_for_prog zip`
ohair@314 2019 [[ -z $GETENT ]] && GETENT=`look_for_prog getent`
ohair@314 2020 [[ -z $WGET ]] && WGET=`look_for_prog wget`
ohair@314 2021
ohair@314 2022 if uname | grep CYGWIN >/dev/null
ohair@314 2023 then
ohair@314 2024 ISWIN=1
ohair@314 2025 # Under windows mercurial outputs '\' instead of '/'
ohair@314 2026 FILTER="tr '\\\\' '/'"
ohair@314 2027 else
ohair@314 2028 FILTER="cat"
ohair@314 2029 fi
ohair@314 2030
ohair@314 2031 if [[ ! -x $PERL ]]; then
ohair@314 2032 print -u2 "Error: No perl interpreter found. Exiting."
ohair@314 2033 exit 1
ohair@314 2034 fi
ohair@314 2035
ohair@314 2036 #
ohair@314 2037 # These aren't fatal, but we want to note them to the user.
ohair@314 2038 # We don't warn on the absence of 'wx' until later when we've
ohair@314 2039 # determined that we actually need to try to invoke it.
ohair@314 2040 #
ohair@314 2041 # [[ ! -x $CODEREVIEW ]] && print -u2 "WARNING: codereview(1) not found."
ohair@314 2042 # [[ ! -x $PS2PDF ]] && print -u2 "WARNING: ps2pdf(1) not found."
ohair@314 2043 # [[ ! -x $WDIFF ]] && print -u2 "WARNING: wdiff not found."
ohair@314 2044
ohair@314 2045 # Declare global total counters.
ohair@314 2046 integer TOTL TINS TDEL TMOD TUNC
ohair@314 2047
ohair@314 2048 flist_mode=
ohair@314 2049 flist_file=
ohair@314 2050 bflag=
ohair@314 2051 iflag=
ohair@314 2052 oflag=
ohair@314 2053 pflag=
ohair@314 2054 uflag=
ohair@314 2055 lflag=
ohair@314 2056 wflag=
ohair@314 2057 Oflag=
ohair@314 2058 rflag=
ohair@314 2059 Nflag=
ohair@314 2060 forestflag=
ohair@314 2061 while getopts "c:i:o:p:r:u:lmtwONvfb" opt
ohair@314 2062 do
ohair@314 2063 case $opt in
ohair@314 2064 b) bflag=1;;
ohair@314 2065
ohair@314 2066 i) iflag=1
ohair@314 2067 INCLUDE_FILE=$OPTARG;;
ohair@314 2068
ohair@314 2069 o) oflag=1
ohair@314 2070 WDIR=$OPTARG;;
ohair@314 2071
ohair@314 2072 p) pflag=1
ohair@314 2073 codemgr_parent=$OPTARG;;
ohair@314 2074
ohair@314 2075 u) uflag=1
ohair@314 2076 username=$OPTARG;;
ohair@314 2077
ohair@314 2078 c) if [[ -z $CRID ]]; then
ohair@314 2079 CRID=$OPTARG
ohair@314 2080 else
ohair@314 2081 CRID="$CRID $OPTARG"
ohair@314 2082 fi;;
ohair@314 2083
ohair@314 2084 m) SCM_MODE="mercurial";;
ohair@314 2085
ohair@314 2086 t) SCM_MODE="teamware";;
ohair@314 2087
ohair@314 2088 #
ohair@314 2089 # If -l has been specified, we need to abort further options
ohair@314 2090 # processing, because subsequent arguments are going to be
ohair@314 2091 # arguments to 'putback -n'.
ohair@314 2092 #
ohair@314 2093 l) lflag=1
ohair@314 2094 break;;
ohair@314 2095
ohair@314 2096 w) wflag=1;;
ohair@314 2097
ohair@314 2098 O) Oflag=1;;
ohair@314 2099
ohair@314 2100 N) Nflag=1;;
ohair@314 2101
ohair@314 2102 f) forestflag=1;;
ohair@314 2103
ohair@314 2104 r) rflag=1
ohair@314 2105 PARENT_REV=$OPTARG;;
ohair@314 2106
ohair@314 2107 v) print "$0 version: $WEBREV_UPDATED";;
mduigou@616 2108
ohair@314 2109
ohair@314 2110 ?) usage;;
ohair@314 2111 esac
ohair@314 2112 done
ohair@314 2113
ohair@314 2114 FLIST=/tmp/$$.flist
ohair@314 2115
ohair@314 2116 if [[ -n $wflag && -n $lflag ]]; then
ohair@314 2117 usage
ohair@314 2118 fi
ohair@314 2119
ohair@314 2120 if [[ -n $forestflag && -n $rflag ]]; then
ohair@314 2121 print "The -r <rev> flag is incompatible with the use of forests"
ohair@314 2122 exit 2
ohair@314 2123 fi
ohair@314 2124
ohair@314 2125 #
ohair@314 2126 # If this manually set as the parent, and it appears to be an earlier webrev,
ohair@314 2127 # then note that fact and set the parent to the raw_files/new subdirectory.
ohair@314 2128 #
ohair@314 2129 if [[ -n $pflag && -d $codemgr_parent/raw_files/new ]]; then
ohair@314 2130 parent_webrev="$codemgr_parent"
ohair@314 2131 codemgr_parent="$codemgr_parent/raw_files/new"
ohair@314 2132 fi
ohair@314 2133
ohair@314 2134 if [[ -z $wflag && -z $lflag ]]; then
ohair@314 2135 shift $(($OPTIND - 1))
ohair@314 2136
ohair@314 2137 if [[ $1 == "-" ]]; then
ohair@314 2138 cat > $FLIST
ohair@314 2139 flist_mode="stdin"
ohair@314 2140 flist_done=1
ohair@314 2141 shift
ohair@314 2142 elif [[ -n $1 ]]; then
ohair@314 2143 if [[ ! -r $1 ]]; then
ohair@314 2144 print -u2 "$1: no such file or not readable"
ohair@314 2145 usage
ohair@314 2146 fi
ohair@314 2147 cat $1 > $FLIST
ohair@314 2148 flist_mode="file"
ohair@314 2149 flist_file=$1
ohair@314 2150 flist_done=1
ohair@314 2151 shift
ohair@314 2152 else
ohair@314 2153 flist_mode="auto"
ohair@314 2154 fi
ohair@314 2155 fi
ohair@314 2156
ohair@314 2157 #
ohair@314 2158 # Before we go on to further consider -l and -w, work out which SCM we think
ohair@314 2159 # is in use.
ohair@314 2160 #
ohair@314 2161 if [[ -z $SCM_MODE ]]; then
ohair@314 2162 SCM_MODE=`detect_scm $FLIST`
ohair@314 2163 fi
ohair@314 2164 if [[ $SCM_MODE == "unknown" ]]; then
ohair@314 2165 print -u2 "Unable to determine SCM type currently in use."
ohair@314 2166 print -u2 "For teamware: webrev looks for \$CODEMGR_WS either in"
ohair@314 2167 print -u2 " the environment or in the file list."
ohair@314 2168 print -u2 "For mercurial: webrev runs 'hg root'."
ohair@314 2169 exit 1
ohair@314 2170 fi
ohair@314 2171
ohair@314 2172 print -u2 " SCM detected: $SCM_MODE"
ohair@314 2173
ohair@314 2174
ohair@314 2175 if [[ $SCM_MODE == "mercurial" ]]; then
ohair@314 2176 #
ohair@314 2177 # determine Workspace and parent workspace paths
ohair@314 2178 #
ohair@314 2179 CWS=`hg root | $FILTER`
ohair@314 2180 if [[ -n $pflag && -z "$PWS" ]]; then
ohair@314 2181 OUTPWS=$codemgr_parent
ohair@314 2182 # Let's try to expand it if it's an alias defined in [paths]
ohair@314 2183 tmp=`hg path $OUTPWS 2>/dev/null | $FILTER`
ohair@314 2184 if [[ -n $tmp ]]; then
ohair@314 2185 OUTPWS="$tmp"
ohair@314 2186 fi
ohair@314 2187 if [[ -n $rflag ]]; then
ohair@314 2188 if expr "$codemgr_parent" : 'ssh://.*' >/dev/null; then
ohair@314 2189 PWS=$codemgr_parent
ohair@314 2190 else
ohair@314 2191 PWS=`hg -R "$codemgr_parent" root 2>/dev/null | $FILTER`
ohair@314 2192 fi
ohair@314 2193 fi
ohair@314 2194 fi
ohair@314 2195 #
ohair@314 2196 # OUTPWS is the parent repository to use when using 'hg outgoing'
ohair@314 2197 #
ohair@314 2198 if [[ -z $Nflag ]]; then
ohair@314 2199 if [[ -n $forestflag ]]; then
ohair@314 2200 #
ohair@314 2201 # for forest we have to rely on properly set default and
ohair@314 2202 # default-push because they can be different from the top one.
ohair@314 2203 # unless of course it was explicitely speficied with -p
ohair@314 2204 if [[ -z $pflag ]]; then
ohair@314 2205 OUTPWS=
ohair@314 2206 fi
ohair@314 2207 else
ohair@314 2208 #
ohair@314 2209 # Unfortunately mercurial is bugged and doesn't handle
ohair@314 2210 # aliases correctly in 'hg path default'
ohair@314 2211 # So let's do it ourselves. Sigh...
ohair@314 2212 if [[ -z "$OUTPWS" ]]; then
ohair@314 2213 OUTPWS=`grep default-push $CWS/.hg/hgrc | $AWK '{print $3}' | $FILTER`
ohair@314 2214 fi
ohair@314 2215 # Still empty, means no default-push
ohair@314 2216 if [[ -z "$OUTPWS" ]]; then
ohair@314 2217 OUTPWS=`grep 'default =' $CWS/.hg/hgrc | $AWK '{print $3}' | $FILTER`
ohair@314 2218 fi
ohair@314 2219 # Let's try to expand it if it's an alias defined in [paths]
ohair@314 2220 tmp=`hg path $OUTPWS 2>/dev/null | $FILTER`
ohair@314 2221 if [[ -n $tmp ]]; then
ohair@314 2222 OUTPWS="$tmp"
ohair@314 2223 fi
ohair@314 2224 fi
ohair@314 2225 fi
ohair@314 2226 #
ohair@314 2227 # OUTPWS may contain username:password, let's make sure we remove the
ohair@314 2228 # sensitive information before we print out anything in the HTML
ohair@314 2229 #
ohair@314 2230 OUTPWS2=$OUTPWS
ohair@314 2231 if [[ -n $OUTPWS ]]; then
ohair@314 2232 if [[ `expr "$OUTPWS" : '.*://[^/]*@.*'` -gt 0 ]]; then
ohair@314 2233 # Remove everything between '://' and '@'
ohair@314 2234 OUTPWS2=`echo $OUTPWS | sed -e 's/\(.*:\/\/\).*@\(.*\)/\1\2/'`
ohair@314 2235 fi
ohair@314 2236 fi
ohair@314 2237
ohair@314 2238 if [[ -z $HG_BRANCH ]]; then
ohair@314 2239 HG_BRANCH=`hg branch`
ohair@314 2240 if [ "$HG_BRANCH" == "default" ]; then
ohair@314 2241 #
ohair@314 2242 # 'default' means no particular branch, so let's cancel that
ohair@314 2243 #
ohair@314 2244 HG_BRANCH=
ohair@314 2245 fi
ohair@314 2246 fi
ohair@314 2247
ohair@314 2248 if [[ -z $forestflag ]]; then
ohair@314 2249 if [[ -z $Nflag ]]; then
ohair@314 2250 #
ohair@314 2251 # If no "-N", always do "hg outgoing" against parent
ohair@314 2252 # repository to determine list of outgoing revisions.
ohair@314 2253 #
ohair@314 2254 ALL_CREV=`hg outgoing -q --template '{rev}\n' $OUTPWS | sort -n`
ohair@314 2255 if [[ -n $ALL_CREV ]]; then
ohair@314 2256 FIRST_CREV=`echo "$ALL_CREV" | head -1`
ohair@314 2257 #
ohair@314 2258 # If no "-r", choose revision to compare against by
ohair@314 2259 # finding the latest revision not in the outgoing list.
ohair@314 2260 #
ohair@314 2261 if [[ -z $rflag ]]; then
ohair@314 2262 OUTREV=`find_outrev "$FIRST_CREV"`
ohair@314 2263 if [[ -n $OUTREV ]]; then
ohair@314 2264 HG_LIST_FROM_COMMIT=1
ohair@314 2265 fi
ohair@314 2266 fi
ohair@314 2267 fi
ohair@314 2268 elif [[ -n $rflag ]]; then
ohair@314 2269 #
ohair@314 2270 # If skipping "hg outgoing" but still comparing against a
ohair@314 2271 # specific revision (not the tip), set revision for comment
ohair@314 2272 # accumulation.
ohair@314 2273 #
ohair@314 2274 FIRST_CREV=`hg log --rev $PARENT_REV --template '{rev}'`
ohair@314 2275 FIRST_CREV=`expr $FIRST_CREV + 1`
ohair@314 2276 fi
ohair@314 2277 fi
ohair@314 2278 #Let's check if a merge is needed, if so, issue a warning
ohair@314 2279 PREV=`hg parent | grep '^tag:.*tip$'`
ohair@314 2280 if [[ -z $PREV ]]; then
ohair@314 2281 print "WARNING: parent rev is not tip. Maybe an update or merge is needed"
ohair@314 2282 fi
ohair@314 2283 fi
ohair@314 2284
ohair@314 2285 if [[ -n $lflag ]]; then
ohair@314 2286 #
ohair@314 2287 # If the -l flag is given instead of the name of a file list,
ohair@314 2288 # then generate the file list by extracting file names from a
ohair@314 2289 # putback -n.
ohair@314 2290 #
ohair@314 2291 shift $(($OPTIND - 1))
ohair@314 2292 if [[ $SCM_MODE == "teamware" ]]; then
ohair@314 2293 flist_from_teamware "$*"
ohair@314 2294 elif [[ $SCM_MODE == "mercurial" ]]; then
ohair@314 2295 flist_from_mercurial
ohair@314 2296 fi
ohair@314 2297 flist_done=1
ohair@314 2298 shift $#
ohair@314 2299
ohair@314 2300 elif [[ -n $wflag ]]; then
ohair@314 2301 #
ohair@314 2302 # If the -w is given then assume the file list is in Bonwick's "wx"
ohair@314 2303 # command format, i.e. pathname lines alternating with SCCS comment
ohair@314 2304 # lines with blank lines as separators. Use the SCCS comments later
ohair@314 2305 # in building the index.html file.
ohair@314 2306 #
ohair@314 2307 shift $(($OPTIND - 1))
ohair@314 2308 wxfile=$1
ohair@314 2309 if [[ -z $wxfile && -n $CODEMGR_WS ]]; then
ohair@314 2310 if [[ -r $CODEMGR_WS/wx/active ]]; then
ohair@314 2311 wxfile=$CODEMGR_WS/wx/active
ohair@314 2312 fi
ohair@314 2313 fi
ohair@314 2314
ohair@314 2315 [[ -z $wxfile ]] && print -u2 "wx file not specified, and could not " \
ohair@314 2316 "be auto-detected (check \$CODEMGR_WS)" && exit 1
ohair@314 2317
ohair@314 2318 print -u2 " File list from: wx 'active' file '$wxfile' ... \c"
ohair@314 2319 flist_from_wx $wxfile
ohair@314 2320 flist_done=1
ohair@314 2321 if [[ -n "$*" ]]; then
ohair@314 2322 shift
ohair@314 2323 fi
ohair@314 2324 elif [[ $flist_mode == "stdin" ]]; then
ohair@314 2325 print -u2 " File list from: standard input"
ohair@314 2326 elif [[ $flist_mode == "file" ]]; then
ohair@314 2327 print -u2 " File list from: $flist_file"
ohair@314 2328 fi
ohair@314 2329
ohair@314 2330 if [[ $# -gt 0 ]]; then
ohair@314 2331 print -u2 "WARNING: unused arguments: $*"
ohair@314 2332 fi
ohair@314 2333
ohair@314 2334 if [[ $SCM_MODE == "teamware" ]]; then
ohair@314 2335 #
ohair@314 2336 # Parent (internally $codemgr_parent) and workspace ($codemgr_ws) can
ohair@314 2337 # be set in a number of ways, in decreasing precedence:
ohair@314 2338 #
ohair@314 2339 # 1) on the command line (only for the parent)
ohair@314 2340 # 2) in the user environment
ohair@314 2341 # 3) in the flist
ohair@314 2342 # 4) automatically based on the workspace (only for the parent)
ohair@314 2343 #
ohair@314 2344
ohair@314 2345 #
ohair@314 2346 # Here is case (2): the user environment
ohair@314 2347 #
ohair@314 2348 [[ -z $codemgr_ws && -n $CODEMGR_WS ]] && codemgr_ws=$CODEMGR_WS
ohair@314 2349 [[ -z $codemgr_ws && -n $WSPACE ]] && codemgr_ws=`$WSPACE name`
mduigou@616 2350
ohair@314 2351 if [[ -n $codemgr_ws && ! -d $codemgr_ws ]]; then
ohair@314 2352 print -u2 "$codemgr_ws: no such workspace"
ohair@314 2353 exit 1
ohair@314 2354 fi
ohair@314 2355
ohair@314 2356 [[ -z $codemgr_parent && -n $CODEMGR_PARENT ]] && \
ohair@314 2357 codemgr_parent=$CODEMGR_PARENT
ohair@314 2358
ohair@314 2359 if [[ -n $codemgr_parent && ! -d $codemgr_parent ]]; then
ohair@314 2360 print -u2 "$codemgr_parent: no such directory"
ohair@314 2361 exit 1
ohair@314 2362 fi
ohair@314 2363
ohair@314 2364 #
ohair@314 2365 # If we're in auto-detect mode and we haven't already gotten the file
ohair@314 2366 # list, then see if we can get it by probing for wx.
ohair@314 2367 #
ohair@314 2368 if [[ -z $flist_done && $flist_mode == "auto" && -n $codemgr_ws ]]; then
ohair@314 2369 if [[ ! -x $WX ]]; then
ohair@314 2370 print -u2 "WARNING: wx not found!"
ohair@314 2371 fi
ohair@314 2372
ohair@314 2373 #
ohair@314 2374 # We need to use wx list -w so that we get renamed files, etc.
ohair@314 2375 # but only if a wx active file exists-- otherwise wx will
ohair@314 2376 # hang asking us to initialize our wx information.
ohair@314 2377 #
ohair@314 2378 if [[ -x $WX && -f $codemgr_ws/wx/active ]]; then
ohair@314 2379 print -u2 " File list from: 'wx list -w' ... \c"
ohair@314 2380 $WX list -w > $FLIST
ohair@314 2381 $WX comments > /tmp/$$.wx_comments
ohair@314 2382 wxfile=/tmp/$$.wx_comments
ohair@314 2383 print -u2 "done"
ohair@314 2384 flist_done=1
ohair@314 2385 fi
ohair@314 2386 fi
ohair@314 2387
ohair@314 2388 #
ohair@314 2389 # If by hook or by crook we've gotten a file list by now (perhaps
ohair@314 2390 # from the command line), eval it to extract environment variables from
ohair@314 2391 # it: This is step (3).
ohair@314 2392 #
ohair@314 2393 env_from_flist
ohair@314 2394
ohair@314 2395 #
ohair@314 2396 # Continuing step (3): If we still have no file list, we'll try to get
ohair@314 2397 # it from teamware.
ohair@314 2398 #
ohair@314 2399 if [[ -z $flist_done ]]; then
ohair@314 2400 flist_from_teamware
ohair@314 2401 env_from_flist
ohair@314 2402 fi
ohair@314 2403
ohair@314 2404 if [[ -z $codemgr_ws && -d $PWD/Codemgr_wsdata ]]; then
ohair@314 2405 codemgr_ws=$PWD
ohair@314 2406 fi
ohair@314 2407 #
ohair@314 2408 # Observe true directory name of CODEMGR_WS, as used later in
ohair@314 2409 # webrev title.
ohair@314 2410 #
ohair@314 2411 if [[ -n $codemgr_ws ]]; then
ohair@314 2412 codemgr_ws=$(cd $codemgr_ws;print $PWD)
ohair@314 2413 fi
ohair@314 2414
ohair@314 2415 if [[ -n $codemgr_parent ]]; then
ohair@314 2416 codemgr_parent=$(cd $codemgr_parent;print $PWD)
ohair@314 2417 fi
ohair@314 2418
ohair@314 2419 #
ohair@314 2420 # (4) If we still don't have a value for codemgr_parent, get it
ohair@314 2421 # from workspace.
ohair@314 2422 #
ohair@314 2423 [[ -z $codemgr_parent && -n $WSPACE ]] && codemgr_parent=`$WSPACE parent`
ohair@314 2424 [[ -z $codemgr_parent ]] && codemgr_parent=`parent_from_teamware $codemgr_ws`
ohair@314 2425
ohair@314 2426 if [[ ! -d $codemgr_parent ]]; then
ohair@314 2427 print -u2 "$CODEMGR_PARENT: no such parent workspace"
ohair@314 2428 exit 1
ohair@314 2429 fi
ohair@314 2430
ohair@314 2431 #
ohair@314 2432 # Reset CODEMGR_WS to make sure teamware commands are happy.
ohair@314 2433 #
ohair@314 2434 CODEMGR_WS=$codemgr_ws
ohair@314 2435 CWS=$codemgr_ws
ohair@314 2436 PWS=$codemgr_parent
ohair@314 2437 elif [[ $SCM_MODE == "mercurial" ]]; then
ohair@314 2438 if [[ -z $flist_done ]]; then
ohair@314 2439 flist_from_mercurial $PWS
ohair@314 2440 fi
ohair@314 2441 fi
ohair@314 2442
ohair@314 2443 #
ohair@314 2444 # If the user didn't specify a -i option, check to see if there is a
ohair@314 2445 # webrev-info file in the workspace directory.
ohair@314 2446 #
ohair@314 2447 if [[ -z $iflag && -r "$CWS/webrev-info" ]]; then
ohair@314 2448 iflag=1
ohair@314 2449 INCLUDE_FILE="$CWS/webrev-info"
ohair@314 2450 fi
ohair@314 2451
ohair@314 2452 if [[ -n $iflag ]]; then
ohair@314 2453 if [[ ! -r $INCLUDE_FILE ]]; then
ohair@314 2454 print -u2 "include file '$INCLUDE_FILE' does not exist or is" \
ohair@314 2455 "not readable."
ohair@314 2456 exit 1
ohair@314 2457 else
ohair@314 2458 #
ohair@314 2459 # $INCLUDE_FILE may be a relative path, and the script alters
ohair@314 2460 # PWD, so we just stash a copy in /tmp.
ohair@314 2461 #
ohair@314 2462 cp $INCLUDE_FILE /tmp/$$.include
ohair@314 2463 fi
ohair@314 2464 fi
ohair@314 2465
ohair@314 2466 #
ohair@314 2467 # Output directory.
ohair@314 2468 #
ohair@314 2469 if [[ -z $WDIR ]]; then
ohair@314 2470 WDIR=$CWS/webrev
ohair@314 2471 else
ohair@314 2472 # If the output directory doesn't end with '/webrev' or '/webrev/'
ohair@314 2473 # then add '/webrev'. This is for backward compatibility
ohair@314 2474 if ! expr $WDIR : '.*/webrev/\?$' >/dev/null
ohair@314 2475 then
ohair@314 2476 WDIR=$WDIR/webrev
ohair@314 2477 fi
ohair@314 2478 fi
ohair@314 2479 # WDIR=${WDIR:-$CWS/webrev}
ohair@314 2480
ohair@314 2481 #
ohair@314 2482 # Name of the webrev, derived from the workspace name; in the
ohair@314 2483 # future this could potentially be an option.
ohair@314 2484 #
ohair@314 2485 # Let's keep what's after the last '/'
ohair@314 2486 WNAME=${CWS##*/}
ohair@314 2487
ohair@314 2488 #
ohair@314 2489 # If WDIR doesn't start with '/' or 'x:' prepend the current dir
ohair@314 2490 #
ohair@314 2491 if [ ${WDIR%%/*} ]; then
ohair@314 2492 if [[ -n $ISWIN ]]; then
ohair@314 2493 if [ ${WDIR%%[A-Za-z]:*} ]; then
ohair@314 2494 WDIR=$PWD/$WDIR
ohair@314 2495 fi
ohair@314 2496 else
ohair@314 2497 WDIR=$PWD/$WDIR
ohair@314 2498 fi
ohair@314 2499 fi
ohair@314 2500
ohair@314 2501 if [[ ! -d $WDIR ]]; then
ohair@314 2502 mkdir -p $WDIR
ohair@314 2503 [[ $? != 0 ]] && exit 1
ohair@314 2504 fi
ohair@314 2505
ohair@314 2506 #
ohair@314 2507 # Summarize what we're going to do.
ohair@314 2508 #
ohair@314 2509 print " Workspace: $CWS"
ohair@314 2510 if [[ -n $parent_webrev ]]; then
ohair@314 2511 print "Compare against: webrev at $parent_webrev"
ohair@314 2512 elif [[ -n $OUTPWS2 ]]; then
ohair@314 2513 print "Compare against: $OUTPWS2"
ohair@314 2514 fi
ohair@314 2515 if [[ -n $HG_BRANCH ]]; then
ohair@314 2516 print " Branch: $HG_BRANCH"
ohair@314 2517 fi
ohair@314 2518 if [[ -n $rflag ]]; then
ohair@314 2519 print "Compare against version: $PARENT_REV"
ohair@314 2520 fi
ohair@314 2521 [[ -n $INCLUDE_FILE ]] && print " Including: $INCLUDE_FILE"
ohair@314 2522 print " Output to: $WDIR"
ohair@314 2523
ohair@314 2524 #
ohair@314 2525 # Save the file list in the webrev dir
ohair@314 2526 #
ohair@314 2527 [[ ! $FLIST -ef $WDIR/file.list ]] && cp $FLIST $WDIR/file.list
ohair@314 2528
ohair@314 2529 #
ohair@314 2530 # Bug IDs will be replaced by a URL. Order of precedence
ohair@314 2531 # is: default location, $WEBREV_BUGURL, the -O flag.
ohair@314 2532 #
mduigou@616 2533 BUGURL='https://jbs.oracle.com/bugs/browse/'
ohair@314 2534 [[ -n $WEBREV_BUGURL ]] && BUGURL="$WEBREV_BUGURL"
mduigou@616 2535 if [[ -n "$Oflag" ]]; then
mduigou@616 2536 CRID=`echo $CRID | sed -e 's/JDK-//'`
ohair@314 2537 BUGURL='http://bugs.sun.com/bugdatabase/view_bug.do?bug_id='
mduigou@616 2538 IDPREFIX=''
mduigou@616 2539 else
mduigou@616 2540 IDPREFIX='JDK-'
mduigou@616 2541 fi
mduigou@616 2542
ohair@314 2543
ohair@314 2544 #
ohair@314 2545 # Likewise, ARC cases will be replaced by a URL. Order of precedence
ohair@314 2546 # is: default, $WEBREV_SACURL, the -O flag.
ohair@314 2547 #
ohair@314 2548 # Note that -O also triggers different substitution behavior for
ohair@314 2549 # SACURL. See sac2url().
ohair@314 2550 #
ohair@314 2551 SACURL='http://sac.eng.sun.com'
ohair@314 2552 [[ -n $WEBREV_SACURL ]] && SACURL="$WEBREV_SACURL"
ohair@314 2553 [[ -n $Oflag ]] && \
ohair@314 2554 SACURL='http://www.opensolaris.org/os/community/arc/caselog'
ohair@314 2555
ohair@314 2556 rm -f $WDIR/$WNAME.patch
ohair@314 2557 rm -f $WDIR/$WNAME.ps
ohair@314 2558 rm -f $WDIR/$WNAME.pdf
ohair@314 2559
ohair@314 2560 touch $WDIR/$WNAME.patch
ohair@314 2561
ohair@314 2562 print " Output Files:"
ohair@314 2563
ohair@314 2564 #
ohair@314 2565 # Clean up the file list: Remove comments, blank lines and env variables.
ohair@314 2566 #
ohair@314 2567 sed -e "s/#.*$//" -e "/=/d" -e "/^[ ]*$/d" $FLIST > /tmp/$$.flist.clean
ohair@314 2568 FLIST=/tmp/$$.flist.clean
ohair@314 2569
ohair@314 2570 #
ohair@314 2571 # Clean up residual raw files
ohair@314 2572 #
ohair@314 2573 if [ -d $WDIR/raw_files ]; then
ohair@314 2574 rm -rf $WDIR/raw_files 2>/dev/null
ohair@314 2575 fi
ohair@314 2576
ohair@314 2577 #
ohair@314 2578 # Should we ignore changes in white spaces when generating diffs?
mduigou@616 2579 #
ohair@314 2580 if [[ -n $bflag ]]; then
ohair@314 2581 DIFFOPTS="-t"
ohair@314 2582 else
ohair@314 2583 DIFFOPTS="-bt"
ohair@314 2584 fi
ohair@314 2585 #
ohair@314 2586 # First pass through the files: generate the per-file webrev HTML-files.
ohair@314 2587 #
ohair@314 2588 while read LINE
ohair@314 2589 do
ohair@314 2590 set - $LINE
ohair@314 2591 P=$1
ohair@314 2592
ohair@314 2593 if [[ $1 == "Revision:" ]]; then
ohair@314 2594 OUTREV=$2
ohair@314 2595 continue
ohair@314 2596 fi
ohair@314 2597 #
ohair@314 2598 # Normally, each line in the file list is just a pathname of a
ohair@314 2599 # file that has been modified or created in the child. A file
ohair@314 2600 # that is renamed in the child workspace has two names on the
ohair@314 2601 # line: new name followed by the old name.
ohair@314 2602 #
ohair@314 2603 oldname=""
ohair@314 2604 oldpath=""
ohair@314 2605 rename=
ohair@314 2606 if [[ $# -eq 2 ]]; then
ohair@314 2607 PP=$2 # old filename
ohair@314 2608 oldname=" (was $PP)"
ohair@314 2609 oldpath="$PP"
ohair@314 2610 rename=1
ohair@314 2611 PDIR=${PP%/*}
ohair@314 2612 if [[ $PDIR == $PP ]]; then
ohair@314 2613 PDIR="." # File at root of workspace
ohair@314 2614 fi
ohair@314 2615
ohair@314 2616 PF=${PP##*/}
ohair@314 2617
ohair@314 2618 DIR=${P%/*}
ohair@314 2619 if [[ $DIR == $P ]]; then
ohair@314 2620 DIR="." # File at root of workspace
ohair@314 2621 fi
ohair@314 2622
ohair@314 2623 F=${P##*/}
ohair@314 2624 else
ohair@314 2625 DIR=${P%/*}
ohair@314 2626 if [[ "$DIR" == "$P" ]]; then
ohair@314 2627 DIR="." # File at root of workspace
ohair@314 2628 fi
ohair@314 2629
ohair@314 2630 F=${P##*/}
ohair@314 2631
ohair@314 2632 PP=$P
ohair@314 2633 PDIR=$DIR
ohair@314 2634 PF=$F
ohair@314 2635 fi
ohair@314 2636
ohair@314 2637 # Make the webrev directory if necessary as it may have been
ohair@314 2638 # removed because it was empty
ohair@314 2639 if [ ! -d $CWS/$DIR ]; then
ohair@314 2640 mkdir -p $CWS/$DIR
ohair@314 2641 fi
ohair@314 2642
ohair@314 2643 COMM=`getcomments html $P $PP`
ohair@314 2644
ohair@314 2645 print "\t$P$oldname\n\t\t\c"
ohair@314 2646
ohair@314 2647 # Make the webrev mirror directory if necessary
ohair@314 2648 mkdir -p $WDIR/$DIR
ohair@314 2649
ohair@314 2650 # cd to the directory so the names are short
ohair@314 2651 cd $CWS/$DIR
ohair@314 2652
ohair@314 2653 #
ohair@314 2654 # If we're in OpenSolaris mode, we enforce a minor policy:
ohair@314 2655 # help to make sure the reviewer doesn't accidentally publish
ohair@314 2656 # source which is in usr/closed/*
ohair@314 2657 #
ohair@314 2658 if [[ -n $Oflag ]]; then
ohair@314 2659 pclosed=${P##usr/closed/}
ohair@314 2660 if [[ $pclosed != $P ]]; then
ohair@314 2661 print "*** Omitting closed source for OpenSolaris" \
ohair@314 2662 "mode review"
ohair@314 2663 continue
ohair@314 2664 fi
ohair@314 2665 fi
ohair@314 2666
ohair@314 2667 #
ohair@314 2668 # We stash old and new files into parallel directories in /tmp
ohair@314 2669 # and do our diffs there. This makes it possible to generate
ohair@314 2670 # clean looking diffs which don't have absolute paths present.
ohair@314 2671 #
ohair@314 2672 olddir=$WDIR/raw_files/old
ohair@314 2673 newdir=$WDIR/raw_files/new
ohair@314 2674 mkdir -p $olddir
ohair@314 2675 mkdir -p $newdir
ohair@314 2676 mkdir -p $olddir/$PDIR
ohair@314 2677 mkdir -p $newdir/$DIR
ohair@314 2678
ohair@314 2679 build_old_new $olddir $newdir $DIR $F
ohair@314 2680
ohair@314 2681 if [[ ! -f $F && ! -f $olddir/$DIR/$F ]]; then
ohair@314 2682 print "*** Error: file not in parent or child"
ohair@314 2683 continue
ohair@314 2684 fi
ohair@314 2685
ohair@314 2686 cd $WDIR/raw_files
ohair@314 2687 ofile=old/$PDIR/$PF
ohair@314 2688 nfile=new/$DIR/$F
ohair@314 2689
ohair@314 2690 mv_but_nodiff=
ohair@314 2691 cmp $ofile $nfile > /dev/null 2>&1
ohair@314 2692 if [[ $? == 0 && $rename == 1 ]]; then
ohair@314 2693 mv_but_nodiff=1
ohair@314 2694 fi
ohair@314 2695
ohair@314 2696 #
ohair@314 2697 # Cleaning up
ohair@314 2698 #
ohair@314 2699 rm -f $WDIR/$DIR/$F.cdiff.html
ohair@314 2700 rm -f $WDIR/$DIR/$F.udiff.html
ohair@314 2701 rm -f $WDIR/$DIR/$F.wdiff.html
ohair@314 2702 rm -f $WDIR/$DIR/$F.sdiff.html
ohair@314 2703 rm -f $WDIR/$DIR/$F-.html
ohair@314 2704 rm -f $WDIR/$DIR/$F.html
ohair@314 2705
ohair@314 2706 its_a_jar=
ohair@314 2707 if expr $F : '.*\.jar' >/dev/null; then
ohair@314 2708 its_a_jar=1
ohair@314 2709 # It's a JAR file, let's do it differntly
ohair@314 2710 if [[ -z $JAR ]]; then
ohair@314 2711 print "No access to jar, so can't produce diffs for jar files"
ohair@314 2712 else
ohair@314 2713 if [ -f $ofile ]; then
ohair@314 2714 $JAR -tvf $ofile >"$ofile".lst
ohair@314 2715 fi
ohair@314 2716 if [ -f $nfile ]; then
ohair@314 2717 $JAR -tvf $nfile >"$nfile".lst
ohair@314 2718 fi
ohair@314 2719
ohair@314 2720 if [[ -f $ofile && -f $nfile && -z $mv_but_nodiff ]]; then
ohair@314 2721
ohair@314 2722 ${CDIFFCMD:-diff -bt -C 5} $ofile.lst $nfile.lst > $WDIR/$DIR/$F.cdiff
ohair@314 2723 diff_to_html $F $DIR/$F "C" "$COMM" < $WDIR/$DIR/$F.cdiff \
ohair@314 2724 > $WDIR/$DIR/$F.cdiff.html
ohair@314 2725 print " cdiffs\c"
ohair@314 2726
ohair@314 2727 ${UDIFFCMD:-diff -bt -U 5} $ofile.lst $nfile.lst > $WDIR/$DIR/$F.udiff
ohair@314 2728 diff_to_html $F $DIR/$F "U" "$COMM" < $WDIR/$DIR/$F.udiff \
ohair@314 2729 > $WDIR/$DIR/$F.udiff.html
ohair@314 2730
ohair@314 2731 print " udiffs\c"
ohair@314 2732
ohair@314 2733 if [[ -x $WDIFF ]]; then
ohair@314 2734 $WDIFF -c "$COMM" \
ohair@314 2735 -t "$WNAME Wdiff $DIR/$F" $ofile.lst $nfile.lst > \
ohair@314 2736 $WDIR/$DIR/$F.wdiff.html 2>/dev/null
ohair@314 2737 if [[ $? -eq 0 ]]; then
ohair@314 2738 print " wdiffs\c"
ohair@314 2739 else
ohair@314 2740 print " wdiffs[fail]\c"
ohair@314 2741 fi
ohair@314 2742 fi
ohair@314 2743
ohair@314 2744 sdiff_to_html $ofile $nfile $F $DIR "$COMM" \
ohair@314 2745 > $WDIR/$DIR/$F.sdiff.html
ohair@314 2746 print " sdiffs\c"
ohair@314 2747
ohair@314 2748 print " frames\c"
ohair@314 2749
ohair@314 2750 rm -f $WDIR/$DIR/$F.cdiff $WDIR/$DIR/$F.udiff
ohair@314 2751
ohair@314 2752 difflines $ofile.lst $nfile.lst > $WDIR/$DIR/$F.count
ohair@314 2753
ohair@314 2754 elif [[ -f $ofile && -f $nfile && -n $mv_but_nodiff ]]; then
ohair@314 2755 # renamed file: may also have differences
ohair@314 2756 difflines $ofile.lst $nfile.lst > $WDIR/$DIR/$F.count
ohair@314 2757 elif [[ -f $nfile ]]; then
ohair@314 2758 # new file: count added lines
ohair@314 2759 difflines /dev/null $nfile.lst > $WDIR/$DIR/$F.count
ohair@314 2760 elif [[ -f $ofile ]]; then
ohair@314 2761 # old file: count deleted lines
ohair@314 2762 difflines $ofile.lst /dev/null > $WDIR/$DIR/$F.count
ohair@314 2763 fi
ohair@314 2764 fi
ohair@314 2765 else
mduigou@616 2766
ohair@314 2767 #
ohair@314 2768 # If we have old and new versions of the file then run the
ohair@314 2769 # appropriate diffs. This is complicated by a couple of factors:
ohair@314 2770 #
ohair@314 2771 # - renames must be handled specially: we emit a 'remove'
ohair@314 2772 # diff and an 'add' diff
ohair@314 2773 # - new files and deleted files must be handled specially
ohair@314 2774 # - Solaris patch(1m) can't cope with file creation
ohair@314 2775 # (and hence renames) as of this writing.
ohair@314 2776 # - To make matters worse, gnu patch doesn't interpret the
ohair@314 2777 # output of Solaris diff properly when it comes to
ohair@314 2778 # adds and deletes. We need to do some "cleansing"
ohair@314 2779 # transformations:
ohair@314 2780 # [to add a file] @@ -1,0 +X,Y @@ --> @@ -0,0 +X,Y @@
ohair@314 2781 # [to del a file] @@ -X,Y +1,0 @@ --> @@ -X,Y +0,0 @@
ohair@314 2782 #
ohair@314 2783 cleanse_rmfile="sed 's/^\(@@ [0-9+,-]*\) [0-9+,-]* @@$/\1 +0,0 @@/'"
ohair@314 2784 cleanse_newfile="sed 's/^@@ [0-9+,-]* \([0-9+,-]* @@\)$/@@ -0,0 \1/'"
ohair@314 2785
jgish@678 2786 if [[ -v NO_OUTGOING ]];
jgish@678 2787 then
jgish@678 2788 # Only need to generate a patch file here if there are no commits in outgoing
jgish@678 2789 rm -f $WDIR/$DIR/$F.patch
jgish@678 2790 if [[ -z $rename ]]; then
jgish@678 2791 if [ ! -f $ofile ]; then
jgish@678 2792 diff -u /dev/null $nfile | sh -c "$cleanse_newfile" \
jgish@678 2793 > $WDIR/$DIR/$F.patch
jgish@678 2794 elif [ ! -f $nfile ]; then
jgish@678 2795 diff -u $ofile /dev/null | sh -c "$cleanse_rmfile" \
jgish@678 2796 > $WDIR/$DIR/$F.patch
jgish@678 2797 else
jgish@678 2798 diff -u $ofile $nfile > $WDIR/$DIR/$F.patch
jgish@678 2799 fi
jgish@678 2800 else
jgish@678 2801 diff -u $ofile /dev/null | sh -c "$cleanse_rmfile" \
jgish@678 2802 > $WDIR/$DIR/$F.patch
jgish@678 2803
jgish@678 2804 diff -u /dev/null $nfile | sh -c "$cleanse_newfile" \
jgish@678 2805 >> $WDIR/$DIR/$F.patch
jgish@678 2806
jgish@678 2807 fi
jgish@678 2808
jgish@678 2809
jgish@678 2810 #
jgish@678 2811 # Tack the patch we just made onto the accumulated patch for the
jgish@678 2812 # whole wad.
jgish@678 2813 #
jgish@678 2814 cat $WDIR/$DIR/$F.patch >> $WDIR/$WNAME.patch
jgish@678 2815 fi
jgish@678 2816
jgish@678 2817 print " patch\c"
ohair@314 2818
ohair@314 2819 if [[ -f $ofile && -f $nfile && -z $mv_but_nodiff ]]; then
ohair@314 2820
ohair@314 2821 ${CDIFFCMD:-diff -bt -C 5} $ofile $nfile > $WDIR/$DIR/$F.cdiff
ohair@314 2822 diff_to_html $F $DIR/$F "C" "$COMM" < $WDIR/$DIR/$F.cdiff \
ohair@314 2823 > $WDIR/$DIR/$F.cdiff.html
ohair@314 2824 print " cdiffs\c"
ohair@314 2825
ohair@314 2826 ${UDIFFCMD:-diff -bt -U 5} $ofile $nfile > $WDIR/$DIR/$F.udiff
ohair@314 2827 diff_to_html $F $DIR/$F "U" "$COMM" < $WDIR/$DIR/$F.udiff \
ohair@314 2828 > $WDIR/$DIR/$F.udiff.html
ohair@314 2829
ohair@314 2830 print " udiffs\c"
ohair@314 2831
ohair@314 2832 if [[ -x $WDIFF ]]; then
ohair@314 2833 $WDIFF -c "$COMM" \
ohair@314 2834 -t "$WNAME Wdiff $DIR/$F" $ofile $nfile > \
ohair@314 2835 $WDIR/$DIR/$F.wdiff.html 2>/dev/null
ohair@314 2836 if [[ $? -eq 0 ]]; then
ohair@314 2837 print " wdiffs\c"
ohair@314 2838 else
ohair@314 2839 print " wdiffs[fail]\c"
ohair@314 2840 fi
ohair@314 2841 fi
ohair@314 2842
ohair@314 2843 sdiff_to_html $ofile $nfile $F $DIR "$COMM" \
ohair@314 2844 > $WDIR/$DIR/$F.sdiff.html
ohair@314 2845 print " sdiffs\c"
ohair@314 2846
ohair@314 2847 print " frames\c"
ohair@314 2848
ohair@314 2849 rm -f $WDIR/$DIR/$F.cdiff $WDIR/$DIR/$F.udiff
ohair@314 2850
ohair@314 2851 difflines $ofile $nfile > $WDIR/$DIR/$F.count
ohair@314 2852
ohair@314 2853 elif [[ -f $ofile && -f $nfile && -n $mv_but_nodiff ]]; then
ohair@314 2854 # renamed file: may also have differences
ohair@314 2855 difflines $ofile $nfile > $WDIR/$DIR/$F.count
ohair@314 2856 elif [[ -f $nfile ]]; then
ohair@314 2857 # new file: count added lines
ohair@314 2858 difflines /dev/null $nfile > $WDIR/$DIR/$F.count
ohair@314 2859 elif [[ -f $ofile ]]; then
ohair@314 2860 # old file: count deleted lines
ohair@314 2861 difflines $ofile /dev/null > $WDIR/$DIR/$F.count
ohair@314 2862 fi
ohair@314 2863 fi
ohair@314 2864 #
ohair@314 2865 # Now we generate the postscript for this file. We generate diffs
ohair@314 2866 # only in the event that there is delta, or the file is new (it seems
ohair@314 2867 # tree-killing to print out the contents of deleted files).
ohair@314 2868 #
ohair@314 2869 if [[ -f $nfile ]]; then
ohair@314 2870 ocr=$ofile
ohair@314 2871 [[ ! -f $ofile ]] && ocr=/dev/null
ohair@314 2872
ohair@314 2873 if [[ -z $mv_but_nodiff ]]; then
ohair@314 2874 textcomm=`getcomments text $P $PP`
ohair@314 2875 if [[ -x $CODEREVIEW ]]; then
ohair@314 2876 $CODEREVIEW -y "$textcomm" \
ohair@314 2877 -e $ocr $nfile \
ohair@314 2878 > /tmp/$$.psfile 2>/dev/null &&
ohair@314 2879 cat /tmp/$$.psfile >> $WDIR/$WNAME.ps
ohair@314 2880 if [[ $? -eq 0 ]]; then
ohair@314 2881 print " ps\c"
ohair@314 2882 else
ohair@314 2883 print " ps[fail]\c"
ohair@314 2884 fi
ohair@314 2885 fi
ohair@314 2886 fi
ohair@314 2887 fi
ohair@314 2888
ohair@314 2889 if [[ -f $ofile && -z $mv_but_nodiff ]]; then
ohair@314 2890 if [[ -n $its_a_jar ]]; then
ohair@314 2891 source_to_html Old $P < $ofile.lst > $WDIR/$DIR/$F-.html
ohair@314 2892 else
ohair@314 2893 source_to_html Old $P < $ofile > $WDIR/$DIR/$F-.html
ohair@314 2894 fi
ohair@314 2895 print " old\c"
ohair@314 2896 fi
ohair@314 2897
ohair@314 2898 if [[ -f $nfile ]]; then
ohair@314 2899 if [[ -n $its_a_jar ]]; then
ohair@314 2900 source_to_html New $P < $nfile.lst > $WDIR/$DIR/$F.html
ohair@314 2901 else
ohair@314 2902 source_to_html New $P < $nfile > $WDIR/$DIR/$F.html
ohair@314 2903 fi
ohair@314 2904 print " new\c"
ohair@314 2905 fi
ohair@314 2906
ohair@314 2907 print
ohair@314 2908 done < $FLIST
ohair@314 2909
jgish@678 2910 # Create the new style mercurial patch here using hg export -r [all-revs] -g -o $CHANGESETPATH
jgish@678 2911 if [[ $SCM_MODE == "mercurial" ]]; then
jgish@678 2912 if [[ !(-v NO_OUTGOING) ]]; then
jgish@678 2913 EXPORTCHANGESET="$WNAME.changeset"
jgish@678 2914 CHANGESETPATH=${WDIR}/${EXPORTCHANGESET}
jgish@678 2915 rm -f $CHANGESETPATH
jgish@678 2916 touch $CHANGESETPATH
jgish@678 2917 if [[ -n $ALL_CREV ]]; then
jgish@678 2918 rev_opt=
jgish@678 2919 for rev in $ALL_CREV; do
jgish@678 2920 rev_opt="$rev_opt --rev $rev"
jgish@678 2921 done
jgish@678 2922 elif [[ -n $FIRST_CREV ]]; then
jgish@678 2923 rev_opt="--rev $FIRST_CREV"
jgish@678 2924 fi
jgish@678 2925
jgish@678 2926 if [[ -n $rev_opt ]]; then
jgish@678 2927 (cd $CWS;hg export -g $rev_opt -o $CHANGESETPATH)
jgish@678 2928 # echo "Created new-patch: $CHANGESETPATH" 1>&2
jgish@678 2929 # Use it in place of the jdk.patch created above
jgish@678 2930 rm -f $WDIR/$WNAME.patch
jgish@678 2931 fi
jgish@678 2932 set +x
jgish@678 2933 fi
jgish@678 2934 fi
jgish@678 2935
ohair@314 2936 frame_nav_js > $WDIR/ancnav.js
ohair@314 2937 frame_navigation > $WDIR/ancnav.html
ohair@314 2938
ohair@314 2939 if [[ -f $WDIR/$WNAME.ps && -x $CODEREVIEW && -x $PS2PDF ]]; then
ohair@314 2940 print " Generating PDF: \c"
ohair@314 2941 fix_postscript $WDIR/$WNAME.ps | $PS2PDF - > $WDIR/$WNAME.pdf
ohair@314 2942 print "Done."
ohair@314 2943 fi
ohair@314 2944
ohair@314 2945 # Now build the index.html file that contains
ohair@314 2946 # links to the source files and their diffs.
ohair@314 2947
ohair@314 2948 cd $CWS
ohair@314 2949
ohair@314 2950 # Save total changed lines for Code Inspection.
ohair@314 2951 print "$TOTL" > $WDIR/TotalChangedLines
ohair@314 2952
ohair@314 2953 print " index.html: \c"
ohair@314 2954 INDEXFILE=$WDIR/index.html
ohair@314 2955 exec 3<&1 # duplicate stdout to FD3.
ohair@314 2956 exec 1<&- # Close stdout.
ohair@314 2957 exec > $INDEXFILE # Open stdout to index file.
ohair@314 2958
ohair@314 2959 print "$HTML<head>"
ohair@314 2960 print "<meta name=\"scm\" content=\"$SCM_MODE\" />"
ohair@314 2961 print "$STDHEAD"
ohair@314 2962 print "<title>$WNAME</title>"
ohair@314 2963 print "</head>"
ohair@314 2964 print "<body id=\"SUNWwebrev\">"
ohair@314 2965 print "<div class=\"summary\">"
ohair@314 2966 print "<h2>Code Review for $WNAME</h2>"
ohair@314 2967
ohair@314 2968 print "<table>"
ohair@314 2969
ohair@314 2970 if [[ -z $uflag ]]
ohair@314 2971 then
ohair@314 2972 if [[ $SCM_MODE == "mercurial" ]]
ohair@314 2973 then
ohair@314 2974 #
ohair@314 2975 # Let's try to extract the user name from the .hgrc file
ohair@314 2976 #
ohair@314 2977 username=`grep '^username' $HOME/.hgrc | sed 's/^username[ ]*=[ ]*\(.*\)/\1/'`
ohair@314 2978 fi
ohair@314 2979
ohair@314 2980 if [[ -z $username ]]
ohair@314 2981 then
ohair@314 2982 #
ohair@314 2983 # Figure out the username and gcos name. To maintain compatibility
ohair@314 2984 # with passwd(4), we must support '&' substitutions.
ohair@314 2985 #
ohair@314 2986 username=`id | cut -d '(' -f 2 | cut -d ')' -f 1`
ohair@314 2987 if [[ -x $GETENT ]]; then
ohair@314 2988 realname=`$GETENT passwd $username | cut -d':' -f 5 | cut -d ',' -f 1`
ohair@314 2989 fi
ohair@314 2990 userupper=`print "$username" | sed 's/\<./\u&/g'`
ohair@314 2991 realname=`print $realname | sed s/\&/$userupper/`
ohair@314 2992 fi
ohair@314 2993 fi
ohair@314 2994
ohair@314 2995 date="on `date`"
ohair@314 2996
ohair@314 2997 if [[ -n "$username" && -n "$realname" ]]; then
ohair@314 2998 print "<tr><th>Prepared by:</th>"
ohair@314 2999 print "<td>$realname ($username) $date</td></tr>"
ohair@314 3000 elif [[ -n "$username" ]]; then
ohair@314 3001 print "<tr><th>Prepared by:</th><td>$username $date</td></tr>"
ohair@314 3002 fi
ohair@314 3003
ohair@314 3004 print "<tr><th>Workspace:</th><td>$CWS</td></tr>"
ohair@314 3005 if [[ -n $parent_webrev ]]; then
ohair@314 3006 print "<tr><th>Compare against:</th><td>"
ohair@314 3007 print "webrev at $parent_webrev"
ohair@314 3008 else
ohair@314 3009 if [[ -n $OUTPWS2 ]]; then
ohair@314 3010 print "<tr><th>Compare against:</th><td>"
ohair@314 3011 print "$OUTPWS2"
ohair@314 3012 fi
ohair@314 3013 fi
ohair@314 3014 print "</td></tr>"
ohair@314 3015 if [[ -n $rflag ]]; then
ohair@314 3016 print "<tr><th>Compare against version:</th><td>$PARENT_REV</td></tr>"
ohair@314 3017 elif [[ -n $OUTREV ]]; then
ohair@314 3018 if [[ -z $forestflag ]]; then
ohair@314 3019 print "<tr><th>Compare against version:</th><td>$OUTREV</td></tr>"
ohair@314 3020 fi
ohair@314 3021 fi
ohair@314 3022 if [[ -n $HG_BRANCH ]]; then
ohair@314 3023 print "<tr><th>Branch:</th><td>$HG_BRANCH</td></tr>"
ohair@314 3024 fi
ohair@314 3025
ohair@314 3026 print "<tr><th>Summary of changes:</th><td>"
ohair@314 3027 printCI $TOTL $TINS $TDEL $TMOD $TUNC
ohair@314 3028 print "</td></tr>"
ohair@314 3029
ohair@314 3030 if [[ -f $WDIR/$WNAME.patch ]]; then
jgish@678 3031 print "<tr><th>Patch of changes:</th><td>"
jgish@678 3032 print "<a href=\"$WNAME.patch\">$WNAME.patch</a></td></tr>"
jgish@678 3033 elif [[ -f $CHANGESETPATH ]]; then
jgish@678 3034 print "<tr><th>Changeset:</th><td>"
jgish@678 3035 print "<a href=\"$EXPORTCHANGESET\">$EXPORTCHANGESET</a></td></tr>"
ohair@314 3036 fi
jgish@678 3037
ohair@314 3038 if [[ -f $WDIR/$WNAME.pdf ]]; then
ohair@314 3039 print "<tr><th>Printable review:</th><td>"
ohair@314 3040 print "<a href=\"$WNAME.pdf\">$WNAME.pdf</a></td></tr>"
ohair@314 3041 fi
ohair@314 3042
ohair@314 3043 if [[ -n "$iflag" ]]; then
ohair@314 3044 print "<tr><th>Author comments:</th><td><div>"
ohair@314 3045 cat /tmp/$$.include
ohair@314 3046 print "</div></td></tr>"
ohair@314 3047 fi
ohair@314 3048 # Add links to referenced CRs, if any
ohair@314 3049 # external URL has a <title> like:
ohair@314 3050 # <title>Bug ID: 6641309 Wrong Cookie separator used in HttpURLConnection</title>
ohair@314 3051 # while internal URL has <title> like:
mduigou@616 3052 # <title>[#JDK-6641309] Wrong Cookie separator used in HttpURLConnection</title>
ohair@314 3053 #
ohair@314 3054 if [[ -n $CRID ]]; then
ohair@314 3055 for id in $CRID
ohair@314 3056 do
mduigou@616 3057 if [[ -z "$Oflag" ]]; then
mduigou@616 3058 #add "JDK-" to raw bug id for jbs links.
mduigou@616 3059 id=`echo ${id} | sed 's/^\([0-9]\{5,\}\)$/JDK-\1/'`
mduigou@616 3060 fi
ohair@314 3061 print "<tr><th>Bug id:</th><td>"
ohair@314 3062 url="${BUGURL}${id}"
mduigou@616 3063 if [[ -n "$Oflag" ]]; then
mduigou@616 3064 cleanup='s/Bug ID: \([0-9]\{5,\}\) \(.*\)/JDK-\1 : \2/'
mduigou@616 3065 else
mduigou@616 3066 cleanup='s|\[#\(JDK-[0-9]\{5,\}\)\] \(.*\)|\1 : \2|'
mduigou@616 3067 fi
ohair@314 3068 if [[ -n $WGET ]]; then
mduigou@643 3069 msg=`$WGET --timeout=10 --tries=1 -q $url -O - | grep '<title>' | sed 's/<title>\(.*\)<\/title>/\1/' | sed "$cleanup" | html_quote`
ohair@314 3070 fi
mduigou@616 3071 if [[ -z $msg ]]; then
mduigou@616 3072 msg="${id}"
ohair@314 3073 fi
mduigou@616 3074
mduigou@616 3075 print "<a href=\"$url\">$msg</a>"
mduigou@616 3076
ohair@314 3077 print "</td></tr>"
ohair@314 3078 done
ohair@314 3079 fi
ohair@314 3080 print "<tr><th>Legend:</th><td>"
ohair@314 3081 print "<b>Modified file</b><br><font color=red><b>Deleted file</b></font><br><font color=green><b>New file</b></font></td></tr>"
ohair@314 3082 print "</table>"
ohair@314 3083 print "</div>"
ohair@314 3084
ohair@314 3085 #
ohair@314 3086 # Second pass through the files: generate the rest of the index file
ohair@314 3087 #
ohair@314 3088 while read LINE
ohair@314 3089 do
ohair@314 3090 set - $LINE
ohair@314 3091 if [[ $1 == "Revision:" ]]; then
ohair@314 3092 FIRST_CREV=`expr $3 + 1`
ohair@314 3093 continue
ohair@314 3094 fi
ohair@314 3095 P=$1
ohair@314 3096
ohair@314 3097 if [[ $# == 2 ]]; then
ohair@314 3098 PP=$2
ohair@314 3099 oldname=" <i>(was $PP)</i>"
ohair@314 3100
ohair@314 3101 else
ohair@314 3102 PP=$P
ohair@314 3103 oldname=""
ohair@314 3104 fi
ohair@314 3105
ohair@314 3106 DIR=${P%/*}
ohair@314 3107 if [[ $DIR == $P ]]; then
ohair@314 3108 DIR="." # File at root of workspace
ohair@314 3109 fi
ohair@314 3110
ohair@314 3111 # Avoid processing the same file twice.
ohair@314 3112 # It's possible for renamed files to
ohair@314 3113 # appear twice in the file list
ohair@314 3114
ohair@314 3115 F=$WDIR/$P
ohair@314 3116
ohair@314 3117 print "<p><code>"
ohair@314 3118
ohair@314 3119 # If there's a diffs file, make diffs links
ohair@314 3120
ohair@314 3121 NODIFFS=
ohair@314 3122 if [[ -f $F.cdiff.html ]]; then
ohair@314 3123 print "<a href=\"$P.cdiff.html\">Cdiffs</a>"
ohair@314 3124 print "<a href=\"$P.udiff.html\">Udiffs</a>"
ohair@314 3125
ohair@314 3126 if [[ -f $F.wdiff.html && -x $WDIFF ]]; then
ohair@314 3127 print "<a href=\"$P.wdiff.html\">Wdiffs</a>"
ohair@314 3128 fi
ohair@314 3129
ohair@314 3130 print "<a href=\"$P.sdiff.html\">Sdiffs</a>"
ohair@314 3131
ohair@314 3132 print "<a href=\"$P.frames.html\">Frames</a>"
ohair@314 3133 else
ohair@314 3134 NODIFFS=1
ohair@314 3135 print " ------ ------ ------"
ohair@314 3136
ohair@314 3137 if [[ -x $WDIFF ]]; then
ohair@314 3138 print " ------"
ohair@314 3139 fi
ohair@314 3140
ohair@314 3141 print " ------"
ohair@314 3142 fi
ohair@314 3143
ohair@314 3144 # If there's an old file, make the link
ohair@314 3145
ohair@314 3146 NOOLD=
ohair@314 3147 if [[ -f $F-.html ]]; then
ohair@314 3148 print "<a href=\"$P-.html\">Old</a>"
ohair@314 3149 else
ohair@314 3150 NOOLD=1
ohair@314 3151 print " ---"
ohair@314 3152 fi
ohair@314 3153
ohair@314 3154 # If there's an new file, make the link
ohair@314 3155
ohair@314 3156 NONEW=
ohair@314 3157 if [[ -f $F.html ]]; then
ohair@314 3158 print "<a href=\"$P.html\">New</a>"
ohair@314 3159 else
ohair@314 3160 NONEW=1
ohair@314 3161 print " ---"
ohair@314 3162 fi
ohair@314 3163
ohair@314 3164 if [[ -f $F.patch ]]; then
ohair@314 3165 print "<a href=\"$P.patch\">Patch</a>"
ohair@314 3166 else
ohair@314 3167 print " -----"
ohair@314 3168 fi
ohair@314 3169
ohair@314 3170 if [[ -f $WDIR/raw_files/new/$P ]]; then
ohair@314 3171 print "<a href=\"raw_files/new/$P\">Raw</a>"
ohair@314 3172 else
ohair@314 3173 print " ---"
ohair@314 3174 fi
ohair@314 3175 print "</code>"
ohair@314 3176 if [[ -n $NODIFFS && -z $oldname ]]; then
ohair@314 3177 if [[ -n $NOOLD ]]; then
ohair@314 3178 print "<font color=green><b>$P</b></font>"
ohair@314 3179 elif [[ -n $NONEW ]]; then
ohair@314 3180 print "<font color=red><b>$P</b></font>"
ohair@314 3181 fi
ohair@314 3182 else
ohair@314 3183 print "<b>$P</b> $oldname"
ohair@314 3184 fi
ohair@314 3185
ohair@314 3186 #
ohair@314 3187 # Check for usr/closed
ohair@314 3188 #
ohair@314 3189 if [ ! -z "$Oflag" ]; then
ohair@314 3190 if [[ $P == usr/closed/* ]]; then
ohair@314 3191 print "&nbsp;&nbsp;<i>Closed source: omitted from" \
ohair@314 3192 "this review</i>"
ohair@314 3193 fi
ohair@314 3194 fi
ohair@314 3195
ohair@314 3196 print "</p><blockquote>\c"
ohair@314 3197 # Insert delta comments if any
ohair@314 3198 comments=`getcomments html $P $PP`
ohair@314 3199 if [ -n "$comments" ]; then
ohair@314 3200 print "<pre>$comments</pre>"
ohair@314 3201 fi
ohair@314 3202
ohair@314 3203 # Add additional comments comment
ohair@314 3204
ohair@314 3205 print "<!-- Add comments to explain changes in $P here -->"
ohair@314 3206
ohair@314 3207 # Add count of changes.
ohair@314 3208
ohair@314 3209 if [[ -f $F.count ]]; then
ohair@314 3210 cat $F.count
ohair@314 3211 rm $F.count
ohair@314 3212 fi
ohair@314 3213 print "</blockquote>"
ohair@314 3214 done < $FLIST
ohair@314 3215
ohair@314 3216 print
ohair@314 3217 print
ohair@314 3218 print "<hr />"
ohair@314 3219 print "<p style=\"font-size: small\">"
ohair@314 3220 print "This code review page was prepared using <b>$0</b>"
ohair@314 3221 print "(vers $WEBREV_UPDATED)."
ohair@314 3222 print "</body>"
ohair@314 3223 print "</html>"
ohair@314 3224
ohair@314 3225 if [[ -n $ZIP ]]; then
ohair@314 3226 # Let's generate a zip file for convenience
ohair@314 3227 cd $WDIR/..
ohair@314 3228 if [ -f webrev.zip ]; then
ohair@314 3229 rm webrev.zip
ohair@314 3230 fi
ohair@314 3231 $ZIP -r webrev webrev >/dev/null 2>&1
ohair@314 3232 fi
ohair@314 3233
ohair@314 3234 exec 1<&- # Close FD 1.
ohair@314 3235 exec 1<&3 # dup FD 3 to restore stdout.
ohair@314 3236 exec 3<&- # close FD 3.
ohair@314 3237
ohair@314 3238 print "Done."
ohair@314 3239 print "Output to: $WDIR"

mercurial