Print this page
3810 remove support for teamware from webrev
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
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 2194 #
2362 2195 # If -l has been specified, we need to abort further options
2363 2196 # processing, because subsequent arguments are going to be
2364 2197 # arguments to 'putback -n'.
2365 2198 #
2366 2199 l) lflag=1
2367 2200 break;;
2368 2201
2369 2202 N) Nflag=1;;
2370 2203
2371 2204 n) nflag=1;;
2372 2205
2373 2206 O) Oflag=1;;
2374 2207
2375 2208 o) oflag=1
2376 2209 # Strip the trailing slash to correctly form remote target.
2377 2210 WDIR=${OPTARG%/};;
2378 2211
2379 2212 p) pflag=1
2380 2213 codemgr_parent=$OPTARG;;
2381 2214
2382 2215 t) tflag=1
2383 2216 remote_target=$OPTARG;;
2384 2217
2385 2218 U) Uflag=1;;
2386 2219
2387 2220 w) wflag=1;;
2388 2221
2389 2222 ?) usage;;
2390 2223 esac
2391 2224 done
2392 2225
2393 2226 FLIST=/tmp/$$.flist
2394 2227
2395 2228 if [[ -n $wflag && -n $lflag ]]; then
2396 2229 usage
2397 2230 fi
2398 2231
2399 2232 # more sanity checking
2400 2233 if [[ -n $nflag && -z $Uflag ]]; then
2401 2234 print "it does not make sense to skip webrev generation" \
2402 2235 "without -U"
2403 2236 exit 1
2404 2237 fi
2405 2238
2406 2239 if [[ -n $tflag && -z $Uflag && -z $Dflag ]]; then
2407 2240 echo "remote target has to be used only for upload or delete"
↓ open down ↓ |
146 lines elided |
↑ open up ↑ |
2408 2241 exit 1
2409 2242 fi
2410 2243
2411 2244 #
2412 2245 # For the invocation "webrev -n -U" with no other options, webrev will assume
2413 2246 # that the webrev exists in ${CWS}/webrev, but will upload it using the name
2414 2247 # $(basename ${CWS}). So we need to get CWS set before we skip any remaining
2415 2248 # logic.
2416 2249 #
2417 2250 $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
2251 +if [[ $SCM_MODE == "mercurial" ]]; then
2434 2252 #
2435 2253 # Mercurial priorities:
2436 2254 # 1. hg root from CODEMGR_WS environment variable
2437 2255 # 1a. hg root from CODEMGR_WS/usr/closed if we're somewhere under
2438 2256 # usr/closed when we run webrev
2439 2257 # 2. hg root from directory of invocation
2440 2258 #
2441 2259 if [[ ${PWD} =~ "usr/closed" ]]; then
2442 2260 testparent=${CODEMGR_WS}/usr/closed
2443 2261 # If we're in OpenSolaris mode, we enforce a minor policy:
2444 2262 # help to make sure the reviewer doesn't accidentally publish
2445 2263 # source which is under usr/closed
2446 2264 if [[ -n "$Oflag" ]]; then
2447 2265 print -u2 "OpenSolaris output not permitted with" \
2448 2266 "usr/closed changes"
2449 2267 exit 1
2450 2268 fi
2451 2269 else
2452 2270 testparent=${CODEMGR_WS}
2453 2271 fi
2454 2272 [[ -z $codemgr_ws && -n $testparent ]] && \
2455 2273 codemgr_ws=$(hg root -R $testparent 2>/dev/null)
2456 2274 [[ -z $codemgr_ws ]] && codemgr_ws=$(hg root 2>/dev/null)
2457 2275 CWS=$codemgr_ws
2458 2276 elif [[ $SCM_MODE == "git" ]]; then
2459 2277 #
2460 2278 # Git priorities:
2461 2279 # 1. git rev-parse --git-dir from CODEMGR_WS environment variable
2462 2280 # 2. git rev-parse --git-dir from directory of invocation
2463 2281 #
2464 2282 [[ -z $codemgr_ws && -n $CODEMGR_WS ]] && \
2465 2283 codemgr_ws=$($GIT --git-dir=$CODEMGR_WS/.git rev-parse --git-dir \
2466 2284 2>/dev/null)
2467 2285 [[ -z $codemgr_ws ]] && \
2468 2286 codemgr_ws=$($GIT rev-parse --git-dir 2>/dev/null)
2469 2287
2470 2288 if [[ "$codemgr_ws" == ".git" ]]; then
2471 2289 codemgr_ws="${PWD}/${codemgr_ws}"
2472 2290 fi
2473 2291
2474 2292 codemgr_ws=$(dirname $codemgr_ws) # Lose the '/.git'
2475 2293 CWS="$codemgr_ws"
2476 2294 elif [[ $SCM_MODE == "subversion" ]]; then
2477 2295 #
2478 2296 # Subversion priorities:
2479 2297 # 1. CODEMGR_WS from environment
2480 2298 # 2. Relative path from current directory to SVN repository root
2481 2299 #
2482 2300 if [[ -n $CODEMGR_WS && -d $CODEMGR_WS/.svn ]]; then
2483 2301 CWS=$CODEMGR_WS
2484 2302 else
2485 2303 svn info | while read line; do
2486 2304 if [[ $line == "URL: "* ]]; then
2487 2305 url=${line#URL: }
2488 2306 elif [[ $line == "Repository Root: "* ]]; then
2489 2307 repo=${line#Repository Root: }
2490 2308 fi
2491 2309 done
2492 2310
2493 2311 rel=${url#$repo}
2494 2312 CWS=${PWD%$rel}
2495 2313 fi
2496 2314 fi
2497 2315
2498 2316 #
2499 2317 # If no SCM has been determined, take either the environment setting
2500 2318 # setting for CODEMGR_WS, or the current directory if that wasn't set.
2501 2319 #
2502 2320 if [[ -z ${CWS} ]]; then
2503 2321 CWS=${CODEMGR_WS:-.}
2504 2322 fi
2505 2323
2506 2324 #
2507 2325 # If the command line options indicate no webrev generation, either
2508 2326 # explicitly (-n) or implicitly (-D but not -U), then there's a whole
2509 2327 # ton of logic we can skip.
2510 2328 #
2511 2329 # Instead of increasing indentation, we intentionally leave this loop
2512 2330 # body open here, and exit via break from multiple points within.
2513 2331 # Search for DO_EVERYTHING below to find the break points and closure.
2514 2332 #
2515 2333 for do_everything in 1; do
2516 2334
2517 2335 # DO_EVERYTHING: break point
2518 2336 if [[ -n $nflag || ( -z $Uflag && -n $Dflag ) ]]; then
2519 2337 break
2520 2338 fi
2521 2339
2522 2340 #
2523 2341 # If this manually set as the parent, and it appears to be an earlier webrev,
2524 2342 # then note that fact and set the parent to the raw_files/new subdirectory.
2525 2343 #
2526 2344 if [[ -n $pflag && -d $codemgr_parent/raw_files/new ]]; then
2527 2345 parent_webrev=$(readlink -f "$codemgr_parent")
2528 2346 codemgr_parent=$(readlink -f "$codemgr_parent/raw_files/new")
2529 2347 fi
2530 2348
2531 2349 if [[ -z $wflag && -z $lflag ]]; then
2532 2350 shift $(($OPTIND - 1))
2533 2351
2534 2352 if [[ $1 == "-" ]]; then
2535 2353 cat > $FLIST
2536 2354 flist_mode="stdin"
2537 2355 flist_done=1
2538 2356 shift
2539 2357 elif [[ -n $1 ]]; then
2540 2358 if [[ ! -r $1 ]]; then
2541 2359 print -u2 "$1: no such file or not readable"
2542 2360 usage
2543 2361 fi
2544 2362 cat $1 > $FLIST
2545 2363 flist_mode="file"
2546 2364 flist_file=$1
2547 2365 flist_done=1
2548 2366 shift
↓ open down ↓ |
105 lines elided |
↑ open up ↑ |
2549 2367 else
2550 2368 flist_mode="auto"
2551 2369 fi
2552 2370 fi
2553 2371
2554 2372 #
2555 2373 # Before we go on to further consider -l and -w, work out which SCM we think
2556 2374 # is in use.
2557 2375 #
2558 2376 case "$SCM_MODE" in
2559 -teamware|mercurial|git|subversion)
2377 +mercurial|git|subversion)
2560 2378 ;;
2561 2379 unknown)
2562 2380 if [[ $flist_mode == "auto" ]]; then
2563 2381 print -u2 "Unable to determine SCM in use and file list not specified"
2564 2382 print -u2 "See which_scm(1) for SCM detection information."
2565 2383 exit 1
2566 2384 fi
2567 2385 ;;
2568 2386 *)
2569 2387 if [[ $flist_mode == "auto" ]]; then
2570 2388 print -u2 "Unsupported SCM in use ($SCM_MODE) and file list not specified"
2571 2389 exit 1
2572 2390 fi
2573 2391 ;;
2574 2392 esac
2575 2393
2576 2394 print -u2 " SCM detected: $SCM_MODE"
2577 2395
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
2396 +if [[ -n $wflag ]]; then
2594 2397 #
2595 2398 # If the -w is given then assume the file list is in Bonwick's "wx"
2596 2399 # command format, i.e. pathname lines alternating with SCCS comment
2597 2400 # lines with blank lines as separators. Use the SCCS comments later
2598 2401 # in building the index.html file.
2599 2402 #
2600 2403 shift $(($OPTIND - 1))
2601 2404 wxfile=$1
2602 2405 if [[ -z $wxfile && -n $CODEMGR_WS ]]; then
2603 2406 if [[ -r $CODEMGR_WS/wx/active ]]; then
2604 2407 wxfile=$CODEMGR_WS/wx/active
2605 2408 fi
2606 2409 fi
2607 2410
2608 2411 [[ -z $wxfile ]] && print -u2 "wx file not specified, and could not " \
2609 2412 "be auto-detected (check \$CODEMGR_WS)" && exit 1
2610 2413
2611 2414 if [[ ! -r $wxfile ]]; then
2612 2415 print -u2 "$wxfile: no such file or not readable"
2613 2416 usage
2614 2417 fi
2615 2418
2616 2419 print -u2 " File list from: wx 'active' file '$wxfile' ... \c"
2617 2420 flist_from_wx $wxfile
2618 2421 flist_done=1
2619 2422 if [[ -n "$*" ]]; then
2620 2423 shift
2621 2424 fi
2622 2425 elif [[ $flist_mode == "stdin" ]]; then
2623 2426 print -u2 " File list from: standard input"
2624 2427 elif [[ $flist_mode == "file" ]]; then
2625 2428 print -u2 " File list from: $flist_file"
↓ open down ↓ |
22 lines elided |
↑ open up ↑ |
2626 2429 fi
2627 2430
2628 2431 if [[ $# -gt 0 ]]; then
2629 2432 print -u2 "WARNING: unused arguments: $*"
2630 2433 fi
2631 2434
2632 2435 #
2633 2436 # Before we entered the DO_EVERYTHING loop, we should have already set CWS
2634 2437 # and CODEMGR_WS as needed. Here, we set the parent workspace.
2635 2438 #
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
2439 +if [[ $SCM_MODE == "mercurial" ]]; then
2707 2440 #
2708 2441 # Parent can either be specified with -p
2709 2442 # Specified with CODEMGR_PARENT in the environment
2710 2443 # or taken from hg's default path.
2711 2444 #
2712 2445
2713 2446 if [[ -z $codemgr_parent && -n $CODEMGR_PARENT ]]; then
2714 2447 codemgr_parent=$CODEMGR_PARENT
2715 2448 fi
2716 2449
2717 2450 if [[ -z $codemgr_parent ]]; then
2718 2451 codemgr_parent=`hg path -R $codemgr_ws default 2>/dev/null`
2719 2452 fi
2720 2453
2721 2454 PWS=$codemgr_parent
2722 2455
2723 2456 #
2724 2457 # If the parent is a webrev, we want to do some things against
2725 2458 # the natural workspace parent (file list, comments, etc)
2726 2459 #
2727 2460 if [[ -n $parent_webrev ]]; then
2728 2461 real_parent=$(hg path -R $codemgr_ws default 2>/dev/null)
2729 2462 else
2730 2463 real_parent=$PWS
2731 2464 fi
2732 2465
2733 2466 #
2734 2467 # If hg-active exists, then we run it. In the case of no explicit
2735 2468 # flist given, we'll use it for our comments. In the case of an
2736 2469 # explicit flist given we'll try to use it for comments for any
2737 2470 # files mentioned in the flist.
2738 2471 #
2739 2472 if [[ -z $flist_done ]]; then
2740 2473 flist_from_mercurial $CWS $real_parent
2741 2474 flist_done=1
2742 2475 fi
2743 2476
2744 2477 #
2745 2478 # If we have a file list now, pull out any variables set
2746 2479 # therein. We do this now (rather than when we possibly use
2747 2480 # hg-active to find comments) to avoid stomping specifications
2748 2481 # in the user-specified flist.
2749 2482 #
2750 2483 if [[ -n $flist_done ]]; then
2751 2484 env_from_flist
2752 2485 fi
2753 2486
2754 2487 #
2755 2488 # Only call hg-active if we don't have a wx formatted file already
2756 2489 #
2757 2490 if [[ -x $HG_ACTIVE && -z $wxfile ]]; then
2758 2491 print " Comments from: hg-active -p $real_parent ...\c"
2759 2492 hg_active_wxfile $CWS $real_parent
2760 2493 print " Done."
2761 2494 fi
2762 2495
2763 2496 #
2764 2497 # At this point we must have a wx flist either from hg-active,
2765 2498 # or in general. Use it to try and find our parent revision,
2766 2499 # if we don't have one.
2767 2500 #
2768 2501 if [[ -z $HG_PARENT ]]; then
2769 2502 eval `$SED -e "s/#.*$//" $wxfile | $GREP HG_PARENT=`
2770 2503 fi
2771 2504
2772 2505 #
2773 2506 # If we still don't have a parent, we must have been given a
2774 2507 # wx-style active list with no HG_PARENT specification, run
2775 2508 # hg-active and pull an HG_PARENT out of it, ignore the rest.
2776 2509 #
2777 2510 if [[ -z $HG_PARENT && -x $HG_ACTIVE ]]; then
2778 2511 $HG_ACTIVE -w $codemgr_ws -p $real_parent | \
2779 2512 eval `$SED -e "s/#.*$//" | $GREP HG_PARENT=`
2780 2513 elif [[ -z $HG_PARENT ]]; then
2781 2514 print -u2 "Error: Cannot discover parent revision"
2782 2515 exit 1
2783 2516 fi
2784 2517
2785 2518 pnode=$(trim_digest $HG_PARENT)
2786 2519 PRETTY_PWS="${PWS} (at ${pnode})"
2787 2520 cnode=$(hg parent -R $codemgr_ws --template '{node|short}' \
2788 2521 2>/dev/null)
2789 2522 PRETTY_CWS="${CWS} (at ${cnode})"}
2790 2523 elif [[ $SCM_MODE == "git" ]]; then
2791 2524 #
2792 2525 # Parent can either be specified with -p, or specified with
2793 2526 # CODEMGR_PARENT in the environment.
2794 2527 #
2795 2528
2796 2529 if [[ -z $codemgr_parent && -n $CODEMGR_PARENT ]]; then
2797 2530 codemgr_parent=$CODEMGR_PARENT
2798 2531 fi
2799 2532
2800 2533 # Try to figure out the parent based on the branch the current
2801 2534 # branch is tracking, if we fail, use origin/master
2802 2535 this_branch=$($GIT branch | nawk '$1 == "*" { print $2 }')
2803 2536 par_branch="origin/master"
2804 2537
2805 2538 # If we're not on a branch there's nothing we can do
2806 2539 if [[ $this_branch != "(no branch)" ]]; then
2807 2540 $GIT for-each-ref \
2808 2541 --format='%(refname:short) %(upstream:short)' refs/heads/ | \
2809 2542 while read local remote; do \
2810 2543 [[ "$local" == "$this_branch" ]] && par_branch="$remote"; \
2811 2544 done
2812 2545 fi
2813 2546
2814 2547 if [[ -z $codemgr_parent ]]; then
2815 2548 codemgr_parent=$par_branch
2816 2549 fi
2817 2550 PWS=$codemgr_parent
2818 2551
2819 2552 #
2820 2553 # If the parent is a webrev, we want to do some things against
2821 2554 # the natural workspace parent (file list, comments, etc)
2822 2555 #
2823 2556 if [[ -n $parent_webrev ]]; then
2824 2557 real_parent=$par_branch
2825 2558 else
2826 2559 real_parent=$PWS
2827 2560 fi
2828 2561
2829 2562 if [[ -z $flist_done ]]; then
2830 2563 flist_from_git "$CWS" "$real_parent"
2831 2564 flist_done=1
2832 2565 fi
2833 2566
2834 2567 #
2835 2568 # If we have a file list now, pull out any variables set
2836 2569 # therein.
2837 2570 #
2838 2571 if [[ -n $flist_done ]]; then
2839 2572 env_from_flist
2840 2573 fi
2841 2574
2842 2575 #
2843 2576 # If we don't have a wx-format file list, build one we can pull change
2844 2577 # comments from.
2845 2578 #
2846 2579 if [[ -z $wxfile ]]; then
2847 2580 print " Comments from: git...\c"
2848 2581 git_wxfile "$CWS" "$real_parent"
2849 2582 print " Done."
2850 2583 fi
2851 2584
2852 2585 if [[ -z $GIT_PARENT ]]; then
2853 2586 GIT_PARENT=$($GIT merge-base "$real_parent" HEAD)
2854 2587 fi
2855 2588 if [[ -z $GIT_PARENT ]]; then
2856 2589 print -u2 "Error: Cannot discover parent revision"
2857 2590 exit 1
2858 2591 fi
2859 2592
2860 2593 pnode=$(trim_digest $GIT_PARENT)
2861 2594
2862 2595 if [[ $real_parent == */* ]]; then
2863 2596 origin=$(echo $real_parent | cut -d/ -f1)
2864 2597 origin=$($GIT remote -v | \
2865 2598 $AWK '$1 == "'$origin'" { print $2; exit }')
2866 2599 PRETTY_PWS="${PWS} (${origin} at ${pnode})"
2867 2600 else
2868 2601 PRETTY_PWS="${PWS} (at ${pnode})"
2869 2602 fi
2870 2603
2871 2604 cnode=$($GIT --git-dir=${codemgr_ws}/.git rev-parse --short=12 HEAD \
2872 2605 2>/dev/null)
2873 2606 PRETTY_CWS="${CWS} (at ${cnode})"
2874 2607 elif [[ $SCM_MODE == "subversion" ]]; then
2875 2608
2876 2609 #
2877 2610 # We only will have a real parent workspace in the case one
2878 2611 # was specified (be it an older webrev, or another checkout).
2879 2612 #
2880 2613 [[ -n $codemgr_parent ]] && PWS=$codemgr_parent
2881 2614
2882 2615 if [[ -z $flist_done && $flist_mode == "auto" ]]; then
2883 2616 flist_from_subversion $CWS $OLDPWD
2884 2617 fi
2885 2618 else
2886 2619 if [[ $SCM_MODE == "unknown" ]]; then
2887 2620 print -u2 " Unknown type of SCM in use"
2888 2621 else
2889 2622 print -u2 " Unsupported SCM in use: $SCM_MODE"
2890 2623 fi
2891 2624
2892 2625 env_from_flist
2893 2626
2894 2627 if [[ -z $CODEMGR_WS ]]; then
2895 2628 print -u2 "SCM not detected/supported and CODEMGR_WS not specified"
2896 2629 exit 1
2897 2630 fi
2898 2631
2899 2632 if [[ -z $CODEMGR_PARENT ]]; then
2900 2633 print -u2 "SCM not detected/supported and CODEMGR_PARENT not specified"
2901 2634 exit 1
2902 2635 fi
2903 2636
2904 2637 CWS=$CODEMGR_WS
2905 2638 PWS=$CODEMGR_PARENT
2906 2639 fi
2907 2640
2908 2641 #
2909 2642 # If the user didn't specify a -i option, check to see if there is a
2910 2643 # webrev-info file in the workspace directory.
2911 2644 #
2912 2645 if [[ -z $iflag && -r "$CWS/webrev-info" ]]; then
2913 2646 iflag=1
2914 2647 INCLUDE_FILE="$CWS/webrev-info"
2915 2648 fi
2916 2649
2917 2650 if [[ -n $iflag ]]; then
2918 2651 if [[ ! -r $INCLUDE_FILE ]]; then
2919 2652 print -u2 "include file '$INCLUDE_FILE' does not exist or is" \
2920 2653 "not readable."
2921 2654 exit 1
2922 2655 else
2923 2656 #
2924 2657 # $INCLUDE_FILE may be a relative path, and the script alters
2925 2658 # PWD, so we just stash a copy in /tmp.
2926 2659 #
2927 2660 cp $INCLUDE_FILE /tmp/$$.include
2928 2661 fi
2929 2662 fi
2930 2663
2931 2664 # DO_EVERYTHING: break point
2932 2665 if [[ -n $Nflag ]]; then
2933 2666 break
2934 2667 fi
2935 2668
2936 2669 typeset -A itsinfo
2937 2670 typeset -r its_sed_script=/tmp/$$.its_sed
2938 2671 valid_prefixes=
2939 2672 if [[ -z $nflag ]]; then
2940 2673 DEFREGFILE="$(/bin/dirname "$(whence $0)")/../etc/its.reg"
2941 2674 if [[ -n $Iflag ]]; then
2942 2675 REGFILE=$ITSREG
2943 2676 elif [[ -r $HOME/.its.reg ]]; then
2944 2677 REGFILE=$HOME/.its.reg
2945 2678 else
2946 2679 REGFILE=$DEFREGFILE
2947 2680 fi
2948 2681 if [[ ! -r $REGFILE ]]; then
2949 2682 print "ERROR: Unable to read database registry file $REGFILE"
2950 2683 exit 1
2951 2684 elif [[ $REGFILE != $DEFREGFILE ]]; then
2952 2685 print " its.reg from: $REGFILE"
2953 2686 fi
2954 2687
2955 2688 $SED -e '/^#/d' -e '/^[ ]*$/d' $REGFILE | while read LINE; do
2956 2689
2957 2690 name=${LINE%%=*}
2958 2691 value="${LINE#*=}"
2959 2692
2960 2693 if [[ $name == PREFIX ]]; then
2961 2694 p=${value}
2962 2695 valid_prefixes="${p} ${valid_prefixes}"
2963 2696 else
2964 2697 itsinfo["${p}_${name}"]="${value}"
2965 2698 fi
2966 2699 done
2967 2700
2968 2701
2969 2702 DEFCONFFILE="$(/bin/dirname "$(whence $0)")/../etc/its.conf"
2970 2703 CONFFILES=$DEFCONFFILE
2971 2704 if [[ -r $HOME/.its.conf ]]; then
2972 2705 CONFFILES="${CONFFILES} $HOME/.its.conf"
2973 2706 fi
2974 2707 if [[ -n $Cflag ]]; then
2975 2708 CONFFILES="${CONFFILES} ${ITSCONF}"
2976 2709 fi
2977 2710 its_domain=
2978 2711 its_priority=
2979 2712 for cf in ${CONFFILES}; do
2980 2713 if [[ ! -r $cf ]]; then
2981 2714 print "ERROR: Unable to read database configuration file $cf"
2982 2715 exit 1
2983 2716 elif [[ $cf != $DEFCONFFILE ]]; then
2984 2717 print " its.conf: reading $cf"
2985 2718 fi
2986 2719 $SED -e '/^#/d' -e '/^[ ]*$/d' $cf | while read LINE; do
2987 2720 eval "${LINE}"
2988 2721 done
2989 2722 done
2990 2723
2991 2724 #
2992 2725 # If an information tracking system is explicitly identified by prefix,
2993 2726 # we want to disregard the specified priorities and resolve it accordingly.
2994 2727 #
2995 2728 # To that end, we'll build a sed script to do each valid prefix in turn.
2996 2729 #
2997 2730 for p in ${valid_prefixes}; do
2998 2731 #
2999 2732 # When an informational URL was provided, translate it to a
3000 2733 # hyperlink. When omitted, simply use the prefix text.
3001 2734 #
3002 2735 if [[ -z ${itsinfo["${p}_INFO"]} ]]; then
3003 2736 itsinfo["${p}_INFO"]=${p}
3004 2737 else
3005 2738 itsinfo["${p}_INFO"]="<a href=\\\"${itsinfo["${p}_INFO"]}\\\">${p}</a>"
3006 2739 fi
3007 2740
3008 2741 #
3009 2742 # Assume that, for this invocation of webrev, all references
3010 2743 # to this information tracking system should resolve through
3011 2744 # the same URL.
3012 2745 #
3013 2746 # If the caller specified -O, then always use EXTERNAL_URL.
3014 2747 #
3015 2748 # Otherwise, look in the list of domains for a matching
3016 2749 # INTERNAL_URL.
3017 2750 #
3018 2751 [[ -z $Oflag ]] && for d in ${its_domain}; do
3019 2752 if [[ -n ${itsinfo["${p}_INTERNAL_URL_${d}"]} ]]; then
3020 2753 itsinfo["${p}_URL"]="${itsinfo[${p}_INTERNAL_URL_${d}]}"
3021 2754 break
3022 2755 fi
3023 2756 done
3024 2757 if [[ -z ${itsinfo["${p}_URL"]} ]]; then
3025 2758 itsinfo["${p}_URL"]="${itsinfo[${p}_EXTERNAL_URL]}"
3026 2759 fi
3027 2760
3028 2761 #
3029 2762 # Turn the destination URL into a hyperlink
3030 2763 #
3031 2764 itsinfo["${p}_URL"]="<a href=\\\"${itsinfo[${p}_URL]}\\\">&</a>"
3032 2765
3033 2766 # The character class below contains a literal tab
3034 2767 print "/^${p}[: ]/ {
3035 2768 s;${itsinfo[${p}_REGEX]};${itsinfo[${p}_URL]};g
3036 2769 s;^${p};${itsinfo[${p}_INFO]};
3037 2770 }" >> ${its_sed_script}
3038 2771 done
3039 2772
3040 2773 #
3041 2774 # The previous loop took care of explicit specification. Now use
3042 2775 # the configured priorities to attempt implicit translations.
3043 2776 #
3044 2777 for p in ${its_priority}; do
3045 2778 print "/^${itsinfo[${p}_REGEX]}[ ]/ {
3046 2779 s;^${itsinfo[${p}_REGEX]};${itsinfo[${p}_URL]};g
3047 2780 }" >> ${its_sed_script}
3048 2781 done
3049 2782 fi
3050 2783
3051 2784 #
3052 2785 # Search for DO_EVERYTHING above for matching "for" statement
3053 2786 # and explanation of this terminator.
3054 2787 #
3055 2788 done
3056 2789
3057 2790 #
3058 2791 # Output directory.
3059 2792 #
3060 2793 WDIR=${WDIR:-$CWS/webrev}
3061 2794
3062 2795 #
3063 2796 # Name of the webrev, derived from the workspace name or output directory;
3064 2797 # in the future this could potentially be an option.
3065 2798 #
3066 2799 if [[ -n $oflag ]]; then
3067 2800 WNAME=${WDIR##*/}
3068 2801 else
3069 2802 WNAME=${CWS##*/}
3070 2803 fi
3071 2804
3072 2805 # Make sure remote target is well formed for remote upload/delete.
3073 2806 if [[ -n $Dflag || -n $Uflag ]]; then
3074 2807 #
3075 2808 # If remote target is not specified, build it from scratch using
3076 2809 # the default values.
3077 2810 #
3078 2811 if [[ -z $tflag ]]; then
3079 2812 remote_target=${DEFAULT_REMOTE_HOST}:${WNAME}
3080 2813 else
3081 2814 #
3082 2815 # Check upload target prefix first.
3083 2816 #
3084 2817 if [[ "${remote_target}" != ${rsync_prefix}* &&
3085 2818 "${remote_target}" != ${ssh_prefix}* ]]; then
3086 2819 print "ERROR: invalid prefix of upload URI" \
3087 2820 "($remote_target)"
3088 2821 exit 1
3089 2822 fi
3090 2823 #
3091 2824 # If destination specification is not in the form of
3092 2825 # host_spec:remote_dir then assume it is just remote hostname
3093 2826 # and append a colon and destination directory formed from
3094 2827 # local webrev directory name.
3095 2828 #
3096 2829 typeset target_no_prefix=${remote_target##*://}
3097 2830 if [[ ${target_no_prefix} == *:* ]]; then
3098 2831 if [[ "${remote_target}" == *: ]]; then
3099 2832 remote_target=${remote_target}${WNAME}
3100 2833 fi
3101 2834 else
3102 2835 if [[ ${target_no_prefix} == */* ]]; then
3103 2836 print "ERROR: badly formed upload URI" \
3104 2837 "($remote_target)"
3105 2838 exit 1
3106 2839 else
3107 2840 remote_target=${remote_target}:${WNAME}
3108 2841 fi
3109 2842 fi
3110 2843 fi
3111 2844
3112 2845 #
3113 2846 # Strip trailing slash. Each upload method will deal with directory
3114 2847 # specification separately.
3115 2848 #
3116 2849 remote_target=${remote_target%/}
3117 2850 fi
3118 2851
3119 2852 #
3120 2853 # Option -D by itself (option -U not present) implies no webrev generation.
3121 2854 #
3122 2855 if [[ -z $Uflag && -n $Dflag ]]; then
3123 2856 delete_webrev 1 1
3124 2857 exit $?
3125 2858 fi
3126 2859
3127 2860 #
3128 2861 # Do not generate the webrev, just upload it or delete it.
3129 2862 #
3130 2863 if [[ -n $nflag ]]; then
3131 2864 if [[ -n $Dflag ]]; then
3132 2865 delete_webrev 1 1
3133 2866 (( $? == 0 )) || exit $?
3134 2867 fi
3135 2868 if [[ -n $Uflag ]]; then
3136 2869 upload_webrev
3137 2870 exit $?
3138 2871 fi
3139 2872 fi
3140 2873
3141 2874 if [ "${WDIR%%/*}" ]; then
3142 2875 WDIR=$PWD/$WDIR
3143 2876 fi
3144 2877
3145 2878 if [[ ! -d $WDIR ]]; then
3146 2879 mkdir -p $WDIR
3147 2880 (( $? != 0 )) && exit 1
3148 2881 fi
3149 2882
3150 2883 #
3151 2884 # Summarize what we're going to do.
3152 2885 #
3153 2886 print " Workspace: ${PRETTY_CWS:-$CWS}"
3154 2887 if [[ -n $parent_webrev ]]; then
3155 2888 print "Compare against: webrev at $parent_webrev"
3156 2889 else
3157 2890 print "Compare against: ${PRETTY_PWS:-$PWS}"
3158 2891 fi
3159 2892
3160 2893 [[ -n $INCLUDE_FILE ]] && print " Including: $INCLUDE_FILE"
3161 2894 print " Output to: $WDIR"
3162 2895
3163 2896 #
3164 2897 # Save the file list in the webrev dir
3165 2898 #
3166 2899 [[ ! $FLIST -ef $WDIR/file.list ]] && cp $FLIST $WDIR/file.list
3167 2900
3168 2901 rm -f $WDIR/$WNAME.patch
3169 2902 rm -f $WDIR/$WNAME.ps
3170 2903 rm -f $WDIR/$WNAME.pdf
3171 2904
3172 2905 touch $WDIR/$WNAME.patch
3173 2906
3174 2907 print " Output Files:"
3175 2908
3176 2909 #
3177 2910 # Clean up the file list: Remove comments, blank lines and env variables.
3178 2911 #
3179 2912 $SED -e "s/#.*$//" -e "/=/d" -e "/^[ ]*$/d" $FLIST > /tmp/$$.flist.clean
3180 2913 FLIST=/tmp/$$.flist.clean
3181 2914
3182 2915 #
3183 2916 # For Mercurial, create a cache of manifest entries.
3184 2917 #
3185 2918 if [[ $SCM_MODE == "mercurial" ]]; then
3186 2919 #
3187 2920 # Transform the FLIST into a temporary sed script that matches
3188 2921 # relevant entries in the Mercurial manifest as follows:
3189 2922 # 1) The script will be used against the parent revision manifest,
3190 2923 # so for FLIST lines that have two filenames (a renamed file)
3191 2924 # keep only the old name.
3192 2925 # 2) Escape all forward slashes the filename.
3193 2926 # 3) Change the filename into another sed command that matches
3194 2927 # that file in "hg manifest -v" output: start of line, three
3195 2928 # octal digits for file permissions, space, a file type flag
3196 2929 # character, space, the filename, end of line.
3197 2930 # 4) Eliminate any duplicate entries. (This can occur if a
3198 2931 # file has been used as the source of an hg cp and it's
3199 2932 # also been modified in the same changeset.)
3200 2933 #
3201 2934 SEDFILE=/tmp/$$.manifest.sed
3202 2935 $SED '
3203 2936 s#^[^ ]* ##
3204 2937 s#/#\\\/#g
3205 2938 s#^.*$#/^... . &$/p#
3206 2939 ' < $FLIST | $SORT -u > $SEDFILE
3207 2940
3208 2941 #
3209 2942 # Apply the generated script to the output of "hg manifest -v"
3210 2943 # to get the relevant subset for this webrev.
3211 2944 #
3212 2945 HG_PARENT_MANIFEST=/tmp/$$.manifest
3213 2946 hg -R $CWS manifest -v -r $HG_PARENT |
3214 2947 $SED -n -f $SEDFILE > $HG_PARENT_MANIFEST
3215 2948 fi
3216 2949
3217 2950 #
3218 2951 # First pass through the files: generate the per-file webrev HTML-files.
3219 2952 #
3220 2953 cat $FLIST | while read LINE
3221 2954 do
3222 2955 set - $LINE
3223 2956 P=$1
3224 2957
3225 2958 #
3226 2959 # Normally, each line in the file list is just a pathname of a
3227 2960 # file that has been modified or created in the child. A file
3228 2961 # that is renamed in the child workspace has two names on the
3229 2962 # line: new name followed by the old name.
3230 2963 #
3231 2964 oldname=""
3232 2965 oldpath=""
3233 2966 rename=
3234 2967 if [[ $# -eq 2 ]]; then
3235 2968 PP=$2 # old filename
3236 2969 if [[ -f $PP ]]; then
3237 2970 oldname=" (copied from $PP)"
3238 2971 else
3239 2972 oldname=" (renamed from $PP)"
3240 2973 fi
3241 2974 oldpath="$PP"
3242 2975 rename=1
3243 2976 PDIR=${PP%/*}
3244 2977 if [[ $PDIR == $PP ]]; then
3245 2978 PDIR="." # File at root of workspace
3246 2979 fi
3247 2980
3248 2981 PF=${PP##*/}
3249 2982
3250 2983 DIR=${P%/*}
3251 2984 if [[ $DIR == $P ]]; then
3252 2985 DIR="." # File at root of workspace
3253 2986 fi
3254 2987
3255 2988 F=${P##*/}
3256 2989
3257 2990 else
3258 2991 DIR=${P%/*}
3259 2992 if [[ "$DIR" == "$P" ]]; then
3260 2993 DIR="." # File at root of workspace
3261 2994 fi
3262 2995
3263 2996 F=${P##*/}
3264 2997
3265 2998 PP=$P
3266 2999 PDIR=$DIR
3267 3000 PF=$F
3268 3001 fi
3269 3002
3270 3003 COMM=`getcomments html $P $PP`
3271 3004
3272 3005 print "\t$P$oldname\n\t\t\c"
3273 3006
3274 3007 # Make the webrev mirror directory if necessary
3275 3008 mkdir -p $WDIR/$DIR
3276 3009
3277 3010 #
3278 3011 # We stash old and new files into parallel directories in $WDIR
3279 3012 # and do our diffs there. This makes it possible to generate
3280 3013 # clean looking diffs which don't have absolute paths present.
3281 3014 #
3282 3015
3283 3016 build_old_new "$WDIR" "$PWS" "$PDIR" "$PF" "$CWS" "$DIR" "$F" || \
3284 3017 continue
3285 3018
3286 3019 #
3287 3020 # Keep the old PWD around, so we can safely switch back after
3288 3021 # diff generation, such that build_old_new runs in a
3289 3022 # consistent environment.
3290 3023 #
3291 3024 OWD=$PWD
3292 3025 cd $WDIR/raw_files
3293 3026 ofile=old/$PDIR/$PF
3294 3027 nfile=new/$DIR/$F
3295 3028
3296 3029 mv_but_nodiff=
3297 3030 cmp $ofile $nfile > /dev/null 2>&1
3298 3031 if [[ $? == 0 && $rename == 1 ]]; then
3299 3032 mv_but_nodiff=1
3300 3033 fi
3301 3034
3302 3035 #
3303 3036 # If we have old and new versions of the file then run the appropriate
3304 3037 # diffs. This is complicated by a couple of factors:
3305 3038 #
3306 3039 # - renames must be handled specially: we emit a 'remove'
3307 3040 # diff and an 'add' diff
3308 3041 # - new files and deleted files must be handled specially
3309 3042 # - Solaris patch(1m) can't cope with file creation
3310 3043 # (and hence renames) as of this writing.
3311 3044 # - To make matters worse, gnu patch doesn't interpret the
3312 3045 # output of Solaris diff properly when it comes to
3313 3046 # adds and deletes. We need to do some "cleansing"
3314 3047 # transformations:
3315 3048 # [to add a file] @@ -1,0 +X,Y @@ --> @@ -0,0 +X,Y @@
3316 3049 # [to del a file] @@ -X,Y +1,0 @@ --> @@ -X,Y +0,0 @@
3317 3050 #
3318 3051 cleanse_rmfile="$SED 's/^\(@@ [0-9+,-]*\) [0-9+,-]* @@$/\1 +0,0 @@/'"
3319 3052 cleanse_newfile="$SED 's/^@@ [0-9+,-]* \([0-9+,-]* @@\)$/@@ -0,0 \1/'"
3320 3053
3321 3054 rm -f $WDIR/$DIR/$F.patch
3322 3055 if [[ -z $rename ]]; then
3323 3056 if [ ! -f "$ofile" ]; then
3324 3057 diff -u /dev/null $nfile | sh -c "$cleanse_newfile" \
3325 3058 > $WDIR/$DIR/$F.patch
3326 3059 elif [ ! -f "$nfile" ]; then
3327 3060 diff -u $ofile /dev/null | sh -c "$cleanse_rmfile" \
3328 3061 > $WDIR/$DIR/$F.patch
3329 3062 else
3330 3063 diff -u $ofile $nfile > $WDIR/$DIR/$F.patch
3331 3064 fi
3332 3065 else
3333 3066 diff -u $ofile /dev/null | sh -c "$cleanse_rmfile" \
3334 3067 > $WDIR/$DIR/$F.patch
3335 3068
3336 3069 diff -u /dev/null $nfile | sh -c "$cleanse_newfile" \
3337 3070 >> $WDIR/$DIR/$F.patch
3338 3071 fi
3339 3072
3340 3073 #
3341 3074 # Tack the patch we just made onto the accumulated patch for the
3342 3075 # whole wad.
3343 3076 #
3344 3077 cat $WDIR/$DIR/$F.patch >> $WDIR/$WNAME.patch
3345 3078
3346 3079 print " patch\c"
3347 3080
3348 3081 if [[ -f $ofile && -f $nfile && -z $mv_but_nodiff ]]; then
3349 3082
3350 3083 ${CDIFFCMD:-diff -bt -C 5} $ofile $nfile > $WDIR/$DIR/$F.cdiff
3351 3084 diff_to_html $F $DIR/$F "C" "$COMM" < $WDIR/$DIR/$F.cdiff \
3352 3085 > $WDIR/$DIR/$F.cdiff.html
3353 3086 print " cdiffs\c"
3354 3087
3355 3088 ${UDIFFCMD:-diff -bt -U 5} $ofile $nfile > $WDIR/$DIR/$F.udiff
3356 3089 diff_to_html $F $DIR/$F "U" "$COMM" < $WDIR/$DIR/$F.udiff \
3357 3090 > $WDIR/$DIR/$F.udiff.html
3358 3091
3359 3092 print " udiffs\c"
3360 3093
3361 3094 if [[ -x $WDIFF ]]; then
3362 3095 $WDIFF -c "$COMM" \
3363 3096 -t "$WNAME Wdiff $DIR/$F" $ofile $nfile > \
3364 3097 $WDIR/$DIR/$F.wdiff.html 2>/dev/null
3365 3098 if [[ $? -eq 0 ]]; then
3366 3099 print " wdiffs\c"
3367 3100 else
3368 3101 print " wdiffs[fail]\c"
3369 3102 fi
3370 3103 fi
3371 3104
3372 3105 sdiff_to_html $ofile $nfile $F $DIR "$COMM" \
3373 3106 > $WDIR/$DIR/$F.sdiff.html
3374 3107 print " sdiffs\c"
3375 3108
3376 3109 print " frames\c"
3377 3110
3378 3111 rm -f $WDIR/$DIR/$F.cdiff $WDIR/$DIR/$F.udiff
3379 3112
3380 3113 difflines $ofile $nfile > $WDIR/$DIR/$F.count
3381 3114
3382 3115 elif [[ -f $ofile && -f $nfile && -n $mv_but_nodiff ]]; then
3383 3116 # renamed file: may also have differences
3384 3117 difflines $ofile $nfile > $WDIR/$DIR/$F.count
3385 3118 elif [[ -f $nfile ]]; then
3386 3119 # new file: count added lines
3387 3120 difflines /dev/null $nfile > $WDIR/$DIR/$F.count
3388 3121 elif [[ -f $ofile ]]; then
3389 3122 # old file: count deleted lines
3390 3123 difflines $ofile /dev/null > $WDIR/$DIR/$F.count
3391 3124 fi
3392 3125
3393 3126 #
3394 3127 # Now we generate the postscript for this file. We generate diffs
3395 3128 # only in the event that there is delta, or the file is new (it seems
3396 3129 # tree-killing to print out the contents of deleted files).
3397 3130 #
3398 3131 if [[ -f $nfile ]]; then
3399 3132 ocr=$ofile
3400 3133 [[ ! -f $ofile ]] && ocr=/dev/null
3401 3134
3402 3135 if [[ -z $mv_but_nodiff ]]; then
3403 3136 textcomm=`getcomments text $P $PP`
3404 3137 if [[ -x $CODEREVIEW ]]; then
3405 3138 $CODEREVIEW -y "$textcomm" \
3406 3139 -e $ocr $nfile \
3407 3140 > /tmp/$$.psfile 2>/dev/null &&
3408 3141 cat /tmp/$$.psfile >> $WDIR/$WNAME.ps
3409 3142 if [[ $? -eq 0 ]]; then
3410 3143 print " ps\c"
3411 3144 else
3412 3145 print " ps[fail]\c"
3413 3146 fi
3414 3147 fi
3415 3148 fi
3416 3149 fi
3417 3150
3418 3151 if [[ -f $ofile ]]; then
3419 3152 source_to_html Old $PP < $ofile > $WDIR/$DIR/$F-.html
3420 3153 print " old\c"
3421 3154 fi
3422 3155
3423 3156 if [[ -f $nfile ]]; then
3424 3157 source_to_html New $P < $nfile > $WDIR/$DIR/$F.html
3425 3158 print " new\c"
3426 3159 fi
3427 3160
3428 3161 cd $OWD
3429 3162
3430 3163 print
3431 3164 done
3432 3165
3433 3166 frame_nav_js > $WDIR/ancnav.js
3434 3167 frame_navigation > $WDIR/ancnav.html
3435 3168
3436 3169 if [[ ! -f $WDIR/$WNAME.ps ]]; then
3437 3170 print " Generating PDF: Skipped: no output available"
3438 3171 elif [[ -x $CODEREVIEW && -x $PS2PDF ]]; then
3439 3172 print " Generating PDF: \c"
3440 3173 fix_postscript $WDIR/$WNAME.ps | $PS2PDF - > $WDIR/$WNAME.pdf
3441 3174 print "Done."
3442 3175 else
3443 3176 print " Generating PDF: Skipped: missing 'ps2pdf' or 'codereview'"
3444 3177 fi
3445 3178
3446 3179 # If we're in OpenSolaris mode and there's a closed dir under $WDIR,
3447 3180 # delete it - prevent accidental publishing of closed source
3448 3181
3449 3182 if [[ -n "$Oflag" ]]; then
3450 3183 $FIND $WDIR -type d -name closed -exec /bin/rm -rf {} \;
3451 3184 fi
3452 3185
3453 3186 # Now build the index.html file that contains
3454 3187 # links to the source files and their diffs.
3455 3188
3456 3189 cd $CWS
3457 3190
3458 3191 # Save total changed lines for Code Inspection.
3459 3192 print "$TOTL" > $WDIR/TotalChangedLines
3460 3193
3461 3194 print " index.html: \c"
3462 3195 INDEXFILE=$WDIR/index.html
3463 3196 exec 3<&1 # duplicate stdout to FD3.
3464 3197 exec 1<&- # Close stdout.
3465 3198 exec > $INDEXFILE # Open stdout to index file.
3466 3199
3467 3200 print "$HTML<head>$STDHEAD"
3468 3201 print "<title>$WNAME</title>"
3469 3202 print "</head>"
3470 3203 print "<body id=\"SUNWwebrev\">"
3471 3204 print "<div class=\"summary\">"
3472 3205 print "<h2>Code Review for $WNAME</h2>"
3473 3206
3474 3207 print "<table>"
3475 3208
3476 3209 #
3477 3210 # Get the preparer's name:
3478 3211 #
3479 3212 # If the SCM detected is Mercurial, and the configuration property
3480 3213 # ui.username is available, use that, but be careful to properly escape
3481 3214 # angle brackets (HTML syntax characters) in the email address.
3482 3215 #
3483 3216 # Otherwise, use the current userid in the form "John Doe (jdoe)", but
3484 3217 # to maintain compatibility with passwd(4), we must support '&' substitutions.
3485 3218 #
3486 3219 preparer=
3487 3220 if [[ "$SCM_MODE" == mercurial ]]; then
3488 3221 preparer=`hg showconfig ui.username 2>/dev/null`
3489 3222 if [[ -n "$preparer" ]]; then
3490 3223 preparer="$(echo "$preparer" | html_quote)"
3491 3224 fi
3492 3225 fi
3493 3226 if [[ -z "$preparer" ]]; then
3494 3227 preparer=$(
3495 3228 $PERL -e '
3496 3229 ($login, $pw, $uid, $gid, $quota, $cmt, $gcos) = getpwuid($<);
3497 3230 if ($login) {
3498 3231 $gcos =~ s/\&/ucfirst($login)/e;
3499 3232 printf "%s (%s)\n", $gcos, $login;
3500 3233 } else {
3501 3234 printf "(unknown)\n";
3502 3235 }
3503 3236 ')
3504 3237 fi
3505 3238
3506 3239 PREPDATE=$(LC_ALL=C /usr/bin/date +%Y-%b-%d\ %R\ %z\ %Z)
3507 3240 print "<tr><th>Prepared by:</th><td>$preparer on $PREPDATE</td></tr>"
3508 3241 print "<tr><th>Workspace:</th><td>${PRETTY_CWS:-$CWS}"
3509 3242 print "</td></tr>"
3510 3243 print "<tr><th>Compare against:</th><td>"
3511 3244 if [[ -n $parent_webrev ]]; then
3512 3245 print "webrev at $parent_webrev"
3513 3246 else
3514 3247 print "${PRETTY_PWS:-$PWS}"
3515 3248 fi
3516 3249 print "</td></tr>"
3517 3250 print "<tr><th>Summary of changes:</th><td>"
3518 3251 printCI $TOTL $TINS $TDEL $TMOD $TUNC
3519 3252 print "</td></tr>"
3520 3253
3521 3254 if [[ -f $WDIR/$WNAME.patch ]]; then
3522 3255 wpatch_url="$(print $WNAME.patch | url_encode)"
3523 3256 print "<tr><th>Patch of changes:</th><td>"
3524 3257 print "<a href=\"$wpatch_url\">$WNAME.patch</a></td></tr>"
3525 3258 fi
3526 3259 if [[ -f $WDIR/$WNAME.pdf ]]; then
3527 3260 wpdf_url="$(print $WNAME.pdf | url_encode)"
3528 3261 print "<tr><th>Printable review:</th><td>"
3529 3262 print "<a href=\"$wpdf_url\">$WNAME.pdf</a></td></tr>"
3530 3263 fi
3531 3264
3532 3265 if [[ -n "$iflag" ]]; then
3533 3266 print "<tr><th>Author comments:</th><td><div>"
3534 3267 cat /tmp/$$.include
3535 3268 print "</div></td></tr>"
3536 3269 fi
3537 3270 print "</table>"
3538 3271 print "</div>"
3539 3272
3540 3273 #
3541 3274 # Second pass through the files: generate the rest of the index file
3542 3275 #
3543 3276 cat $FLIST | while read LINE
3544 3277 do
3545 3278 set - $LINE
3546 3279 P=$1
3547 3280
3548 3281 if [[ $# == 2 ]]; then
3549 3282 PP=$2
3550 3283 oldname="$PP"
3551 3284 else
3552 3285 PP=$P
3553 3286 oldname=""
3554 3287 fi
3555 3288
3556 3289 mv_but_nodiff=
3557 3290 cmp $WDIR/raw_files/old/$PP $WDIR/raw_files/new/$P > /dev/null 2>&1
3558 3291 if [[ $? == 0 && -n "$oldname" ]]; then
3559 3292 mv_but_nodiff=1
3560 3293 fi
3561 3294
3562 3295 DIR=${P%/*}
3563 3296 if [[ $DIR == $P ]]; then
3564 3297 DIR="." # File at root of workspace
3565 3298 fi
3566 3299
3567 3300 # Avoid processing the same file twice.
3568 3301 # It's possible for renamed files to
3569 3302 # appear twice in the file list
3570 3303
3571 3304 F=$WDIR/$P
3572 3305
3573 3306 print "<p>"
3574 3307
3575 3308 # If there's a diffs file, make diffs links
3576 3309
3577 3310 if [[ -f $F.cdiff.html ]]; then
3578 3311 cdiff_url="$(print $P.cdiff.html | url_encode)"
3579 3312 udiff_url="$(print $P.udiff.html | url_encode)"
3580 3313 print "<a href=\"$cdiff_url\">Cdiffs</a>"
3581 3314 print "<a href=\"$udiff_url\">Udiffs</a>"
3582 3315
3583 3316 if [[ -f $F.wdiff.html && -x $WDIFF ]]; then
3584 3317 wdiff_url="$(print $P.wdiff.html | url_encode)"
3585 3318 print "<a href=\"$wdiff_url\">Wdiffs</a>"
3586 3319 fi
3587 3320
3588 3321 sdiff_url="$(print $P.sdiff.html | url_encode)"
3589 3322 print "<a href=\"$sdiff_url\">Sdiffs</a>"
3590 3323
3591 3324 frames_url="$(print $P.frames.html | url_encode)"
3592 3325 print "<a href=\"$frames_url\">Frames</a>"
3593 3326 else
3594 3327 print " ------ ------ ------"
3595 3328
3596 3329 if [[ -x $WDIFF ]]; then
3597 3330 print " ------"
3598 3331 fi
3599 3332
3600 3333 print " ------"
3601 3334 fi
3602 3335
3603 3336 # If there's an old file, make the link
3604 3337
3605 3338 if [[ -f $F-.html ]]; then
3606 3339 oldfile_url="$(print $P-.html | url_encode)"
3607 3340 print "<a href=\"$oldfile_url\">Old</a>"
3608 3341 else
3609 3342 print " ---"
3610 3343 fi
3611 3344
3612 3345 # If there's an new file, make the link
3613 3346
3614 3347 if [[ -f $F.html ]]; then
3615 3348 newfile_url="$(print $P.html | url_encode)"
3616 3349 print "<a href=\"$newfile_url\">New</a>"
3617 3350 else
3618 3351 print " ---"
3619 3352 fi
3620 3353
3621 3354 if [[ -f $F.patch ]]; then
3622 3355 patch_url="$(print $P.patch | url_encode)"
3623 3356 print "<a href=\"$patch_url\">Patch</a>"
3624 3357 else
3625 3358 print " -----"
3626 3359 fi
3627 3360
3628 3361 if [[ -f $WDIR/raw_files/new/$P ]]; then
3629 3362 rawfiles_url="$(print raw_files/new/$P | url_encode)"
3630 3363 print "<a href=\"$rawfiles_url\">Raw</a>"
3631 3364 else
3632 3365 print " ---"
3633 3366 fi
3634 3367
3635 3368 print "<b>$P</b>"
3636 3369
3637 3370 # For renamed files, clearly state whether or not they are modified
3638 3371 if [[ -f "$oldname" ]]; then
3639 3372 if [[ -n "$mv_but_nodiff" ]]; then
3640 3373 print "<i>(copied from $oldname)</i>"
3641 3374 else
3642 3375 print "<i>(copied and modified from $oldname)</i>"
3643 3376 fi
3644 3377 elif [[ -n "$oldname" ]]; then
3645 3378 if [[ -n "$mv_but_nodiff" ]]; then
3646 3379 print "<i>(renamed from $oldname)</i>"
3647 3380 else
3648 3381 print "<i>(renamed and modified from $oldname)</i>"
3649 3382 fi
3650 3383 fi
3651 3384
3652 3385 # If there's an old file, but no new file, the file was deleted
3653 3386 if [[ -f $F-.html && ! -f $F.html ]]; then
3654 3387 print " <i>(deleted)</i>"
3655 3388 fi
3656 3389
3657 3390 #
3658 3391 # Check for usr/closed and deleted_files/usr/closed
3659 3392 #
3660 3393 if [ ! -z "$Oflag" ]; then
3661 3394 if [[ $P == usr/closed/* || \
3662 3395 $P == deleted_files/usr/closed/* ]]; then
3663 3396 print " <i>Closed source: omitted from" \
3664 3397 "this review</i>"
3665 3398 fi
3666 3399 fi
3667 3400
3668 3401 print "</p>"
3669 3402 # Insert delta comments
3670 3403
3671 3404 print "<blockquote><pre>"
3672 3405 getcomments html $P $PP
3673 3406 print "</pre>"
3674 3407
3675 3408 # Add additional comments comment
↓ open down ↓ |
959 lines elided |
↑ open up ↑ |
3676 3409
3677 3410 print "<!-- Add comments to explain changes in $P here -->"
3678 3411
3679 3412 # Add count of changes.
3680 3413
3681 3414 if [[ -f $F.count ]]; then
3682 3415 cat $F.count
3683 3416 rm $F.count
3684 3417 fi
3685 3418
3686 - if [[ $SCM_MODE == "teamware" ||
3687 - $SCM_MODE == "mercurial" ||
3419 + if [[ $SCM_MODE == "mercurial" ||
3688 3420 $SCM_MODE == "unknown" ]]; then
3689 3421
3690 3422 # Include warnings for important file mode situations:
3691 3423 # 1) New executable files
3692 3424 # 2) Permission changes of any kind
3693 3425 # 3) Existing executable files
3694 3426
3695 3427 old_mode=
3696 3428 if [[ -f $WDIR/raw_files/old/$PP ]]; then
3697 3429 old_mode=`get_file_mode $WDIR/raw_files/old/$PP`
3698 3430 fi
3699 3431
3700 3432 new_mode=
3701 3433 if [[ -f $WDIR/raw_files/new/$P ]]; then
3702 3434 new_mode=`get_file_mode $WDIR/raw_files/new/$P`
3703 3435 fi
3704 3436
3705 3437 if [[ -z "$old_mode" && "$new_mode" = *[1357]* ]]; then
3706 3438 print "<span class=\"chmod\">"
3707 3439 print "<p>new executable file: mode $new_mode</p>"
3708 3440 print "</span>"
3709 3441 elif [[ -n "$old_mode" && -n "$new_mode" &&
3710 3442 "$old_mode" != "$new_mode" ]]; then
3711 3443 print "<span class=\"chmod\">"
3712 3444 print "<p>mode change: $old_mode to $new_mode</p>"
3713 3445 print "</span>"
3714 3446 elif [[ "$new_mode" = *[1357]* ]]; then
3715 3447 print "<span class=\"chmod\">"
3716 3448 print "<p>executable file: mode $new_mode</p>"
3717 3449 print "</span>"
3718 3450 fi
3719 3451 fi
3720 3452
3721 3453 print "</blockquote>"
3722 3454 done
3723 3455
3724 3456 print
3725 3457 print
3726 3458 print "<hr></hr>"
3727 3459 print "<p style=\"font-size: small\">"
3728 3460 print "This code review page was prepared using <b>$0</b>."
3729 3461 print "Webrev is maintained by the <a href=\"http://www.illumos.org\">"
3730 3462 print "illumos</a> project. The latest version may be obtained"
3731 3463 print "<a href=\"http://src.illumos.org/source/xref/illumos-gate/usr/src/tools/scripts/webrev.sh\">here</a>.</p>"
3732 3464 print "</body>"
3733 3465 print "</html>"
3734 3466
3735 3467 exec 1<&- # Close FD 1.
3736 3468 exec 1<&3 # dup FD 3 to restore stdout.
3737 3469 exec 3<&- # close FD 3.
3738 3470
3739 3471 print "Done."
3740 3472
3741 3473 #
3742 3474 # If remote deletion was specified and fails do not continue.
3743 3475 #
3744 3476 if [[ -n $Dflag ]]; then
3745 3477 delete_webrev 1 1
3746 3478 (( $? == 0 )) || exit $?
3747 3479 fi
3748 3480
3749 3481 if [[ -n $Uflag ]]; then
3750 3482 upload_webrev
3751 3483 exit $?
3752 3484 fi
↓ open down ↓ |
55 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX