Print this page
3810 remove support for teamware from webrev
Reviewed by: Andrew Stormont <AStormont@racktopsystems.com>
Reviewed by: Garrett D'Amore <garrett@damore.org>
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/tools/scripts/webrev.sh
+++ new/usr/src/tools/scripts/webrev.sh
1 1 #!/usr/bin/ksh93 -p
2 2 #
3 3 # CDDL HEADER START
4 4 #
5 5 # The contents of this file are subject to the terms of the
6 6 # Common Development and Distribution License (the "License").
7 7 # You may not use this file except in compliance with the License.
8 8 #
9 9 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 10 # or http://www.opensolaris.org/os/licensing.
11 11 # See the License for the specific language governing permissions
12 12 # and limitations under the License.
13 13 #
14 14 # When distributing Covered Code, include this CDDL HEADER in each
15 15 # file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 16 # If applicable, add the following below this CDDL HEADER, with the
17 17 # fields enclosed by brackets "[]" replaced with your own identifying
18 18 # information: Portions Copyright [yyyy] [name of copyright owner]
↓ open down ↓ |
18 lines elided |
↑ open up ↑ |
19 19 #
20 20 # CDDL HEADER END
21 21 #
22 22
23 23 #
24 24 # Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
25 25 #
26 26
27 27 # Copyright 2008, 2010, Richard Lowe
28 28 # Copyright 2012 Marcel Telka <marcel@telka.sk>
29 +# Copyright 2014 Bart Coddens <bart.coddens@gmail.com>
29 30
30 31 #
31 32 # This script takes a file list and a workspace and builds a set of html files
32 33 # suitable for doing a code review of source changes via a web page.
33 34 # Documentation is available via the manual page, webrev.1, or just
34 35 # type 'webrev -h'.
35 36 #
36 37 # Acknowledgements to contributors to webrev are listed in the webrev(1)
37 38 # man page.
38 39 #
39 40
40 41 REMOVED_COLOR=brown
41 42 CHANGED_COLOR=blue
42 43 NEW_COLOR=blue
43 44
44 45 HTML='<?xml version="1.0"?>
45 46 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
46 47 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
47 48 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">\n'
48 49
49 50 FRAMEHTML='<?xml version="1.0"?>
50 51 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"
51 52 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
52 53 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">\n'
53 54
54 55 STDHEAD='<meta http-equiv="cache-control" content="no-cache"></meta>
55 56 <meta http-equiv="Pragma" content="no-cache"></meta>
56 57 <meta http-equiv="Expires" content="-1"></meta>
57 58 <!--
58 59 Note to customizers: the body of the webrev is IDed as SUNWwebrev
59 60 to allow easy overriding by users of webrev via the userContent.css
60 61 mechanism available in some browsers.
61 62
62 63 For example, to have all "removed" information be red instead of
63 64 brown, set a rule in your userContent.css file like:
64 65
65 66 body#SUNWwebrev span.removed { color: red ! important; }
66 67 -->
67 68 <style type="text/css" media="screen">
68 69 body {
69 70 background-color: #eeeeee;
70 71 }
71 72 hr {
72 73 border: none 0;
73 74 border-top: 1px solid #aaa;
74 75 height: 1px;
75 76 }
76 77 div.summary {
77 78 font-size: .8em;
78 79 border-bottom: 1px solid #aaa;
79 80 padding-left: 1em;
80 81 padding-right: 1em;
81 82 }
82 83 div.summary h2 {
83 84 margin-bottom: 0.3em;
84 85 }
85 86 div.summary table th {
86 87 text-align: right;
87 88 vertical-align: top;
88 89 white-space: nowrap;
89 90 }
90 91 span.lineschanged {
91 92 font-size: 0.7em;
92 93 }
93 94 span.oldmarker {
94 95 color: red;
95 96 font-size: large;
96 97 font-weight: bold;
97 98 }
98 99 span.newmarker {
99 100 color: green;
100 101 font-size: large;
101 102 font-weight: bold;
102 103 }
103 104 span.removed {
104 105 color: brown;
105 106 }
106 107 span.changed {
107 108 color: blue;
108 109 }
109 110 span.new {
110 111 color: blue;
111 112 font-weight: bold;
112 113 }
113 114 span.chmod {
114 115 font-size: 0.7em;
115 116 color: #db7800;
116 117 }
117 118 a.print { font-size: x-small; }
118 119 a:hover { background-color: #ffcc99; }
119 120 </style>
120 121
121 122 <style type="text/css" media="print">
122 123 pre { font-size: 0.8em; font-family: courier, monospace; }
123 124 span.removed { color: #444; font-style: italic }
124 125 span.changed { font-weight: bold; }
125 126 span.new { font-weight: bold; }
126 127 span.newmarker { font-size: 1.2em; font-weight: bold; }
127 128 span.oldmarker { font-size: 1.2em; font-weight: bold; }
128 129 a.print {display: none}
129 130 hr { border: none 0; border-top: 1px solid #aaa; height: 1px; }
130 131 </style>
131 132 '
132 133
133 134 #
134 135 # UDiffs need a slightly different CSS rule for 'new' items (we don't
135 136 # want them to be bolded as we do in cdiffs or sdiffs).
136 137 #
137 138 UDIFFCSS='
138 139 <style type="text/css" media="screen">
139 140 span.new {
140 141 color: blue;
141 142 font-weight: normal;
142 143 }
143 144 </style>
144 145 '
145 146
146 147 #
147 148 # Display remote target with prefix and trailing slash.
148 149 #
149 150 function print_upload_header
150 151 {
151 152 typeset -r prefix=$1
152 153 typeset display_target
153 154
154 155 if [[ -z $tflag ]]; then
155 156 display_target=${prefix}${remote_target}
156 157 else
157 158 display_target=${remote_target}
158 159 fi
159 160
160 161 if [[ ${display_target} != */ ]]; then
161 162 display_target=${display_target}/
162 163 fi
163 164
164 165 print " Upload to: ${display_target}\n" \
165 166 " Uploading: \c"
166 167 }
167 168
168 169 #
169 170 # Upload the webrev via rsync. Return 0 on success, 1 on error.
170 171 #
171 172 function rsync_upload
172 173 {
173 174 if (( $# != 2 )); then
174 175 print "\nERROR: rsync_upload: wrong usage ($#)"
175 176 exit 1
176 177 fi
177 178
178 179 typeset -r dst=$1
179 180 integer -r print_err_msg=$2
180 181
181 182 print_upload_header ${rsync_prefix}
182 183 print "rsync ... \c"
183 184 typeset -r err_msg=$( $MKTEMP /tmp/rsync_err.XXXXXX )
184 185 if [[ -z $err_msg ]]; then
185 186 print "\nERROR: rsync_upload: cannot create temporary file"
186 187 return 1
187 188 fi
188 189 #
189 190 # The source directory must end with a slash in order to copy just
190 191 # directory contents, not the whole directory.
191 192 #
192 193 typeset src_dir=$WDIR
193 194 if [[ ${src_dir} != */ ]]; then
194 195 src_dir=${src_dir}/
195 196 fi
196 197 $RSYNC -r -q ${src_dir} $dst 2>$err_msg
197 198 if (( $? != 0 )); then
198 199 if (( ${print_err_msg} > 0 )); then
199 200 print "Failed.\nERROR: rsync failed"
200 201 print "src dir: '${src_dir}'\ndst dir: '$dst'"
201 202 print "error messages:"
202 203 $SED 's/^/> /' $err_msg
203 204 rm -f $err_msg
204 205 fi
205 206 return 1
206 207 fi
207 208
208 209 rm -f $err_msg
209 210 print "Done."
210 211 return 0
211 212 }
212 213
213 214 #
214 215 # Create directories on remote host using SFTP. Return 0 on success,
215 216 # 1 on failure.
216 217 #
217 218 function remote_mkdirs
218 219 {
219 220 typeset -r dir_spec=$1
220 221 typeset -r host_spec=$2
221 222
222 223 #
223 224 # If the supplied path is absolute we assume all directories are
224 225 # created, otherwise try to create all directories in the path
225 226 # except the last one which will be created by scp.
226 227 #
227 228 if [[ "${dir_spec}" == */* && "${dir_spec}" != /* ]]; then
228 229 print "mkdirs \c"
229 230 #
230 231 # Remove the last directory from directory specification.
231 232 #
232 233 typeset -r dirs_mk=${dir_spec%/*}
233 234 typeset -r batch_file_mkdir=$( $MKTEMP \
234 235 /tmp/webrev_mkdir.XXXXXX )
235 236 if [[ -z $batch_file_mkdir ]]; then
236 237 print "\nERROR: remote_mkdirs:" \
237 238 "cannot create temporary file for batch file"
238 239 return 1
239 240 fi
240 241 OLDIFS=$IFS
241 242 IFS=/
242 243 typeset dir
243 244 for dir in ${dirs_mk}; do
244 245 #
245 246 # Use the '-' prefix to ignore mkdir errors in order
246 247 # to avoid an error in case the directory already
247 248 # exists. We check the directory with chdir to be sure
248 249 # there is one.
249 250 #
250 251 print -- "-mkdir ${dir}" >> ${batch_file_mkdir}
251 252 print "chdir ${dir}" >> ${batch_file_mkdir}
252 253 done
253 254 IFS=$OLDIFS
254 255 typeset -r sftp_err_msg=$( $MKTEMP /tmp/webrev_scp_err.XXXXXX )
255 256 if [[ -z ${sftp_err_msg} ]]; then
256 257 print "\nERROR: remote_mkdirs:" \
257 258 "cannot create temporary file for error messages"
258 259 return 1
259 260 fi
260 261 $SFTP -b ${batch_file_mkdir} ${host_spec} 2>${sftp_err_msg} 1>&2
261 262 if (( $? != 0 )); then
262 263 print "\nERROR: failed to create remote directories"
263 264 print "error messages:"
264 265 $SED 's/^/> /' ${sftp_err_msg}
265 266 rm -f ${sftp_err_msg} ${batch_file_mkdir}
266 267 return 1
267 268 fi
268 269 rm -f ${sftp_err_msg} ${batch_file_mkdir}
269 270 fi
270 271
271 272 return 0
272 273 }
273 274
274 275 #
275 276 # Upload the webrev via SSH. Return 0 on success, 1 on error.
276 277 #
277 278 function ssh_upload
278 279 {
279 280 if (( $# != 1 )); then
280 281 print "\nERROR: ssh_upload: wrong number of arguments"
281 282 exit 1
282 283 fi
283 284
284 285 typeset dst=$1
285 286 typeset -r host_spec=${dst%%:*}
286 287 typeset -r dir_spec=${dst#*:}
287 288
288 289 #
289 290 # Display the upload information before calling delete_webrev
290 291 # because it will also print its progress.
291 292 #
292 293 print_upload_header ${ssh_prefix}
293 294
294 295 #
295 296 # If the deletion was explicitly requested there is no need
296 297 # to perform it again.
297 298 #
298 299 if [[ -z $Dflag ]]; then
299 300 #
300 301 # We do not care about return value because this might be
301 302 # the first time this directory is uploaded.
302 303 #
303 304 delete_webrev 0
304 305 fi
305 306
306 307 #
307 308 # Create remote directories. Any error reporting will be done
308 309 # in remote_mkdirs function.
309 310 #
310 311 remote_mkdirs ${dir_spec} ${host_spec}
311 312 if (( $? != 0 )); then
312 313 return 1
313 314 fi
314 315
315 316 print "upload ... \c"
316 317 typeset -r scp_err_msg=$( $MKTEMP /tmp/scp_err.XXXXXX )
317 318 if [[ -z ${scp_err_msg} ]]; then
318 319 print "\nERROR: ssh_upload:" \
319 320 "cannot create temporary file for error messages"
320 321 return 1
321 322 fi
322 323 $SCP -q -C -B -o PreferredAuthentications=publickey -r \
323 324 $WDIR $dst 2>${scp_err_msg}
324 325 if (( $? != 0 )); then
325 326 print "Failed.\nERROR: scp failed"
326 327 print "src dir: '$WDIR'\ndst dir: '$dst'"
327 328 print "error messages:"
328 329 $SED 's/^/> /' ${scp_err_msg}
329 330 rm -f ${scp_err_msg}
330 331 return 1
331 332 fi
332 333
333 334 rm -f ${scp_err_msg}
334 335 print "Done."
335 336 return 0
336 337 }
337 338
338 339 #
339 340 # Delete webrev at remote site. Return 0 on success, 1 or exit code from sftp
340 341 # on failure. If first argument is 1 then perform the check of sftp return
341 342 # value otherwise ignore it. If second argument is present it means this run
342 343 # only performs deletion.
343 344 #
344 345 function delete_webrev
345 346 {
346 347 if (( $# < 1 )); then
347 348 print "delete_webrev: wrong number of arguments"
348 349 exit 1
349 350 fi
350 351
351 352 integer -r check=$1
352 353 integer delete_only=0
353 354 if (( $# == 2 )); then
354 355 delete_only=1
355 356 fi
356 357
357 358 #
358 359 # Strip the transport specification part of remote target first.
359 360 #
360 361 typeset -r stripped_target=${remote_target##*://}
361 362 typeset -r host_spec=${stripped_target%%:*}
362 363 typeset -r dir_spec=${stripped_target#*:}
363 364 typeset dir_rm
364 365
365 366 #
366 367 # Do not accept an absolute path.
367 368 #
368 369 if [[ ${dir_spec} == /* ]]; then
369 370 return 1
370 371 fi
371 372
372 373 #
373 374 # Strip the ending slash.
374 375 #
375 376 if [[ ${dir_spec} == */ ]]; then
376 377 dir_rm=${dir_spec%%/}
377 378 else
378 379 dir_rm=${dir_spec}
379 380 fi
380 381
381 382 if (( ${delete_only} > 0 )); then
382 383 print " Removing: \c"
383 384 else
384 385 print "rmdir \c"
385 386 fi
386 387 if [[ -z "$dir_rm" ]]; then
387 388 print "\nERROR: empty directory for removal"
388 389 return 1
389 390 fi
390 391
391 392 #
392 393 # Prepare batch file.
393 394 #
394 395 typeset -r batch_file_rm=$( $MKTEMP /tmp/webrev_remove.XXXXXX )
395 396 if [[ -z $batch_file_rm ]]; then
396 397 print "\nERROR: delete_webrev: cannot create temporary file"
397 398 return 1
398 399 fi
399 400 print "rename $dir_rm $TRASH_DIR/removed.$$" > $batch_file_rm
400 401
401 402 #
402 403 # Perform remote deletion and remove the batch file.
403 404 #
404 405 typeset -r sftp_err_msg=$( $MKTEMP /tmp/webrev_scp_err.XXXXXX )
405 406 if [[ -z ${sftp_err_msg} ]]; then
406 407 print "\nERROR: delete_webrev:" \
407 408 "cannot create temporary file for error messages"
408 409 return 1
409 410 fi
410 411 $SFTP -b $batch_file_rm $host_spec 2>${sftp_err_msg} 1>&2
411 412 integer -r ret=$?
412 413 rm -f $batch_file_rm
413 414 if (( $ret != 0 && $check > 0 )); then
414 415 print "Failed.\nERROR: failed to remove remote directories"
415 416 print "error messages:"
416 417 $SED 's/^/> /' ${sftp_err_msg}
417 418 rm -f ${sftp_err_msg}
418 419 return $ret
419 420 fi
420 421 rm -f ${sftp_err_msg}
421 422 if (( ${delete_only} > 0 )); then
422 423 print "Done."
423 424 fi
424 425
425 426 return 0
426 427 }
427 428
428 429 #
429 430 # Upload webrev to remote site
430 431 #
431 432 function upload_webrev
432 433 {
433 434 integer ret
434 435
435 436 if [[ ! -d "$WDIR" ]]; then
436 437 print "\nERROR: webrev directory '$WDIR' does not exist"
437 438 return 1
438 439 fi
439 440
440 441 #
441 442 # Perform a late check to make sure we do not upload closed source
442 443 # to remote target when -n is used. If the user used custom remote
443 444 # target he probably knows what he is doing.
444 445 #
445 446 if [[ -n $nflag && -z $tflag ]]; then
446 447 $FIND $WDIR -type d -name closed \
447 448 | $GREP closed >/dev/null
448 449 if (( $? == 0 )); then
449 450 print "\nERROR: directory '$WDIR' contains" \
450 451 "\"closed\" directory"
451 452 return 1
452 453 fi
453 454 fi
454 455
455 456
456 457 #
457 458 # We have the URI for remote destination now so let's start the upload.
458 459 #
459 460 if [[ -n $tflag ]]; then
460 461 if [[ "${remote_target}" == ${rsync_prefix}?* ]]; then
461 462 rsync_upload ${remote_target##$rsync_prefix} 1
462 463 ret=$?
463 464 return $ret
464 465 elif [[ "${remote_target}" == ${ssh_prefix}?* ]]; then
465 466 ssh_upload ${remote_target##$ssh_prefix}
466 467 ret=$?
467 468 return $ret
468 469 fi
469 470 else
470 471 #
471 472 # Try rsync first and fallback to SSH in case it fails.
472 473 #
473 474 rsync_upload ${remote_target} 0
474 475 ret=$?
475 476 if (( $ret != 0 )); then
476 477 print "Failed. (falling back to SSH)"
477 478 ssh_upload ${remote_target}
478 479 ret=$?
479 480 fi
480 481 return $ret
481 482 fi
482 483 }
483 484
484 485 #
485 486 # input_cmd | url_encode | output_cmd
486 487 #
487 488 # URL-encode (percent-encode) reserved characters as defined in RFC 3986.
488 489 #
489 490 # Reserved characters are: :/?#[]@!$&'()*+,;=
490 491 #
491 492 # While not a reserved character itself, percent '%' is reserved by definition
492 493 # so encode it first to avoid recursive transformation, and skip '/' which is
493 494 # a path delimiter.
494 495 #
495 496 # The quotation character is deliberately not escaped in order to make
496 497 # the substitution work with GNU sed.
497 498 #
498 499 function url_encode
499 500 {
500 501 $SED -e "s|%|%25|g" -e "s|:|%3A|g" -e "s|\&|%26|g" \
501 502 -e "s|?|%3F|g" -e "s|#|%23|g" -e "s|\[|%5B|g" \
502 503 -e "s|*|%2A|g" -e "s|@|%40|g" -e "s|\!|%21|g" \
503 504 -e "s|=|%3D|g" -e "s|;|%3B|g" -e "s|\]|%5D|g" \
504 505 -e "s|(|%28|g" -e "s|)|%29|g" -e "s|'|%27|g" \
505 506 -e "s|+|%2B|g" -e "s|\,|%2C|g" -e "s|\\\$|%24|g"
506 507 }
507 508
508 509 #
509 510 # input_cmd | html_quote | output_cmd
510 511 # or
511 512 # html_quote filename | output_cmd
512 513 #
513 514 # Make a piece of source code safe for display in an HTML <pre> block.
514 515 #
515 516 html_quote()
516 517 {
517 518 $SED -e "s/&/\&/g" -e "s/</\</g" -e "s/>/\>/g" "$@" | expand
518 519 }
519 520
520 521 #
521 522 # Trim a digest-style revision to a conventionally readable yet useful length
522 523 #
523 524 trim_digest()
524 525 {
525 526 typeset digest=$1
526 527
527 528 echo $digest | $SED -e 's/\([0-9a-f]\{12\}\).*/\1/'
528 529 }
529 530
530 531 #
531 532 # input_cmd | its2url | output_cmd
532 533 #
533 534 # Scan for information tracking system references and insert <a> links to the
534 535 # relevant databases.
535 536 #
536 537 its2url()
537 538 {
538 539 $SED -f ${its_sed_script}
539 540 }
540 541
541 542 #
542 543 # strip_unchanged <infile> | output_cmd
543 544 #
544 545 # Removes chunks of sdiff documents that have not changed. This makes it
545 546 # easier for a code reviewer to find the bits that have changed.
546 547 #
547 548 # Deleted lines of text are replaced by a horizontal rule. Some
548 549 # identical lines are retained before and after the changed lines to
549 550 # provide some context. The number of these lines is controlled by the
550 551 # variable C in the $AWK script below.
551 552 #
552 553 # The script detects changed lines as any line that has a "<span class="
553 554 # string embedded (unchanged lines have no particular class and are not
554 555 # part of a <span>). Blank lines (without a sequence number) are also
555 556 # detected since they flag lines that have been inserted or deleted.
556 557 #
557 558 strip_unchanged()
558 559 {
559 560 $AWK '
560 561 BEGIN { C = c = 20 }
561 562 NF == 0 || /<span class="/ {
562 563 if (c > C) {
563 564 c -= C
564 565 inx = 0
565 566 if (c > C) {
566 567 print "\n</pre><hr></hr><pre>"
567 568 inx = c % C
568 569 c = C
569 570 }
570 571
571 572 for (i = 0; i < c; i++)
572 573 print ln[(inx + i) % C]
573 574 }
574 575 c = 0;
575 576 print
576 577 next
577 578 }
578 579 { if (c >= C) {
579 580 ln[c % C] = $0
580 581 c++;
581 582 next;
582 583 }
583 584 c++;
584 585 print
585 586 }
586 587 END { if (c > (C * 2)) print "\n</pre><hr></hr>" }
587 588
588 589 ' $1
589 590 }
590 591
591 592 #
592 593 # sdiff_to_html
593 594 #
594 595 # This function takes two files as arguments, obtains their diff, and
595 596 # processes the diff output to present the files as an HTML document with
596 597 # the files displayed side-by-side, differences shown in color. It also
597 598 # takes a delta comment, rendered as an HTML snippet, as the third
598 599 # argument. The function takes two files as arguments, then the name of
599 600 # file, the path, and the comment. The HTML will be delivered on stdout,
600 601 # e.g.
601 602 #
602 603 # $ sdiff_to_html old/usr/src/tools/scripts/webrev.sh \
603 604 # new/usr/src/tools/scripts/webrev.sh \
604 605 # webrev.sh usr/src/tools/scripts \
605 606 # '<a href="http://monaco.sfbay.sun.com/detail.jsp?cr=1234567">
606 607 # 1234567</a> my bugid' > <file>.html
607 608 #
608 609 # framed_sdiff() is then called which creates $2.frames.html
609 610 # in the webrev tree.
610 611 #
611 612 # FYI: This function is rather unusual in its use of awk. The initial
612 613 # diff run produces conventional diff output showing changed lines mixed
613 614 # with editing codes. The changed lines are ignored - we're interested in
614 615 # the editing codes, e.g.
615 616 #
616 617 # 8c8
617 618 # 57a61
618 619 # 63c66,76
619 620 # 68,93d80
620 621 # 106d90
621 622 # 108,110d91
622 623 #
623 624 # These editing codes are parsed by the awk script and used to generate
624 625 # another awk script that generates HTML, e.g the above lines would turn
625 626 # into something like this:
626 627 #
627 628 # BEGIN { printf "<pre>\n" }
628 629 # function sp(n) {for (i=0;i<n;i++)printf "\n"}
629 630 # function wl(n) {printf "<font color=%s>%4d %s </font>\n", n, NR, $0}
630 631 # NR==8 {wl("#7A7ADD");next}
631 632 # NR==54 {wl("#7A7ADD");sp(3);next}
632 633 # NR==56 {wl("#7A7ADD");next}
633 634 # NR==57 {wl("black");printf "\n"; next}
634 635 # : :
635 636 #
636 637 # This script is then run on the original source file to generate the
637 638 # HTML that corresponds to the source file.
638 639 #
639 640 # The two HTML files are then combined into a single piece of HTML that
640 641 # uses an HTML table construct to present the files side by side. You'll
641 642 # notice that the changes are color-coded:
642 643 #
643 644 # black - unchanged lines
644 645 # blue - changed lines
645 646 # bold blue - new lines
646 647 # brown - deleted lines
647 648 #
648 649 # Blank lines are inserted in each file to keep unchanged lines in sync
649 650 # (side-by-side). This format is familiar to users of sdiff(1) or
650 651 # Teamware's filemerge tool.
651 652 #
652 653 sdiff_to_html()
653 654 {
654 655 diff -b $1 $2 > /tmp/$$.diffs
655 656
656 657 TNAME=$3
657 658 TPATH=$4
658 659 COMMENT=$5
659 660
660 661 #
661 662 # Now we have the diffs, generate the HTML for the old file.
662 663 #
663 664 $AWK '
664 665 BEGIN {
665 666 printf "function sp(n) {for (i=0;i<n;i++)printf \"\\n\"}\n"
666 667 printf "function removed() "
667 668 printf "{printf \"<span class=\\\"removed\\\">%%4d %%s</span>\\n\", NR, $0}\n"
668 669 printf "function changed() "
669 670 printf "{printf \"<span class=\\\"changed\\\">%%4d %%s</span>\\n\", NR, $0}\n"
670 671 printf "function bl() {printf \"%%4d %%s\\n\", NR, $0}\n"
671 672 }
672 673 /^</ {next}
673 674 /^>/ {next}
674 675 /^---/ {next}
675 676
676 677 {
677 678 split($1, a, /[cad]/) ;
678 679 if (index($1, "a")) {
679 680 if (a[1] == 0) {
680 681 n = split(a[2], r, /,/);
681 682 if (n == 1)
682 683 printf "BEGIN\t\t{sp(1)}\n"
683 684 else
684 685 printf "BEGIN\t\t{sp(%d)}\n",\
685 686 (r[2] - r[1]) + 1
686 687 next
687 688 }
688 689
689 690 printf "NR==%s\t\t{", a[1]
690 691 n = split(a[2], r, /,/);
691 692 s = r[1];
692 693 if (n == 1)
693 694 printf "bl();printf \"\\n\"; next}\n"
694 695 else {
695 696 n = r[2] - r[1]
696 697 printf "bl();sp(%d);next}\n",\
697 698 (r[2] - r[1]) + 1
698 699 }
699 700 next
700 701 }
701 702 if (index($1, "d")) {
702 703 n = split(a[1], r, /,/);
703 704 n1 = r[1]
704 705 n2 = r[2]
705 706 if (n == 1)
706 707 printf "NR==%s\t\t{removed(); next}\n" , n1
707 708 else
708 709 printf "NR==%s,NR==%s\t{removed(); next}\n" , n1, n2
709 710 next
710 711 }
711 712 if (index($1, "c")) {
712 713 n = split(a[1], r, /,/);
713 714 n1 = r[1]
714 715 n2 = r[2]
715 716 final = n2
716 717 d1 = 0
717 718 if (n == 1)
718 719 printf "NR==%s\t\t{changed();" , n1
719 720 else {
720 721 d1 = n2 - n1
721 722 printf "NR==%s,NR==%s\t{changed();" , n1, n2
722 723 }
723 724 m = split(a[2], r, /,/);
724 725 n1 = r[1]
725 726 n2 = r[2]
726 727 if (m > 1) {
727 728 d2 = n2 - n1
728 729 if (d2 > d1) {
729 730 if (n > 1) printf "if (NR==%d)", final
730 731 printf "sp(%d);", d2 - d1
731 732 }
732 733 }
733 734 printf "next}\n" ;
734 735
735 736 next
736 737 }
737 738 }
738 739
739 740 END { printf "{printf \"%%4d %%s\\n\", NR, $0 }\n" }
740 741 ' /tmp/$$.diffs > /tmp/$$.file1
741 742
742 743 #
743 744 # Now generate the HTML for the new file
744 745 #
745 746 $AWK '
746 747 BEGIN {
747 748 printf "function sp(n) {for (i=0;i<n;i++)printf \"\\n\"}\n"
748 749 printf "function new() "
749 750 printf "{printf \"<span class=\\\"new\\\">%%4d %%s</span>\\n\", NR, $0}\n"
750 751 printf "function changed() "
751 752 printf "{printf \"<span class=\\\"changed\\\">%%4d %%s</span>\\n\", NR, $0}\n"
752 753 printf "function bl() {printf \"%%4d %%s\\n\", NR, $0}\n"
753 754 }
754 755
755 756 /^</ {next}
756 757 /^>/ {next}
757 758 /^---/ {next}
758 759
759 760 {
760 761 split($1, a, /[cad]/) ;
761 762 if (index($1, "d")) {
762 763 if (a[2] == 0) {
763 764 n = split(a[1], r, /,/);
764 765 if (n == 1)
765 766 printf "BEGIN\t\t{sp(1)}\n"
766 767 else
767 768 printf "BEGIN\t\t{sp(%d)}\n",\
768 769 (r[2] - r[1]) + 1
769 770 next
770 771 }
771 772
772 773 printf "NR==%s\t\t{", a[2]
773 774 n = split(a[1], r, /,/);
774 775 s = r[1];
775 776 if (n == 1)
776 777 printf "bl();printf \"\\n\"; next}\n"
777 778 else {
778 779 n = r[2] - r[1]
779 780 printf "bl();sp(%d);next}\n",\
780 781 (r[2] - r[1]) + 1
781 782 }
782 783 next
783 784 }
784 785 if (index($1, "a")) {
785 786 n = split(a[2], r, /,/);
786 787 n1 = r[1]
787 788 n2 = r[2]
788 789 if (n == 1)
789 790 printf "NR==%s\t\t{new() ; next}\n" , n1
790 791 else
791 792 printf "NR==%s,NR==%s\t{new() ; next}\n" , n1, n2
792 793 next
793 794 }
794 795 if (index($1, "c")) {
795 796 n = split(a[2], r, /,/);
796 797 n1 = r[1]
797 798 n2 = r[2]
798 799 final = n2
799 800 d2 = 0;
800 801 if (n == 1) {
801 802 final = n1
802 803 printf "NR==%s\t\t{changed();" , n1
803 804 } else {
804 805 d2 = n2 - n1
805 806 printf "NR==%s,NR==%s\t{changed();" , n1, n2
806 807 }
807 808 m = split(a[1], r, /,/);
808 809 n1 = r[1]
809 810 n2 = r[2]
810 811 if (m > 1) {
811 812 d1 = n2 - n1
812 813 if (d1 > d2) {
813 814 if (n > 1) printf "if (NR==%d)", final
814 815 printf "sp(%d);", d1 - d2
815 816 }
816 817 }
817 818 printf "next}\n" ;
818 819 next
819 820 }
820 821 }
821 822 END { printf "{printf \"%%4d %%s\\n\", NR, $0 }\n" }
822 823 ' /tmp/$$.diffs > /tmp/$$.file2
823 824
824 825 #
825 826 # Post-process the HTML files by running them back through $AWK
826 827 #
827 828 html_quote < $1 | $AWK -f /tmp/$$.file1 > /tmp/$$.file1.html
828 829
829 830 html_quote < $2 | $AWK -f /tmp/$$.file2 > /tmp/$$.file2.html
830 831
831 832 #
832 833 # Now combine into a valid HTML file and side-by-side into a table
833 834 #
834 835 print "$HTML<head>$STDHEAD"
835 836 print "<title>$WNAME Sdiff $TPATH/$TNAME</title>"
836 837 print "</head><body id=\"SUNWwebrev\">"
837 838 print "<a class=\"print\" href=\"javascript:print()\">Print this page</a>"
838 839 print "<pre>$COMMENT</pre>\n"
839 840 print "<table><tr valign=\"top\">"
840 841 print "<td><pre>"
841 842
842 843 strip_unchanged /tmp/$$.file1.html
843 844
844 845 print "</pre></td><td><pre>"
845 846
846 847 strip_unchanged /tmp/$$.file2.html
847 848
848 849 print "</pre></td>"
849 850 print "</tr></table>"
850 851 print "</body></html>"
851 852
852 853 framed_sdiff $TNAME $TPATH /tmp/$$.file1.html /tmp/$$.file2.html \
853 854 "$COMMENT"
854 855 }
855 856
856 857
857 858 #
858 859 # framed_sdiff <filename> <filepath> <lhsfile> <rhsfile> <comment>
859 860 #
860 861 # Expects lefthand and righthand side html files created by sdiff_to_html.
861 862 # We use insert_anchors() to augment those with HTML navigation anchors,
862 863 # and then emit the main frame. Content is placed into:
863 864 #
864 865 # $WDIR/DIR/$TNAME.lhs.html
865 866 # $WDIR/DIR/$TNAME.rhs.html
866 867 # $WDIR/DIR/$TNAME.frames.html
867 868 #
868 869 # NOTE: We rely on standard usage of $WDIR and $DIR.
869 870 #
870 871 function framed_sdiff
871 872 {
872 873 typeset TNAME=$1
873 874 typeset TPATH=$2
874 875 typeset lhsfile=$3
875 876 typeset rhsfile=$4
876 877 typeset comments=$5
877 878 typeset RTOP
878 879
879 880 # Enable html files to access WDIR via a relative path.
880 881 RTOP=$(relative_dir $TPATH $WDIR)
881 882
882 883 # Make the rhs/lhs files and output the frameset file.
883 884 print "$HTML<head>$STDHEAD" > $WDIR/$DIR/$TNAME.lhs.html
884 885
885 886 cat >> $WDIR/$DIR/$TNAME.lhs.html <<-EOF
886 887 <script type="text/javascript" src="${RTOP}ancnav.js"></script>
887 888 </head>
888 889 <body id="SUNWwebrev" onkeypress="keypress(event);">
889 890 <a name="0"></a>
890 891 <pre>$comments</pre><hr></hr>
891 892 EOF
892 893
893 894 cp $WDIR/$DIR/$TNAME.lhs.html $WDIR/$DIR/$TNAME.rhs.html
894 895
895 896 insert_anchors $lhsfile >> $WDIR/$DIR/$TNAME.lhs.html
896 897 insert_anchors $rhsfile >> $WDIR/$DIR/$TNAME.rhs.html
897 898
898 899 close='</body></html>'
899 900
900 901 print $close >> $WDIR/$DIR/$TNAME.lhs.html
901 902 print $close >> $WDIR/$DIR/$TNAME.rhs.html
902 903
903 904 print "$FRAMEHTML<head>$STDHEAD" > $WDIR/$DIR/$TNAME.frames.html
904 905 print "<title>$WNAME Framed-Sdiff " \
905 906 "$TPATH/$TNAME</title> </head>" >> $WDIR/$DIR/$TNAME.frames.html
906 907 cat >> $WDIR/$DIR/$TNAME.frames.html <<-EOF
907 908 <frameset rows="*,60">
908 909 <frameset cols="50%,50%">
909 910 <frame src="$TNAME.lhs.html" scrolling="auto" name="lhs"></frame>
910 911 <frame src="$TNAME.rhs.html" scrolling="auto" name="rhs"></frame>
911 912 </frameset>
912 913 <frame src="${RTOP}ancnav.html" scrolling="no" marginwidth="0"
913 914 marginheight="0" name="nav"></frame>
914 915 <noframes>
915 916 <body id="SUNWwebrev">
916 917 Alas 'frames' webrev requires that your browser supports frames
917 918 and has the feature enabled.
918 919 </body>
919 920 </noframes>
920 921 </frameset>
921 922 </html>
922 923 EOF
923 924 }
924 925
925 926
926 927 #
927 928 # fix_postscript
928 929 #
929 930 # Merge codereview output files to a single conforming postscript file, by:
930 931 # - removing all extraneous headers/trailers
931 932 # - making the page numbers right
932 933 # - removing pages devoid of contents which confuse some
933 934 # postscript readers.
934 935 #
935 936 # From Casper.
936 937 #
937 938 function fix_postscript
938 939 {
939 940 infile=$1
940 941
941 942 cat > /tmp/$$.crmerge.pl << \EOF
942 943
943 944 print scalar(<>); # %!PS-Adobe---
944 945 print "%%Orientation: Landscape\n";
945 946
946 947 $pno = 0;
947 948 $doprint = 1;
948 949
949 950 $page = "";
950 951
951 952 while (<>) {
952 953 next if (/^%%Pages:\s*\d+/);
953 954
954 955 if (/^%%Page:/) {
955 956 if ($pno == 0 || $page =~ /\)S/) {
956 957 # Header or single page containing text
957 958 print "%%Page: ? $pno\n" if ($pno > 0);
958 959 print $page;
959 960 $pno++;
960 961 } else {
961 962 # Empty page, skip it.
962 963 }
963 964 $page = "";
964 965 $doprint = 1;
965 966 next;
966 967 }
967 968
968 969 # Skip from %%Trailer of one document to Endprolog
969 970 # %%Page of the next
970 971 $doprint = 0 if (/^%%Trailer/);
971 972 $page .= $_ if ($doprint);
972 973 }
973 974
974 975 if ($page =~ /\)S/) {
975 976 print "%%Page: ? $pno\n";
976 977 print $page;
977 978 } else {
978 979 $pno--;
979 980 }
980 981 print "%%Trailer\n%%Pages: $pno\n";
981 982 EOF
982 983
983 984 $PERL /tmp/$$.crmerge.pl < $infile
984 985 }
985 986
986 987
987 988 #
988 989 # input_cmd | insert_anchors | output_cmd
989 990 #
990 991 # Flag blocks of difference with sequentially numbered invisible
991 992 # anchors. These are used to drive the frames version of the
992 993 # sdiffs output.
993 994 #
994 995 # NOTE: Anchor zero flags the top of the file irrespective of changes,
995 996 # an additional anchor is also appended to flag the bottom.
996 997 #
997 998 # The script detects changed lines as any line that has a "<span
998 999 # class=" string embedded (unchanged lines have no class set and are
999 1000 # not part of a <span>. Blank lines (without a sequence number)
1000 1001 # are also detected since they flag lines that have been inserted or
1001 1002 # deleted.
1002 1003 #
1003 1004 function insert_anchors
1004 1005 {
1005 1006 $AWK '
1006 1007 function ia() {
1007 1008 printf "<a name=\"%d\" id=\"anc%d\"></a>", anc, anc++;
1008 1009 }
1009 1010
1010 1011 BEGIN {
1011 1012 anc=1;
1012 1013 inblock=1;
1013 1014 printf "<pre>\n";
1014 1015 }
1015 1016 NF == 0 || /^<span class=/ {
1016 1017 if (inblock == 0) {
1017 1018 ia();
1018 1019 inblock=1;
1019 1020 }
1020 1021 print;
1021 1022 next;
1022 1023 }
1023 1024 {
1024 1025 inblock=0;
1025 1026 print;
1026 1027 }
1027 1028 END {
1028 1029 ia();
1029 1030
1030 1031 printf "<b style=\"font-size: large; color: red\">";
1031 1032 printf "--- EOF ---</b>"
1032 1033 for(i=0;i<8;i++) printf "\n\n\n\n\n\n\n\n\n\n";
1033 1034 printf "</pre>"
1034 1035 printf "<form name=\"eof\">";
1035 1036 printf "<input name=\"value\" value=\"%d\" " \
1036 1037 "type=\"hidden\"></input>", anc - 1;
1037 1038 printf "</form>";
1038 1039 }
1039 1040 ' $1
1040 1041 }
1041 1042
1042 1043
1043 1044 #
1044 1045 # relative_dir
1045 1046 #
1046 1047 # Print a relative return path from $1 to $2. For example if
1047 1048 # $1=/tmp/myreview/raw_files/usr/src/tools/scripts and $2=/tmp/myreview,
1048 1049 # this function would print "../../../../".
1049 1050 #
1050 1051 # In the event that $1 is not in $2 a warning is printed to stderr,
1051 1052 # and $2 is returned-- the result of this is that the resulting webrev
1052 1053 # is not relocatable.
1053 1054 #
1054 1055 function relative_dir
1055 1056 {
1056 1057 typeset cur="${1##$2?(/)}"
1057 1058
1058 1059 #
1059 1060 # If the first path was specified absolutely, and it does
1060 1061 # not start with the second path, it's an error.
1061 1062 #
1062 1063 if [[ "$cur" = "/${1#/}" ]]; then
1063 1064 # Should never happen.
1064 1065 print -u2 "\nWARNING: relative_dir: \"$1\" not relative "
1065 1066 print -u2 "to \"$2\". Check input paths. Framed webrev "
1066 1067 print -u2 "will not be relocatable!"
1067 1068 print $2
1068 1069 return
1069 1070 fi
1070 1071
1071 1072 #
1072 1073 # This is kind of ugly. The sed script will do the following:
1073 1074 #
1074 1075 # 1. Strip off a leading "." or "./": this is important to get
1075 1076 # the correct arcnav links for files in $WDIR.
1076 1077 # 2. Strip off a trailing "/": this is not strictly necessary,
1077 1078 # but is kind of nice, since it doesn't end up in "//" at
1078 1079 # the end of a relative path.
1079 1080 # 3. Replace all remaining sequences of non-"/" with "..": the
1080 1081 # assumption here is that each dirname represents another
1081 1082 # level of relative separation.
1082 1083 # 4. Append a trailing "/" only for non-empty paths: this way
1083 1084 # the caller doesn't need to duplicate this logic, and does
1084 1085 # not end up using $RTOP/file for files in $WDIR.
1085 1086 #
1086 1087 print $cur | $SED -e '{
1087 1088 s:^\./*::
1088 1089 s:/$::
1089 1090 s:[^/][^/]*:..:g
1090 1091 s:^\(..*\)$:\1/:
1091 1092 }'
1092 1093 }
1093 1094
1094 1095 #
1095 1096 # frame_nav_js
1096 1097 #
1097 1098 # Emit javascript for frame navigation
1098 1099 #
1099 1100 function frame_nav_js
1100 1101 {
1101 1102 cat << \EOF
1102 1103 var myInt;
1103 1104 var scrolling=0;
1104 1105 var sfactor = 3;
1105 1106 var scount=10;
1106 1107
1107 1108 function scrollByPix() {
1108 1109 if (scount<=0) {
1109 1110 sfactor*=1.2;
1110 1111 scount=10;
1111 1112 }
1112 1113 parent.lhs.scrollBy(0,sfactor);
1113 1114 parent.rhs.scrollBy(0,sfactor);
1114 1115 scount--;
1115 1116 }
1116 1117
1117 1118 function scrollToAnc(num) {
1118 1119
1119 1120 // Update the value of the anchor in the form which we use as
1120 1121 // storage for this value. setAncValue() will take care of
1121 1122 // correcting for overflow and underflow of the value and return
1122 1123 // us the new value.
1123 1124 num = setAncValue(num);
1124 1125
1125 1126 // Set location and scroll back a little to expose previous
1126 1127 // lines.
1127 1128 //
1128 1129 // Note that this could be improved: it is possible although
1129 1130 // complex to compute the x and y position of an anchor, and to
1130 1131 // scroll to that location directly.
1131 1132 //
1132 1133 parent.lhs.location.replace(parent.lhs.location.pathname + "#" + num);
1133 1134 parent.rhs.location.replace(parent.rhs.location.pathname + "#" + num);
1134 1135
1135 1136 parent.lhs.scrollBy(0,-30);
1136 1137 parent.rhs.scrollBy(0,-30);
1137 1138 }
1138 1139
1139 1140 function getAncValue()
1140 1141 {
1141 1142 return (parseInt(parent.nav.document.diff.real.value));
1142 1143 }
1143 1144
1144 1145 function setAncValue(val)
1145 1146 {
1146 1147 if (val <= 0) {
1147 1148 val = 0;
1148 1149 parent.nav.document.diff.real.value = val;
1149 1150 parent.nav.document.diff.display.value = "BOF";
1150 1151 return (val);
1151 1152 }
1152 1153
1153 1154 //
1154 1155 // The way we compute the max anchor value is to stash it
1155 1156 // inline in the left and right hand side pages-- it's the same
1156 1157 // on each side, so we pluck from the left.
1157 1158 //
1158 1159 maxval = parent.lhs.document.eof.value.value;
1159 1160 if (val < maxval) {
1160 1161 parent.nav.document.diff.real.value = val;
1161 1162 parent.nav.document.diff.display.value = val.toString();
1162 1163 return (val);
1163 1164 }
1164 1165
1165 1166 // this must be: val >= maxval
1166 1167 val = maxval;
1167 1168 parent.nav.document.diff.real.value = val;
1168 1169 parent.nav.document.diff.display.value = "EOF";
1169 1170 return (val);
1170 1171 }
1171 1172
1172 1173 function stopScroll() {
1173 1174 if (scrolling==1) {
1174 1175 clearInterval(myInt);
1175 1176 scrolling=0;
1176 1177 }
1177 1178 }
1178 1179
1179 1180 function startScroll() {
1180 1181 stopScroll();
1181 1182 scrolling=1;
1182 1183 myInt=setInterval("scrollByPix()",10);
1183 1184 }
1184 1185
1185 1186 function handlePress(b) {
1186 1187
1187 1188 switch (b) {
1188 1189 case 1 :
1189 1190 scrollToAnc(-1);
1190 1191 break;
1191 1192 case 2 :
1192 1193 scrollToAnc(getAncValue() - 1);
1193 1194 break;
1194 1195 case 3 :
1195 1196 sfactor=-3;
1196 1197 startScroll();
1197 1198 break;
1198 1199 case 4 :
1199 1200 sfactor=3;
1200 1201 startScroll();
1201 1202 break;
1202 1203 case 5 :
1203 1204 scrollToAnc(getAncValue() + 1);
1204 1205 break;
1205 1206 case 6 :
1206 1207 scrollToAnc(999999);
1207 1208 break;
1208 1209 }
1209 1210 }
1210 1211
1211 1212 function handleRelease(b) {
1212 1213 stopScroll();
1213 1214 }
1214 1215
1215 1216 function keypress(ev) {
1216 1217 var keynum;
1217 1218 var keychar;
1218 1219
1219 1220 if (window.event) { // IE
1220 1221 keynum = ev.keyCode;
1221 1222 } else if (ev.which) { // non-IE
1222 1223 keynum = ev.which;
1223 1224 }
1224 1225
1225 1226 keychar = String.fromCharCode(keynum);
1226 1227
1227 1228 if (keychar == "k") {
1228 1229 handlePress(2);
1229 1230 return (0);
1230 1231 } else if (keychar == "j" || keychar == " ") {
1231 1232 handlePress(5);
1232 1233 return (0);
1233 1234 }
1234 1235 return (1);
1235 1236 }
1236 1237
1237 1238 function ValidateDiffNum(){
1238 1239 val = parent.nav.document.diff.display.value;
1239 1240 if (val == "EOF") {
1240 1241 scrollToAnc(999999);
1241 1242 return;
1242 1243 }
1243 1244
1244 1245 if (val == "BOF") {
1245 1246 scrollToAnc(0);
1246 1247 return;
1247 1248 }
1248 1249
1249 1250 i=parseInt(val);
1250 1251 if (isNaN(i)) {
1251 1252 parent.nav.document.diff.display.value = getAncValue();
1252 1253 } else {
1253 1254 scrollToAnc(i);
1254 1255 }
1255 1256 return false;
1256 1257 }
1257 1258
1258 1259 EOF
1259 1260 }
1260 1261
1261 1262 #
1262 1263 # frame_navigation
1263 1264 #
1264 1265 # Output anchor navigation file for framed sdiffs.
1265 1266 #
1266 1267 function frame_navigation
1267 1268 {
1268 1269 print "$HTML<head>$STDHEAD"
1269 1270
1270 1271 cat << \EOF
1271 1272 <title>Anchor Navigation</title>
1272 1273 <meta http-equiv="Content-Script-Type" content="text/javascript">
1273 1274 <meta http-equiv="Content-Type" content="text/html">
1274 1275
1275 1276 <style type="text/css">
1276 1277 div.button td { padding-left: 5px; padding-right: 5px;
1277 1278 background-color: #eee; text-align: center;
1278 1279 border: 1px #444 outset; cursor: pointer; }
1279 1280 div.button a { font-weight: bold; color: black }
1280 1281 div.button td:hover { background: #ffcc99; }
1281 1282 </style>
1282 1283 EOF
1283 1284
1284 1285 print "<script type=\"text/javascript\" src=\"ancnav.js\"></script>"
1285 1286
1286 1287 cat << \EOF
1287 1288 </head>
1288 1289 <body id="SUNWwebrev" bgcolor="#eeeeee" onload="document.diff.real.focus();"
1289 1290 onkeypress="keypress(event);">
1290 1291 <noscript lang="javascript">
1291 1292 <center>
1292 1293 <p><big>Framed Navigation controls require Javascript</big><br></br>
1293 1294 Either this browser is incompatable or javascript is not enabled</p>
1294 1295 </center>
1295 1296 </noscript>
1296 1297 <table width="100%" border="0" align="center">
1297 1298 <tr>
1298 1299 <td valign="middle" width="25%">Diff navigation:
1299 1300 Use 'j' and 'k' for next and previous diffs; or use buttons
1300 1301 at right</td>
1301 1302 <td align="center" valign="top" width="50%">
1302 1303 <div class="button">
1303 1304 <table border="0" align="center">
1304 1305 <tr>
1305 1306 <td>
1306 1307 <a onMouseDown="handlePress(1);return true;"
1307 1308 onMouseUp="handleRelease(1);return true;"
1308 1309 onMouseOut="handleRelease(1);return true;"
1309 1310 onClick="return false;"
1310 1311 title="Go to Beginning Of file">BOF</a></td>
1311 1312 <td>
1312 1313 <a onMouseDown="handlePress(3);return true;"
1313 1314 onMouseUp="handleRelease(3);return true;"
1314 1315 onMouseOut="handleRelease(3);return true;"
1315 1316 title="Scroll Up: Press and Hold to accelerate"
1316 1317 onClick="return false;">Scroll Up</a></td>
1317 1318 <td>
1318 1319 <a onMouseDown="handlePress(2);return true;"
1319 1320 onMouseUp="handleRelease(2);return true;"
1320 1321 onMouseOut="handleRelease(2);return true;"
1321 1322 title="Go to previous Diff"
1322 1323 onClick="return false;">Prev Diff</a>
1323 1324 </td></tr>
1324 1325
1325 1326 <tr>
1326 1327 <td>
1327 1328 <a onMouseDown="handlePress(6);return true;"
1328 1329 onMouseUp="handleRelease(6);return true;"
1329 1330 onMouseOut="handleRelease(6);return true;"
1330 1331 onClick="return false;"
1331 1332 title="Go to End Of File">EOF</a></td>
1332 1333 <td>
1333 1334 <a onMouseDown="handlePress(4);return true;"
1334 1335 onMouseUp="handleRelease(4);return true;"
1335 1336 onMouseOut="handleRelease(4);return true;"
1336 1337 title="Scroll Down: Press and Hold to accelerate"
1337 1338 onClick="return false;">Scroll Down</a></td>
1338 1339 <td>
1339 1340 <a onMouseDown="handlePress(5);return true;"
1340 1341 onMouseUp="handleRelease(5);return true;"
1341 1342 onMouseOut="handleRelease(5);return true;"
1342 1343 title="Go to next Diff"
1343 1344 onClick="return false;">Next Diff</a></td>
1344 1345 </tr>
1345 1346 </table>
1346 1347 </div>
1347 1348 </td>
1348 1349 <th valign="middle" width="25%">
1349 1350 <form action="" name="diff" onsubmit="return ValidateDiffNum();">
1350 1351 <input name="display" value="BOF" size="8" type="text"></input>
1351 1352 <input name="real" value="0" size="8" type="hidden"></input>
1352 1353 </form>
1353 1354 </th>
1354 1355 </tr>
1355 1356 </table>
1356 1357 </body>
1357 1358 </html>
1358 1359 EOF
1359 1360 }
1360 1361
1361 1362
1362 1363
1363 1364 #
1364 1365 # diff_to_html <filename> <filepath> { U | C } <comment>
1365 1366 #
1366 1367 # Processes the output of diff to produce an HTML file representing either
1367 1368 # context or unified diffs.
1368 1369 #
1369 1370 diff_to_html()
1370 1371 {
1371 1372 TNAME=$1
1372 1373 TPATH=$2
1373 1374 DIFFTYPE=$3
1374 1375 COMMENT=$4
1375 1376
1376 1377 print "$HTML<head>$STDHEAD"
1377 1378 print "<title>$WNAME ${DIFFTYPE}diff $TPATH</title>"
1378 1379
1379 1380 if [[ $DIFFTYPE == "U" ]]; then
1380 1381 print "$UDIFFCSS"
1381 1382 fi
1382 1383
1383 1384 cat <<-EOF
1384 1385 </head>
1385 1386 <body id="SUNWwebrev">
1386 1387 <a class="print" href="javascript:print()">Print this page</a>
1387 1388 <pre>$COMMENT</pre>
1388 1389 <pre>
1389 1390 EOF
1390 1391
1391 1392 html_quote | $AWK '
1392 1393 /^--- new/ { next }
1393 1394 /^\+\+\+ new/ { next }
1394 1395 /^--- old/ { next }
1395 1396 /^\*\*\* old/ { next }
1396 1397 /^\*\*\*\*/ { next }
1397 1398 /^-------/ { printf "<center><h1>%s</h1></center>\n", $0; next }
1398 1399 /^\@\@.*\@\@$/ { printf "</pre><hr></hr><pre>\n";
1399 1400 printf "<span class=\"newmarker\">%s</span>\n", $0;
1400 1401 next}
1401 1402
1402 1403 /^\*\*\*/ { printf "<hr></hr><span class=\"oldmarker\">%s</span>\n", $0;
1403 1404 next}
1404 1405 /^---/ { printf "<span class=\"newmarker\">%s</span>\n", $0;
1405 1406 next}
1406 1407 /^\+/ {printf "<span class=\"new\">%s</span>\n", $0; next}
1407 1408 /^!/ {printf "<span class=\"changed\">%s</span>\n", $0; next}
1408 1409 /^-/ {printf "<span class=\"removed\">%s</span>\n", $0; next}
1409 1410 {printf "%s\n", $0; next}
1410 1411 '
1411 1412
1412 1413 print "</pre></body></html>\n"
1413 1414 }
1414 1415
1415 1416
1416 1417 #
1417 1418 # source_to_html { new | old } <filename>
1418 1419 #
1419 1420 # Process a plain vanilla source file to transform it into an HTML file.
1420 1421 #
1421 1422 source_to_html()
1422 1423 {
1423 1424 WHICH=$1
1424 1425 TNAME=$2
↓ open down ↓ |
1386 lines elided |
↑ open up ↑ |
1425 1426
1426 1427 print "$HTML<head>$STDHEAD"
1427 1428 print "<title>$WNAME $WHICH $TNAME</title>"
1428 1429 print "<body id=\"SUNWwebrev\">"
1429 1430 print "<pre>"
1430 1431 html_quote | $AWK '{line += 1 ; printf "%4d %s\n", line, $0 }'
1431 1432 print "</pre></body></html>"
1432 1433 }
1433 1434
1434 1435 #
1435 -# comments_from_teamware {text|html} parent-file child-file
1436 -#
1437 -# Find the first delta in the child that's not in the parent. Get the
1438 -# newest delta from the parent, get all deltas from the child starting
1439 -# with that delta, and then get all info starting with the second oldest
1440 -# delta in that list (the first delta unique to the child).
1441 -#
1442 -# This code adapted from Bill Shannon's "spc" script
1443 -#
1444 -comments_from_teamware()
1445 -{
1446 - fmt=$1
1447 - pfile=$PWS/$2
1448 - cfile=$CWS/$3
1449 -
1450 - if [[ ! -f $PWS/${2%/*}/SCCS/s.${2##*/} && -n $RWS ]]; then
1451 - pfile=$RWS/$2
1452 - fi
1453 -
1454 - if [[ -f $pfile ]]; then
1455 - psid=$($SCCS prs -d:I: $pfile 2>/dev/null)
1456 - else
1457 - psid=1.1
1458 - fi
1459 -
1460 - set -A sids $($SCCS prs -l -r$psid -d:I: $cfile 2>/dev/null)
1461 - N=${#sids[@]}
1462 -
1463 - nawkprg='
1464 - /^COMMENTS:/ {p=1; continue}
1465 - /^D [0-9]+\.[0-9]+/ {printf "--- %s ---\n", $2; p=0; }
1466 - NF == 0u { continue }
1467 - {if (p==0) continue; print $0 }'
1468 -
1469 - if [[ $N -ge 2 ]]; then
1470 - sid1=${sids[$((N-2))]} # Gets 2nd to last sid
1471 -
1472 - if [[ $fmt == "text" ]]; then
1473 - $SCCS prs -l -r$sid1 $cfile 2>/dev/null | \
1474 - $AWK "$nawkprg"
1475 - return
1476 - fi
1477 -
1478 - $SCCS prs -l -r$sid1 $cfile 2>/dev/null | \
1479 - html_quote | its2url | $AWK "$nawkprg"
1480 - fi
1481 -}
1482 -
1483 -#
1484 1436 # comments_from_wx {text|html} filepath
1485 1437 #
1486 1438 # Given the pathname of a file, find its location in a "wx" active
1487 1439 # file list and print the following comment. Output is either text or
1488 1440 # HTML; if the latter, embedded bugids (sequence of 5 or more digits)
1489 1441 # are turned into URLs.
1490 1442 #
1491 1443 # This is also used with Mercurial and the file list provided by hg-active.
1492 1444 #
1493 1445 comments_from_wx()
1494 1446 {
1495 1447 typeset fmt=$1
1496 1448 typeset p=$2
1497 1449
1498 1450 comm=`$AWK '
1499 1451 $1 == "'$p'" {
1500 1452 do getline ; while (NF > 0)
1501 1453 getline
1502 1454 while (NF > 0) { print ; getline }
1503 1455 exit
1504 1456 }' < $wxfile`
1505 1457
1506 1458 if [[ -z $comm ]]; then
1507 1459 comm="*** NO COMMENTS ***"
1508 1460 fi
1509 1461
1510 1462 if [[ $fmt == "text" ]]; then
1511 1463 print -- "$comm"
1512 1464 return
1513 1465 fi
1514 1466
1515 1467 print -- "$comm" | html_quote | its2url
1516 1468
1517 1469 }
1518 1470
1519 1471 #
1520 1472 # getcomments {text|html} filepath parentpath
1521 1473 #
1522 1474 # Fetch the comments depending on what SCM mode we're in.
1523 1475 #
1524 1476 getcomments()
1525 1477 {
1526 1478 typeset fmt=$1
1527 1479 typeset p=$2
1528 1480 typeset pp=$3
↓ open down ↓ |
35 lines elided |
↑ open up ↑ |
1529 1481
1530 1482 if [[ -n $Nflag ]]; then
1531 1483 return
1532 1484 fi
1533 1485 #
1534 1486 # Mercurial support uses a file list in wx format, so this
1535 1487 # will be used there, too
1536 1488 #
1537 1489 if [[ -n $wxfile ]]; then
1538 1490 comments_from_wx $fmt $p
1539 - else
1540 - if [[ $SCM_MODE == "teamware" ]]; then
1541 - comments_from_teamware $fmt $pp $p
1542 - fi
1543 1491 fi
1544 1492 }
1545 1493
1546 1494 #
1547 1495 # printCI <total-changed> <inserted> <deleted> <modified> <unchanged>
1548 1496 #
1549 1497 # Print out Code Inspection figures similar to sccs-prt(1) format.
1550 1498 #
1551 1499 function printCI
1552 1500 {
1553 1501 integer tot=$1 ins=$2 del=$3 mod=$4 unc=$5
1554 1502 typeset str
1555 1503 if (( tot == 1 )); then
1556 1504 str="line"
1557 1505 else
1558 1506 str="lines"
1559 1507 fi
1560 1508 printf '%d %s changed: %d ins; %d del; %d mod; %d unchg\n' \
1561 1509 $tot $str $ins $del $mod $unc
1562 1510 }
1563 1511
1564 1512
1565 1513 #
1566 1514 # difflines <oldfile> <newfile>
1567 1515 #
1568 1516 # Calculate and emit number of added, removed, modified and unchanged lines,
1569 1517 # and total lines changed, the sum of added + removed + modified.
1570 1518 #
1571 1519 function difflines
1572 1520 {
1573 1521 integer tot mod del ins unc err
1574 1522 typeset filename
1575 1523
1576 1524 eval $( diff -e $1 $2 | $AWK '
1577 1525 # Change range of lines: N,Nc
1578 1526 /^[0-9]*,[0-9]*c$/ {
1579 1527 n=split(substr($1,1,length($1)-1), counts, ",");
1580 1528 if (n != 2) {
1581 1529 error=2
1582 1530 exit;
1583 1531 }
1584 1532 #
1585 1533 # 3,5c means lines 3 , 4 and 5 are changed, a total of 3 lines.
1586 1534 # following would be 5 - 3 = 2! Hence +1 for correction.
1587 1535 #
1588 1536 r=(counts[2]-counts[1])+1;
1589 1537
1590 1538 #
1591 1539 # Now count replacement lines: each represents a change instead
1592 1540 # of a delete, so increment c and decrement r.
1593 1541 #
1594 1542 while (getline != /^\.$/) {
1595 1543 c++;
1596 1544 r--;
1597 1545 }
1598 1546 #
1599 1547 # If there were more replacement lines than original lines,
1600 1548 # then r will be negative; in this case there are no deletions,
1601 1549 # but there are r changes that should be counted as adds, and
1602 1550 # since r is negative, subtract it from a and add it to c.
1603 1551 #
1604 1552 if (r < 0) {
1605 1553 a-=r;
1606 1554 c+=r;
1607 1555 }
1608 1556
1609 1557 #
1610 1558 # If there were more original lines than replacement lines, then
1611 1559 # r will be positive; in this case, increment d by that much.
1612 1560 #
1613 1561 if (r > 0) {
1614 1562 d+=r;
1615 1563 }
1616 1564 next;
1617 1565 }
1618 1566
1619 1567 # Change lines: Nc
1620 1568 /^[0-9].*c$/ {
1621 1569 # The first line is a replacement; any more are additions.
1622 1570 if (getline != /^\.$/) {
1623 1571 c++;
1624 1572 while (getline != /^\.$/) a++;
1625 1573 }
1626 1574 next;
1627 1575 }
1628 1576
1629 1577 # Add lines: both Na and N,Na
1630 1578 /^[0-9].*a$/ {
1631 1579 while (getline != /^\.$/) a++;
1632 1580 next;
1633 1581 }
1634 1582
1635 1583 # Delete range of lines: N,Nd
1636 1584 /^[0-9]*,[0-9]*d$/ {
1637 1585 n=split(substr($1,1,length($1)-1), counts, ",");
1638 1586 if (n != 2) {
1639 1587 error=2
1640 1588 exit;
1641 1589 }
1642 1590 #
1643 1591 # 3,5d means lines 3 , 4 and 5 are deleted, a total of 3 lines.
1644 1592 # following would be 5 - 3 = 2! Hence +1 for correction.
1645 1593 #
1646 1594 r=(counts[2]-counts[1])+1;
1647 1595 d+=r;
1648 1596 next;
1649 1597 }
1650 1598
1651 1599 # Delete line: Nd. For example 10d says line 10 is deleted.
1652 1600 /^[0-9]*d$/ {d++; next}
1653 1601
1654 1602 # Should not get here!
1655 1603 {
1656 1604 error=1;
1657 1605 exit;
1658 1606 }
1659 1607
1660 1608 # Finish off - print results
1661 1609 END {
1662 1610 printf("tot=%d;mod=%d;del=%d;ins=%d;err=%d\n",
1663 1611 (c+d+a), c, d, a, error);
1664 1612 }' )
1665 1613
1666 1614 # End of $AWK, Check to see if any trouble occurred.
1667 1615 if (( $? > 0 || err > 0 )); then
1668 1616 print "Unexpected Error occurred reading" \
1669 1617 "\`diff -e $1 $2\`: \$?=$?, err=" $err
1670 1618 return
1671 1619 fi
1672 1620
1673 1621 # Accumulate totals
1674 1622 (( TOTL += tot ))
1675 1623 (( TMOD += mod ))
1676 1624 (( TDEL += del ))
1677 1625 (( TINS += ins ))
1678 1626 # Calculate unchanged lines
1679 1627 unc=`wc -l < $1`
1680 1628 if (( unc > 0 )); then
1681 1629 (( unc -= del + mod ))
1682 1630 (( TUNC += unc ))
1683 1631 fi
1684 1632 # print summary
1685 1633 print "<span class=\"lineschanged\">"
1686 1634 printCI $tot $ins $del $mod $unc
1687 1635 print "</span>"
1688 1636 }
1689 1637
1690 1638
1691 1639 #
1692 1640 # flist_from_wx
1693 1641 #
1694 1642 # Sets up webrev to source its information from a wx-formatted file.
1695 1643 # Sets the global 'wxfile' variable.
1696 1644 #
1697 1645 function flist_from_wx
1698 1646 {
1699 1647 typeset argfile=$1
1700 1648 if [[ -n ${argfile%%/*} ]]; then
1701 1649 #
1702 1650 # If the wx file pathname is relative then make it absolute
1703 1651 # because the webrev does a "cd" later on.
1704 1652 #
1705 1653 wxfile=$PWD/$argfile
1706 1654 else
1707 1655 wxfile=$argfile
1708 1656 fi
1709 1657
1710 1658 $AWK '{ c = 1; print;
↓ open down ↓ |
158 lines elided |
↑ open up ↑ |
1711 1659 while (getline) {
1712 1660 if (NF == 0) { c = -c; continue }
1713 1661 if (c > 0) print
1714 1662 }
1715 1663 }' $wxfile > $FLIST
1716 1664
1717 1665 print " Done."
1718 1666 }
1719 1667
1720 1668 #
1721 -# flist_from_teamware [ <args-to-putback-n> ]
1722 -#
1723 -# Generate the file list by extracting file names from a putback -n. Some
1724 -# names may come from the "update/create" messages and others from the
1725 -# "currently checked out" warning. Renames are detected here too. Extract
1726 -# values for CODEMGR_WS and CODEMGR_PARENT from the output of the putback
1727 -# -n as well, but remove them if they are already defined.
1728 -#
1729 -function flist_from_teamware
1730 -{
1731 - if [[ -n $codemgr_parent && -z $parent_webrev ]]; then
1732 - if [[ ! -d $codemgr_parent/Codemgr_wsdata ]]; then
1733 - print -u2 "parent $codemgr_parent doesn't look like a" \
1734 - "valid teamware workspace"
1735 - exit 1
1736 - fi
1737 - parent_args="-p $codemgr_parent"
1738 - fi
1739 -
1740 - print " File list from: 'putback -n $parent_args $*' ... \c"
1741 -
1742 - putback -n $parent_args $* 2>&1 |
1743 - $AWK '
1744 - /^update:|^create:/ {print $2}
1745 - /^Parent workspace:/ {printf("CODEMGR_PARENT=%s\n",$3)}
1746 - /^Child workspace:/ {printf("CODEMGR_WS=%s\n",$3)}
1747 - /^The following files are currently checked out/ {p = 1; continue}
1748 - NF == 0 {p=0 ; continue}
1749 - /^rename/ {old=$3}
1750 - $1 == "to:" {print $2, old}
1751 - /^"/ {continue}
1752 - p == 1 {print $1}' |
1753 - sort -r -k 1,1 -u | sort > $FLIST
1754 -
1755 - print " Done."
1756 -}
1757 -
1758 -#
1759 1669 # Call hg-active to get the active list output in the wx active list format
1760 1670 #
1761 1671 function hg_active_wxfile
1762 1672 {
1763 1673 typeset child=$1
1764 1674 typeset parent=$2
1765 1675
1766 1676 TMPFLIST=/tmp/$$.active
1767 1677 $HG_ACTIVE -w $child -p $parent -o $TMPFLIST
1768 1678 wxfile=$TMPFLIST
1769 1679 }
1770 1680
1771 1681 #
1772 1682 # flist_from_mercurial
1773 1683 # Call hg-active to get a wx-style active list, and hand it off to
1774 1684 # flist_from_wx
1775 1685 #
1776 1686 function flist_from_mercurial
1777 1687 {
1778 1688 typeset child=$1
1779 1689 typeset parent=$2
1780 1690
1781 1691 print " File list from: hg-active -p $parent ...\c"
1782 1692 if [[ ! -x $HG_ACTIVE ]]; then
1783 1693 print # Blank line for the \c above
1784 1694 print -u2 "Error: hg-active tool not found. Exiting"
1785 1695 exit 1
1786 1696 fi
1787 1697 hg_active_wxfile $child $parent
1788 1698
1789 1699 # flist_from_wx prints the Done, so we don't have to.
1790 1700 flist_from_wx $TMPFLIST
1791 1701 }
1792 1702
1793 1703 #
1794 1704 # Transform a specified 'git log' output format into a wx-like active list.
1795 1705 #
1796 1706 function git_wxfile
1797 1707 {
1798 1708 typeset child="$1"
1799 1709 typeset parent="$2"
1800 1710
1801 1711 TMPFLIST=/tmp/$$.active
1802 1712 $PERL -e 'my (%files, %realfiles, $msg);
1803 1713 my $branch = $ARGV[0];
1804 1714
1805 1715 open(F, "git diff -M --name-status $branch |");
1806 1716 while (<F>) {
1807 1717 chomp;
1808 1718 if (/^R(\d+)\s+([^ ]+)\s+([^ ]+)/) { # rename
1809 1719 if ($1 >= 75) { # Probably worth treating as a rename
1810 1720 $realfiles{$3} = $2;
1811 1721 } else {
1812 1722 $realfiles{$3} = $3;
1813 1723 $realfiles{$2} = $2;
1814 1724 }
1815 1725 } else {
1816 1726 my $f = (split /\s+/, $_)[1];
1817 1727 $realfiles{$f} = $f;
1818 1728 }
1819 1729 }
1820 1730 close(F);
1821 1731
1822 1732 my $state = 1; # 0|comments, 1|files
1823 1733 open(F, "git whatchanged --pretty=format:%B $branch.. |");
1824 1734 while (<F>) {
1825 1735 chomp;
1826 1736 if (/^:[0-9]{6}/) {
1827 1737 my $fname = (split /\t/, $_)[1];
1828 1738 next if !defined($realfiles{$fname}); # No real change
1829 1739 $state = 1;
1830 1740 chomp $msg;
1831 1741 $files{$fname} .= $msg;
1832 1742 } else {
1833 1743 if ($state == 1) {
1834 1744 $state = 0;
1835 1745 $msg = /^\n/ ? "" : "\n";
1836 1746 }
1837 1747 $msg .= "$_\n" if ($_);
1838 1748 }
1839 1749 }
1840 1750 close(F);
1841 1751
1842 1752 for (sort keys %files) {
1843 1753 if ($realfiles{$_} ne $_) {
1844 1754 print "$_ $realfiles{$_}\n$files{$_}\n\n";
1845 1755 } else {
1846 1756 print "$_\n$files{$_}\n\n"
1847 1757 }
1848 1758 }' ${parent} > $TMPFLIST
1849 1759
1850 1760 wxfile=$TMPFLIST
1851 1761 }
1852 1762
1853 1763 #
1854 1764 # flist_from_git
1855 1765 # Build a wx-style active list, and hand it off to flist_from_wx
1856 1766 #
1857 1767 function flist_from_git
1858 1768 {
1859 1769 typeset child=$1
1860 1770 typeset parent=$2
1861 1771
1862 1772 print " File list from: git ...\c"
1863 1773 git_wxfile "$child" "$parent";
1864 1774
1865 1775 # flist_from_wx prints the Done, so we don't have to.
1866 1776 flist_from_wx $TMPFLIST
1867 1777 }
1868 1778
1869 1779 #
1870 1780 # flist_from_subversion
1871 1781 #
1872 1782 # Generate the file list by extracting file names from svn status.
1873 1783 #
1874 1784 function flist_from_subversion
1875 1785 {
1876 1786 CWS=$1
1877 1787 OLDPWD=$2
1878 1788
1879 1789 cd $CWS
1880 1790 print -u2 " File list from: svn status ... \c"
1881 1791 svn status | $AWK '/^[ACDMR]/ { print $NF }' > $FLIST
1882 1792 print -u2 " Done."
1883 1793 cd $OLDPWD
1884 1794 }
1885 1795
1886 1796 function env_from_flist
1887 1797 {
1888 1798 [[ -r $FLIST ]] || return
1889 1799
1890 1800 #
1891 1801 # Use "eval" to set env variables that are listed in the file
1892 1802 # list. Then copy those into our local versions of those
1893 1803 # variables if they have not been set already.
1894 1804 #
1895 1805 eval `$SED -e "s/#.*$//" $FLIST | $GREP = `
1896 1806
1897 1807 if [[ -z $codemgr_ws && -n $CODEMGR_WS ]]; then
1898 1808 codemgr_ws=$CODEMGR_WS
1899 1809 export CODEMGR_WS
1900 1810 fi
1901 1811
1902 1812 #
1903 1813 # Check to see if CODEMGR_PARENT is set in the flist file.
1904 1814 #
1905 1815 if [[ -z $codemgr_parent && -n $CODEMGR_PARENT ]]; then
1906 1816 codemgr_parent=$CODEMGR_PARENT
1907 1817 export CODEMGR_PARENT
1908 1818 fi
↓ open down ↓ |
140 lines elided |
↑ open up ↑ |
1909 1819 }
1910 1820
1911 1821 function look_for_prog
1912 1822 {
1913 1823 typeset path
1914 1824 typeset ppath
1915 1825 typeset progname=$1
1916 1826
1917 1827 ppath=$PATH
1918 1828 ppath=$ppath:/usr/sfw/bin:/usr/bin:/usr/sbin
1919 - ppath=$ppath:/opt/teamware/bin:/opt/onbld/bin
1829 + ppath=$ppath:/opt/onbld/bin
1920 1830 ppath=$ppath:/opt/onbld/bin/`uname -p`
1921 1831
1922 1832 PATH=$ppath prog=`whence $progname`
1923 1833 if [[ -n $prog ]]; then
1924 1834 print $prog
1925 1835 fi
1926 1836 }
1927 1837
1928 1838 function get_file_mode
1929 1839 {
1930 1840 $PERL -e '
↓ open down ↓ |
1 lines elided |
↑ open up ↑ |
1931 1841 if (@stat = stat($ARGV[0])) {
1932 1842 $mode = $stat[2] & 0777;
1933 1843 printf "%03o\n", $mode;
1934 1844 exit 0;
1935 1845 } else {
1936 1846 exit 1;
1937 1847 }
1938 1848 ' $1
1939 1849 }
1940 1850
1941 -function build_old_new_teamware
1942 -{
1943 - typeset olddir="$1"
1944 - typeset newdir="$2"
1945 -
1946 - # If the child's version doesn't exist then
1947 - # get a readonly copy.
1948 -
1949 - if [[ ! -f $CWS/$DIR/$F && -f $CWS/$DIR/SCCS/s.$F ]]; then
1950 - $SCCS get -s -p $CWS/$DIR/$F > $CWS/$DIR/$F
1951 - fi
1952 -
1953 - # The following two sections propagate file permissions the
1954 - # same way SCCS does. If the file is already under version
1955 - # control, always use permissions from the SCCS/s.file. If
1956 - # the file is not under SCCS control, use permissions from the
1957 - # working copy. In all cases, the file copied to the webrev
1958 - # is set to read only, and group/other permissions are set to
1959 - # match those of the file owner. This way, even if the file
1960 - # is currently checked out, the webrev will display the final
1961 - # permissions that would result after check in.
1962 -
1963 - #
1964 - # Snag new version of file.
1965 - #
1966 - rm -f $newdir/$DIR/$F
1967 - cp $CWS/$DIR/$F $newdir/$DIR/$F
1968 - if [[ -f $CWS/$DIR/SCCS/s.$F ]]; then
1969 - chmod `get_file_mode $CWS/$DIR/SCCS/s.$F` \
1970 - $newdir/$DIR/$F
1971 - fi
1972 - chmod u-w,go=u $newdir/$DIR/$F
1973 -
1974 - #
1975 - # Get the parent's version of the file. First see whether the
1976 - # child's version is checked out and get the parent's version
1977 - # with keywords expanded or unexpanded as appropriate.
1978 - #
1979 - if [[ -f $PWS/$PDIR/$PF && ! -f $PWS/$PDIR/SCCS/s.$PF && \
1980 - ! -f $PWS/$PDIR/SCCS/p.$PF ]]; then
1981 - # Parent is not a real workspace, but just a raw
1982 - # directory tree - use the file that's there as
1983 - # the old file.
1984 -
1985 - rm -f $olddir/$PDIR/$PF
1986 - cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF
1987 - else
1988 - if [[ -f $PWS/$PDIR/SCCS/s.$PF ]]; then
1989 - real_parent=$PWS
1990 - else
1991 - real_parent=$RWS
1992 - fi
1993 -
1994 - rm -f $olddir/$PDIR/$PF
1995 -
1996 - if [[ -f $real_parent/$PDIR/$PF ]]; then
1997 - if [ -f $CWS/$DIR/SCCS/p.$F ]; then
1998 - $SCCS get -s -p -k $real_parent/$PDIR/$PF > \
1999 - $olddir/$PDIR/$PF
2000 - else
2001 - $SCCS get -s -p $real_parent/$PDIR/$PF > \
2002 - $olddir/$PDIR/$PF
2003 - fi
2004 - chmod `get_file_mode $real_parent/$PDIR/SCCS/s.$PF` \
2005 - $olddir/$PDIR/$PF
2006 - fi
2007 - fi
2008 - if [[ -f $olddir/$PDIR/$PF ]]; then
2009 - chmod u-w,go=u $olddir/$PDIR/$PF
2010 - fi
2011 -}
2012 -
2013 1851 function build_old_new_mercurial
2014 1852 {
2015 1853 typeset olddir="$1"
2016 1854 typeset newdir="$2"
2017 1855 typeset old_mode=
2018 1856 typeset new_mode=
2019 1857 typeset file
2020 1858
2021 1859 #
2022 1860 # Get old file mode, from the parent revision manifest entry.
2023 1861 # Mercurial only stores a "file is executable" flag, but the
2024 1862 # manifest will display an octal mode "644" or "755".
2025 1863 #
2026 1864 if [[ "$PDIR" == "." ]]; then
2027 1865 file="$PF"
2028 1866 else
2029 1867 file="$PDIR/$PF"
2030 1868 fi
2031 1869 file=`echo $file | $SED 's#/#\\\/#g'`
2032 1870 # match the exact filename, and return only the permission digits
2033 1871 old_mode=`$SED -n -e "/^\\(...\\) . ${file}$/s//\\1/p" \
2034 1872 < $HG_PARENT_MANIFEST`
2035 1873
2036 1874 #
2037 1875 # Get new file mode, directly from the filesystem.
2038 1876 # Normalize the mode to match Mercurial's behavior.
2039 1877 #
2040 1878 new_mode=`get_file_mode $CWS/$DIR/$F`
2041 1879 if [[ -n "$new_mode" ]]; then
2042 1880 if [[ "$new_mode" = *[1357]* ]]; then
2043 1881 new_mode=755
2044 1882 else
2045 1883 new_mode=644
2046 1884 fi
2047 1885 fi
2048 1886
2049 1887 #
2050 1888 # new version of the file.
2051 1889 #
2052 1890 rm -rf $newdir/$DIR/$F
2053 1891 if [[ -e $CWS/$DIR/$F ]]; then
2054 1892 cp $CWS/$DIR/$F $newdir/$DIR/$F
2055 1893 if [[ -n $new_mode ]]; then
2056 1894 chmod $new_mode $newdir/$DIR/$F
2057 1895 else
2058 1896 # should never happen
2059 1897 print -u2 "ERROR: set mode of $newdir/$DIR/$F"
2060 1898 fi
2061 1899 fi
2062 1900
2063 1901 #
2064 1902 # parent's version of the file
2065 1903 #
2066 1904 # Note that we get this from the last version common to both
2067 1905 # ourselves and the parent. References are via $CWS since we have no
2068 1906 # guarantee that the parent workspace is reachable via the filesystem.
2069 1907 #
2070 1908 if [[ -n $parent_webrev && -e $PWS/$PDIR/$PF ]]; then
2071 1909 cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF
2072 1910 elif [[ -n $HG_PARENT ]]; then
2073 1911 hg cat -R $CWS -r $HG_PARENT $CWS/$PDIR/$PF > \
2074 1912 $olddir/$PDIR/$PF 2>/dev/null
2075 1913
2076 1914 if (( $? != 0 )); then
2077 1915 rm -f $olddir/$PDIR/$PF
2078 1916 else
2079 1917 if [[ -n $old_mode ]]; then
2080 1918 chmod $old_mode $olddir/$PDIR/$PF
2081 1919 else
2082 1920 # should never happen
2083 1921 print -u2 "ERROR: set mode of $olddir/$PDIR/$PF"
2084 1922 fi
2085 1923 fi
2086 1924 fi
2087 1925 }
2088 1926
2089 1927 function build_old_new_git
2090 1928 {
2091 1929 typeset olddir="$1"
2092 1930 typeset newdir="$2"
2093 1931 typeset o_mode=
2094 1932 typeset n_mode=
2095 1933 typeset o_object=
2096 1934 typeset n_object=
2097 1935 typeset OWD=$PWD
2098 1936 typeset file
2099 1937 typeset type
2100 1938
2101 1939 cd $CWS
2102 1940
2103 1941 #
2104 1942 # Get old file and its mode from the git object tree
2105 1943 #
2106 1944 if [[ "$PDIR" == "." ]]; then
2107 1945 file="$PF"
2108 1946 else
2109 1947 file="$PDIR/$PF"
2110 1948 fi
2111 1949
2112 1950 if [[ -n $parent_webrev && -e $PWS/$PDIR/$PF ]]; then
2113 1951 cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF
2114 1952 else
2115 1953 $GIT ls-tree $GIT_PARENT $file | read o_mode type o_object junk
2116 1954 $GIT cat-file $type $o_object > $olddir/$file 2>/dev/null
2117 1955
2118 1956 if (( $? != 0 )); then
2119 1957 rm -f $olddir/$file
2120 1958 elif [[ -n $o_mode ]]; then
2121 1959 # Strip the first 3 digits, to get a regular octal mode
2122 1960 o_mode=${o_mode/???/}
2123 1961 chmod $o_mode $olddir/$file
2124 1962 else
2125 1963 # should never happen
2126 1964 print -u2 "ERROR: set mode of $olddir/$file"
2127 1965 fi
2128 1966 fi
2129 1967
2130 1968 #
2131 1969 # new version of the file.
2132 1970 #
2133 1971 if [[ "$DIR" == "." ]]; then
2134 1972 file="$F"
2135 1973 else
2136 1974 file="$DIR/$F"
2137 1975 fi
2138 1976 rm -rf $newdir/$file
2139 1977
2140 1978 if [[ -e $CWS/$DIR/$F ]]; then
2141 1979 cp $CWS/$DIR/$F $newdir/$DIR/$F
2142 1980 chmod $(get_file_mode $CWS/$DIR/$F) $newdir/$DIR/$F
2143 1981 fi
2144 1982 cd $OWD
2145 1983 }
2146 1984
2147 1985 function build_old_new_subversion
2148 1986 {
2149 1987 typeset olddir="$1"
2150 1988 typeset newdir="$2"
2151 1989
2152 1990 # Snag new version of file.
2153 1991 rm -f $newdir/$DIR/$F
2154 1992 [[ -e $CWS/$DIR/$F ]] && cp $CWS/$DIR/$F $newdir/$DIR/$F
2155 1993
2156 1994 if [[ -n $PWS && -e $PWS/$PDIR/$PF ]]; then
2157 1995 cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF
2158 1996 else
2159 1997 # Get the parent's version of the file.
2160 1998 svn status $CWS/$DIR/$F | read stat file
2161 1999 if [[ $stat != "A" ]]; then
2162 2000 svn cat -r BASE $CWS/$DIR/$F > $olddir/$PDIR/$PF
2163 2001 fi
2164 2002 fi
2165 2003 }
2166 2004
2167 2005 function build_old_new_unknown
2168 2006 {
2169 2007 typeset olddir="$1"
2170 2008 typeset newdir="$2"
2171 2009
2172 2010 #
2173 2011 # Snag new version of file.
2174 2012 #
2175 2013 rm -f $newdir/$DIR/$F
2176 2014 [[ -e $CWS/$DIR/$F ]] && cp $CWS/$DIR/$F $newdir/$DIR/$F
2177 2015
2178 2016 #
2179 2017 # Snag the parent's version of the file.
2180 2018 #
2181 2019 if [[ -f $PWS/$PDIR/$PF ]]; then
2182 2020 rm -f $olddir/$PDIR/$PF
2183 2021 cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF
2184 2022 fi
2185 2023 }
2186 2024
2187 2025 function build_old_new
2188 2026 {
2189 2027 typeset WDIR=$1
2190 2028 typeset PWS=$2
2191 2029 typeset PDIR=$3
2192 2030 typeset PF=$4
↓ open down ↓ |
170 lines elided |
↑ open up ↑ |
2193 2031 typeset CWS=$5
2194 2032 typeset DIR=$6
2195 2033 typeset F=$7
2196 2034
2197 2035 typeset olddir="$WDIR/raw_files/old"
2198 2036 typeset newdir="$WDIR/raw_files/new"
2199 2037
2200 2038 mkdir -p $olddir/$PDIR
2201 2039 mkdir -p $newdir/$DIR
2202 2040
2203 - if [[ $SCM_MODE == "teamware" ]]; then
2204 - build_old_new_teamware "$olddir" "$newdir"
2205 - elif [[ $SCM_MODE == "mercurial" ]]; then
2041 + if [[ $SCM_MODE == "mercurial" ]]; then
2206 2042 build_old_new_mercurial "$olddir" "$newdir"
2207 2043 elif [[ $SCM_MODE == "git" ]]; then
2208 2044 build_old_new_git "$olddir" "$newdir"
2209 2045 elif [[ $SCM_MODE == "subversion" ]]; then
2210 2046 build_old_new_subversion "$olddir" "$newdir"
2211 2047 elif [[ $SCM_MODE == "unknown" ]]; then
2212 2048 build_old_new_unknown "$olddir" "$newdir"
2213 2049 fi
2214 2050
2215 2051 if [[ ! -f $olddir/$PDIR/$PF && ! -f $newdir/$DIR/$F ]]; then
2216 2052 print "*** Error: file not in parent or child"
2217 2053 return 1
2218 2054 fi
2219 2055 return 0
2220 2056 }
2221 2057
2222 2058
2223 2059 #
2224 2060 # Usage message.
2225 2061 #
2226 2062 function usage
2227 2063 {
2228 2064 print 'Usage:\twebrev [common-options]
2229 2065 webrev [common-options] ( <file> | - )
2230 2066 webrev [common-options] -w <wx file>
2231 2067
2232 2068 Options:
2233 2069 -C <filename>: Use <filename> for the information tracking configuration.
2234 2070 -D: delete remote webrev
2235 2071 -i <filename>: Include <filename> in the index.html file.
2236 2072 -I <filename>: Use <filename> for the information tracking registry.
2237 2073 -n: do not generate the webrev (useful with -U)
2238 2074 -O: Print bugids/arc cases suitable for OpenSolaris.
↓ open down ↓ |
23 lines elided |
↑ open up ↑ |
2239 2075 -o <outdir>: Output webrev to specified directory.
2240 2076 -p <compare-against>: Use specified parent wkspc or basis for comparison
2241 2077 -t <remote_target>: Specify remote destination for webrev upload
2242 2078 -U: upload the webrev to remote destination
2243 2079 -w <wxfile>: Use specified wx active file.
2244 2080
2245 2081 Environment:
2246 2082 WDIR: Control the output directory.
2247 2083 WEBREV_TRASH_DIR: Set directory for webrev delete.
2248 2084
2249 -SCM Specific Options:
2250 - TeamWare: webrev [common-options] -l [arguments to 'putback']
2251 -
2252 2085 SCM Environment:
2253 2086 CODEMGR_WS: Workspace location.
2254 2087 CODEMGR_PARENT: Parent workspace location.
2255 2088 '
2256 2089
2257 2090 exit 2
2258 2091 }
2259 2092
2260 2093 #
2261 2094 #
2262 2095 # Main program starts here
2263 2096 #
2264 2097 #
2265 2098
2266 2099 trap "rm -f /tmp/$$.* ; exit" 0 1 2 3 15
2267 2100
2268 2101 set +o noclobber
2269 2102
2270 2103 PATH=$(/bin/dirname "$(whence $0)"):$PATH
2271 2104
2272 2105 [[ -z $WDIFF ]] && WDIFF=`look_for_prog wdiff`
2273 2106 [[ -z $WX ]] && WX=`look_for_prog wx`
2274 2107 [[ -z $HG_ACTIVE ]] && HG_ACTIVE=`look_for_prog hg-active`
2275 2108 [[ -z $GIT ]] && GIT=`look_for_prog git`
2276 2109 [[ -z $WHICH_SCM ]] && WHICH_SCM=`look_for_prog which_scm`
2277 2110 [[ -z $CODEREVIEW ]] && CODEREVIEW=`look_for_prog codereview`
2278 2111 [[ -z $PS2PDF ]] && PS2PDF=`look_for_prog ps2pdf`
2279 2112 [[ -z $PERL ]] && PERL=`look_for_prog perl`
2280 2113 [[ -z $RSYNC ]] && RSYNC=`look_for_prog rsync`
2281 2114 [[ -z $SCCS ]] && SCCS=`look_for_prog sccs`
2282 2115 [[ -z $AWK ]] && AWK=`look_for_prog nawk`
2283 2116 [[ -z $AWK ]] && AWK=`look_for_prog gawk`
2284 2117 [[ -z $AWK ]] && AWK=`look_for_prog awk`
2285 2118 [[ -z $SCP ]] && SCP=`look_for_prog scp`
2286 2119 [[ -z $SED ]] && SED=`look_for_prog sed`
2287 2120 [[ -z $SFTP ]] && SFTP=`look_for_prog sftp`
2288 2121 [[ -z $SORT ]] && SORT=`look_for_prog sort`
2289 2122 [[ -z $MKTEMP ]] && MKTEMP=`look_for_prog mktemp`
2290 2123 [[ -z $GREP ]] && GREP=`look_for_prog grep`
2291 2124 [[ -z $FIND ]] && FIND=`look_for_prog find`
2292 2125
2293 2126 # set name of trash directory for remote webrev deletion
2294 2127 TRASH_DIR=".trash"
2295 2128 [[ -n $WEBREV_TRASH_DIR ]] && TRASH_DIR=$WEBREV_TRASH_DIR
2296 2129
2297 2130 if [[ ! -x $PERL ]]; then
2298 2131 print -u2 "Error: No perl interpreter found. Exiting."
2299 2132 exit 1
2300 2133 fi
2301 2134
2302 2135 if [[ ! -x $WHICH_SCM ]]; then
2303 2136 print -u2 "Error: Could not find which_scm. Exiting."
2304 2137 exit 1
2305 2138 fi
2306 2139
2307 2140 #
2308 2141 # These aren't fatal, but we want to note them to the user.
2309 2142 # We don't warn on the absence of 'wx' until later when we've
2310 2143 # determined that we actually need to try to invoke it.
2311 2144 #
2312 2145 [[ ! -x $CODEREVIEW ]] && print -u2 "WARNING: codereview(1) not found."
2313 2146 [[ ! -x $PS2PDF ]] && print -u2 "WARNING: ps2pdf(1) not found."
2314 2147 [[ ! -x $WDIFF ]] && print -u2 "WARNING: wdiff not found."
2315 2148
2316 2149 # Declare global total counters.
2317 2150 integer TOTL TINS TDEL TMOD TUNC
2318 2151
2319 2152 # default remote host for upload/delete
2320 2153 typeset -r DEFAULT_REMOTE_HOST="cr.opensolaris.org"
2321 2154 # prefixes for upload targets
2322 2155 typeset -r rsync_prefix="rsync://"
2323 2156 typeset -r ssh_prefix="ssh://"
2324 2157
2325 2158 Cflag=
2326 2159 Dflag=
2327 2160 flist_mode=
2328 2161 flist_file=
2329 2162 iflag=
2330 2163 Iflag=
2331 2164 lflag=
2332 2165 Nflag=
2333 2166 nflag=
2334 2167 Oflag=
2335 2168 oflag=
2336 2169 pflag=
2337 2170 tflag=
2338 2171 uflag=
2339 2172 Uflag=
2340 2173 wflag=
2341 2174 remote_target=
2342 2175
2343 2176 #
2344 2177 # NOTE: when adding/removing options it is necessary to sync the list
2345 2178 # with usr/src/tools/onbld/hgext/cdm.py
2346 2179 #
2347 2180 while getopts "C:Di:I:lnNo:Op:t:Uw" opt
2348 2181 do
2349 2182 case $opt in
2350 2183 C) Cflag=1
↓ open down ↓ |
89 lines elided |
↑ open up ↑ |
2351 2184 ITSCONF=$OPTARG;;
2352 2185
2353 2186 D) Dflag=1;;
2354 2187
2355 2188 i) iflag=1
2356 2189 INCLUDE_FILE=$OPTARG;;
2357 2190
2358 2191 I) Iflag=1
2359 2192 ITSREG=$OPTARG;;
2360 2193
2361 - #
2362 - # If -l has been specified, we need to abort further options
2363 - # processing, because subsequent arguments are going to be
2364 - # arguments to 'putback -n'.
2365 - #
2366 - l) lflag=1
2367 - break;;
2368 -
2369 2194 N) Nflag=1;;
2370 2195
2371 2196 n) nflag=1;;
2372 2197
2373 2198 O) Oflag=1;;
2374 2199
2375 2200 o) oflag=1
2376 2201 # Strip the trailing slash to correctly form remote target.
2377 2202 WDIR=${OPTARG%/};;
2378 2203
2379 2204 p) pflag=1
2380 2205 codemgr_parent=$OPTARG;;
2381 2206
2382 2207 t) tflag=1
2383 2208 remote_target=$OPTARG;;
2384 2209
2385 2210 U) Uflag=1;;
2386 2211
2387 2212 w) wflag=1;;
2388 2213
2389 2214 ?) usage;;
2390 2215 esac
2391 2216 done
2392 2217
2393 2218 FLIST=/tmp/$$.flist
2394 2219
2395 2220 if [[ -n $wflag && -n $lflag ]]; then
2396 2221 usage
2397 2222 fi
2398 2223
2399 2224 # more sanity checking
2400 2225 if [[ -n $nflag && -z $Uflag ]]; then
2401 2226 print "it does not make sense to skip webrev generation" \
2402 2227 "without -U"
2403 2228 exit 1
2404 2229 fi
2405 2230
2406 2231 if [[ -n $tflag && -z $Uflag && -z $Dflag ]]; then
2407 2232 echo "remote target has to be used only for upload or delete"
↓ open down ↓ |
29 lines elided |
↑ open up ↑ |
2408 2233 exit 1
2409 2234 fi
2410 2235
2411 2236 #
2412 2237 # For the invocation "webrev -n -U" with no other options, webrev will assume
2413 2238 # that the webrev exists in ${CWS}/webrev, but will upload it using the name
2414 2239 # $(basename ${CWS}). So we need to get CWS set before we skip any remaining
2415 2240 # logic.
2416 2241 #
2417 2242 $WHICH_SCM | read SCM_MODE junk || exit 1
2418 -if [[ $SCM_MODE == "teamware" ]]; then
2419 - #
2420 - # Teamware priorities:
2421 - # 1. CODEMGR_WS from the environment
2422 - # 2. workspace name
2423 - #
2424 - [[ -z $codemgr_ws && -n $CODEMGR_WS ]] && codemgr_ws=$CODEMGR_WS
2425 - if [[ -n $codemgr_ws && ! -d $codemgr_ws ]]; then
2426 - print -u2 "$codemgr_ws: no such workspace"
2427 - exit 1
2428 - fi
2429 - [[ -z $codemgr_ws ]] && codemgr_ws=$(workspace name)
2430 - codemgr_ws=$(cd $codemgr_ws;print $PWD)
2431 - CODEMGR_WS=$codemgr_ws
2432 - CWS=$codemgr_ws
2433 -elif [[ $SCM_MODE == "mercurial" ]]; then
2243 +if [[ $SCM_MODE == "mercurial" ]]; then
2434 2244 #
2435 2245 # Mercurial priorities:
2436 2246 # 1. hg root from CODEMGR_WS environment variable
2437 2247 # 1a. hg root from CODEMGR_WS/usr/closed if we're somewhere under
2438 2248 # usr/closed when we run webrev
2439 2249 # 2. hg root from directory of invocation
2440 2250 #
2441 2251 if [[ ${PWD} =~ "usr/closed" ]]; then
2442 2252 testparent=${CODEMGR_WS}/usr/closed
2443 2253 # If we're in OpenSolaris mode, we enforce a minor policy:
2444 2254 # help to make sure the reviewer doesn't accidentally publish
2445 2255 # source which is under usr/closed
2446 2256 if [[ -n "$Oflag" ]]; then
2447 2257 print -u2 "OpenSolaris output not permitted with" \
2448 2258 "usr/closed changes"
2449 2259 exit 1
2450 2260 fi
2451 2261 else
2452 2262 testparent=${CODEMGR_WS}
2453 2263 fi
2454 2264 [[ -z $codemgr_ws && -n $testparent ]] && \
2455 2265 codemgr_ws=$(hg root -R $testparent 2>/dev/null)
2456 2266 [[ -z $codemgr_ws ]] && codemgr_ws=$(hg root 2>/dev/null)
2457 2267 CWS=$codemgr_ws
2458 2268 elif [[ $SCM_MODE == "git" ]]; then
2459 2269 #
2460 2270 # Git priorities:
2461 2271 # 1. git rev-parse --git-dir from CODEMGR_WS environment variable
2462 2272 # 2. git rev-parse --git-dir from directory of invocation
2463 2273 #
2464 2274 [[ -z $codemgr_ws && -n $CODEMGR_WS ]] && \
2465 2275 codemgr_ws=$($GIT --git-dir=$CODEMGR_WS/.git rev-parse --git-dir \
2466 2276 2>/dev/null)
2467 2277 [[ -z $codemgr_ws ]] && \
2468 2278 codemgr_ws=$($GIT rev-parse --git-dir 2>/dev/null)
2469 2279
2470 2280 if [[ "$codemgr_ws" == ".git" ]]; then
2471 2281 codemgr_ws="${PWD}/${codemgr_ws}"
2472 2282 fi
2473 2283
2474 2284 codemgr_ws=$(dirname $codemgr_ws) # Lose the '/.git'
2475 2285 CWS="$codemgr_ws"
2476 2286 elif [[ $SCM_MODE == "subversion" ]]; then
2477 2287 #
2478 2288 # Subversion priorities:
2479 2289 # 1. CODEMGR_WS from environment
2480 2290 # 2. Relative path from current directory to SVN repository root
2481 2291 #
2482 2292 if [[ -n $CODEMGR_WS && -d $CODEMGR_WS/.svn ]]; then
2483 2293 CWS=$CODEMGR_WS
2484 2294 else
2485 2295 svn info | while read line; do
2486 2296 if [[ $line == "URL: "* ]]; then
2487 2297 url=${line#URL: }
2488 2298 elif [[ $line == "Repository Root: "* ]]; then
2489 2299 repo=${line#Repository Root: }
2490 2300 fi
2491 2301 done
2492 2302
2493 2303 rel=${url#$repo}
2494 2304 CWS=${PWD%$rel}
2495 2305 fi
2496 2306 fi
2497 2307
2498 2308 #
2499 2309 # If no SCM has been determined, take either the environment setting
2500 2310 # setting for CODEMGR_WS, or the current directory if that wasn't set.
2501 2311 #
2502 2312 if [[ -z ${CWS} ]]; then
2503 2313 CWS=${CODEMGR_WS:-.}
2504 2314 fi
2505 2315
2506 2316 #
2507 2317 # If the command line options indicate no webrev generation, either
2508 2318 # explicitly (-n) or implicitly (-D but not -U), then there's a whole
2509 2319 # ton of logic we can skip.
2510 2320 #
2511 2321 # Instead of increasing indentation, we intentionally leave this loop
2512 2322 # body open here, and exit via break from multiple points within.
2513 2323 # Search for DO_EVERYTHING below to find the break points and closure.
2514 2324 #
2515 2325 for do_everything in 1; do
2516 2326
2517 2327 # DO_EVERYTHING: break point
2518 2328 if [[ -n $nflag || ( -z $Uflag && -n $Dflag ) ]]; then
2519 2329 break
2520 2330 fi
2521 2331
2522 2332 #
2523 2333 # If this manually set as the parent, and it appears to be an earlier webrev,
2524 2334 # then note that fact and set the parent to the raw_files/new subdirectory.
2525 2335 #
2526 2336 if [[ -n $pflag && -d $codemgr_parent/raw_files/new ]]; then
2527 2337 parent_webrev=$(readlink -f "$codemgr_parent")
2528 2338 codemgr_parent=$(readlink -f "$codemgr_parent/raw_files/new")
2529 2339 fi
2530 2340
2531 2341 if [[ -z $wflag && -z $lflag ]]; then
2532 2342 shift $(($OPTIND - 1))
2533 2343
2534 2344 if [[ $1 == "-" ]]; then
2535 2345 cat > $FLIST
2536 2346 flist_mode="stdin"
2537 2347 flist_done=1
2538 2348 shift
2539 2349 elif [[ -n $1 ]]; then
2540 2350 if [[ ! -r $1 ]]; then
2541 2351 print -u2 "$1: no such file or not readable"
2542 2352 usage
2543 2353 fi
2544 2354 cat $1 > $FLIST
2545 2355 flist_mode="file"
2546 2356 flist_file=$1
2547 2357 flist_done=1
2548 2358 shift
↓ open down ↓ |
105 lines elided |
↑ open up ↑ |
2549 2359 else
2550 2360 flist_mode="auto"
2551 2361 fi
2552 2362 fi
2553 2363
2554 2364 #
2555 2365 # Before we go on to further consider -l and -w, work out which SCM we think
2556 2366 # is in use.
2557 2367 #
2558 2368 case "$SCM_MODE" in
2559 -teamware|mercurial|git|subversion)
2369 +mercurial|git|subversion)
2560 2370 ;;
2561 2371 unknown)
2562 2372 if [[ $flist_mode == "auto" ]]; then
2563 2373 print -u2 "Unable to determine SCM in use and file list not specified"
2564 2374 print -u2 "See which_scm(1) for SCM detection information."
2565 2375 exit 1
2566 2376 fi
2567 2377 ;;
2568 2378 *)
2569 2379 if [[ $flist_mode == "auto" ]]; then
2570 2380 print -u2 "Unsupported SCM in use ($SCM_MODE) and file list not specified"
2571 2381 exit 1
2572 2382 fi
2573 2383 ;;
2574 2384 esac
2575 2385
2576 2386 print -u2 " SCM detected: $SCM_MODE"
2577 2387
2578 -if [[ -n $lflag ]]; then
2579 - #
2580 - # If the -l flag is given instead of the name of a file list,
2581 - # then generate the file list by extracting file names from a
2582 - # putback -n.
2583 - #
2584 - shift $(($OPTIND - 1))
2585 - if [[ $SCM_MODE == "teamware" ]]; then
2586 - flist_from_teamware "$*"
2587 - else
2588 - print -u2 -- "Error: -l option only applies to TeamWare"
2589 - exit 1
2590 - fi
2591 - flist_done=1
2592 - shift $#
2593 -elif [[ -n $wflag ]]; then
2388 +if [[ -n $wflag ]]; then
2594 2389 #
2595 2390 # If the -w is given then assume the file list is in Bonwick's "wx"
2596 2391 # command format, i.e. pathname lines alternating with SCCS comment
2597 2392 # lines with blank lines as separators. Use the SCCS comments later
2598 2393 # in building the index.html file.
2599 2394 #
2600 2395 shift $(($OPTIND - 1))
2601 2396 wxfile=$1
2602 2397 if [[ -z $wxfile && -n $CODEMGR_WS ]]; then
2603 2398 if [[ -r $CODEMGR_WS/wx/active ]]; then
2604 2399 wxfile=$CODEMGR_WS/wx/active
2605 2400 fi
2606 2401 fi
2607 2402
2608 2403 [[ -z $wxfile ]] && print -u2 "wx file not specified, and could not " \
2609 2404 "be auto-detected (check \$CODEMGR_WS)" && exit 1
2610 2405
2611 2406 if [[ ! -r $wxfile ]]; then
2612 2407 print -u2 "$wxfile: no such file or not readable"
2613 2408 usage
2614 2409 fi
2615 2410
2616 2411 print -u2 " File list from: wx 'active' file '$wxfile' ... \c"
2617 2412 flist_from_wx $wxfile
2618 2413 flist_done=1
2619 2414 if [[ -n "$*" ]]; then
2620 2415 shift
2621 2416 fi
2622 2417 elif [[ $flist_mode == "stdin" ]]; then
2623 2418 print -u2 " File list from: standard input"
2624 2419 elif [[ $flist_mode == "file" ]]; then
2625 2420 print -u2 " File list from: $flist_file"
↓ open down ↓ |
22 lines elided |
↑ open up ↑ |
2626 2421 fi
2627 2422
2628 2423 if [[ $# -gt 0 ]]; then
2629 2424 print -u2 "WARNING: unused arguments: $*"
2630 2425 fi
2631 2426
2632 2427 #
2633 2428 # Before we entered the DO_EVERYTHING loop, we should have already set CWS
2634 2429 # and CODEMGR_WS as needed. Here, we set the parent workspace.
2635 2430 #
2636 -
2637 -if [[ $SCM_MODE == "teamware" ]]; then
2638 -
2639 - #
2640 - # Teamware priorities:
2641 - #
2642 - # 1) via -p command line option
2643 - # 2) in the user environment
2644 - # 3) in the flist
2645 - # 4) automatically based on the workspace
2646 - #
2647 -
2648 - #
2649 - # For 1, codemgr_parent will already be set. Here's 2:
2650 - #
2651 - [[ -z $codemgr_parent && -n $CODEMGR_PARENT ]] && \
2652 - codemgr_parent=$CODEMGR_PARENT
2653 - if [[ -n $codemgr_parent && ! -d $codemgr_parent ]]; then
2654 - print -u2 "$codemgr_parent: no such directory"
2655 - exit 1
2656 - fi
2657 -
2658 - #
2659 - # If we're in auto-detect mode and we haven't already gotten the file
2660 - # list, then see if we can get it by probing for wx.
2661 - #
2662 - if [[ -z $flist_done && $flist_mode == "auto" && -n $codemgr_ws ]]; then
2663 - if [[ ! -x $WX ]]; then
2664 - print -u2 "WARNING: wx not found!"
2665 - fi
2666 -
2667 - #
2668 - # We need to use wx list -w so that we get renamed files, etc.
2669 - # but only if a wx active file exists-- otherwise wx will
2670 - # hang asking us to initialize our wx information.
2671 - #
2672 - if [[ -x $WX && -f $codemgr_ws/wx/active ]]; then
2673 - print -u2 " File list from: 'wx list -w' ... \c"
2674 - $WX list -w > $FLIST
2675 - $WX comments > /tmp/$$.wx_comments
2676 - wxfile=/tmp/$$.wx_comments
2677 - print -u2 "done"
2678 - flist_done=1
2679 - fi
2680 - fi
2681 -
2682 - #
2683 - # If by hook or by crook we've gotten a file list by now (perhaps
2684 - # from the command line), eval it to extract environment variables from
2685 - # it: This is method 3 for finding the parent.
2686 - #
2687 - if [[ -z $flist_done ]]; then
2688 - flist_from_teamware
2689 - fi
2690 - env_from_flist
2691 -
2692 - #
2693 - # (4) If we still don't have a value for codemgr_parent, get it
2694 - # from workspace.
2695 - #
2696 - [[ -z $codemgr_parent ]] && codemgr_parent=`workspace parent`
2697 - if [[ ! -d $codemgr_parent ]]; then
2698 - print -u2 "$CODEMGR_PARENT: no such parent workspace"
2699 - exit 1
2700 - fi
2701 -
2702 - PWS=$codemgr_parent
2703 -
2704 - [[ -n $parent_webrev ]] && RWS=$(workspace parent $CWS)
2705 -
2706 -elif [[ $SCM_MODE == "mercurial" ]]; then
2431 +if [[ $SCM_MODE == "mercurial" ]]; then
2707 2432 #
2708 2433 # Parent can either be specified with -p
2709 2434 # Specified with CODEMGR_PARENT in the environment
2710 2435 # or taken from hg's default path.
2711 2436 #
2712 2437
2713 2438 if [[ -z $codemgr_parent && -n $CODEMGR_PARENT ]]; then
2714 2439 codemgr_parent=$CODEMGR_PARENT
2715 2440 fi
2716 2441
2717 2442 if [[ -z $codemgr_parent ]]; then
2718 2443 codemgr_parent=`hg path -R $codemgr_ws default 2>/dev/null`
2719 2444 fi
2720 2445
2721 2446 PWS=$codemgr_parent
2722 2447
2723 2448 #
2724 2449 # If the parent is a webrev, we want to do some things against
2725 2450 # the natural workspace parent (file list, comments, etc)
2726 2451 #
2727 2452 if [[ -n $parent_webrev ]]; then
2728 2453 real_parent=$(hg path -R $codemgr_ws default 2>/dev/null)
2729 2454 else
2730 2455 real_parent=$PWS
2731 2456 fi
2732 2457
2733 2458 #
2734 2459 # If hg-active exists, then we run it. In the case of no explicit
2735 2460 # flist given, we'll use it for our comments. In the case of an
2736 2461 # explicit flist given we'll try to use it for comments for any
2737 2462 # files mentioned in the flist.
2738 2463 #
2739 2464 if [[ -z $flist_done ]]; then
2740 2465 flist_from_mercurial $CWS $real_parent
2741 2466 flist_done=1
2742 2467 fi
2743 2468
2744 2469 #
2745 2470 # If we have a file list now, pull out any variables set
2746 2471 # therein. We do this now (rather than when we possibly use
2747 2472 # hg-active to find comments) to avoid stomping specifications
2748 2473 # in the user-specified flist.
2749 2474 #
2750 2475 if [[ -n $flist_done ]]; then
2751 2476 env_from_flist
2752 2477 fi
2753 2478
2754 2479 #
2755 2480 # Only call hg-active if we don't have a wx formatted file already
2756 2481 #
2757 2482 if [[ -x $HG_ACTIVE && -z $wxfile ]]; then
2758 2483 print " Comments from: hg-active -p $real_parent ...\c"
2759 2484 hg_active_wxfile $CWS $real_parent
2760 2485 print " Done."
2761 2486 fi
2762 2487
2763 2488 #
2764 2489 # At this point we must have a wx flist either from hg-active,
2765 2490 # or in general. Use it to try and find our parent revision,
2766 2491 # if we don't have one.
2767 2492 #
2768 2493 if [[ -z $HG_PARENT ]]; then
2769 2494 eval `$SED -e "s/#.*$//" $wxfile | $GREP HG_PARENT=`
2770 2495 fi
2771 2496
2772 2497 #
2773 2498 # If we still don't have a parent, we must have been given a
2774 2499 # wx-style active list with no HG_PARENT specification, run
2775 2500 # hg-active and pull an HG_PARENT out of it, ignore the rest.
2776 2501 #
2777 2502 if [[ -z $HG_PARENT && -x $HG_ACTIVE ]]; then
2778 2503 $HG_ACTIVE -w $codemgr_ws -p $real_parent | \
2779 2504 eval `$SED -e "s/#.*$//" | $GREP HG_PARENT=`
2780 2505 elif [[ -z $HG_PARENT ]]; then
2781 2506 print -u2 "Error: Cannot discover parent revision"
2782 2507 exit 1
2783 2508 fi
2784 2509
2785 2510 pnode=$(trim_digest $HG_PARENT)
2786 2511 PRETTY_PWS="${PWS} (at ${pnode})"
2787 2512 cnode=$(hg parent -R $codemgr_ws --template '{node|short}' \
2788 2513 2>/dev/null)
2789 2514 PRETTY_CWS="${CWS} (at ${cnode})"}
2790 2515 elif [[ $SCM_MODE == "git" ]]; then
2791 2516 #
2792 2517 # Parent can either be specified with -p, or specified with
2793 2518 # CODEMGR_PARENT in the environment.
2794 2519 #
2795 2520
2796 2521 if [[ -z $codemgr_parent && -n $CODEMGR_PARENT ]]; then
2797 2522 codemgr_parent=$CODEMGR_PARENT
2798 2523 fi
2799 2524
2800 2525 # Try to figure out the parent based on the branch the current
2801 2526 # branch is tracking, if we fail, use origin/master
2802 2527 this_branch=$($GIT branch | nawk '$1 == "*" { print $2 }')
2803 2528 par_branch="origin/master"
2804 2529
2805 2530 # If we're not on a branch there's nothing we can do
2806 2531 if [[ $this_branch != "(no branch)" ]]; then
2807 2532 $GIT for-each-ref \
2808 2533 --format='%(refname:short) %(upstream:short)' refs/heads/ | \
2809 2534 while read local remote; do \
2810 2535 [[ "$local" == "$this_branch" ]] && par_branch="$remote"; \
2811 2536 done
2812 2537 fi
2813 2538
2814 2539 if [[ -z $codemgr_parent ]]; then
2815 2540 codemgr_parent=$par_branch
2816 2541 fi
2817 2542 PWS=$codemgr_parent
2818 2543
2819 2544 #
2820 2545 # If the parent is a webrev, we want to do some things against
2821 2546 # the natural workspace parent (file list, comments, etc)
2822 2547 #
2823 2548 if [[ -n $parent_webrev ]]; then
2824 2549 real_parent=$par_branch
2825 2550 else
2826 2551 real_parent=$PWS
2827 2552 fi
2828 2553
2829 2554 if [[ -z $flist_done ]]; then
2830 2555 flist_from_git "$CWS" "$real_parent"
2831 2556 flist_done=1
2832 2557 fi
2833 2558
2834 2559 #
2835 2560 # If we have a file list now, pull out any variables set
2836 2561 # therein.
2837 2562 #
2838 2563 if [[ -n $flist_done ]]; then
2839 2564 env_from_flist
2840 2565 fi
2841 2566
2842 2567 #
2843 2568 # If we don't have a wx-format file list, build one we can pull change
2844 2569 # comments from.
2845 2570 #
2846 2571 if [[ -z $wxfile ]]; then
2847 2572 print " Comments from: git...\c"
2848 2573 git_wxfile "$CWS" "$real_parent"
2849 2574 print " Done."
2850 2575 fi
2851 2576
2852 2577 if [[ -z $GIT_PARENT ]]; then
2853 2578 GIT_PARENT=$($GIT merge-base "$real_parent" HEAD)
2854 2579 fi
2855 2580 if [[ -z $GIT_PARENT ]]; then
2856 2581 print -u2 "Error: Cannot discover parent revision"
2857 2582 exit 1
2858 2583 fi
2859 2584
2860 2585 pnode=$(trim_digest $GIT_PARENT)
2861 2586
2862 2587 if [[ $real_parent == */* ]]; then
2863 2588 origin=$(echo $real_parent | cut -d/ -f1)
2864 2589 origin=$($GIT remote -v | \
2865 2590 $AWK '$1 == "'$origin'" { print $2; exit }')
2866 2591 PRETTY_PWS="${PWS} (${origin} at ${pnode})"
2867 2592 else
2868 2593 PRETTY_PWS="${PWS} (at ${pnode})"
2869 2594 fi
2870 2595
2871 2596 cnode=$($GIT --git-dir=${codemgr_ws}/.git rev-parse --short=12 HEAD \
2872 2597 2>/dev/null)
2873 2598 PRETTY_CWS="${CWS} (at ${cnode})"
2874 2599 elif [[ $SCM_MODE == "subversion" ]]; then
2875 2600
2876 2601 #
2877 2602 # We only will have a real parent workspace in the case one
2878 2603 # was specified (be it an older webrev, or another checkout).
2879 2604 #
2880 2605 [[ -n $codemgr_parent ]] && PWS=$codemgr_parent
2881 2606
2882 2607 if [[ -z $flist_done && $flist_mode == "auto" ]]; then
2883 2608 flist_from_subversion $CWS $OLDPWD
2884 2609 fi
2885 2610 else
2886 2611 if [[ $SCM_MODE == "unknown" ]]; then
2887 2612 print -u2 " Unknown type of SCM in use"
2888 2613 else
2889 2614 print -u2 " Unsupported SCM in use: $SCM_MODE"
2890 2615 fi
2891 2616
2892 2617 env_from_flist
2893 2618
2894 2619 if [[ -z $CODEMGR_WS ]]; then
2895 2620 print -u2 "SCM not detected/supported and CODEMGR_WS not specified"
2896 2621 exit 1
2897 2622 fi
2898 2623
2899 2624 if [[ -z $CODEMGR_PARENT ]]; then
2900 2625 print -u2 "SCM not detected/supported and CODEMGR_PARENT not specified"
2901 2626 exit 1
2902 2627 fi
2903 2628
2904 2629 CWS=$CODEMGR_WS
2905 2630 PWS=$CODEMGR_PARENT
2906 2631 fi
2907 2632
2908 2633 #
2909 2634 # If the user didn't specify a -i option, check to see if there is a
2910 2635 # webrev-info file in the workspace directory.
2911 2636 #
2912 2637 if [[ -z $iflag && -r "$CWS/webrev-info" ]]; then
2913 2638 iflag=1
2914 2639 INCLUDE_FILE="$CWS/webrev-info"
2915 2640 fi
2916 2641
2917 2642 if [[ -n $iflag ]]; then
2918 2643 if [[ ! -r $INCLUDE_FILE ]]; then
2919 2644 print -u2 "include file '$INCLUDE_FILE' does not exist or is" \
2920 2645 "not readable."
2921 2646 exit 1
2922 2647 else
2923 2648 #
2924 2649 # $INCLUDE_FILE may be a relative path, and the script alters
2925 2650 # PWD, so we just stash a copy in /tmp.
2926 2651 #
2927 2652 cp $INCLUDE_FILE /tmp/$$.include
2928 2653 fi
2929 2654 fi
2930 2655
2931 2656 # DO_EVERYTHING: break point
2932 2657 if [[ -n $Nflag ]]; then
2933 2658 break
2934 2659 fi
2935 2660
2936 2661 typeset -A itsinfo
2937 2662 typeset -r its_sed_script=/tmp/$$.its_sed
2938 2663 valid_prefixes=
2939 2664 if [[ -z $nflag ]]; then
2940 2665 DEFREGFILE="$(/bin/dirname "$(whence $0)")/../etc/its.reg"
2941 2666 if [[ -n $Iflag ]]; then
2942 2667 REGFILE=$ITSREG
2943 2668 elif [[ -r $HOME/.its.reg ]]; then
2944 2669 REGFILE=$HOME/.its.reg
2945 2670 else
2946 2671 REGFILE=$DEFREGFILE
2947 2672 fi
2948 2673 if [[ ! -r $REGFILE ]]; then
2949 2674 print "ERROR: Unable to read database registry file $REGFILE"
2950 2675 exit 1
2951 2676 elif [[ $REGFILE != $DEFREGFILE ]]; then
2952 2677 print " its.reg from: $REGFILE"
2953 2678 fi
2954 2679
2955 2680 $SED -e '/^#/d' -e '/^[ ]*$/d' $REGFILE | while read LINE; do
2956 2681
2957 2682 name=${LINE%%=*}
2958 2683 value="${LINE#*=}"
2959 2684
2960 2685 if [[ $name == PREFIX ]]; then
2961 2686 p=${value}
2962 2687 valid_prefixes="${p} ${valid_prefixes}"
2963 2688 else
2964 2689 itsinfo["${p}_${name}"]="${value}"
2965 2690 fi
2966 2691 done
2967 2692
2968 2693
2969 2694 DEFCONFFILE="$(/bin/dirname "$(whence $0)")/../etc/its.conf"
2970 2695 CONFFILES=$DEFCONFFILE
2971 2696 if [[ -r $HOME/.its.conf ]]; then
2972 2697 CONFFILES="${CONFFILES} $HOME/.its.conf"
2973 2698 fi
2974 2699 if [[ -n $Cflag ]]; then
2975 2700 CONFFILES="${CONFFILES} ${ITSCONF}"
2976 2701 fi
2977 2702 its_domain=
2978 2703 its_priority=
2979 2704 for cf in ${CONFFILES}; do
2980 2705 if [[ ! -r $cf ]]; then
2981 2706 print "ERROR: Unable to read database configuration file $cf"
2982 2707 exit 1
2983 2708 elif [[ $cf != $DEFCONFFILE ]]; then
2984 2709 print " its.conf: reading $cf"
2985 2710 fi
2986 2711 $SED -e '/^#/d' -e '/^[ ]*$/d' $cf | while read LINE; do
2987 2712 eval "${LINE}"
2988 2713 done
2989 2714 done
2990 2715
2991 2716 #
2992 2717 # If an information tracking system is explicitly identified by prefix,
2993 2718 # we want to disregard the specified priorities and resolve it accordingly.
2994 2719 #
2995 2720 # To that end, we'll build a sed script to do each valid prefix in turn.
2996 2721 #
2997 2722 for p in ${valid_prefixes}; do
2998 2723 #
2999 2724 # When an informational URL was provided, translate it to a
3000 2725 # hyperlink. When omitted, simply use the prefix text.
3001 2726 #
3002 2727 if [[ -z ${itsinfo["${p}_INFO"]} ]]; then
3003 2728 itsinfo["${p}_INFO"]=${p}
3004 2729 else
3005 2730 itsinfo["${p}_INFO"]="<a href=\\\"${itsinfo["${p}_INFO"]}\\\">${p}</a>"
3006 2731 fi
3007 2732
3008 2733 #
3009 2734 # Assume that, for this invocation of webrev, all references
3010 2735 # to this information tracking system should resolve through
3011 2736 # the same URL.
3012 2737 #
3013 2738 # If the caller specified -O, then always use EXTERNAL_URL.
3014 2739 #
3015 2740 # Otherwise, look in the list of domains for a matching
3016 2741 # INTERNAL_URL.
3017 2742 #
3018 2743 [[ -z $Oflag ]] && for d in ${its_domain}; do
3019 2744 if [[ -n ${itsinfo["${p}_INTERNAL_URL_${d}"]} ]]; then
3020 2745 itsinfo["${p}_URL"]="${itsinfo[${p}_INTERNAL_URL_${d}]}"
3021 2746 break
3022 2747 fi
3023 2748 done
3024 2749 if [[ -z ${itsinfo["${p}_URL"]} ]]; then
3025 2750 itsinfo["${p}_URL"]="${itsinfo[${p}_EXTERNAL_URL]}"
3026 2751 fi
3027 2752
3028 2753 #
3029 2754 # Turn the destination URL into a hyperlink
3030 2755 #
3031 2756 itsinfo["${p}_URL"]="<a href=\\\"${itsinfo[${p}_URL]}\\\">&</a>"
3032 2757
3033 2758 # The character class below contains a literal tab
3034 2759 print "/^${p}[: ]/ {
3035 2760 s;${itsinfo[${p}_REGEX]};${itsinfo[${p}_URL]};g
3036 2761 s;^${p};${itsinfo[${p}_INFO]};
3037 2762 }" >> ${its_sed_script}
3038 2763 done
3039 2764
3040 2765 #
3041 2766 # The previous loop took care of explicit specification. Now use
3042 2767 # the configured priorities to attempt implicit translations.
3043 2768 #
3044 2769 for p in ${its_priority}; do
3045 2770 print "/^${itsinfo[${p}_REGEX]}[ ]/ {
3046 2771 s;^${itsinfo[${p}_REGEX]};${itsinfo[${p}_URL]};g
3047 2772 }" >> ${its_sed_script}
3048 2773 done
3049 2774 fi
3050 2775
3051 2776 #
3052 2777 # Search for DO_EVERYTHING above for matching "for" statement
3053 2778 # and explanation of this terminator.
3054 2779 #
3055 2780 done
3056 2781
3057 2782 #
3058 2783 # Output directory.
3059 2784 #
3060 2785 WDIR=${WDIR:-$CWS/webrev}
3061 2786
3062 2787 #
3063 2788 # Name of the webrev, derived from the workspace name or output directory;
3064 2789 # in the future this could potentially be an option.
3065 2790 #
3066 2791 if [[ -n $oflag ]]; then
3067 2792 WNAME=${WDIR##*/}
3068 2793 else
3069 2794 WNAME=${CWS##*/}
3070 2795 fi
3071 2796
3072 2797 # Make sure remote target is well formed for remote upload/delete.
3073 2798 if [[ -n $Dflag || -n $Uflag ]]; then
3074 2799 #
3075 2800 # If remote target is not specified, build it from scratch using
3076 2801 # the default values.
3077 2802 #
3078 2803 if [[ -z $tflag ]]; then
3079 2804 remote_target=${DEFAULT_REMOTE_HOST}:${WNAME}
3080 2805 else
3081 2806 #
3082 2807 # Check upload target prefix first.
3083 2808 #
3084 2809 if [[ "${remote_target}" != ${rsync_prefix}* &&
3085 2810 "${remote_target}" != ${ssh_prefix}* ]]; then
3086 2811 print "ERROR: invalid prefix of upload URI" \
3087 2812 "($remote_target)"
3088 2813 exit 1
3089 2814 fi
3090 2815 #
3091 2816 # If destination specification is not in the form of
3092 2817 # host_spec:remote_dir then assume it is just remote hostname
3093 2818 # and append a colon and destination directory formed from
3094 2819 # local webrev directory name.
3095 2820 #
3096 2821 typeset target_no_prefix=${remote_target##*://}
3097 2822 if [[ ${target_no_prefix} == *:* ]]; then
3098 2823 if [[ "${remote_target}" == *: ]]; then
3099 2824 remote_target=${remote_target}${WNAME}
3100 2825 fi
3101 2826 else
3102 2827 if [[ ${target_no_prefix} == */* ]]; then
3103 2828 print "ERROR: badly formed upload URI" \
3104 2829 "($remote_target)"
3105 2830 exit 1
3106 2831 else
3107 2832 remote_target=${remote_target}:${WNAME}
3108 2833 fi
3109 2834 fi
3110 2835 fi
3111 2836
3112 2837 #
3113 2838 # Strip trailing slash. Each upload method will deal with directory
3114 2839 # specification separately.
3115 2840 #
3116 2841 remote_target=${remote_target%/}
3117 2842 fi
3118 2843
3119 2844 #
3120 2845 # Option -D by itself (option -U not present) implies no webrev generation.
3121 2846 #
3122 2847 if [[ -z $Uflag && -n $Dflag ]]; then
3123 2848 delete_webrev 1 1
3124 2849 exit $?
3125 2850 fi
3126 2851
3127 2852 #
3128 2853 # Do not generate the webrev, just upload it or delete it.
3129 2854 #
3130 2855 if [[ -n $nflag ]]; then
3131 2856 if [[ -n $Dflag ]]; then
3132 2857 delete_webrev 1 1
3133 2858 (( $? == 0 )) || exit $?
3134 2859 fi
3135 2860 if [[ -n $Uflag ]]; then
3136 2861 upload_webrev
3137 2862 exit $?
3138 2863 fi
3139 2864 fi
3140 2865
3141 2866 if [ "${WDIR%%/*}" ]; then
3142 2867 WDIR=$PWD/$WDIR
3143 2868 fi
3144 2869
3145 2870 if [[ ! -d $WDIR ]]; then
3146 2871 mkdir -p $WDIR
3147 2872 (( $? != 0 )) && exit 1
3148 2873 fi
3149 2874
3150 2875 #
3151 2876 # Summarize what we're going to do.
3152 2877 #
3153 2878 print " Workspace: ${PRETTY_CWS:-$CWS}"
3154 2879 if [[ -n $parent_webrev ]]; then
3155 2880 print "Compare against: webrev at $parent_webrev"
3156 2881 else
3157 2882 print "Compare against: ${PRETTY_PWS:-$PWS}"
3158 2883 fi
3159 2884
3160 2885 [[ -n $INCLUDE_FILE ]] && print " Including: $INCLUDE_FILE"
3161 2886 print " Output to: $WDIR"
3162 2887
3163 2888 #
3164 2889 # Save the file list in the webrev dir
3165 2890 #
3166 2891 [[ ! $FLIST -ef $WDIR/file.list ]] && cp $FLIST $WDIR/file.list
3167 2892
3168 2893 rm -f $WDIR/$WNAME.patch
3169 2894 rm -f $WDIR/$WNAME.ps
3170 2895 rm -f $WDIR/$WNAME.pdf
3171 2896
3172 2897 touch $WDIR/$WNAME.patch
3173 2898
3174 2899 print " Output Files:"
3175 2900
3176 2901 #
3177 2902 # Clean up the file list: Remove comments, blank lines and env variables.
3178 2903 #
3179 2904 $SED -e "s/#.*$//" -e "/=/d" -e "/^[ ]*$/d" $FLIST > /tmp/$$.flist.clean
3180 2905 FLIST=/tmp/$$.flist.clean
3181 2906
3182 2907 #
3183 2908 # For Mercurial, create a cache of manifest entries.
3184 2909 #
3185 2910 if [[ $SCM_MODE == "mercurial" ]]; then
3186 2911 #
3187 2912 # Transform the FLIST into a temporary sed script that matches
3188 2913 # relevant entries in the Mercurial manifest as follows:
3189 2914 # 1) The script will be used against the parent revision manifest,
3190 2915 # so for FLIST lines that have two filenames (a renamed file)
3191 2916 # keep only the old name.
3192 2917 # 2) Escape all forward slashes the filename.
3193 2918 # 3) Change the filename into another sed command that matches
3194 2919 # that file in "hg manifest -v" output: start of line, three
3195 2920 # octal digits for file permissions, space, a file type flag
3196 2921 # character, space, the filename, end of line.
3197 2922 # 4) Eliminate any duplicate entries. (This can occur if a
3198 2923 # file has been used as the source of an hg cp and it's
3199 2924 # also been modified in the same changeset.)
3200 2925 #
3201 2926 SEDFILE=/tmp/$$.manifest.sed
3202 2927 $SED '
3203 2928 s#^[^ ]* ##
3204 2929 s#/#\\\/#g
3205 2930 s#^.*$#/^... . &$/p#
3206 2931 ' < $FLIST | $SORT -u > $SEDFILE
3207 2932
3208 2933 #
3209 2934 # Apply the generated script to the output of "hg manifest -v"
3210 2935 # to get the relevant subset for this webrev.
3211 2936 #
3212 2937 HG_PARENT_MANIFEST=/tmp/$$.manifest
3213 2938 hg -R $CWS manifest -v -r $HG_PARENT |
3214 2939 $SED -n -f $SEDFILE > $HG_PARENT_MANIFEST
3215 2940 fi
3216 2941
3217 2942 #
3218 2943 # First pass through the files: generate the per-file webrev HTML-files.
3219 2944 #
3220 2945 cat $FLIST | while read LINE
3221 2946 do
3222 2947 set - $LINE
3223 2948 P=$1
3224 2949
3225 2950 #
3226 2951 # Normally, each line in the file list is just a pathname of a
3227 2952 # file that has been modified or created in the child. A file
3228 2953 # that is renamed in the child workspace has two names on the
3229 2954 # line: new name followed by the old name.
3230 2955 #
3231 2956 oldname=""
3232 2957 oldpath=""
3233 2958 rename=
3234 2959 if [[ $# -eq 2 ]]; then
3235 2960 PP=$2 # old filename
3236 2961 if [[ -f $PP ]]; then
3237 2962 oldname=" (copied from $PP)"
3238 2963 else
3239 2964 oldname=" (renamed from $PP)"
3240 2965 fi
3241 2966 oldpath="$PP"
3242 2967 rename=1
3243 2968 PDIR=${PP%/*}
3244 2969 if [[ $PDIR == $PP ]]; then
3245 2970 PDIR="." # File at root of workspace
3246 2971 fi
3247 2972
3248 2973 PF=${PP##*/}
3249 2974
3250 2975 DIR=${P%/*}
3251 2976 if [[ $DIR == $P ]]; then
3252 2977 DIR="." # File at root of workspace
3253 2978 fi
3254 2979
3255 2980 F=${P##*/}
3256 2981
3257 2982 else
3258 2983 DIR=${P%/*}
3259 2984 if [[ "$DIR" == "$P" ]]; then
3260 2985 DIR="." # File at root of workspace
3261 2986 fi
3262 2987
3263 2988 F=${P##*/}
3264 2989
3265 2990 PP=$P
3266 2991 PDIR=$DIR
3267 2992 PF=$F
3268 2993 fi
3269 2994
3270 2995 COMM=`getcomments html $P $PP`
3271 2996
3272 2997 print "\t$P$oldname\n\t\t\c"
3273 2998
3274 2999 # Make the webrev mirror directory if necessary
3275 3000 mkdir -p $WDIR/$DIR
3276 3001
3277 3002 #
3278 3003 # We stash old and new files into parallel directories in $WDIR
3279 3004 # and do our diffs there. This makes it possible to generate
3280 3005 # clean looking diffs which don't have absolute paths present.
3281 3006 #
3282 3007
3283 3008 build_old_new "$WDIR" "$PWS" "$PDIR" "$PF" "$CWS" "$DIR" "$F" || \
3284 3009 continue
3285 3010
3286 3011 #
3287 3012 # Keep the old PWD around, so we can safely switch back after
3288 3013 # diff generation, such that build_old_new runs in a
3289 3014 # consistent environment.
3290 3015 #
3291 3016 OWD=$PWD
3292 3017 cd $WDIR/raw_files
3293 3018 ofile=old/$PDIR/$PF
3294 3019 nfile=new/$DIR/$F
3295 3020
3296 3021 mv_but_nodiff=
3297 3022 cmp $ofile $nfile > /dev/null 2>&1
3298 3023 if [[ $? == 0 && $rename == 1 ]]; then
3299 3024 mv_but_nodiff=1
3300 3025 fi
3301 3026
3302 3027 #
3303 3028 # If we have old and new versions of the file then run the appropriate
3304 3029 # diffs. This is complicated by a couple of factors:
3305 3030 #
3306 3031 # - renames must be handled specially: we emit a 'remove'
3307 3032 # diff and an 'add' diff
3308 3033 # - new files and deleted files must be handled specially
3309 3034 # - Solaris patch(1m) can't cope with file creation
3310 3035 # (and hence renames) as of this writing.
3311 3036 # - To make matters worse, gnu patch doesn't interpret the
3312 3037 # output of Solaris diff properly when it comes to
3313 3038 # adds and deletes. We need to do some "cleansing"
3314 3039 # transformations:
3315 3040 # [to add a file] @@ -1,0 +X,Y @@ --> @@ -0,0 +X,Y @@
3316 3041 # [to del a file] @@ -X,Y +1,0 @@ --> @@ -X,Y +0,0 @@
3317 3042 #
3318 3043 cleanse_rmfile="$SED 's/^\(@@ [0-9+,-]*\) [0-9+,-]* @@$/\1 +0,0 @@/'"
3319 3044 cleanse_newfile="$SED 's/^@@ [0-9+,-]* \([0-9+,-]* @@\)$/@@ -0,0 \1/'"
3320 3045
3321 3046 rm -f $WDIR/$DIR/$F.patch
3322 3047 if [[ -z $rename ]]; then
3323 3048 if [ ! -f "$ofile" ]; then
3324 3049 diff -u /dev/null $nfile | sh -c "$cleanse_newfile" \
3325 3050 > $WDIR/$DIR/$F.patch
3326 3051 elif [ ! -f "$nfile" ]; then
3327 3052 diff -u $ofile /dev/null | sh -c "$cleanse_rmfile" \
3328 3053 > $WDIR/$DIR/$F.patch
3329 3054 else
3330 3055 diff -u $ofile $nfile > $WDIR/$DIR/$F.patch
3331 3056 fi
3332 3057 else
3333 3058 diff -u $ofile /dev/null | sh -c "$cleanse_rmfile" \
3334 3059 > $WDIR/$DIR/$F.patch
3335 3060
3336 3061 diff -u /dev/null $nfile | sh -c "$cleanse_newfile" \
3337 3062 >> $WDIR/$DIR/$F.patch
3338 3063 fi
3339 3064
3340 3065 #
3341 3066 # Tack the patch we just made onto the accumulated patch for the
3342 3067 # whole wad.
3343 3068 #
3344 3069 cat $WDIR/$DIR/$F.patch >> $WDIR/$WNAME.patch
3345 3070
3346 3071 print " patch\c"
3347 3072
3348 3073 if [[ -f $ofile && -f $nfile && -z $mv_but_nodiff ]]; then
3349 3074
3350 3075 ${CDIFFCMD:-diff -bt -C 5} $ofile $nfile > $WDIR/$DIR/$F.cdiff
3351 3076 diff_to_html $F $DIR/$F "C" "$COMM" < $WDIR/$DIR/$F.cdiff \
3352 3077 > $WDIR/$DIR/$F.cdiff.html
3353 3078 print " cdiffs\c"
3354 3079
3355 3080 ${UDIFFCMD:-diff -bt -U 5} $ofile $nfile > $WDIR/$DIR/$F.udiff
3356 3081 diff_to_html $F $DIR/$F "U" "$COMM" < $WDIR/$DIR/$F.udiff \
3357 3082 > $WDIR/$DIR/$F.udiff.html
3358 3083
3359 3084 print " udiffs\c"
3360 3085
3361 3086 if [[ -x $WDIFF ]]; then
3362 3087 $WDIFF -c "$COMM" \
3363 3088 -t "$WNAME Wdiff $DIR/$F" $ofile $nfile > \
3364 3089 $WDIR/$DIR/$F.wdiff.html 2>/dev/null
3365 3090 if [[ $? -eq 0 ]]; then
3366 3091 print " wdiffs\c"
3367 3092 else
3368 3093 print " wdiffs[fail]\c"
3369 3094 fi
3370 3095 fi
3371 3096
3372 3097 sdiff_to_html $ofile $nfile $F $DIR "$COMM" \
3373 3098 > $WDIR/$DIR/$F.sdiff.html
3374 3099 print " sdiffs\c"
3375 3100
3376 3101 print " frames\c"
3377 3102
3378 3103 rm -f $WDIR/$DIR/$F.cdiff $WDIR/$DIR/$F.udiff
3379 3104
3380 3105 difflines $ofile $nfile > $WDIR/$DIR/$F.count
3381 3106
3382 3107 elif [[ -f $ofile && -f $nfile && -n $mv_but_nodiff ]]; then
3383 3108 # renamed file: may also have differences
3384 3109 difflines $ofile $nfile > $WDIR/$DIR/$F.count
3385 3110 elif [[ -f $nfile ]]; then
3386 3111 # new file: count added lines
3387 3112 difflines /dev/null $nfile > $WDIR/$DIR/$F.count
3388 3113 elif [[ -f $ofile ]]; then
3389 3114 # old file: count deleted lines
3390 3115 difflines $ofile /dev/null > $WDIR/$DIR/$F.count
3391 3116 fi
3392 3117
3393 3118 #
3394 3119 # Now we generate the postscript for this file. We generate diffs
3395 3120 # only in the event that there is delta, or the file is new (it seems
3396 3121 # tree-killing to print out the contents of deleted files).
3397 3122 #
3398 3123 if [[ -f $nfile ]]; then
3399 3124 ocr=$ofile
3400 3125 [[ ! -f $ofile ]] && ocr=/dev/null
3401 3126
3402 3127 if [[ -z $mv_but_nodiff ]]; then
3403 3128 textcomm=`getcomments text $P $PP`
3404 3129 if [[ -x $CODEREVIEW ]]; then
3405 3130 $CODEREVIEW -y "$textcomm" \
3406 3131 -e $ocr $nfile \
3407 3132 > /tmp/$$.psfile 2>/dev/null &&
3408 3133 cat /tmp/$$.psfile >> $WDIR/$WNAME.ps
3409 3134 if [[ $? -eq 0 ]]; then
3410 3135 print " ps\c"
3411 3136 else
3412 3137 print " ps[fail]\c"
3413 3138 fi
3414 3139 fi
3415 3140 fi
3416 3141 fi
3417 3142
3418 3143 if [[ -f $ofile ]]; then
3419 3144 source_to_html Old $PP < $ofile > $WDIR/$DIR/$F-.html
3420 3145 print " old\c"
3421 3146 fi
3422 3147
3423 3148 if [[ -f $nfile ]]; then
3424 3149 source_to_html New $P < $nfile > $WDIR/$DIR/$F.html
3425 3150 print " new\c"
3426 3151 fi
3427 3152
3428 3153 cd $OWD
3429 3154
3430 3155 print
3431 3156 done
3432 3157
3433 3158 frame_nav_js > $WDIR/ancnav.js
3434 3159 frame_navigation > $WDIR/ancnav.html
3435 3160
3436 3161 if [[ ! -f $WDIR/$WNAME.ps ]]; then
3437 3162 print " Generating PDF: Skipped: no output available"
3438 3163 elif [[ -x $CODEREVIEW && -x $PS2PDF ]]; then
3439 3164 print " Generating PDF: \c"
3440 3165 fix_postscript $WDIR/$WNAME.ps | $PS2PDF - > $WDIR/$WNAME.pdf
3441 3166 print "Done."
3442 3167 else
3443 3168 print " Generating PDF: Skipped: missing 'ps2pdf' or 'codereview'"
3444 3169 fi
3445 3170
3446 3171 # If we're in OpenSolaris mode and there's a closed dir under $WDIR,
3447 3172 # delete it - prevent accidental publishing of closed source
3448 3173
3449 3174 if [[ -n "$Oflag" ]]; then
3450 3175 $FIND $WDIR -type d -name closed -exec /bin/rm -rf {} \;
3451 3176 fi
3452 3177
3453 3178 # Now build the index.html file that contains
3454 3179 # links to the source files and their diffs.
3455 3180
3456 3181 cd $CWS
3457 3182
3458 3183 # Save total changed lines for Code Inspection.
3459 3184 print "$TOTL" > $WDIR/TotalChangedLines
3460 3185
3461 3186 print " index.html: \c"
3462 3187 INDEXFILE=$WDIR/index.html
3463 3188 exec 3<&1 # duplicate stdout to FD3.
3464 3189 exec 1<&- # Close stdout.
3465 3190 exec > $INDEXFILE # Open stdout to index file.
3466 3191
3467 3192 print "$HTML<head>$STDHEAD"
3468 3193 print "<title>$WNAME</title>"
3469 3194 print "</head>"
3470 3195 print "<body id=\"SUNWwebrev\">"
3471 3196 print "<div class=\"summary\">"
3472 3197 print "<h2>Code Review for $WNAME</h2>"
3473 3198
3474 3199 print "<table>"
3475 3200
3476 3201 #
3477 3202 # Get the preparer's name:
3478 3203 #
3479 3204 # If the SCM detected is Mercurial, and the configuration property
3480 3205 # ui.username is available, use that, but be careful to properly escape
3481 3206 # angle brackets (HTML syntax characters) in the email address.
3482 3207 #
3483 3208 # Otherwise, use the current userid in the form "John Doe (jdoe)", but
3484 3209 # to maintain compatibility with passwd(4), we must support '&' substitutions.
3485 3210 #
3486 3211 preparer=
3487 3212 if [[ "$SCM_MODE" == mercurial ]]; then
3488 3213 preparer=`hg showconfig ui.username 2>/dev/null`
3489 3214 if [[ -n "$preparer" ]]; then
3490 3215 preparer="$(echo "$preparer" | html_quote)"
3491 3216 fi
3492 3217 fi
3493 3218 if [[ -z "$preparer" ]]; then
3494 3219 preparer=$(
3495 3220 $PERL -e '
3496 3221 ($login, $pw, $uid, $gid, $quota, $cmt, $gcos) = getpwuid($<);
3497 3222 if ($login) {
3498 3223 $gcos =~ s/\&/ucfirst($login)/e;
3499 3224 printf "%s (%s)\n", $gcos, $login;
3500 3225 } else {
3501 3226 printf "(unknown)\n";
3502 3227 }
3503 3228 ')
3504 3229 fi
3505 3230
3506 3231 PREPDATE=$(LC_ALL=C /usr/bin/date +%Y-%b-%d\ %R\ %z\ %Z)
3507 3232 print "<tr><th>Prepared by:</th><td>$preparer on $PREPDATE</td></tr>"
3508 3233 print "<tr><th>Workspace:</th><td>${PRETTY_CWS:-$CWS}"
3509 3234 print "</td></tr>"
3510 3235 print "<tr><th>Compare against:</th><td>"
3511 3236 if [[ -n $parent_webrev ]]; then
3512 3237 print "webrev at $parent_webrev"
3513 3238 else
3514 3239 print "${PRETTY_PWS:-$PWS}"
3515 3240 fi
3516 3241 print "</td></tr>"
3517 3242 print "<tr><th>Summary of changes:</th><td>"
3518 3243 printCI $TOTL $TINS $TDEL $TMOD $TUNC
3519 3244 print "</td></tr>"
3520 3245
3521 3246 if [[ -f $WDIR/$WNAME.patch ]]; then
3522 3247 wpatch_url="$(print $WNAME.patch | url_encode)"
3523 3248 print "<tr><th>Patch of changes:</th><td>"
3524 3249 print "<a href=\"$wpatch_url\">$WNAME.patch</a></td></tr>"
3525 3250 fi
3526 3251 if [[ -f $WDIR/$WNAME.pdf ]]; then
3527 3252 wpdf_url="$(print $WNAME.pdf | url_encode)"
3528 3253 print "<tr><th>Printable review:</th><td>"
3529 3254 print "<a href=\"$wpdf_url\">$WNAME.pdf</a></td></tr>"
3530 3255 fi
3531 3256
3532 3257 if [[ -n "$iflag" ]]; then
3533 3258 print "<tr><th>Author comments:</th><td><div>"
3534 3259 cat /tmp/$$.include
3535 3260 print "</div></td></tr>"
3536 3261 fi
3537 3262 print "</table>"
3538 3263 print "</div>"
3539 3264
3540 3265 #
3541 3266 # Second pass through the files: generate the rest of the index file
3542 3267 #
3543 3268 cat $FLIST | while read LINE
3544 3269 do
3545 3270 set - $LINE
3546 3271 P=$1
3547 3272
3548 3273 if [[ $# == 2 ]]; then
3549 3274 PP=$2
3550 3275 oldname="$PP"
3551 3276 else
3552 3277 PP=$P
3553 3278 oldname=""
3554 3279 fi
3555 3280
3556 3281 mv_but_nodiff=
3557 3282 cmp $WDIR/raw_files/old/$PP $WDIR/raw_files/new/$P > /dev/null 2>&1
3558 3283 if [[ $? == 0 && -n "$oldname" ]]; then
3559 3284 mv_but_nodiff=1
3560 3285 fi
3561 3286
3562 3287 DIR=${P%/*}
3563 3288 if [[ $DIR == $P ]]; then
3564 3289 DIR="." # File at root of workspace
3565 3290 fi
3566 3291
3567 3292 # Avoid processing the same file twice.
3568 3293 # It's possible for renamed files to
3569 3294 # appear twice in the file list
3570 3295
3571 3296 F=$WDIR/$P
3572 3297
3573 3298 print "<p>"
3574 3299
3575 3300 # If there's a diffs file, make diffs links
3576 3301
3577 3302 if [[ -f $F.cdiff.html ]]; then
3578 3303 cdiff_url="$(print $P.cdiff.html | url_encode)"
3579 3304 udiff_url="$(print $P.udiff.html | url_encode)"
3580 3305 print "<a href=\"$cdiff_url\">Cdiffs</a>"
3581 3306 print "<a href=\"$udiff_url\">Udiffs</a>"
3582 3307
3583 3308 if [[ -f $F.wdiff.html && -x $WDIFF ]]; then
3584 3309 wdiff_url="$(print $P.wdiff.html | url_encode)"
3585 3310 print "<a href=\"$wdiff_url\">Wdiffs</a>"
3586 3311 fi
3587 3312
3588 3313 sdiff_url="$(print $P.sdiff.html | url_encode)"
3589 3314 print "<a href=\"$sdiff_url\">Sdiffs</a>"
3590 3315
3591 3316 frames_url="$(print $P.frames.html | url_encode)"
3592 3317 print "<a href=\"$frames_url\">Frames</a>"
3593 3318 else
3594 3319 print " ------ ------ ------"
3595 3320
3596 3321 if [[ -x $WDIFF ]]; then
3597 3322 print " ------"
3598 3323 fi
3599 3324
3600 3325 print " ------"
3601 3326 fi
3602 3327
3603 3328 # If there's an old file, make the link
3604 3329
3605 3330 if [[ -f $F-.html ]]; then
3606 3331 oldfile_url="$(print $P-.html | url_encode)"
3607 3332 print "<a href=\"$oldfile_url\">Old</a>"
3608 3333 else
3609 3334 print " ---"
3610 3335 fi
3611 3336
3612 3337 # If there's an new file, make the link
3613 3338
3614 3339 if [[ -f $F.html ]]; then
3615 3340 newfile_url="$(print $P.html | url_encode)"
3616 3341 print "<a href=\"$newfile_url\">New</a>"
3617 3342 else
3618 3343 print " ---"
3619 3344 fi
3620 3345
3621 3346 if [[ -f $F.patch ]]; then
3622 3347 patch_url="$(print $P.patch | url_encode)"
3623 3348 print "<a href=\"$patch_url\">Patch</a>"
3624 3349 else
3625 3350 print " -----"
3626 3351 fi
3627 3352
3628 3353 if [[ -f $WDIR/raw_files/new/$P ]]; then
3629 3354 rawfiles_url="$(print raw_files/new/$P | url_encode)"
3630 3355 print "<a href=\"$rawfiles_url\">Raw</a>"
3631 3356 else
3632 3357 print " ---"
3633 3358 fi
3634 3359
3635 3360 print "<b>$P</b>"
3636 3361
3637 3362 # For renamed files, clearly state whether or not they are modified
3638 3363 if [[ -f "$oldname" ]]; then
3639 3364 if [[ -n "$mv_but_nodiff" ]]; then
3640 3365 print "<i>(copied from $oldname)</i>"
3641 3366 else
3642 3367 print "<i>(copied and modified from $oldname)</i>"
3643 3368 fi
3644 3369 elif [[ -n "$oldname" ]]; then
3645 3370 if [[ -n "$mv_but_nodiff" ]]; then
3646 3371 print "<i>(renamed from $oldname)</i>"
3647 3372 else
3648 3373 print "<i>(renamed and modified from $oldname)</i>"
3649 3374 fi
3650 3375 fi
3651 3376
3652 3377 # If there's an old file, but no new file, the file was deleted
3653 3378 if [[ -f $F-.html && ! -f $F.html ]]; then
3654 3379 print " <i>(deleted)</i>"
3655 3380 fi
3656 3381
3657 3382 #
3658 3383 # Check for usr/closed and deleted_files/usr/closed
3659 3384 #
3660 3385 if [ ! -z "$Oflag" ]; then
3661 3386 if [[ $P == usr/closed/* || \
3662 3387 $P == deleted_files/usr/closed/* ]]; then
3663 3388 print " <i>Closed source: omitted from" \
3664 3389 "this review</i>"
3665 3390 fi
3666 3391 fi
3667 3392
3668 3393 print "</p>"
3669 3394 # Insert delta comments
3670 3395
3671 3396 print "<blockquote><pre>"
3672 3397 getcomments html $P $PP
3673 3398 print "</pre>"
3674 3399
3675 3400 # Add additional comments comment
↓ open down ↓ |
959 lines elided |
↑ open up ↑ |
3676 3401
3677 3402 print "<!-- Add comments to explain changes in $P here -->"
3678 3403
3679 3404 # Add count of changes.
3680 3405
3681 3406 if [[ -f $F.count ]]; then
3682 3407 cat $F.count
3683 3408 rm $F.count
3684 3409 fi
3685 3410
3686 - if [[ $SCM_MODE == "teamware" ||
3687 - $SCM_MODE == "mercurial" ||
3411 + if [[ $SCM_MODE == "mercurial" ||
3688 3412 $SCM_MODE == "unknown" ]]; then
3689 3413
3690 3414 # Include warnings for important file mode situations:
3691 3415 # 1) New executable files
3692 3416 # 2) Permission changes of any kind
3693 3417 # 3) Existing executable files
3694 3418
3695 3419 old_mode=
3696 3420 if [[ -f $WDIR/raw_files/old/$PP ]]; then
3697 3421 old_mode=`get_file_mode $WDIR/raw_files/old/$PP`
3698 3422 fi
3699 3423
3700 3424 new_mode=
3701 3425 if [[ -f $WDIR/raw_files/new/$P ]]; then
3702 3426 new_mode=`get_file_mode $WDIR/raw_files/new/$P`
3703 3427 fi
3704 3428
3705 3429 if [[ -z "$old_mode" && "$new_mode" = *[1357]* ]]; then
3706 3430 print "<span class=\"chmod\">"
3707 3431 print "<p>new executable file: mode $new_mode</p>"
3708 3432 print "</span>"
3709 3433 elif [[ -n "$old_mode" && -n "$new_mode" &&
3710 3434 "$old_mode" != "$new_mode" ]]; then
3711 3435 print "<span class=\"chmod\">"
3712 3436 print "<p>mode change: $old_mode to $new_mode</p>"
3713 3437 print "</span>"
3714 3438 elif [[ "$new_mode" = *[1357]* ]]; then
3715 3439 print "<span class=\"chmod\">"
3716 3440 print "<p>executable file: mode $new_mode</p>"
3717 3441 print "</span>"
3718 3442 fi
3719 3443 fi
3720 3444
3721 3445 print "</blockquote>"
3722 3446 done
3723 3447
3724 3448 print
3725 3449 print
3726 3450 print "<hr></hr>"
3727 3451 print "<p style=\"font-size: small\">"
3728 3452 print "This code review page was prepared using <b>$0</b>."
3729 3453 print "Webrev is maintained by the <a href=\"http://www.illumos.org\">"
3730 3454 print "illumos</a> project. The latest version may be obtained"
3731 3455 print "<a href=\"http://src.illumos.org/source/xref/illumos-gate/usr/src/tools/scripts/webrev.sh\">here</a>.</p>"
3732 3456 print "</body>"
3733 3457 print "</html>"
3734 3458
3735 3459 exec 1<&- # Close FD 1.
3736 3460 exec 1<&3 # dup FD 3 to restore stdout.
3737 3461 exec 3<&- # close FD 3.
3738 3462
3739 3463 print "Done."
3740 3464
3741 3465 #
3742 3466 # If remote deletion was specified and fails do not continue.
3743 3467 #
3744 3468 if [[ -n $Dflag ]]; then
3745 3469 delete_webrev 1 1
3746 3470 (( $? == 0 )) || exit $?
3747 3471 fi
3748 3472
3749 3473 if [[ -n $Uflag ]]; then
3750 3474 upload_webrev
3751 3475 exit $?
3752 3476 fi
↓ open down ↓ |
55 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX