1#!/bin/ksh -p 2# 3# CDDL HEADER START 4# 5# The contents of this file are subject to the terms of the 6# Common Development and Distribution License (the "License"). 7# You may not use this file except in compliance with the License. 8# 9# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10# or http://www.opensolaris.org/os/licensing. 11# See the License for the specific language governing permissions 12# and limitations under the License. 13# 14# When distributing Covered Code, include this CDDL HEADER in each 15# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16# If applicable, add the following below this CDDL HEADER, with the 17# fields enclosed by brackets "[]" replaced with your own identifying 18# information: Portions Copyright [yyyy] [name of copyright owner] 19# 20# CDDL HEADER END 21# 22# 23 24# 25# Copyright 2009 Sun Microsystems, Inc. All rights reserved. 26# Use is subject to license terms. 27# 28 29# wx -- workspace extensions. Jeff Bonwick, December 1992. 30 31# The bugster cat/subcat = consolidation/os-net-tools 32 33version() { 34 if [[ $(whence $0) = "/opt/onbld/bin/wx" ]] && \ 35 pkginfo SUNWonbld > /dev/null 2>&1; then 36 pkginfo -l SUNWonbld | egrep "PKGINST:|VERSION:|PSTAMP:" 37 else 38 ls -l $(whence $0) 39 fi 40} 41 42ring_bell() { 43 # Sound bell to stderr, no newline 44 print -u2 "\007\c" 45} 46 47fail() { 48 ring_bell 49 # output error message to stderr 50 print -u2 "$@ Aborting $command." 51 exit 1 52} 53 54ask() { 55 typeset question=$1 default_answer=$2 56 if [ -z "$default_answer" ]; then 57 echo "$question \c" 58 else 59 echo "$question [$default_answer]: \c" 60 fi 61 read answer 62 [ -z "$answer" ] && answer="$default_answer" 63} 64 65yesno() { 66 typeset question="$1" 67 answer= 68 while [ -z "$answer" ]; do 69 ask "$question" y/n 70 case $answer in 71 y|yes) answer=yes;; 72 n|no) answer=no;; 73 *) answer=;; 74 esac 75 done 76} 77 78ok_to_proceed() { 79 yesno "$*" 80 if [[ "$answer" == no ]]; then 81 echo "Exiting, no action performed" 82 exit 1 83 fi 84} 85 86escape_re() { 87 # Escape the . so they are treated as literals in greps. 88 echo "$1"|sed 's{\.{\\.{g' 89} 90 91remove_local_nt_entry() { 92 # remove entries in local nt cache 93 grep -v "^$(escape_re $1) " $wxdir/local_nametable > \ 94 $wxtmp/local_nametable 95 [[ ! -f $wxtmp/local_nametable ]] && \ 96 fail "Error: cannot create $wxtmp/local_nametable" 97 mv -f $wxtmp/local_nametable $wxdir/local_nametable || 98 fail "Error: cannot create $wxdir/local_nametable." 99} 100 101remove_renamed_entry() { 102 # remove entries in renamed list 103 # assuming arg is the new filename to remove 104 grep -v "^$(escape_re $1) " $wxdir/renamed > \ 105 $wxtmp/renamed 106 [[ ! -f $wxtmp/renamed ]] && fail "Error: cannot create $wxtmp/renamed" 107 mv -f $wxtmp/renamed $wxdir/renamed || 108 fail "Error: mv -f $wxtmp/renamed $wxdir/renamed failed" 109} 110 111add_local_nt_entry() { 112 # Add workspace nametable entry to local nt cache for better perf. 113 [[ -r $wsdata/nametable ]] || return 0 114 if ! grep -q "^$(escape_re $1) " $wxdir/local_nametable; then 115 # add entries from workspace nt to local nt cache 116 grep "^$(escape_re $1) " $wsdata/nametable >> \ 117 $wxdir/local_nametable 118 [[ ! -f $wxdir/local_nametable ]] && \ 119 fail "Error: cannot create $wxdir/local_nametable" 120 fi 121 return 0 122} 123 124remove_active_entry() { 125 # Remove entry from active list 126 # $1 is the filepath to remove 127 128 nawk ' 129 $1 == target { 130 # Get past filepath line 131 while(NF > 0) 132 getline; 133 # Get past blank lines 134 while(NF == 0) 135 getline; 136 # Get past comments 137 while(NF > 0) 138 getline; 139 # Get past ending blank lines 140 while(NF == 0) { 141 if (getline) { 142 continue; 143 } else { 144 next; 145 } 146 } 147 } 148 # print the other active list entries 149 { print $0; } ' target=$1 $wxdir/active >$wxtmp/tmp_active || 150 fail "Error: cannot create $wxtmp/tmp_active." 151 if mv -f $wxtmp/tmp_active $wxdir/active; then 152 echo "$1 removed from active list." 153 remove_local_nt_entry $1 154 else 155 cat >&2 <<-EOF 156An error occured trying to remove $1 from the active list. 157The active list may be corrupt. You should check it out and 158possibly run '$ME update' to fix. 159 EOF 160 fail 161 fi 162} 163 164rename_active_entry() { 165 # renamed $1 to $2 filepath in active list 166 sed "s|^$(escape_re $1)$|$2|" $wxdir/active >\ 167 $wxtmp/active || fail "Error: cannot create $wxtmp/active." 168 mv -f $wxtmp/active $wxdir/active || \ 169 fail "Error: mv $wxtmp/active $wxdir/active failed." 170} 171 172is_active() { 173 # Return 0 if filepath arg is found in active list. 174 wx_active|grep -q "^$(escape_re $1)$" 175} 176 177# 178# ask user if s/he wants to remove an entry from the active list. 179# Will not remove entries that differ from parent or are new. 180# 181ask_remove_active_entry() { 182 # if an arg is passed in then this is assumed to be the filepath 183 # otherwise we assume the variables were set properly by the caller 184 if [[ $# -eq 1 ]]; then 185 dir=$(dirname $1) 186 file=$(basename $1) 187 filepath=$1 188 189 if [[ ! -f $file ]]; then 190 echo "Cannot find $file" 191 return 1 192 fi 193 fi 194 195 if is_active $filepath; then 196 if wx_pnt_filepath $filepath; then 197 if ! cmp -s $file $parentfilepath; then 198 cat <<-EOF 199 200The file $filepath 201differs from parent file: 202$parentfilepath 203and will remain in the active list. 204 EOF 205 return 206 fi 207 else 208 # New file, leave in active list. 209 cat <<-EOF 210$filepath 211is new and will remain in active list. Use: 212'$ME uncreate $filepath' 213to remove from active list. 214 EOF 215 return 216 fi 217 # Remove entry from active list because it is the same as 218 # the parent. 219 echo "There is no difference between $filepath and the parent" 220 echo "$parentfilepath" 221 yesno "Okay to remove $filepath from active list?" 222 if [[ "$answer" == 'yes' ]]; then 223 remove_active_entry $filepath 224 fi 225 fi 226} 227 228refresh_pnt_nt_cache() { 229 # Refresh the parent nametable cache if necessary. 230 # Note, this is a cache for the parent nametable entries that 231 # have the same hash as the local active and renamed files. 232 233 # no parent so nothing to update. 234 [[ -z $parent ]] && return 0 235 236 if [[ ! -r $parent/Codemgr_wsdata/nametable ]]; then 237 fail "Error: cannot read $parent/Codemgr_wsdata/nametable" 238 fi 239 240 if [[ ! -f $wxtmp/parent_nametable || 241 $parent/Codemgr_wsdata/nametable -nt $wxtmp/parent_nametable || 242 $wsdata/parent -nt $wxtmp/parent_nametable || 243 $wxdir/local_nametable -nt $wxtmp/parent_nametable ]]; then 244 cut -f2- -d' ' $wxdir/local_nametable > $wxtmp/hash_list 245 246 if [[ ! -f $wxtmp/hash_list ]]; then 247 fail "Error: cannot create $wxtmp/hash_list." 248 fi 249 250 if [[ -s $wxtmp/hash_list ]]; then 251 # Use hash list to get only the parent files 252 # we're interested in. 253 fgrep -f $wxtmp/hash_list \ 254 $parent/Codemgr_wsdata/nametable \ 255 > $wxtmp/parent_nametable 256 [[ ! -f $wxtmp/parent_nametable ]] && \ 257 fail "Error: cannot create $wxtmp/parent_nametable" 258 else 259 260 # There aren't any files to search for so just 261 # update the timestamp. 262 263 touch $wxtmp/parent_nametable 264 fi 265 fi 266} 267 268# add an active file to the new list 269add_new() { 270 typeset efp=$(escape_re $1) 271 # update new file list 272 if [[ ! -f $wxdir/new ]]; then 273 touch $wxdir/new || fail "Error: cannot create $wxdir/new." 274 fi 275 if is_active $1 && ! grep -q "^$efp$" $wxdir/new; then 276 echo "$1" >> $wxdir/new || fail "Error: cannot update $wxdir/new." 277 fi 278} 279 280# remove a file from the new list 281remove_new() { 282 # remove entries in new list 283 typeset efp=$(escape_re $1) 284 if [[ -f $wxdir/new ]] && grep -q "^$efp$" $wxdir/new; then 285 grep -v "^$efp$" $wxdir/new > $wxtmp/new 286 [[ ! -f $wxtmp/new ]] && fail "Error: cannot create $wxtmp/new" 287 mv -f $wxtmp/new $wxdir/new || fail "Error: cannot create $wxdir/new." 288 fi 289} 290 291update_active() { 292 # Try to add an entry to the active list 293 typeset efp=$(escape_re $1) 294 295 if ! is_active $1; then 296 if [[ -n "$comment_file" ]]; then 297 # Use sed to remove any empty lines from comment file. 298 (echo $1; echo; sed '/^[ ]*$/d' $comment_file;\ 299 echo) >>$wxdir/active || 300 fail "Could not update active list." 301 else 302 (echo $1; echo; wx_show_comment; echo) \ 303 >> $wxdir/active || 304 fail "Could not update active list." 305 echo "Remember to edit the comment in the active list "\ 306 "(use '$ME ea')." 307 fi 308 add_local_nt_entry $1 309 fi # End if not in active list 310} 311 312sort_active() { 313 typeset origfp=$filepath 314 315 # Note must use filepath for wx_show_comment 316 wx_active | sort | while read filepath; do 317 (print "$filepath"; print; wx_show_comment; print) 318 done > $wxtmp/active_sort || \ 319 fail "Error: cannot create $wxtmp/active_sort" 320 mv -f $wxtmp/active_sort $wxdir/active || \ 321 fail "Error: cannot create $wxdir/active" 322 323 filepath=$origfp 324} 325 326sort_renamed() { 327 sort $wxdir/renamed > $wxtmp/renamed_sort || \ 328 fail "Error: cannot create $wxtmp/renamed_sort" 329 mv -f $wxtmp/renamed_sort $wxdir/renamed || \ 330 fail "Error: cannot create $wxdir/active" 331} 332 333update_active_comment() { 334 # replace comment in active list entry with contents of $comment_file 335 nawk ' 336 # find active list entry to modify 337 $1 == filepath { 338 # print filepath line 339 while(NF > 0){ 340 print $1; 341 getline; 342 } 343 #print 1 blank (delimit) 344 print ""; 345 # Get past blank lines 346 while(NF == 0){ 347 getline; 348 } 349 # Get past active entry comments 350 # append to or replace comment 351 if (comment_mode == "append"){ 352 while(NF > 0) { 353 # output existing comments 354 print $0; 355 getline; 356 } 357 } else { 358 # get past existing comments 359 while(NF > 0) getline; 360 } 361 362 # output new comments 363 while (getline < comments){ 364 # do not print blank lines 365 if (NF > 0) 366 print $0 367 } 368 close comments 369 # print delimiting blank line 370 printf "\n" 371 372 # Get past ending blank lines in active entry 373 NF=0 374 while(NF == 0) { 375 if (getline) { 376 continue; 377 } else { 378 next; 379 } 380 } 381 } 382 # print the other active list entries 383 { print $0; } ' filepath=$1 comment_mode=$comment_mode \ 384 comments=$comment_file $wxdir/active >$wxtmp/tmp_active && \ 385 mv $wxtmp/tmp_active $wxdir/active 386 if [[ $? -eq 0 ]]; then 387 echo "$1 comment(s) updated in active list." 388 else 389 cat <<-EOF 390 391An error occured trying to update comments for $1 in the active list. 392The active list ($wxdir/active) may be corrupt. You should check it out 393and possilbly run '$ME ea' to fix. 394 395 EOF 396 fail 397 fi 398} 399 400lookup_parent() { 401 # Find a local file's parent filepath. 402 # Returns 1 if not found (local file is new) 403 # Sets env var. parentfilepath and parenthash if found 404 # Requires a file arg. 405 # Updates local and parent nt caches. 406 407 typeset efp parententry localfile hash1 hash2 hash3 hash4 \ 408 local_nt pnt_nt 409 410 parentfile= 411 parenthash= 412 413 if [[ -z $parent ]]; then 414 cat >&2 <<-EOF 415 416Warning: there is no parent for the current workspace so local file: 417$1 418is assumed to be new. 419 EOF 420 return 1 421 fi 422 if [[ ! -f $wsdata/nametable ]]; then 423 # Nothing has been brought over so assuming new file. 424 cat >&2 <<-EOF 425 426Warning: the $wsdata/nametable 427doesn't exist so 428$1 429is assumed to be new. 430 EOF 431 return 1 432 fi 433 434 if [[ ! -r $parent/Codemgr_wsdata/nametable ]]; then 435 fail "Error: cannot read $parent/Codemgr_wsdata/nametable." 436 fi 437 if [[ ! -f $wxtmp/parent_nametable ]] || $need_pnt_refresh; then 438 refresh_pnt_nt_cache 439 need_pnt_refresh=false 440 fi 441 if [[ ! -f $wxdir/local_nametable ]]; then 442 touch $wxdir/local_nametable || 443 fail "Error: cannot create $wxdir/local_nametable." 444 fi 445 446 efp=$(escape_re $1) 447 448 for local_nt in $wxdir/local_nametable $wsdata/nametable; do 449 450 # May be multiple entries in nametable, see if one 451 # matches parent. 452 453 grep "^$efp " $local_nt |\ 454 while read localfile hash1 hash2 hash3 hash4; do 455 for pnt_nt in $wxtmp/parent_nametable \ 456 $parent/Codemgr_wsdata/nametable; do 457 # get current parent nt entry 458 parententry=$(grep \ 459 " $hash1 $hash2 $hash3 $hash4$" $pnt_nt) 460 if [[ -n "$parententry" ]]; then 461 # found parent entry 462 parentfile=$(echo "$parententry" |\ 463 cut -f1 -d' ') 464 parenthash="$(echo "$parententry" |\ 465 cut -f2- -d' ')" 466 if [[ "$local_nt" == \ 467 "$wsdata/nametable" ]]; then 468 469 # Update the local nt 470 # hash cache if parent 471 # found and local 472 # workspace nt used. 473 474 add_local_nt_entry $localfile 475 fi 476 if [[ $pnt_nt == \ 477 $parent/Codemgr_wsdata/nametable ]] 478 then 479 480 # Update the parent nt 481 # hash cache if actual 482 # parent nt used. 483 484 echo $parententry >>\ 485 $wxtmp/parent_nametable 486 fi 487 488 # break out of all the loops if 489 # parent found 490 491 break 3 492 fi 493 done # for pnt_nt 494 done # while read active file 495 done # for local_nt 496 497 if [[ -z "$parentfile" ]]; then 498 # parent filepath not found. 499 return 1 500 else 501 # parent filepath found. 502 return 0 503 fi 504} 505 506# 507# Detect if a file was locally renamed 508# 509renamed() { 510 # Return 0 if renamed, 1 if not locally renamed 511 # parentfile and parenthash set as side effect 512 # Must be used by commands that set filepath (like wx_eval) 513 514 if [[ ! -f $wxdir/renamed ]]; then 515 update_renamed_dir 516 fi 517 518 # new is the new filename in the current ws, old is the previous 519 # filename that should exist in parent ws. 520 521 if grep -q "^$(escape_re $filepath) " $wxdir/renamed; then 522 if lookup_parent $filepath; then 523 return 0 524 else 525 526 # New files aren't in $wxdir/renamed so no 527 # parent is a problem 528 529 fail "Error: renamed $filepath but no matching parent"\ 530 "file in $parent" 531 fi 532 else 533 # not locally renamed 534 return 1 535 fi 536} 537 538wx_pnt_filepath() { 539 # return 0 if parent file found. Side effect: sets parentfilepath 540 # and parentsdot. parentfile and parenthash are set via lookup_parent. 541 542 # if an arg is passed in then this is assumed to be the filepath 543 # otherwise we assume the variables were set properly by the caller 544 if [[ $# -eq 1 ]]; then 545 dir=$(dirname $1) 546 file=$(basename $1) 547 filepath=$1 548 fi 549 550 # Find the parent filename 551 if lookup_parent $filepath; then 552 parentfilepath=$parent/$parentfile 553 parentsdot=$parent/$(dirname $parentfile)/SCCS/s.$(basename \ 554 $parentfile) 555 if [[ -f $parentfilepath && -s $parentsdot ]]; then 556 # found 557 return 0 558 else 559 fail "Error: located parent filepath $parentfilepath"\ 560 "but file does not exist or SCCS file is empty." 561 fi 562 fi 563 564 # wasn't found 565 return 1 566} 567 568get_pb_output() { 569 # Get output of putback -n (useful for parsing to find diffs between 570 # workspaces). Creates $wxtmp/putback.err and $wxtmp/putback.out 571 typeset -i rc=0 572 typeset origdir=$(pwd) 573 # clean up if interrupted. 574 trap "rm $wxtmp/putback.out;exit 1" HUP INT QUIT TERM 575 576 cat <<-EOF 577Doing a '$PUTBACK -n $*' to find diffs between workspaces. 578Please be patient as this can take several minutes. 579 EOF 580 581 cd $workspace 582 583 $PUTBACK -n $* 2>$wxtmp/putback.err >$wxtmp/putback.out 584 rc=$? 585 # Note a blocked putback returns a 2 but is not a problem. 586 if [[ $rc -ne 0 && $rc -ne 2 ]]; then 587 rm $wxtmp/putback.out 588 fail "Error, $PUTBACK -n $* failed. See $wxtmp/putback.err"\ 589 "for details." 590 fi 591 trap - HUP INT QUIT TERM 592 cd $origdir 593 return 0 594} 595 596wx_usage() { 597 version 598 599 cat << EOF 600 601See <http://www.opensolaris.org/os/community/on/wx/> for usage tips. 602 603Usage: $ME command [-D] [args] 604 605 -D turn on debugging for any command (output to stderr) 606 607===================== Initialization and Update Commands ==================== 608 $ME init [-f(t|q|n) [-s]] [src-root-dir] 609 initialize workspace for $ME usage 610 -f(t|q|n): non-interactive mode of update. Use this 611 to keep init from asking questions. 612 -ft: thorough update (update both active and 613 renamed lists with all diffs between parent 614 and current workspace). 615 -fq: quick update (update active list with files 616 currently checked out in current workspace). 617 -fn: no update (just create empty active and 618 renamed lists if they don't exist already). 619 -s: keep active list sorted by default. Must 620 follow a -f(t|q|n) flag. 621 src-root-dir: optional path relative to top of 622 workspace where wx will search for files. 623 Use "." to set src-root to top of 624 workspace. Default is usr. 625 $ME update [-q|-r] [-s] 626 Update the active and renamed file lists by 627 appending names of all files that have been 628 checked out, changed, created or renamed as 629 compared to the parent workspace. This is the 630 most accurate way of updating but it is slow. 631 All files in the workspace must be under SCCS 632 control in order for update to find them. Note, 633 this operation can be sped up in some cases by 634 setting the PUTBACK env. variable to use 635 "cm_env -g -o putback". (See 636 http://webhome.holland.sun.com/casper/ for more 637 info about the turbo def.dir.flp tool). 638 639 -q: quick update (only updates active list with 640 files currently checked out in workspace). This 641 is faster but will not find renames or files that 642 have been checked-in/delget'ed. 643 -r: only update the renamed list. Does not update 644 the active list. 645 -s: sort the active list. 646 647======================== Information Commands =========================== 648 $ME list [-r|-p|-w] list active files (the ones you are working on) 649 -r: list only renamed active files. 650 -p: output list of both active and renamed files 651 suitable for input to putback. 652 -w: output list of both active and renamed files 653 suitable for input to webrev (see $ME webrev 654 subcommand below). 655 $ME active alias for list 656 $ME pblist alias for list -p (see above). 657 658 $ME renamed [-a|-d|-p] 659 list locally renamed files. The output format is: 660 "new_name previous_name". Note, deleted files are 661 a special case of rename. 662 -a: list only renamed active files (same as list -r) 663 -d: list only deleted files 664 -p: show "new_name parent_name" (Note, parent_name 665 may not be the same as previous_name) 666 $ME new [-t] List new active files (files that exist in child only) 667 Note, should be run before reedit (see reedit below). 668 -t: thorough, does not use new cache (slower but more 669 accurate if new cache isn't current). 670 $ME out find all checked-out files in workspace 671 $ME info [file ...] show all info about active files 672 673 $ME diffs [file ...] 674 show sccs diffs for files (current vs previous 675 local version). Will show diffs for all active 676 files if no files given on command line. Will 677 use WXDIFFCMD environment variable if set. Hint, 678 try: export WXDIFFCMD="diff -bwU5" 679 680 $ME tdiffs [file ...] 681 Similar to diffs but new files are also displayed. 682 New files are those listed by '$ME new'. 683 684 $ME pdiffs [file ...] show diffs against parent files 685 Will show diffs between local file and it's 686 parent for all active files if no files given on 687 command line. Will use WXDIFFCMD environment 688 variable if set. 689 690 $ME tpdiffs [file ...] show diffs against parent files 691 Similar to pdiffs but new files are also displayed. 692 A file is considered new if it does not exist in 693 the parent. 694 695 $ME prt [-y] show sccs history for all active files 696 697 $ME comments display check-in comments for active files 698 $ME bugs [-u] display all bugids in check-in comments 699 $ME arcs [-u] display all ARC cases in check-in comments 700 $ME pbcom [-v] [-u] [-N] display summarized comments suitable for putback 701 Default is to display only bugs and arc cases. Will 702 display warnings about non-bug comments to stderr. 703 -v: display all comments verbatim including non-bug/arc 704 -u: prevent sorting, order determined by active list 705 -N: don't check bug synopsis against bug database 706 707======================== File Manipulation Commands ====================== 708 $ME edit [-s] [file ...] 709 check out either file(s) on command line or 710 all active files if no file args. 711 (Updates the active list.) 712 -s: silent, less sccs diagnostic output. This is 713 true for the other commands that accept the 714 -s flag. 715 $ME checkout Alias for edit command. 716 $ME co Alias for edit command. 717 718 $ME unedit [-s][-f] [file ...] 719 Returns file(s) to state prior to edit/checkout 720 Note, files will be unlocked and any changes made 721 when file was last checked out will be lost. 722 Unedit all active files if no files listed on 723 command line. Removes active list entry if there 724 are no diffs between local and parent file. 725 (Updates active list) 726 -f: force unedit, non-interactive. Will backup 727 if wx files newer than last backup. 728 $ME uncheckout Alias for unedit command. 729 $ME unco Alias for unedit command. 730 731 $ME delget [-(c|C) comment_file][-s][-f] [file ...] 732 Check in all active files or files on command 733 line. Check in comments will be those in active 734 file. See '$ME comments' for more info. 735 -c comment_file: use comment(s) in specified comment 736 file when checking in file(s). Note, 737 each comment should be on new line, 738 blank lines not allowed. Existing 739 comments in active list will be 740 replaced by contents of comment_file. 741 -C comment_file: Similar to -c but comments are 742 appended to current active list 743 comments. 744 -f: force checkin, no checks, non-interactive. 745 Use this if your sure the files okay to checkin 746 otherwise this command will check for 747 keyword problems. Will backup if wx files 748 newer than last backup. 749 750 NOTE: use redelget to reset new file's version to 1.1. 751 752 $ME checkin Alias for delget command. 753 $ME ci Alias for delget command. 754 755 $ME create [-(c|C) comment_file] [-f] [-o] file [file ...] 756 Creates one or more files in the workspace. 757 (Updates active list) 758 -(c|C) comment_file: see delget 759 -f: force create regardless of warnings, 760 (non-interactive). 761 -o: also check out file for further editing. 762 763 $ME uncreate [-f] [file ...] 764 Undoes the create of a new file. The file's 765 active list entry, its SCCS history and the 766 entry in the workspace nametable will be removed 767 but the file will stay in the workspace. 768 Will uncreate all new files in active list if 769 no file argument is specified. 770 -f: force uncreate, non-interactive. Will backup 771 if wx files newer than last backup. 772 773 $ME get [-k][-r #][-p] [file ...] 774 Get a copy of all active files or files on command 775 line. By default this is a read only version of 776 the file. 777 -r #: get specified version # 778 -p: output to stdout 779 -k: don't expand the sccs ID string 780 $ME extract Alias for get command. 781 782 $ME reedit [-m] [-s] [file ...] 783 Collapse the sccs delta (file history) such that 784 all changes made to the file in the current 785 workspace are now in one delta. If no files are 786 given on command line then all the active files 787 are processed. The files are left in a checked 788 out state so you can make further changes if a 789 resolve to make all your changes look like a 790 single delta. This eliminates the uninteresting 791 leaf deltas that arise from resolving conflicts, 792 so your putbacks do not contain a bunch of noise 793 about every bringover/resolve you did in the 794 interim. Accepts the same compression flags as 795 $ME backup. If [file ...] given, wx only 796 reedits files passed on command line. This adds 797 files to active list if not already there. 798 799 NOTE: reedit is appropriate for leaf workspaces 800 ONLY -- applying reedit to an interior-node 801 workspace would delete all childrens comments 802 and confuse Teamware tools in general. 803 804 NOTE: if files are listed as new that are not 805 then DO NOT use the reedit as it will destroy 806 the file history. 807 808 NOTE: if a file is new reedit will leave the 809 file checked out so in order to keep the delta 810 version at 1.1 redelget must be used for 811 checkin. 812 813 -m: only reedit files that have more that one 814 delta as compared to parent file. New files 815 will be recreated with comment found in 816 active list. 817 -s: silent checkin 818 819 $ME recheckout Alias for reedit command. 820 $ME reco Alias for reedit command. 821 822 $ME redelget [-m][-s] [file ...] 823 Similar to reedit but the file is checked in 824 when the command is done. This is the command to 825 use to collapse new files to their initial 826 1.1 delta (will assign comment in active list). 827 $ME recheckin Alias for redelget command. 828 $ME reci Alias for redelget command. 829 830 $ME delete [-f] [file ...] 831 Delete one or more files from the workspace. 832 Will delete all files in active list if no file 833 args. Note, for files brought over from parent, 834 this command actually moves the file under the 835 deleted_files/ subdir so it can be recovered. 836 For new files this command can remove the file 837 and file history completely. 838 (Updates active list if file is in there.) 839 -f : force delete regardless of warnings 840 (non-interactive) 841 842 Warning, this will completely remove new 843 files from the workspace. Will backup 844 if wx files newer than last backup. 845 $ME rm Alias for delete command. 846 847 $ME mv file newfile 848 Rename file to newfile 849 (Updates active list with new file name) 850 $ME mv file newdir 851 $ME mv dir newdir 852 Renames dir or file to newdir. If newdir exists 853 then dir will be subdir under newdir. Note, 854 this renames all files in dir and can take a 855 while if there are a lot of files affected by 856 the rename. (Updates active list) 857 858 $ME reset [-f] [file ...] 859 Resets file contents and history to that of 860 parent file. If the file was renamed locally it 861 will be renamed to that of the parent. It does not 862 work on new files (see uncreate or delete). 863 864 NOTE: use with care. If something goes wrong, 865 do a wx restore from the last backup and copy 866 wx/tmp/nametable.orig to Codemgr_wsdata/nametable. 867 868======================== Teamware Commands ====================== 869 $ME putback [-v][-f][-N][Teamware putback flags, see below][file ...] 870 Use Teamware putback command to putback either 871 file(s) specified or *all* active and renamed 872 files if no file(s) specified. Will use pbcom 873 output as the putback comments. 874 -f: force non-interactive mode (will not prompt) 875 -v: pass comments verbatim to putback(see pbcom) 876 -N: don't check bug synopsis against bug database 877 Accepts -n, -p pws, -q putback flags ('man putback' 878 for more info). 879 $ME pb alias for putback. 880 881 $ME resolve [Teamware resolve args] 882 resolve bringover conflicts and reedit merged 883 files. See 'man resolve' for args. 884 885======================== ON Rules checking Commands ====================== 886 $ME cstyle run cstyle over all active .c and .h files 887 skips files in wx/cstyle.NOT 888 $ME jstyle run jstyle over all active .java files 889 skips files in wx/jstyle.NOT 890 $ME hdrchk run 'hdrchk -a' over all active .h files 891 skips files in wx/hdrchk.NOT 892 $ME makestyle run makestyle over all active Makefiles 893 $ME keywords run keywords over all active files 894 skips files in wx/keywords.NOT 895 $ME copyright make sure there is a correct copyright message 896 that contains the current year 897 skips files in wx/copyright.NOT 898 $ME cddlchk make sure there is a current CDDL block in 899 active files 900 skips files in wx/cddlchk.NOT 901 $ME rmdelchk make sure sccs rmdel was not run on active files 902 (This causes Teamware problems.) 903 $ME deltachk make sure only 1 sccs delta in active files 904 (more than 1 breaks gate putback rules unless > 1 905 bug in putback.) 906 $ME comchk make sure comments are okay 907 $ME rtichk make sure RTI is approved for bugs/rfe's listed 908 in active list comments. Will skip rtichk if 909 wx/rtichk.NOT exists. 910 $ME outchk warn if there are files checked out that aren't in 911 active list. 912 $ME nits [file ...] 913 nits checking. Run cstyle, jstyle, hdrchk, copyright, 914 cddlchk, and keywords over files to which they are 915 applicable (makestyle is not currently run 916 because it seems to be quite broken -- more 917 noise than data). This is a subset of pbchk checks 918 suitable for checking files during development. 919 Use pbchk before doing the final putback. 920 Will run checks on all active files if no file args. 921 Will skip checks for files listed in wx/nits.NOT. 922 $ME pbchk [file ...] 923 putback check. Run cstyle, jstyle, hdrchk, copyright, 924 cddlchk, keywords, rmdelchk, deltachk, comchk, rtichk 925 and outchk over files to which they are 926 applicable (makestyle is not currently run 927 because it seems to be quite broken -- more 928 noise than data). Good command to run before 929 doing a putback. 930 Will run checks on all active files if no file args. 931 Will skip checks for files listed in wx/pbchk.NOT. 932 933======================== Code Review Commands ====================== 934 $ME webrev [webrev-args] 935 generate webrev for active and renamed/deleted files. 936 Note, uses comments in the active list. This is the 937 preferred way of reviewing code. Arguments to webrev 938 may also be specified. 939 Will skip files listed in wx/webrev.NOT 940 941 $ME codereview [-N] [codereview options] 942 generate environmentally friendly codereview diffs 943 for all active files. -N indicates that delta 944 comments should not be included. 945 946 $ME fullreview [-N] [codereview options] 947 generate full codereview diffs for all active files. 948 -N indicates that delta comments should not be 949 included. 950 951======================== Backup and Restore Commands ====================== 952 $ME backup [-i|-n|-z|-b|-t] 953 make backup copies of all active and renamed files. 954 -i: info about backups (backup dir and contents) 955 -n: no compression 956 -z: use gzip, faster than bzip2 but less compression. 957 -b: use bzip2, slower but better compression. 958 -t: backup if wx files are newer than last backup. 959 Defaults to the compression of the previous backup. 960 $ME bu Alias for backup command. 961 962 $ME restore [-f] [backup_dir] 963 restore a backup in a workspace (restores both 964 active files and performs file renames). A path 965 to the directory containing the backup to 966 restore from can be optionally specified. 967 -f: non-interactive. Will restore from last backup. 968 969======================== Misc Commands ============================ 970 $ME apply <cmd> apply cmd to all active files; for example, 971 "$ME apply cat" cats every file 972 $ME eval <cmd> like apply, but more general. In fact, 973 "$ME apply cmd" is implemented internally as 974 "$ME eval 'cmd \$file'". When using eval, 975 you can refer to \$dir, \$file, \$filepath, 976 \$parent, and \$workspace. For example: 977 $ME eval 'echo \$dir; sccs prt \$file | more' 978 will show the sccs history for each active file, 979 preceded by its directory. 980 $ME grep search all active files for pattern; equivalent to 981 "$ME eval 'echo \$filepath; grep pattern \$file'" 982 $ME egrep see $ME grep 983 $ME sed see $ME grep 984 $ME nawk see $ME grep 985 986 $ME dir echo the $ME directory path (\$workspace/$ME) 987 $ME e <file> edit the named $ME control file, e.g. "$ME e active". 988 The editor is \$EDITOR if set, else vi. 989 990 $ME ea shorthand for "$ME e active" (edit active list). 991 Note, the format for each entry in the active 992 list is: 993 994 filepath 995 <empty line> # no spaces allowed 996 one or more comment lines # no blank lines between. 997 <empty line> # no spaces allowed, ends the entry. 998 999 In general, it is best to only edit the active 1000 list to update comments. Use the other $ME 1001 commands like edit or create to update the 1002 active list when possible. 1003 1004 $ME ws <file> cat the named workspace control file, i.e. 1005 \$workspace/Codemgr_wsdata/file 1006 $ME args shorthand for "$ME ws args" 1007 $ME access shorthand for "$ME ws access_control" 1008 1009 $ME help print this usage message 1010 $ME version print current version of this program 1011EOF 1012 exit 1 1013} 1014 1015list_putback() { 1016 (wx_active; list_renamed -n)|nawk '!seen[$0]++' 1017} 1018 1019list_new() { 1020 # list new files (not found in parent ws) 1021 typeset new 1022 1023 if [[ $1 == '-t' ]]; then 1024 wx_active| 1025 while read new; do 1026 # thorough, skip new cache 1027 if ! lookup_parent $new; then 1028 # no parent, new file 1029 echo "$new" 1030 fi 1031 done 1032 else 1033 while read new; do 1034 # use new cache 1035 if ! lookup_parent $new; then 1036 # no parent, new file 1037 echo "$new" 1038 fi 1039 done < $wxdir/new 1040 fi 1041} 1042 1043list_renamed() { 1044 typeset active current old 1045 1046 if [[ $# -eq 0 ]]; then 1047 cat $wxdir/renamed 1048 elif [[ $1 == '-d' ]]; then 1049 # Only list only deleted file renames 1050 grep '^deleted_files/' $wxdir/renamed 1051 elif [[ $1 == '-n' ]]; then 1052 # Only list only current filenames 1053 cut -f1 -d' ' $wxdir/renamed 1054 elif [[ $1 == '-p' ]]; then 1055 # list parent for current instead of local previous name 1056 while read current old; do 1057 if lookup_parent $current; then 1058 print "$current $parentfile" 1059 else 1060 ring_bell 1061 print -u2 "Warning: cannot find parent file"\ 1062 "for $current" 1063 fi 1064 done < $wxdir/renamed 1065 elif [[ $1 == '-a' ]]; then 1066 # Just list active renamed files 1067 for active in $(wx_active); do 1068 grep "^$(escape_re $active) " $wxdir/renamed 1069 done 1070 elif [[ $1 == '-r' ]]; then 1071 wx_active > $wxtmp/alist || fail "Error: cannot create $wxtmp/alist" 1072 # Just list non-active renamed files (just current name) 1073 while read current old; do 1074 grep -q "^$(escape_re $current)$" $wxtmp/alist || 1075 echo $current 1076 done < $wxdir/renamed 1077 rm -f $wxtmp/alist 1078 else 1079 fail "Invalid flag $i. Run 'wx help' for info." 1080 fi 1081} 1082 1083list_webrev() { 1084 # Output a list of active and renamed files suitable for webrev 1085 for filepath in $( (wx_active; list_renamed -n)|nawk '!seen[$0]++'); do 1086 if renamed; then 1087 echo "$filepath $parentfile" 1088 else 1089 echo "$filepath" 1090 fi 1091 done 1092} 1093 1094wx_webrev() { 1095 typeset origdir=$PWD 1096 1097 cd $workspace 1098 # skip files listed in .NOT files 1099 cat -s $wxdir/$command.NOT >$wxtmp/NOT 1100 1101 ( # do the loops in a subshell so there is only one file open 1102 for filepath in $(wx_active); do 1103 if grep -q "^$(escape_re $filepath)$" $wxtmp/NOT; then 1104 print -u2 "$filepath (skipping)" 1105 continue 1106 fi 1107 if renamed; then 1108 echo "$filepath $parentfile" 1109 else 1110 echo "$filepath" 1111 fi 1112 echo "\n$(wx_show_comment)\n" 1113 done 1114 1115 # Do non-active renamed files 1116 for filepath in $(list_renamed -r); do 1117 if grep -q "^$(escape_re $filepath)$" $wxtmp/NOT; then 1118 print -u2 "renamed $filepath (skipping)" 1119 continue 1120 fi 1121 lookup_parent $filepath || 1122 fail "Error: cannot find parent for $filepath." 1123 if [[ $filepath != $parentfile ]]; then 1124 echo "$filepath $parentfile" 1125 # output empty line, comment, empty line 1126 echo "\nRenamed only (webrev comment generated by "\ 1127 "$ME, not an sccs comment)\n" 1128 else 1129 echo "$filepath" 1130 echo "\nWarning, file in renamed list but has same "\ 1131 "name as parent (not an sccs comment)\n" 1132 fi 1133 done 1134 # End of subshell 1135 ) > $wxtmp/webrev.list 1136 1137 # Note that the file list must come last. 1138 ${WXWEBREV:-webrev} -w "$@" $wxtmp/webrev.list 1139 1140 cd $origdir 1141} 1142 1143# 1144# list all active files 1145# 1146wx_active() { 1147 # do not print hash by default 1148 typeset rc hash=0 1149 1150 case $1 in 1151 # list only renamed active files 1152 -r) list_renamed -a; return 0;; 1153 # list suitable for putback (both active and renamed) 1154 -p) list_putback; return 0;; 1155 # list suitable for webrev (both active and renamed) 1156 -w) list_webrev; return 0;; 1157 -*) fail "Invalid flag $1. See 'wx help' for more info.";; 1158 esac 1159 1160 if [[ ! -r $wxdir/active ]]; then 1161 fail "Error: cannot read $wxdir/active" 1162 fi 1163 1164 nawk ' 1165 { 1166 # skip blank lines 1167 while (NF == 0) { 1168 if (getline == 0) 1169 next; 1170 } 1171 if (NF > 0){ 1172 # print the active filepath 1173 print $1; 1174 getline; 1175 } 1176 # skip blank lines 1177 while (NF == 0) { 1178 if (getline == 0){ 1179 # Error, corrupt active list (missing comment) 1180 exit 1 1181 } 1182 } 1183 # skip comment 1184 while (NF > 0) { 1185 if (getline == 0){ 1186 # Error, blank line after comment missing 1187 exit 2 1188 } 1189 } 1190 }' $wxdir/active 1191 1192 rc=$? 1193 if [[ $rc -eq 1 ]];then 1194 fail "Corrupt active list (missing comment)." 1195 elif [[ $rc -eq 2 ]];then 1196 fail "Corrupt active list (blank line needed after comment)." 1197 fi 1198} 1199 1200# 1201# show the comment for $filepath 1202# 1203wx_show_comment() { 1204 if [[ -f $wxdir/active ]]; then 1205 nawk ' 1206 { 1207 filename=$1 1208 getline 1209 while (getline) { 1210 if (length == 0) 1211 next 1212 if (filename == target) { 1213 if ($0 == "NO_COMMENT") { 1214 found = 0 1215 exit 1 1216 } 1217 found = 1 1218 print 1219 } 1220 } 1221 } 1222 END { 1223 if (found == 0) 1224 print "NO_COMMENT" 1225 exit 1 - found 1226 }' target=$filepath $wxdir/active 1227 return $? 1228 else 1229 echo "NO_COMMENT" 1230 fi 1231} 1232 1233bugdb_lookup_monaco() { 1234 typeset buglist=$1 1235 typeset monaco=/net/monaco.sfbay/export/bin/monaco 1236 1237 if [[ ! -x $monaco ]]; then 1238 return 1 1239 fi 1240 1241 $monaco -text <<-EOF 1242 set What = 1243 substr(cr.cr_number, 1, 7), synopsis 1244 1245 set Which = 1246 cr.cr_number in ($buglist) 1247 1248 set FinalClauses = 1249 order by cr.cr_number 1250 1251 do query/CR 1252 EOF 1253} 1254 1255bugdb_compare() { 1256 nawk -v bugdb=$1 -v active=$2 -f - <<-"EOF" 1257 BEGIN { 1258 file = bugdb 1259 while (getline < file) { 1260 synbugdb[$1] = substr($0, length($1) + 1) 1261 } 1262 1263 file = active 1264 while (getline < file) { 1265 synactive = substr($0, length($1) + 1) 1266 # If the synopsis doesn't match the bug database 1267 # and the synopsis isn't what's in the database 1268 # with " (something)" appended, spew a warning. 1269 if (!($1 in synbugdb)) { 1270 print "Bug " $1 " is not in the database" 1271 } else if (synbugdb[$1] != synactive && 1272 !(index(synactive, synbugdb[$1]) == 1 && 1273 substr(synactive, length(synbugdb[$1])) ~ \ 1274 / \([^)]*\)$/)) { 1275 print "Synopsis of " $1 " is wrong:" 1276 print " should be:" synbugdb[$1] 1277 print " is:" synactive 1278 } 1279 } 1280 } 1281 EOF 1282} 1283 1284# 1285# Summarize all comments listing, in order: 1286# - free-form comments 1287# - ARC case comments 1288# - Bug comments 1289# 1290# -a will suppress ARC case comments 1291# -b will suppress bug comments 1292# -n will do pbchk processing (give all warnings, no error exit) 1293# -o will suppress free-form (other) comments 1294# -p will do pbcom checking and exit if it finds problems unless -v is given 1295# -u will prevent sorting of the ARC case comments and bug comments 1296# -v will output all comments verbatim (no sorting) 1297# -N will prevent bug lookup, which may take a while. 1298# 1299# Note, be careful when modifying this function as sometimes the output 1300# should go to stdout, as in the case of being called via pbchk and 1301# sometimes the output should go to stderr. Think about this when 1302# making changes in here. 1303# 1304 1305function wx_summary { 1306 typeset i comment arc arcerr bug bugnospc bugid buglist synopsis \ 1307 show_arcs=true \ 1308 show_bugs=true \ 1309 show_others=true \ 1310 verbatim=false \ 1311 pbchk=false \ 1312 pbcom=false \ 1313 cmd=sort \ 1314 nolookup=false 1315 1316 while getopts :abnopuvN i; do 1317 case $i in 1318 a) show_arcs=false;; 1319 b) show_bugs=false;; 1320 n) pbchk=true;; 1321 o) show_others=false;; 1322 p) pbcom=true;; 1323 v) verbatim=true;; 1324 u) cmd=cat;; 1325 N) nolookup=true;; 1326 *) fail "Invalid flag -$OPTARG. See 'wx help' for more"\ 1327 "info.";; 1328 esac 1329 done 1330 1331 # Store all the comments in a tmp file 1332 for filepath in $file_list; do 1333 wx_show_comment 1334 done | nawk '!seen[$0]++' > $wxtmp/comments 1335 1336 if grep -q "^NO_COMMENT$" $wxtmp/comments; then 1337 print -u2 "Warning, found NO_COMMENT. Run '$ME ea' to edit the "\ 1338 "comments." 1339 if $pbcom; then 1340 # Don't want to output anything to stdout for a pbcom 1341 # if there is an error. 1342 return 1 1343 fi 1344 fi 1345 if $pbcom && $verbatim; then 1346 # All comments output verbatim. Note, is hacky because 1347 # of the wx_summary interface. pbcom calls wx_summary 1348 # with -po assuming other comments shouldn't be output. 1349 show_others=true 1350 fi 1351 1352 # Note, hard tab in the arc regex. This only recognizes FWARC, 1353 # LSARC and PSARC. Also, regex must be compat with both egrep 1354 # and nawk. 1355 arc='(FW|LS|PS)ARC[\/ ][12][0-9][0-9][0-9]\/[0-9][0-9][0-9][^0-9]' 1356 # bug ID must followed by single space 1357 bug='[0-9][0-9][0-9][0-9][0-9][0-9][0-9] ' 1358 bugnospc='[0-9][0-9][0-9][0-9][0-9][0-9][0-9][^ ]' 1359 1360 if $show_arcs; then 1361 # Note must use /usr/bin/sort. 1362 if ! egrep "^$arc" $wxtmp/comments | 1363 sed 's#\([A-Z][A-Z]*ARC\)[/ ]#\1 #' | sort | 1364 /usr/bin/sort -cu -k 1,2 2>$wxtmp/error >/dev/null 1365 then 1366 arcerr=$(nawk '{match($0, '"/$arc/"'); \ 1367 print substr($0, RSTART, RLENGTH);}' \ 1368 $wxtmp/error) 1369 1370 if $pbchk; then 1371 # if pbchk print to stdout 1372 print "Inconsistent ARC summaries for: $arcerr" 1373 else 1374 # else print to stderr 1375 print -u2 \ 1376 "Inconsistent ARC summaries for: $arcerr" 1377 fi 1378 if $pbcom && ! $verbatim; then 1379 1380 # Don't want to output anything to 1381 # stdout for a pbcom if there is an 1382 # error. 1383 1384 return 1 1385 fi 1386 fi 1387 fi 1388 1389 if $show_bugs; then 1390 # Treating bug comments with "(nit comment)" at the end as the 1391 # same as the original bug hence the sed and nawk below 1392 # Note hard tabs in sed arg. 1393 # Must use /usr/bin/sort. 1394 if ! grep "^$bug" $wxtmp/comments |sort| 1395 sed 's/[ ][ ]*([^)]*) *$//' | 1396 nawk '!seen[$0]++'| 1397 /usr/bin/sort -cnu 2>$wxtmp/error >/dev/null; then 1398 if $pbchk; then 1399 print -n "Inconsistent bug summaries for: " 1400 sed 's#^[^0-9]*\('"${bug}"'\).*#\1#' \ 1401 $wxtmp/error 1402 else 1403 print -nu2 "Inconsistent bug summaries for: " 1404 sed 's#^[^0-9]*\('"${bug}"'\).*#\1#' \ 1405 $wxtmp/error >&2 1406 fi 1407 if $pbcom && ! $verbatim; then 1408 # Don't want to output anything to 1409 # stdout for a pbcom if there is an 1410 # error. 1411 return 1 1412 fi 1413 fi 1414 1415 # Compare bug synopsis in active comments with the bug database. 1416 # If we've been passed -N, then we just never set buglist, thus 1417 # skipping the lookup. 1418 if ! $nolookup; then 1419 grep "^$bug" $wxtmp/comments | sort > $wxtmp/buglist.active 1420 cat $wxtmp/buglist.active | while read bugid synopsis; do 1421 buglist=$buglist,$bugid 1422 done 1423 buglist=${buglist#,} 1424 else 1425 if $pbchk; then 1426 print "Not performing bug synopsis check (be careful)" 1427 else 1428 print -u2 "Not performing bug synopsis check (be careful)" 1429 fi 1430 fi 1431 if [[ -n $buglist ]]; then 1432 bugdb_lookup_monaco $buglist > $wxtmp/buglist.bugdb 1433 if [[ -s $wxtmp/buglist.bugdb && $? -eq 0 ]]; then 1434 bugdb_compare $wxtmp/buglist.bugdb \ 1435 $wxtmp/buglist.active > $wxtmp/error 1436 if [[ -s $wxtmp/error ]]; then 1437 if $pbchk; then 1438 cat $wxtmp/error 1439 else 1440 cat $wxtmp/error >&2 1441 fi 1442 if $pbcom && ! $verbatim; then 1443 # Don't want to output anything 1444 # to stdout for a pbcom if there 1445 # is an error. 1446 return 1 1447 fi 1448 fi 1449 else 1450 if $pbchk; then 1451 print "Could not perform bug synopsis check" 1452 else 1453 print -u2 "Could not perform bug synopsis check" 1454 if $pbcom; then 1455 print -u2 "Use -N to skip bug synopsis check (be careful)" 1456 fi 1457 fi 1458 if $pbcom && ! $verbatim; then 1459 # Don't want to output anything 1460 # to stdout for a pbcom if there 1461 # is an error. 1462 return 1 1463 fi 1464 fi 1465 fi 1466 1467 if egrep "^$bugnospc" $wxtmp/comments >$wxtmp/error; then 1468 # must have single space following bug ID 1469 if $pbchk; then 1470 print "\nThese bugs are missing single space following the bug ID" 1471 print "(output prefaced by active file line number ':'):" 1472 while read comment 1473 do 1474 grep -n "^$comment" $wxdir/active 1475 done < $wxtmp/error 1476 else 1477 print -u2 "\nThese bugs are missing single space following the bug ID" 1478 print -u2 "(output prefaced by active file line number ':'):" 1479 while read comment 1480 do 1481 grep -n "^$comment" $wxdir/active >&2 1482 done < $wxtmp/error 1483 fi 1484 if $pbcom && ! $verbatim; then 1485 # Don't want to output anything to 1486 # stdout for a pbcom if there is an 1487 # error. 1488 return 1 1489 fi 1490 fi 1491 fi 1492 1493 # Create warning for pbchk or pbcom. 1494 if $pbchk || ($pbcom && ! $verbatim) && 1495 egrep -v "^($bug|$bugnospc|$arc|NO_COMMENT$)" $wxtmp/comments\ 1496 > $wxtmp/other_comments; then 1497 cat <<-EOF 1498Warning, the following comments are found in your active list 1499that are neither bug or arc cases: 1500 1501 EOF 1502 cat $wxtmp/other_comments 1503 print -- "\n---- End of active list comment warnings ----" 1504 fi > $wxtmp/comment_warning 1505 1506 if [[ -s $wxtmp/comment_warning ]]; then 1507 if $pbchk; then 1508 # output to stdout, don't exist in case there are more 1509 # warnings. 1510 cat $wxtmp/comment_warning 1511 elif $pbcom && ! $verbatim ; then 1512 # Don't want to output anything to stdout for a pbcom 1513 # if there is an error. 1514 cat $wxtmp/comment_warning >&2 1515 return 1 1516 fi 1517 fi 1518 1519 if $pbchk; then 1520 cd $workspace 1521 # See if sccs delta comment is the same as active list comment 1522 for filepath in $file_list; do 1523 # extract most recent delta comment 1524 sccs prs -d ':C:' $filepath | sort > $wxtmp/com1 || 1525 fail "sccs prs -d ':C:' $filepath failed." 1526 1527 # Add blank line to active comments so following cmp will 1528 # work properly. 1529 (wx_show_comment; print) | sort > $wxtmp/com2 1530 1531 if ! cmp -s $wxtmp/com1 $wxtmp/com2; then 1532 print "\n$filepath" 1533 print "Warning: current sccs comment does not"\ 1534 "match active list comment" 1535 print "(< sccs comment, > active list comment):" 1536 diff $wxtmp/com1 $wxtmp/com2 1537 fi 1538 done 1539 # Just output warnings for pbchk 1540 return 0 1541 fi 1542 1543 if $show_others; then 1544 if ! $verbatim; then 1545 # The non-verbatim check should have produced the 1546 # other_comments file. 1547 cat $wxtmp/other_comments| $cmd 1548 else 1549 # just output comments verbatim then return 1550 cat $wxtmp/comments 1551 return 0 1552 fi 1553 fi 1554 1555 if $show_arcs; then 1556 egrep "^$arc" $wxtmp/comments | $cmd 1557 fi 1558 1559 if $show_bugs; then 1560 egrep "^$bug" $wxtmp/comments | $cmd 1561 fi 1562 return 0 1563} 1564 1565update_renamed_file() { 1566 # Try to add a entry to the renamed list. Note, this stores the new 1567 # name and previous name, not the parent name as this is more useful in 1568 # detecting cyclic renames. 1569 1570 # ofp: old filepath, nfp: new filepath 1571 typeset ofp=$1 nfp=$2 1572 1573 # remove old and new entries from renamed 1574 egrep -v "^($(escape_re $ofp)|$(escape_re $nfp)) " $wxdir/renamed \ 1575 >$wxtmp/renamed 1576 [[ ! -f $wxtmp/renamed ]] && fail "Error: cannot create $wxtmp/renamed" 1577 mv -f $wxtmp/renamed $wxdir/renamed || \ 1578 fail "Error: cannot create $wxdir/renamed." 1579 1580 # remove old entries from local nt cache 1581 remove_local_nt_entry $ofp 1582 1583 # Do not update renamed list if the filepath is the same as 1584 # the parent or the file is new. 1585 if lookup_parent $nfp; then 1586 if [[ $parentfile != $nfp ]]; then 1587 print "$nfp $ofp" >> $wxdir/renamed || \ 1588 fail "Error: cannot append $wxdir/renamed." 1589 1590 [[ $ACTSORT == sort ]] && do_renamed_sort=true 1591 fi 1592 fi 1593 return 0 1594} 1595 1596update_renamed_dir() { 1597 typeset append pb_files new orig 1598 typeset -i rc 1599 1600 if [[ $# -eq 0 ]]; then 1601 # No args so we need to create the renamed list from 1602 # the source root. 1603 append=false 1604 if [ -r $wxdir/srcroot_dir ]; then 1605 pb_files=$(cat $wxdir/srcroot_dir) 1606 else 1607 pb_files=$DEFAULT_SRCDIR 1608 fi 1609 else 1610 # Assuming one or more filepaths as args 1611 append=true 1612 pb_files="$*" 1613 fi 1614 echo "Updating $ME renamed list... this may take several minutes." 1615 1616 # Get output of putback -n to detect renames elsewhere in 1617 # this script. 1618 1619 get_pb_output $pb_files 1620 1621 nawk ' 1622 /^rename from:/{orig_file=$3} 1623 $1 == "to:" {print $2 " " orig_file}' \ 1624 $wxtmp/putback.out >$wxtmp/pb_renames || \ 1625 fail "Error, creation of $wxtmp/pb_renames failed." 1626 1627 cp $wxdir/renamed $wxdir/renamed.old || 1628 fail "Error: cannot create $wxdir/renamed.old." 1629 1630 if $append; then 1631 nawk '!seen[$0]++' $wxtmp/pb_renames $wxdir/renamed \ 1632 > $wxtmp/renamed || \ 1633 fail "Error: cannot create $wxtmp/renamed." 1634 mv -f $wxtmp/renamed $wxdir/renamed || \ 1635 fail "Error: cannot create $wxdir/renamed." 1636 else 1637 mv -f $wxtmp/pb_renames $wxdir/renamed || 1638 fail "Error: cannot create $wxdir/renamed." 1639 fi 1640 1641 [[ $ACTSORT == sort ]] && do_renamed_sort=true 1642} 1643 1644# returns 0 if a pattern in patternfile matches input path arg 1645pathcheck() { 1646 typeset pattern path=$1 patternfile=$2 1647 1648 while read pattern; do 1649 if [[ $path == $pattern ]]; then 1650 return 0 # pattern matched path 1651 fi 1652 done < $patternfile 1653 return 1 # file path not matched by pattern 1654} 1655 1656# 1657# Evaluate a command for all listed files. This is the basic building 1658# block for most wx functionality. 1659# 1660 1661wx_eval() { 1662 typeset -i changedir=1 1663 1664 if [[ $# -gt 1 && "$1" == "-r" ]]; then 1665 changedir=0 1666 shift 1667 fi 1668 1669 pre_eval=$* 1670 # skip files listed in .NOT files 1671 cat -s $wxdir/$command.NOT >$wxtmp/NOT 1672 for filepath in $file_list; do 1673 if pathcheck $filepath $wxtmp/NOT; then 1674 print "$filepath (skipping)" 1675 else 1676 cd $workspace 1677 dir=`dirname $filepath` 1678 file=`basename $filepath` 1679 [[ $changedir -eq 1 ]] && cd $dir 1680 eval $pre_eval 1681 fi 1682 done 1683} 1684 1685# 1686# Initialize a workspace for wx. 1687# 1688 1689wx_init() { 1690 typeset srcroot_dir force=false 1691 1692 # check that srcroot is relative to top of workspace 1693 if cd $workspace/$1; then 1694 # normalize the srcroot dir for test below 1695 srcroot_dir=$(/bin/pwd) 1696 srcroot_dir="${srcroot_dir#$workspace/}" 1697 if [[ $srcroot_dir == $workspace ]]; then 1698 # Special case need to set srcroot_dir to 1699 # a relative path but we're at the top of the 1700 # workspace. 1701 srcroot_dir="." 1702 fi 1703 else 1704 fail "Source root '$1' does not exist in workspace"\ 1705 "($workspace)." 1706 fi 1707 1708 if [ -d $wxtmp ]; then 1709 if [[ $2 != -f[nqt] ]]; then 1710 echo "This workspace has already been initialized." 1711 ok_to_proceed 'Do you really want to re-initialize?' 1712 fi 1713 else 1714 mkdir -p $wxtmp 1715 fi 1716 1717 # 1718 # Make sure to save $srcroot_dir as a path relative to the workspace 1719 # root; an absolute path would break if the workspace name changed. 1720 # 1721 rm -f $wxdir/srcroot_dir 1722 echo $srcroot_dir >$wxdir/srcroot_dir 1723 1724 backup_dir=$HOME/$ME.backup/$workspace_basename 1725 [[ -d $backup_dir ]] || mkdir -p $backup_dir || 1726 fail "mkdir -p $backup_dir failed." 1727 cd $backup_dir 1728 rm -f $wxdir/backup_dir 1729 pwd >$wxdir/backup_dir || fail "Creation of $wxdir/backup_dir failed." 1730 1731 touch $wxdir/renamed 1732 touch $wxdir/active 1733 touch $wxdir/new 1734 touch $wxdir/local_nametable 1735 1736 if [[ -z "$2" ]]; then 1737 # Interactive mode 1738 cat << EOF 1739 Pick one of the following update methods: 1740 1741 1) Thorough: Detect any differences between the current workspace 1742 and its parent and update the active, new and renamed lists. Use 1743 this in workspaces where files have been renamed or deleted or 1744 there are files that are different from the parent that are not 1745 checked out. Note, files must be under SCCS control in order for 1746 this method to compare them to the parent workspace. 1747 1748 2) Quick: Only update the active list with files that are currently 1749 checked out. Will not update the renamed list. 1750 1751 3) None: Use this on workspaces where there are no changes between 1752 the workspace and its parent. This is very quick but will not 1753 update the active, new or renamed lists. 1754 1755EOF 1756 read answer?"Which update method? [1|2|3]: " 1757 case $answer in 1758 1) wx_update;; 1759 2) wx_update -q;; 1760 3) ;; 1761 *) fail "Bad answer: ${answer}. Rerun init command"\ 1762 "again";; 1763 esac 1764 yesno "Keep active list sorted by default?" 1765 if [[ "$answer" == 'yes' ]]; then 1766 print "true" > $wxdir/sort_active 1767 else 1768 print "false" > $wxdir/sort_active 1769 fi 1770 else 1771 # non-interactive mode 1772 case $2 in 1773 # forced thorough update 1774 -ft) wx_update; force=true;; 1775 # forced quick update 1776 -fq) wx_update -q; force=true;; 1777 # forced no update 1778 -fn) force=true;; 1779 # invalid arg 1780 -*) fail "$ME $command: unrecognized argument";; 1781 esac 1782 if [[ $3 == -s ]]; then 1783 print "true" > $wxdir/sort_active 1784 else 1785 print "false" > $wxdir/sort_active 1786 fi 1787 fi 1788 print 1789 1790 if [ -s $wxdir/active ]; then 1791 basedir=$workspace 1792 file_list=`wx_active` 1793 if $force; then 1794 # only backup if necessary 1795 print "Will backup wx and active files if necessary" 1796 wx_backup -t 1797 else 1798 print "Making backup copies of all wx and active files" 1799 wx_backup 1800 fi 1801 else 1802 echo "Active list empty, not doing backup." 1803 echo 1804 fi 1805 1806 echo "$ME initialization complete" 1807} 1808 1809# 1810# Find all checked out files 1811# 1812 1813wx_checked_out() { 1814 typeset origdir=$(pwd) 1815 cd $workspace 1816 x=$(ls -t $wsdata/nametable $wxdir/sccs_dirs 2>/dev/null) 1817 if [[ -z $x || "`basename $x`" == nametable ]]; then 1818 if [ -f $wxdir/srcroot_dir ]; then 1819 srcroot_dir=`cat $wxdir/srcroot_dir` 1820 else 1821 srcroot_dir=$DEFAULT_SRCDIR 1822 fi 1823 print -u2 "Workspace nametable changed: sccs_dirs out of date" 1824 print -u2 "Updating $wxdir/sccs_dirs...this may take a few minutes.\n" 1825 rm -f $wxdir/sccs_dirs 1826 find $srcroot_dir -name SCCS -print | sort >$wxdir/sccs_dirs 1827 fi 1828 cd $workspace 1829 rm -f $wxtmp/checked_out 1830 # Note if srcroot_dir = . this must be removed from the front of the 1831 # filepaths. 1832 echo $(sed -e 's,$,/p.*,' $wxdir/sccs_dirs) | \ 1833 tr \\040 \\012 | \ 1834 grep -v '*' | \ 1835 sed -e 's,SCCS/p.,,' |sed -e 's,^\./,,' >$wxtmp/checked_out 1836 cd $origdir 1837} 1838 1839deal_ws_renames() { 1840 # See if any active/renamed files were renamed externally 1841 # (perhaps by bringover?) and try to rename the active entry 1842 # filepath. 1843 typeset fp newfp renamed localfile hash1 hash2 hash3 hash4 \ 1844 notrenamed_list origdir=$(pwd) 1845 cd $workspace 1846 list_putback |\ 1847 while read fp; do 1848 if [[ ! -f $fp ]]; then 1849 # file not found, suspect rename. 1850 # using renamed for error checking. 1851 renamed=false 1852 # search cached local nt to find old hash info 1853 grep "^$(escape_re $fp) " $wxdir/local_nametable |\ 1854 while read localfile hash1 hash2 hash3 hash4; do 1855 # find new filepath 1856 newfp=$(fgrep " $hash1 $hash2 $hash3 $hash4"\ 1857 $wsdata/nametable|cut -f1 -d' ') 1858 1859 [[ -z $newfp ]] && continue 1860 1861 if [[ $newfp != $fp ]]; then 1862 update_renamed_file $fp $newfp 1863 rename_active_entry $fp $newfp 1864 echo "\nRenamed active file"\ 1865 "$fp to $newfp" 1866 renamed=true 1867 break 1868 fi 1869 done 1870 if ! $renamed; then 1871 if [[ -z $notrenamed_list ]]; then 1872 notrenamed_list="$fp" 1873 else 1874 notrenamed_list="$notrenamed_list\n$fp" 1875 fi 1876 fi 1877 fi 1878 done 1879 if [[ -n $notrenamed_list ]]; then 1880 ring_bell 1881 cat <<-EOF 1882Warning, active file(s): 1883 $(echo $notrenamed_list) 1884not found and cannot be renamed. Use "$ME ea" to edit the active list to 1885remove these entries if they do not exist in this workspace. 1886 EOF 1887 fi 1888 cd $origdir 1889} 1890 1891# 1892# Old style update the active file list (by appending all checked out files). 1893# This is what the original wx update did. 1894# 1895wx_update_quick() { 1896 1897 # Sort active if requested. 1898 [[ "$1" == "-s" ]] && ACTSORT=sort 1899 1900 wx_checked_out 1901 cd $wxdir 1902 rm -f tmp/files.old tmp/files.new active.new 1903 wx_active >tmp/files.old || fail "Error: cannot create $wxtmp/files.old" 1904 # sed has a hard tab, used to delete lines containing only whitespace 1905 sed '/^[ ]*$/d' tmp/files.old tmp/checked_out| 1906 nawk '!seen[$0]++' | $ACTSORT > tmp/files.new || 1907 fail "Error: cannot create $wxtmp/files.new" 1908 cp -f new new.old || fail "Error: cannot create new.old." 1909 while read filepath ; do 1910 add_local_nt_entry $filepath 1911 (echo "$filepath"; echo; wx_show_comment; echo) 1912 done < tmp/files.new > active.new || 1913 fail "Error: cannot create $wxdir/active.new" 1914 1915 mv -f active active.old 1916 mv -f active.new active 1917 1918 echo 1919 echo "New active file list:" 1920 echo 1921 cat tmp/files.new 1922 echo 1923 echo "Diffs from previous active file list:" 1924 echo 1925 ${WXDIFFCMD:-diff} tmp/files.old tmp/files.new 1926 echo "End active diffs ==========================" 1927 1928 # Do new file processing after active list is updated. 1929 1930 # Note, the parent nt read check below is hackish because we are 1931 # assuming that lookup_parent needs to read the parent nt and if it 1932 # can't then we want to just issue the warning. 1933 if [[ -n $parent && ! -r $parent/Codemgr_wsdata/nametable ]]; then 1934 echo "\nWarning: cannot read parent nametable, new file list"\ 1935 "not output." >&2 1936 else 1937 while read filepath; do 1938 # lookup_parent populates local nt cache 1939 if lookup_parent $filepath; then 1940 remove_new $filepath 1941 else 1942 add_new $filepath 1943 fi 1944 done < tmp/files.new 1945 1946 echo 1947 echo "New new-file list:" 1948 echo 1949 cat new 1950 echo 1951 echo "Diffs from previous new-file list:" 1952 echo 1953 ${WXDIFFCMD:-diff} new.old new 1954 echo "End new diffs ==========================" 1955 fi 1956} 1957 1958# 1959# Update various lists (active, renamed, new) 1960# 1961 1962wx_update() { 1963 typeset i efp sortarg do_quick=false 1964 typeset -i rc found 1965 # default, update all lists 1966 typeset update_active=true update_renamed=true update_new=true 1967 1968 while getopts :qrs i; do 1969 case $i in 1970 q) do_quick=true;; 1971 r) update_active=false 1972 update_new=false;; 1973 s) ACTSORT=sort; sortarg="-s";; 1974 *) fail "Invalid flag -$OPTARG. See 'wx help' for more"\ 1975 "info.";; 1976 esac 1977 done 1978 1979 deal_ws_renames 1980 1981 if $do_quick; then 1982 # Do old school wx update (only for checked out files) 1983 # This is faster but not as thorough. 1984 wx_update_quick $sortarg 1985 return 1986 fi 1987 1988 if [[ -z $parent ]]; then 1989 fail "Error: cannot do thorough update, no parent. Use 'update -q'"\ 1990 "instead." 1991 fi 1992 if [[ ! -r $parent/Codemgr_wsdata/nametable ]]; then 1993 fail "Error: cannot read $parent/Codemgr_wsdata/nametable" 1994 fi 1995 1996 # create tmp/checked_out file which putback -n may not list. 1997 # Do this before putback so it doesn't unnecessarily update the 1998 # sccs dirs cache. 1999 wx_checked_out 2000 2001 # Get output of putback -n to detect renames and active files. 2002 if [ -f $wxdir/srcroot_dir ]; then 2003 get_pb_output $(cat $wxdir/srcroot_dir) 2004 else 2005 get_pb_output $DEFAULT_SRCDIR 2006 fi 2007 2008 cd $wxdir 2009 2010 if $update_renamed; then 2011 if [[ -f renamed ]]; then 2012 mv renamed renamed.old || 2013 fail "Error: cannot create $wxdir/renamed.old." 2014 else 2015 touch renamed.old || 2016 fail "Error: cannot create $wxdir/renamed.old." 2017 fi 2018 2019 nawk ' /^rename from:/{orig_file=$3} 2020 $1 == "to:" {print $2 " " orig_file}' \ 2021 tmp/putback.out |$ACTSORT > tmp/renamed ||\ 2022 fail "Error, creation of $wxdir/tmp/renamed failed." 2023 mv -f tmp/renamed renamed || \ 2024 fail "Error: cannot create $wxdir/renamed" 2025 2026 for filepath in $(cut -f1 -d' ' renamed); do 2027 add_local_nt_entry $filepath 2028 done 2029 2030 echo "New renamed file list:" 2031 echo 2032 cat renamed 2033 echo 2034 echo "Diffs from previous renamed file list:" 2035 echo 2036 ${WXDIFFCMD:-diff} renamed.old renamed 2037 echo "End renamed diffs ==========================" 2038 fi 2039 2040 if $update_active; then 2041 # Create active list from putback output. 2042 nawk '/^(update|create): / {print $2}; 2043 /^The following files are currently checked out/ \ 2044 {p=1; continue}; 2045 /^"/ {continue}; 2046 NF == 0 {p=0; continue}; 2047 {if (p==1) 2048 print $1}' tmp/putback.out | 2049 sort -u > tmp/active_nawk_out || 2050 fail "Error: cannot create $wxtmp/active_nawk_out" 2051 2052 # list files in conflict also 2053 nawk '/^(conflict): / {print $2}' tmp/putback.out | 2054 sort -u > tmp/conflict_nawk_out || 2055 fail "Error: cannot create $wxtmp/conflict_nawk_out" 2056 2057 # Need to read $wsdata/nametable if there are conflicts 2058 if [[ -s tmp/conflict_nawk_out && ! -r $wsdata/nametable ]] 2059 then 2060 fail "Error: cannot read $wsdata/nametable." 2061 fi 2062 2063 # clear the tmp active file 2064 print -n > tmp/active.new || fail "Error: cannot create tmp/active.new." 2065 2066 # store current active list 2067 wx_active > tmp/files.old || 2068 fail "Error: cannot create $wxtmp/files.old" 2069 2070 # go through all the possible active files (keeping the existing 2071 # ones as well). Note hard tab in sed arg. 2072 for filepath in $(sed '/^[ ]*$/d' tmp/files.old \ 2073 tmp/checked_out tmp/conflict_nawk_out \ 2074 tmp/active_nawk_out | nawk '!seen[$0]++' | $ACTSORT); do 2075 2076 efp=$(escape_re $filepath) 2077 2078 if grep -q "^$efp$" tmp/conflict_nawk_out; then 2079 2080 # conflict files have a parent but the 2081 # putback output only shows the parent's 2082 # filename, need to find local name in 2083 # case of rename 2084 2085 grep "^$efp " $parent/Codemgr_wsdata/nametable|\ 2086 read localfile hash1 hash2 hash3 hash4 2087 local_file="$(\ 2088 fgrep " $hash1 $hash2 $hash3 $hash4" \ 2089 $wsdata/nametable | cut -f1 -d' ')" 2090 2091 # continue if empty string 2092 [[ -z "$local_file" ]] && continue 2093 2094 if ! grep -q "^$local_file" tmp/active.new; then 2095 filepath=$local_file 2096 else 2097 continue 2098 fi 2099 fi 2100 add_local_nt_entry $filepath 2101 (echo $filepath; echo; wx_show_comment; echo)\ 2102 >> tmp/active.new 2103 done 2104 2105 rm -f tmp/active_nawk_out 2106 2107 mv -f active active.old 2108 mv -f tmp/active.new active 2109 wx_active > tmp/files.new 2110 2111 echo 2112 echo "New active file list:" 2113 echo 2114 cat tmp/files.new 2115 echo 2116 echo "Diffs from previous active file list:" 2117 echo 2118 ${WXDIFFCMD:-diff} tmp/files.old tmp/files.new 2119 echo "End active diffs ==========================" 2120 rm -f tmp/files.old tmp/files.new 2121 2122 fi 2123 2124 # The new list is for caching names of new files to speed up commands 2125 # that list the new files. 2126 if $update_new; then 2127 if [ -f new ]; then 2128 cp -f new new.old || fail "Error: cannot create file new.old." 2129 elif [ ! -f new.old ]; then 2130 touch new.old || fail "Error: cannot create file new.old." 2131 fi 2132 # Create new list from putback output. 2133 nawk '/^create: / {print $2};' tmp/putback.out | 2134 sort -u > tmp/new || fail "Error: cannot create $wxtmp/new." 2135 mv -f tmp/new new 2136 echo 2137 echo "New new-file list:" 2138 echo 2139 cat new 2140 echo 2141 echo "Diffs from previous new-file list:" 2142 echo 2143 ${WXDIFFCMD:-diff} new.old new 2144 echo "End new diffs ==========================" 2145 fi 2146} 2147 2148wx_edit() { 2149 # Must be called via wx_eval 2150 if [ -f SCCS/p.$file ]; then 2151 echo "$filepath already checked out" 2152 update_active $filepath 2153 elif [ -f $file ]; then 2154 echo $filepath 2155 if sccs edit $silent $file; then 2156 update_active $filepath 2157 else 2158 fail "sccs edit $filepath failed." 2159 fi 2160 else 2161 ring_bell 2162 echo "Warning. file $filepath not found." 2163 fi 2164 2165 [[ $ACTSORT == sort ]] && do_active_sort=true 2166} 2167 2168wx_unedit() { 2169 # Must be called via wx_eval 2170 typeset -i force=0 2171 typeset arg msg 2172 2173 # set positional args to contents of global $args 2174 set -- $args 2175 2176 while getopts :f arg; do 2177 case $arg in 2178 f) force=1;; 2179 *) fail "Invalid flag -$OPTARG. See 'wx help' for"\ 2180 "more info.";; 2181 esac 2182 done 2183 2184 msg="differs from parent file, will remain in active list." 2185 2186 if [[ ! -f SCCS/p.$file ]]; then 2187 echo "$filepath not checked out" 2188 else 2189 if [[ $backup_done -eq 0 ]]; then 2190 if [[ $force -eq 0 ]]; then 2191 yesno "Do you want to backup files first?" 2192 if [[ "$answer" == "yes" ]]; then 2193 wx_backup || fail "Backup failed." 2194 fi 2195 else 2196 # only backup if necessary 2197 print "Will backup wx and active files if necessary" 2198 wx_backup -t || fail "Backup failed." 2199 fi 2200 backup_done=1; 2201 2202 # cd to the dir where the file is in case 2203 # wx_backup took us somewhere else. 2204 2205 cd ${workspace}/$dir 2206 fi 2207 2208 echo $filepath 2209 if sccs unedit $silent $file; then 2210 if [[ $force -eq 1 ]]; then 2211 if is_active $filepath; then 2212 if wx_pnt_filepath $filepath; then 2213 if cmp -s $file $parentfilepath; then 2214 remove_active_entry $filepath 2215 else 2216 print "$filepath $msg" 2217 fi 2218 fi 2219 fi 2220 else 2221 ask_remove_active_entry 2222 fi 2223 fi 2224 fi 2225} 2226 2227wx_create() { 2228 # Must be called via wx_eval 2229 typeset -i checkout=0 force=0 2230 typeset arg 2231 2232 while getopts :fo arg; do 2233 case $arg in 2234 o) checkout=1;; 2235 f) force=1;; 2236 *) fail "Invalid flag -$OPTARG. See 'wx help' for"\ 2237 "more info.";; 2238 esac 2239 done 2240 2241 if [ ! -f $file ]; then 2242 ring_bell 2243 echo "Error! $filepath is not a file." 2244 return 1 2245 elif [ -f $workspace/deleted_files/$filepath ]; then 2246 ring_bell 2247 cat >&2 <<-EOF 2248Error: a deleted version of $filepath exists. 2249You must undelete the file and edit that version. 2250Run: 2251'cd $workspace' 2252'$ME mv deleted_files/$filepath $filepath' 2253'$ME edit $filepath' 2254 EOF 2255 return 1 2256 elif [[ -n $parent && -f $parent/$filepath ]]; then 2257 ring_bell 2258 cat >&2 <<-EOF 2259Error! $filepath exists in the parent workspace $parent. 2260Choose a different name. 2261 EOF 2262 return 1 2263 elif [[ -n $parent && -f $parent/deleted_files/$filepath ]]; then 2264 ring_bell 2265 cat >&2 <<-EOF 2266Error! a deleted version of $filepath exists in the parent workspace 2267You must undelete the file and edit that version. 2268Run: 2269'cd $workspace' 2270'bringover deleted_files/$filepath' 2271'$ME mv deleted_files/$filepath $filepath' 2272'$ME edit $filepath' 2273 EOF 2274 return 1 2275 elif [ -f SCCS/s.$file ]; then 2276 echo "$filepath already created, active list not"\ 2277 "updated." >&2 2278 else 2279 # XXX it would be nice if keyword would work on new files 2280 if ! egrep "$SCCSKEYWORD" $file >/dev/null; then 2281 ring_bell 2282 cat >&2 <<-EOF 2283 2284Warning!!! 2285$filepath 2286is missing SCCS keywords. See 2287/net/wizard.eng/export/misc/general_docs/keyword_info.txt 2288for more info. Note, pay attention to the tabs. 2289 EOF 2290 if [[ $force -ne 1 ]]; then 2291 yesno "Continue with create?" 2292 if [[ "$answer" != 'yes' ]]; then 2293 echo "Aborting create $filepath" 2294 return 1 2295 fi 2296 fi 2297 fi 2298 2299 if ! copyrightchk $file; then 2300 # Sound bell 2301 ring_bell 2302 cat >&2 <<-EOF 2303 2304Warning!!! 2305$filepath 2306has copyright problems. See 2307/net/wizard.eng/export/misc/general_docs/golden_rules.txt 2308for more info. 2309 EOF 2310 if [[ $force -ne 1 ]]; then 2311 yesno "Continue with create?" 2312 if [[ "$answer" != 'yes' ]]; then 2313 echo "Aborting create $filepath" 2314 return 1 2315 fi 2316 fi 2317 fi 2318 2319 if ! cddlchk -a $file; then 2320 # Sound bell 2321 ring_bell 2322 cat >&2 <<-EOF 2323 2324Warning!!! 2325$filepath 2326has CDDL block problems. See 2327http://www.opensolaris.org/os/community/onnv/devref_toc/devref_7/#7_2_3_nonformatting_considerations 2328for more info. 2329 EOF 2330 if [[ $force -ne 1 ]]; then 2331 yesno "Continue with create?" 2332 if [[ "$answer" != 'yes' ]]; then 2333 echo "Aborting create $filepath" 2334 return 1 2335 fi 2336 fi 2337 fi 2338 2339 if [[ ! -d SCCS ]]; then 2340 mkdir SCCS || fail "Error: cannot create SCCS dir." 2341 fi 2342 2343 if [[ -n "$comment_file" ]]; then 2344 sccs create $silent -y"$(\ 2345 sed '/^[ ]*$/d' $comment_file)" $file || 2346 fail "sccs create $filepath failed." 2347 else 2348 sccs create $silent $file || 2349 fail "sccs create $filepath failed." 2350 fi 2351 rm -f ,$file 2352 update_active $filepath 2353 add_new $filepath 2354 if [[ $checkout -eq 1 ]]; then 2355 sccs edit $silent $file || 2356 fail "sccs edit $filepath failed." 2357 fi 2358 [[ $ACTSORT == sort ]] && do_active_sort=true 2359 fi 2360} 2361 2362wx_uncreate() { 2363 # Must be called via wx_eval 2364 # undoes a 'wx create' 2365 2366 typeset efp 2367 typeset -i force=0 2368 2369 case $1 in 2370 -f) force=1;; 2371 -*) fail "$ME $command: unrecognized argument";; 2372 esac 2373 2374 if [[ $backup_done -eq 0 ]]; then 2375 if [[ $force -eq 0 ]]; then 2376 yesno "Do you want to backup files first?" 2377 if [[ "$answer" == 'yes' ]]; then 2378 wx_backup || fail "Backup failed." 2379 fi 2380 else 2381 # only backup if necessary 2382 print "Will backup wx and active files if necessary" 2383 wx_backup -t || fail "Backup failed." 2384 fi 2385 backup_done=1; 2386 cd $workspace/$dir 2387 fi 2388 2389 if [[ ! -f $file ]]; then 2390 echo "$filepath not found, skipping" 2391 return 1 2392 fi 2393 2394 efp=$(escape_re $filepath) 2395 2396 if ! wx_pnt_filepath; then 2397 # This is a new file so let's uncreate it. 2398 answer='no' 2399 if [[ $force -ne 1 ]]; then 2400 cat <<-EOF 2401 2402$filepath appears to be a new file. 2403Note, $command will remove its SCCS info from your 2404workspace and entry in the active list but will leave 2405the file in your workspace. 2406 2407 EOF 2408 # yesno sets answer 2409 yesno "Continue $command $filepath?" 2410 else 2411 # forced to yes 2412 answer='yes' 2413 fi 2414 2415 if [[ "$answer" == 'yes' ]]; then 2416 if [[ ! -f SCCS/p.$file ]]; then 2417 sccs edit $file || 2418 fail "sccs edit $filepath failed." 2419 fi 2420 rm -f SCCS/s.$file SCCS/p.$file 2421 # For later cleanup on exit 2422 if grep -q "^$efp " $wsdata/nametable 2>/dev/null; then 2423 NEED_WS_CLEAN='y' 2424 fi 2425 2426 if is_active $filepath; then 2427 remove_active_entry $filepath 2428 fi 2429 remove_new $filepath 2430 else 2431 echo "skipping $filepath" 2432 fi 2433 else 2434 echo "Not new, skipping $filepath" 2435 fi # if ! wx_pnt_filepath 2436} 2437 2438wx_reset() { 2439 # Must be called via wx_eval 2440 # resets a local file to the parent version 2441 2442 typeset efp 2443 typeset -i force=0 2444 2445 case $1 in 2446 -f) force=1;; 2447 -*) fail "$ME $command: unrecognized argument";; 2448 esac 2449 2450 if [[ $backup_done -eq 0 ]]; then 2451 if [[ $force -eq 0 ]]; then 2452 yesno "Do you want to backup files first?" 2453 if [[ "$answer" == 'yes' ]]; then 2454 wx_backup || fail "Backup failed." 2455 fi 2456 else 2457 # only backup if necessary 2458 print "Will backup wx and active files if necessary" 2459 wx_backup -t || fail "Backup failed." 2460 fi 2461 backup_done=1; 2462 fi 2463 2464 if [[ ! -f $file ]]; then 2465 print "$filepath not found, skipping" 2466 return 1 2467 fi 2468 2469 efp=$(escape_re $filepath) 2470 2471 if wx_pnt_filepath; then 2472 if [[ $force -ne 1 ]]; then 2473 answer='no' # safe default 2474 cat <<-EOF 2475 2476Regarding: $filepath 2477$command will reset the file contents and sccs history to that of the parent: 2478$parentfilepath 2479and remove the entry from the active and renamed lists. 2480 2481 EOF 2482 if [[ $filepath != $parentfile ]]; then 2483 print "Note: local file will be reset to parent filepath." 2484 fi 2485 # yesno sets answer 2486 yesno "Continue $command $filepath?" 2487 else 2488 # forced to yes 2489 answer='yes' 2490 fi 2491 2492 if [[ "$answer" == 'yes' ]]; then 2493 if is_active $filepath; then 2494 remove_active_entry $filepath 2495 fi 2496 if renamed; then 2497 remove_renamed_entry $filepath 2498 fi 2499 rm -f $file SCCS/[ps].$file 2500 grep -v "^$efp " $wsdata/nametable > $wxtmp/nametable.new || \ 2501 fail "Error: cannot create $wxtmp/nametable.new ." 2502 mv -f $wxtmp/nametable.new $wsdata/nametable || \ 2503 fail "Error: mv -f $wxtmp/nametable.new $wsdata/nametable failed." 2504 2505 # add to bringover list for more efficient bringover 2506 bofilelist="$bofilelist $parentfile" 2507 else 2508 print -u2 "Skipping $filepath" 2509 fi 2510 else 2511 cat >&2 <<-EOF 2512 2513Warning: skipping $filepath 2514as it appears to be new. Use 'uncreate' to remove this new file from the 2515workspace. 2516 EOF 2517 fi # if ! wx_pnt_filepath 2518} 2519 2520 2521cyclic_rename() { 2522 # Detect the cyclic rename that causes Teamware problems. 2523 # See 'man workspace' for more info 2524 typeset new_filepath=$1 old_filepath=$2\ 2525 found_new=false found_old=false 2526 typeset prev_new prev_old 2527 2528 while read prev_new prev_old; do 2529 if [[ "deleted_files/$new_filepath" == $prev_new && 2530 $old_filepath != $prev_new ]]; then 2531 2532 # Cyclic rename 2533 return 0 2534 fi 2535 2536 if [[ $new_filepath == $prev_old && $prev_new != $old_filepath ]] 2537 then 2538 # The new file was the old file of a previous rename 2539 found_new=true 2540 if $found_old; then 2541 # Cyclic rename 2542 return 0 2543 fi 2544 elif [[ $old_filepath == $prev_new && 2545 $new_filepath != $prev_old ]]; then 2546 2547 # The old filepath was the new filepath of a 2548 # previous rename and this rename is not an undo 2549 # (new filepath is diff from previous old 2550 # filepath) 2551 2552 found_old=true 2553 if $found_new; then 2554 # Cyclic rename 2555 return 0 2556 fi 2557 fi 2558 done < $wxdir/renamed 2559 2560 # Not a cyclic rename 2561 return 1 2562} 2563 2564wx_delete() { 2565 # Must be called via wx_eval 2566 typeset efp 2567 typeset -i force=0 2568 2569 case $1 in 2570 -f) force=1;; 2571 -*) fail "$ME $command: unrecognized argument";; 2572 esac 2573 2574 if [[ $backup_done -eq 0 ]]; then 2575 if [[ $force -eq 0 ]]; then 2576 yesno "Do you want to backup files first?" 2577 if [[ "$answer" == 'yes' ]]; then 2578 wx_backup || fail "Backup failed." 2579 fi 2580 else 2581 # only backup if necessary 2582 print "Will backup wx and active files if necessary" 2583 wx_backup -t || fail "Backup failed." 2584 fi 2585 backup_done=1; 2586 cd $workspace/$dir 2587 fi 2588 2589 if [[ ! -f $file ]]; then 2590 fail "$filepath isn't a file." 2591 fi 2592 2593 # this is used a couple times so save escape_re value 2594 efp=$(escape_re $filepath) 2595 2596 if wx_pnt_filepath; then 2597 # Not a new file (has a parent) 2598 if is_active $filepath; then 2599 ring_bell 2600 cat >&2 <<-EOF 2601 2602Warning! $filepath 2603is in active list. You should run 2604"$ME reedit $filepath" 2605"$ME unedit $filepath" 2606which should remove it from the active list then run 2607"$ME $command $filepath". 2608Note, if you have made changes to this file that you want to keep, back 2609it up first. 2610 2611$filepath not deleted. 2612 2613 EOF 2614 return 1 2615 fi 2616 # See if this is already in the renamed list 2617 if grep -q "^deleted_files/$efp " $wxdir/renamed; then 2618 ring_bell 2619 if [[ -f $workspace/deleted_files/$filepath ]]; then 2620 cat >&2 <<-EOF 2621Warning: $filepath 2622has already been deleted. 2623Check for deleted_files/$filepath 2624in $wxdir/renamed . 2625 EOF 2626 else 2627 cat >&2 <<-EOF 2628Warning! the $ME renamed list appears to be corrupt. 2629 EOF 2630 fail "Please run '$ME update -r' and try this"\ 2631 "command again." 2632 fi 2633 fi 2634 if workspace filerm $file; then 2635 # we know filerm renames files under deleted_files/ 2636 update_renamed_file $filepath deleted_files/$filepath 2637 2638 print "$filepath deleted" 2639 print 2640 print "To recover $filepath do:" 2641 print "'cd $workspace'" 2642 print "'$ME mv deleted_files/$filepath $filepath'" 2643 else 2644 print "There was an error while trying to delete $filepath" 2645 fi 2646 else 2647 # This is a new file so let's remove it. 2648 if is_active $filepath; then 2649 ring_bell 2650 cat >&2 <<-EOF 2651 2652Warning: $filepath 2653is in active list. You should run 2654"$ME uncreate $filepath" 2655which should remove it from the active list 2656then run "$ME $command $filepath". 2657 2658$filepath not deleted. 2659 2660 EOF 2661 return 1 2662 fi 2663 2664 answer='no' 2665 if [[ $force -ne 1 ]]; then 2666 cat <<-EOF 2667 2668Warning: $filepath 2669appears to be a new file. 2670 2671Do you want to completely remove the file and SCCS info from 2672your workspace? (If you answer no, the file will just be 2673removed from the active list if it's in there. If you answer 2674yes, the file and associated SCCS history files will removed 2675from the active list and also removed entirely from the 2676workspace.) 2677 2678 EOF 2679 # yesno sets answer 2680 yesno "Completely remove $filepath?" 2681 else 2682 # forced to yes 2683 answer='yes' 2684 fi 2685 2686 if [[ "$answer" == 'yes' ]]; then 2687 rm -f $file SCCS/s.$file 2688 [[ -f SCCS/p.$file ]] && rm -f SCCS/p.$file 2689 echo "$filepath removed from workspace." 2690 # For later cleanup, optional 2691 if grep -q "^$efp " $wsdata/nametable 2>/dev/null; then 2692 NEED_WS_CLEAN='y' 2693 fi 2694 fi 2695 remove_new $filepath 2696 fi 2697} 2698 2699wx_mv() { 2700 # create some local variables to avoid side effects 2701 typeset efp old_filepath new_filepath 2702 2703 cd $workspace 2704 2705 old_filepath=$1 2706 new_filepath=$2 2707 2708 if [[ -d $old_filepath && ( -d $new_filepath || ! -f $new_filepath ) ]] 2709 then 2710 2711 if [[ $(basename $old_filepath) == "SCCS" ]]; then 2712 return 2713 fi 2714 2715 echo "Doing a $command between two directories can take a "\ 2716 "while, please be patient." 2717 # deal with directory to directory move 2718 if [[ -d $new_filepath ]]; then 2719 base="$(basename $old_filepath)/" 2720 else 2721 base= 2722 fi 2723 2724 sccsmv $old_filepath $new_filepath || 2725 fail "sccsmv $old_filepath $new_filepath failed." 2726 2727 # remove previous renamed entry 2728 remove_renamed_entry $old_filepath 2729 2730 update_renamed_dir $new_filepath/$base 2731 2732 if grep -q "^$efp/" $wsdata/nametable 2>/dev/null; then 2733 # Old entries in workspace nametable so set this 2734 # to clean up on exit 2735 NEED_WS_CLEAN='y' 2736 fi 2737 2738 # rename path of active entry 2739 sed "s|^$efp/|$new_filepath/$base|" $wxdir/active \ 2740 > $wxtmp/active || fail "Error: cannot create $wxtmp/active." 2741 mv $wxtmp/active $wxdir/active || 2742 fail "Error: cannot create $wxdir/active." 2743 sed "s|^$efp/|$new_filepath/$base|" $wxdir/new \ 2744 > $wxtmp/new || fail "Error: cannot create $wxtmp/new." 2745 mv $wxtmp/new $wxdir/new || fail "Error: cannot create $wxdir/new." 2746 2747 elif [[ -f $old_filepath && -d $new_filepath ]]; then 2748 wx_mv_file $old_filepath $new_filepath/$(basename $old_filepath) 2749 elif [[ -f $old_filepath && ! -f $new_filepath ]]; then 2750 wx_mv_file $old_filepath $new_filepath 2751 elif [[ ! -f $old_filepath ]]; then 2752 fail "Error! $old_filepath not found." 2753 elif [[ -f $new_filepath ]]; then 2754 fail "Error! $new_filepath exists." 2755 fi 2756} 2757 2758wx_mv_file() { 2759 # store literal filepath in local var. to avoid side effects 2760 typeset efp old_filepath new_filepath 2761 2762 cd $workspace 2763 2764 old_filepath=$1 2765 new_filepath=$2 2766 2767 if [[ ! -f $old_filepath ]]; then 2768 fail "Error! $old_filepath does not exist." 2769 2770 elif [[ -f $new_filepath ]]; then 2771 fail "Error! $new_filepath already exists." 2772 2773 else 2774 if cyclic_rename $new_filepath $old_filepath; then 2775 fail "Cyclic renamed detected. See 'man workspace'"\ 2776 "for more info." 2777 fi 2778 2779 if workspace filemv $old_filepath $new_filepath; then 2780 update_renamed_file $old_filepath $new_filepath 2781 efp=$(escape_re $old_filepath) 2782 if is_active $old_filepath; then 2783 # In active list so update list with new 2784 # file name 2785 rename_active_entry $old_filepath $new_filepath 2786 fi 2787 if grep -q "^$efp$" $wxdir/new; then 2788 remove_new $old_filepath 2789 add_new $new_filepath 2790 fi 2791 if grep -q "^$efp " $wsdata/nametable 2>/dev/null; then 2792 NEED_WS_CLEAN=y 2793 fi 2794 else 2795 echo "There was an error renaming $old_filepath to "\ 2796 "$new_filepath" 2797 fi 2798 fi 2799} 2800 2801sccs_rmdel_done() { 2802 # Note there are literal tabs in the []'s below so be careful when 2803 # editing. 2804 2805 # file not in SCCS so return false (1) 2806 [[ ! -f SCCS/s.$file ]] && return 1 2807 2808 if wx_pnt_filepath; then 2809 sccs prt -a $parentfilepath > $wxtmp/parenthist 2810 sccs prt -a $file > $wxtmp/filehist 2811 diff $wxtmp/parenthist $wxtmp/filehist | 2812 grep '^> R [0-9]\.[0-9]'| 2813 egrep -v ' (Codemgr|Fake)[ ]' | 2814 sed 's/^> //' > $wxtmp/newrmdels 2815 [[ ! -f $wxtmp/newrmdels ]] && fail "Error: cannot create $wxtmp/newrmdels" 2816 rm -f $wxtmp/parenthist $wxtmp/filehist 2817 else 2818 # New file, no parent 2819 sccs prt -a $file | 2820 egrep -v \ 2821 '^R [0-9]+(\.[0-9]+)+[ ].* (Codemgr|Fake)[ ]' | 2822 egrep '^R [0-9]+(\.[0-9]+)+[ ]' > $wxtmp/newrmdels 2823 [[ ! -f $wxtmp/newrmdels ]] && fail "Error: cannot create $wxtmp/newrmdels" 2824 fi 2825 2826 if [[ -s $wxtmp/newrmdels ]]; then 2827 cat $wxtmp/newrmdels 2828 rm -f $wxtmp/newrmdels 2829 # an rmdel was done so return true 2830 return 0 2831 else 2832 rm -f $wxtmp/newrmdels 2833 # no rmdel was done so return false 2834 return 1 2835 fi 2836} 2837 2838rmdelchk() { 2839 # returns 0 (success) if an rmdel was done. 2840 # Should be called via wx_eval(). 2841 if sccs_rmdel_done ; then 2842 ring_bell 2843 cat <<-EOF 2844 2845Warning, it looks like 'sccs rmdel' was run on $filepath 2846This will cause a problem for Teamware. Please fix this. 2847Note, this can be fixed by doing '$ME reedit $filepath' 2848 EOF 2849 return 0 2850 else 2851 return 1 2852 fi 2853} 2854 2855wx_delget() { 2856 typeset -i force=0 2857 typeset arg comment_found=false 2858 2859 while getopts :f arg; do 2860 case $arg in 2861 f) force=1;; 2862 *) fail "Invalid flag -$OPTARG. See 'wx help' for"\ 2863 "more info.";; 2864 esac 2865 done 2866 2867 if [[ (! -f SCCS/s.$file && ! -f SCCS/p.$file) || 2868 (-f SCCS/s.$file && -f SCCS/p.$file) ]]; then 2869 2870 # Check for keywords unless force is set or file is in 2871 # keywords.NOT 2872 if [[ $force -ne 1 ]] && [ -f SCCS/p.$file ] && 2873 ! grep -q "^$(escape_re $filepath)$" \ 2874 $wxdir/keywords.NOT 2>/dev/null && 2875 ! keywords -p $file; then 2876 2877 ring_bell 2878 cat <<-EOF 2879 2880The keywords check has detected a problem with $filepath 2881If this check should be skipped for this file, put the filepath in 2882${wxdir}/keywords.NOT. 2883See /net/wizard.eng/export/misc/general_docs/keyword_info.txt 2884for more info about keywords. Note, pay attention to the tabs. 2885 2886 EOF 2887 yesno "Continue with $command for $filepath?" 2888 if [[ "$answer" != 'yes' ]]; then 2889 echo "Aborting $command $filepath\n" 2890 return 2891 fi 2892 fi 2893 2894 [[ -f $wxtmp/comment ]] && rm $wxtmp/comment 2895 if [[ -n "$comment_file" ]]; then 2896 # note hard tab in sed r.e. 2897 sed '/^[ ]*$/d' $comment_file > $wxtmp/comment && 2898 comment_found=true 2899 else 2900 wx_show_comment >$wxtmp/comment && comment_found=true 2901 fi 2902 if $comment_found; then 2903 echo $filepath 2904 cat $wxtmp/comment 2905 if [[ -f SCCS/s.$file ]]; then 2906 # file history so check in file 2907 sccs delget $silent -y"`cat $wxtmp/comment`" \ 2908 $file || 2909 fail "sccs delget failed $filepath." 2910 else 2911 # no file history so create file 2912 sccs create $silent -y"`cat $wxtmp/comment`" \ 2913 $file || 2914 fail "sccs create $filepath failed." 2915 rm -f ,$file 2916 fi 2917 [[ -n "$comment_file" ]] && 2918 update_active_comment $filepath 2919 else 2920 ring_bell 2921 print "\nError: no comments (NO_COMMENT) registered for $filepath" 2922 if [[ $force -ne 1 ]] ; then 2923 yesno "Invoke ${EDITOR:-vi} to edit"\ 2924 "$wxdir/active"'?' 2925 if [ "$answer" == 'yes' ]; then 2926 ${EDITOR:-vi} $wxdir/active 2927 wx_delget 2928 else 2929 fail "Edit $wxdir/active and try again." 2930 fi 2931 else 2932 fail "Edit $wxdir/active and try again." 2933 fi 2934 fi 2935 elif [[ -f SCCS/s.$file && ! -f SCCS/p.$file ]]; then 2936 echo "$filepath already checked in" 2937 elif [[ ! -f SCCS/s.$file && -f SCCS/p.$file ]]; then 2938 fail "Error, $filepath is missing SCCS/s.$file ." 2939 fi 2940} 2941 2942wx_get() { 2943 if [[ -f SCCS/s.$file ]]; then 2944 sccs get $args -s $file || fail "sccs get $file failed." 2945 else 2946 ring_bell 2947 echo "$filepath not in SCCS" 2948 fi 2949} 2950 2951wx_info() { 2952 if [ -f SCCS/p.$file ]; then 2953 if [[ -w $file ]]; then 2954 echo "$filepath (checked out)" 2955 else 2956 ring_bell 2957 echo "$filepath (Warning, inconsistent state." 2958 echo " SCCS/p.$file exists but $file is readonly.)" 2959 fi 2960 elif [[ ! -f $file ]]; then 2961 ring_bell 2962 echo "$filepath (Warning, not found in $workspace)" 2963 elif [[ ! -f SCCS/s.$file ]]; then 2964 ring_bell 2965 echo "$filepath (Warning, not in SCCS)" 2966 else 2967 echo "$filepath (checked in)" 2968 fi 2969 echo "Check-in comment:" 2970 wx_show_comment 2971 if [ -f SCCS/s.$file ]; then 2972 echo "Most recent delta: \c" 2973 sccs prt -y $file 2974 fi 2975 echo "File name status:" 2976 if renamed; then 2977 # old is set by renamed 2978 echo "Locally renamed, parent file = $parentfile" 2979 elif lookup_parent $filepath; then 2980 # parentfile is set by lookup_parent 2981 if [[ "$filepath" != "$parentfile" ]]; then 2982 echo "In parent ws, file renamed to: $parentfile" 2983 else 2984 echo "Same as parent." 2985 fi 2986 else 2987 echo "New file (does not exist in parent ws)." 2988 fi 2989 echo 2990} 2991 2992get_multi_deltas() { 2993 # Get list of files with more that one delta when putback. 2994 # set global multi_delta_list. 2995 if ! deltachk >/dev/null 2>&1; then 2996 multi_delta_list="$multi_delta_list $filepath" 2997 fi 2998} 2999 3000wx_reedit() { 3001 typeset -i numkids=`workspace children | wc -l` 3002 typeset i newfiles only_multideltas=false 3003 3004 case $1 in 3005 -m) only_multideltas=true;; 3006 -*) fail "Invalid flag $1. See 'wx help' for more"\ 3007 "info.";; 3008 esac 3009 3010 if [[ ! -f $wsdata/nametable ]]; then 3011 echo "$wsdata/nametable not found, all files assumed new." 3012 ok_to_proceed "Okay to continue with $command?" 3013 elif [[ ! -r $wsdata/nametable ]]; then 3014 fail "Error: cannot read $wsdata/nametable." 3015 fi 3016 3017 if $only_multideltas; then 3018 # get_multi_deltas sets multi_delta_list 3019 wx_eval get_multi_deltas 3020 # set file_list for wx_eval wx_reedit_file below 3021 file_list=$multi_delta_list 3022 fi 3023 3024 cd $workspace 3025 3026 for i in $file_list; do 3027 if [[ ! -f $i ]]; then 3028 fail "$i does not exist." 3029 fi 3030 if ! lookup_parent $i; then 3031 if [[ -z $newfiles ]]; then 3032 newfiles="$i" 3033 else 3034 newfiles="$newfiles\n$i" 3035 fi 3036 fi 3037 done 3038 3039 if [[ -n $newfiles ]]; then 3040 # If there are some new files, give user a warning 3041 cat <<-EOF | ${PAGER:-more} 3042 3043$ME thinks following files are new (not in parent workspace) and will 3044reset their file histories to version 1.1 (exit if this list isn't correct): 3045$(echo $newfiles) 3046 3047 EOF 3048 ok_to_proceed "Okay to continue with $command?" 3049 if ! $CHECKIN; then 3050 cat <<-EOF 3051 3052Hint, use '$ME redelget' to collapse/reset new file histories to version 30531.1 since '$ME $command' will check out the file and '$ME delget' always 3054increments the file version doing the check in. 3055 3056 EOF 3057 fi 3058 fi 3059 3060 if [ $numkids -gt 0 ]; then 3061 echo "WARNING: This workspace has the following children:" 3062 echo 3063 workspace children 3064 echo 3065 echo "The reedit command will coalesce all children's deltas" 3066 echo "into one, losing all delta comments in the process." 3067 ok_to_proceed 'Are you sure you want to proceed?' 3068 fi 3069 echo 3070 yesno "Do you want to backup files first?" 3071 if [[ "$answer" == 'yes' ]]; then 3072 wx_backup || fail "Backup failed." 3073 fi 3074 3075 echo "$command beginning..." 3076 echo 3077 wx_eval wx_reedit_file 3078 echo 3079 echo "$command complete" 3080 echo 3081 [[ $ACTSORT == sort ]] && do_active_sort=true 3082} 3083 3084wx_reedit_file() { 3085 # Must be called via wx_eval 3086 typeset comment_found=false 3087 3088 if [[ ! -f $file ]]; then 3089 echo "$file does not exist. Can not reedit $file" 3090 return 3091 fi 3092 3093 echo $filepath 3094 # Is there a parent file? 3095 if wx_pnt_filepath; then 3096 rm -f $wxtmp/s.$file 3097 cp -p $parentsdot $wxtmp/s.$file || 3098 fail "Error: cannot cp $parentsdot $wxtmp/s.$file ." 3099 3100 # get the latest parent delta and comment and filter out 3101 # certain fields removing trailing spaces 3102 3103 p_delta="$(sccs prt -y $parentsdot|expand -1|grep 'SCCS'|\ 3104 cut -f'4,5,6,9-' -d' '|sed 's/ *$//')" 3105 3106 if [[ -z "$p_delta" ]]; then 3107 ring_bell 3108 echo "Warning ${command}: skipping $filepath," 3109 echo "cannot get parent delta info" 3110 echo 3111 return 1 3112 fi 3113 3114 # create a list of local deltas in the same format 3115 # also removing trailing spaces 3116 sccs prt $file|expand -1| 3117 nawk ' 3118 /^D [0-9]+(\.[0-9]+)+ +[0-9][0-9]\/[0-9][0-9]/ { 3119 if (delta != "") { 3120 # print previous delta info 3121 print delta comment; 3122 } 3123 delta=sprintf("%s %s %s %s ",$3, $4, $5, $8); 3124 comment = ""; 3125 } 3126 ! /^D [0-9]+(\.[0-9]+)+ +[0-9][0-9]\/[0-9][0-9]/ { 3127 # Add comment lines to comment variable 3128 if (comment == "") { 3129 if (NF > 0) { 3130 comment = $0; 3131 } else { 3132 # empty lines require a space 3133 # in comment. 3134 comment = " "; 3135 } 3136 } else { 3137 if (NF > 0) { 3138 comment = comment " " $0; 3139 } else { 3140 comment = comment " "; 3141 } 3142 } 3143 } 3144 END { 3145 if (delta != "") { 3146 # print last delta info 3147 print delta comment; 3148 } 3149 }' | sed 's/ *$//' > $wxtmp/l_deltas || 3150 fail "Error: cannot create $wxtmp/l_deltas." 3151 3152 # If the latest parent delta doesn't appear in the local file 3153 # then a bringover is required. Use fgrep because comment may 3154 # have RE chars in it. 3155 if ! fgrep "$p_delta" $wxtmp/l_deltas >/dev/null; then 3156 ring_bell 3157 echo "\nWarning ${command}: skipping $filepath because:" 3158 echo "parent's version of $filepath" 3159 echo "is newer than child's -- bringover required." 3160 echo 3161 return 1 3162 fi 3163 3164 if [ ! -f SCCS/p.$file ]; then 3165 if sccs edit $silent $file; then 3166 update_active $filepath 3167 else 3168 fail "sccs edit $file failed." 3169 fi 3170 fi 3171 3172 # make copy of local file and copy parent's SCCS s. file over 3173 # local. 3174 mv -f $file ${file}.wx_reedit || 3175 fail "mv -f $file ${file}.wx_reedit failed." 3176 rm -f SCCS/s.$file SCCS/p.$file 3177 cp $wxtmp/s.$file SCCS/s.$file || 3178 fail "cp $wxtmp/s.$file SCCS/s.$file failed." 3179 3180 if sccs edit $silent $file; then 3181 update_active $filepath 3182 else 3183 fail "sccs edit $file failed." 3184 fi 3185 3186 mv -f ${file}.wx_reedit $file || 3187 fail "mv -f ${file}.wx_reedit $file failed." 3188 3189 if $CHECKIN; then 3190 wx_delget 3191 fi 3192 touch $file 3193 else 3194 # reediting a new file. 3195 if [[ -f SCCS/s.$file ]]; then 3196 if [[ ! -f SCCS/p.$file ]]; then 3197 # File needs to be checked out 3198 sccs edit $silent $file || 3199 fail "sccs edit $file failed." 3200 fi 3201 # clean up SCCS since we are going to create again. 3202 rm -f SCCS/s.$file 3203 fi 3204 # clean up SCCS since we are going to create again. 3205 [[ -f SCCS/p.$file ]] && rm -f SCCS/p.$file 3206 3207 [[ -f $wxtmp/comment ]] && rm $wxtmp/comment 3208 wx_show_comment >$wxtmp/comment && comment_found=true 3209 if $comment_found; then 3210 echo $filepath 3211 cat $wxtmp/comment 3212 rm -f SCCS/s.$file SCCS/p.$file 3213 sccs create $silent -y"`cat $wxtmp/comment`" $file || 3214 fail "sccs create $filepath failed." 3215 rm -f ,$file 3216 [[ -n "$comment_file" ]] && 3217 update_active_comment $filepath 3218 else 3219 ring_bell 3220 echo "\nError, no comments registered for $filepath" 3221 if [[ $force -ne 1 ]] ; then 3222 yesno "Invoke ${EDITOR:-vi} to edit"\ 3223 "$wxdir/active"'?' 3224 if [[ "$answer" == 'yes' ]]; then 3225 ${EDITOR:-vi} $wxdir/active 3226 wx_reedit_file 3227 else 3228 fail "Edit $wxdir/active and try again." 3229 fi 3230 else 3231 fail "Edit $wxdir/active and try again." 3232 fi 3233 fi 3234 3235 if $CHECKIN; then 3236 # No need to check out file. 3237 return 3238 fi 3239 3240 if sccs edit $silent $file; then 3241 update_active $filepath 3242 add_new $filepath 3243 else 3244 fail "sccs edit $file failed." 3245 fi 3246 fi 3247} 3248 3249# 3250# Warn if there are sccs delta issues 3251# 3252deltachk() { 3253 # must be run via wx_eval 3254 typeset -i numdeltas 3255 typeset newfile checkedout=false 3256 3257 if wx_pnt_filepath; then 3258 # find number of deltas by subtracting the number in the parent 3259 # from the local file (note the literal Control-A in the grep 3260 # R.E.s below). 3261 (( numdeltas = $(grep '^d D' SCCS/s.$file|wc -l) - \ 3262 $(grep '^d D' $parentsdot|wc -l) )) 3263 newfile=false 3264 else 3265 # checking a new file (note the literal Control-A in the grep 3266 # R.E.) 3267 numdeltas=$(grep '^d D' SCCS/s.$file|wc -l) 3268 newfile=true 3269 fi 3270 3271 if [[ -z $numdeltas ]]; then 3272 cat <<-EOF 3273 3274Warning: the local file: 3275$filepath 3276does not appear to have a sccs delta history file or the sccs delta 3277history file is corrupt. If the local file is new try using: 3278"cd $dir" 3279"$ME create $file" 3280 3281If the file is not new (exists in parent): 3282"cd $dir" 3283Save a copy of the local file 3284Remove the SCCS/[ps].$file history files 3285"bringover $filepath" 3286"$ME edit $file" 3287Then carefuly merge the saved copy of local file with the 3288file brought over from parent. Hint: twmerge is a good merge 3289tool. 3290 EOF 3291 return 1 3292 fi 3293 3294 [[ -f SCCS/p.$file ]] && checkedout=true 3295 3296 # Note the use of hard tabs in the messages 3297 case $numdeltas in 3298 0) if $checkedout; then 3299 # file is checked out so assume there 3300 # will be 1 delta when checked in. 3301 return 0 3302 else 3303 if [[ -n $parentfilepath ]]; then 3304 if cmp -s $file $parentfilepath; then 3305 cat <<-EOF 3306 3307Warning: the local file: 3308$filepath 3309and the parent file: 3310$parentfilepath 3311content are identical. There are no new deltas in the local file. 3312If this file is no longer required in the active list use: 3313"cd $dir" 3314"$ME reset $file" 3315to remove file from the wx state files (active list, etc...) 3316 EOF 3317 else 3318 cat <<-EOF 3319 3320Warning: the local file: 3321$filepath 3322and the parent file: 3323$parentfilepath 3324have the same number of deltas but contents differ. A bringover may be 3325required before putback. 3326 EOF 3327 fi 3328 else 3329 cat <<-EOF 3330 3331Warning: the local file: 3332$filepath 3333is new but doesn't appear to contain any deltas. The SCCS delta history file 3334may need to be recreated. If so: 3335"cd $dir" 3336"rm SCCS/s.$file" 3337"$ME create $file" 3338 EOF 3339 fi 3340 return 1 3341 fi ;; 3342 3343 1) if $checkedout; then 3344 cat <<-EOF 3345 3346Regarding $filepath 3347Warning! There may be more than 1 delta when you check this file in 3348(currently checked out). Run '$ME redelget' on this file to collapse 3349the deltas and check in with 1 delta unless putting back > 1 bug. 3350 EOF 3351 return 1 3352 else 3353 return 0 3354 fi ;; 3355 3356 -*) # a negative number means the parent has more deltas 3357 3358 cat <<-EOF 3359 3360Regarding $filepath 3361Warning! The parent file has more deltas than the local file. 3362You should bringover the local file to fix this. 3363 EOF 3364 ;; 3365 3366 *) if $newfile && $checkedout; then 3367 cat <<-EOF 3368 3369Regarding $filepath 3370Warning! There may be more than 1 delta when you check this file in 3371(currently checked out). Run '$ME redelget' on this file to collapse 3372the deltas and check in with 1 delta unless putting back > 1 bug. 3373 EOF 3374 else 3375 cat <<-EOF 3376 3377Regarding $filepath 3378Warning! There is more than 1 delta. Run: 3379'cd $dir; $ME redelget $file' 3380to collapse the deltas on this file and check in with 1 delta unless 3381putting back > 1 bug. 3382 EOF 3383 fi 3384 return 1;; 3385 esac 3386} 3387 3388wx_cstyle() { 3389 case $file in 3390 *.[ch]) ;; 3391 *) return;; 3392 esac 3393 ((CSTYLE_INDEX = CSTYLE_INDEX + 1)) 3394 (cd $workspace; 3395 cstyle ${CSTYLE_FLAGS} $args $filepath >\ 3396 $wxtmp/wx.cstyle.$CSTYLE_INDEX) & 3397} 3398 3399wx_jstyle() { 3400 case $file in 3401 *.java) ;; 3402 *) return;; 3403 esac 3404 ((JSTYLE_INDEX = JSTYLE_INDEX + 1)) 3405 (cd $workspace; 3406 jstyle ${JSTYLE_FLAGS} $args $filepath >\ 3407 $wxtmp/wx.jstyle.$JSTYLE_INDEX) & 3408} 3409 3410wx_find_compression_progs() { 3411 gzip=/usr/bin/gzip 3412 if [[ ! -x $gzip && -n "$GZIPBIN" ]]; then 3413 gzip=$GZIPBIN 3414 fi 3415 3416 bzip2=/usr/bin/bzip2 3417 if [[ ! -x $bzip2 && -n "$BZIP2BIN" ]]; then 3418 bzip2=$BZIP2BIN 3419 fi 3420} 3421 3422wx_get_backup_dir() { 3423 typeset backup_dir_file 3424 # if backup_dir hasn't been set already... 3425 if [[ -z "$backup_dir" ]]; then 3426 # use the backup dir specifier in the wx/ 3427 backup_dir_file=$wxdir/backup_dir 3428 if [[ ! ( -f $backup_dir_file && -r $backup_dir_file && 3429 -s $backup_dir_file ) ]]; then 3430 fail "$backup_dir_file: missing, empty, or not readable" 3431 fi 3432 backup_dir=`cat $backup_dir_file` 3433 fi 3434 if [[ ! ( -d $backup_dir && -x $backup_dir && -r $backup_dir ) ]]; then 3435 fail "$backup_dir: missing, not a directory, or bad permissions" 3436 fi 3437} 3438 3439# 3440# This code requires that the files (n.sdot, n.pdot and n.clear) for a given 3441# backup have the same extension (.tar, .tar.gz, or .tar.bz2). It also 3442# disallows the existance of two incarnations of the same file (i.e. 3443# n.clear.tar and n.clear.tar.gz) 3444# 3445# It's up to the user to straighten things out if the above conditions are 3446# violated. The only time that is a problem is if they are trying to 3447# restore a version which violates the above rules. 3448# 3449# Takes one argument, the version number. 3450# 3451# Returns: 3452# (return code) 0 if exists and consistent, 3453# 1 if not found, 3454# 2 if inconsistent 3455# b_clear, b_sdot, b_pdot On success, the full path to the clear, sdot 3456# and pdot files comp, ext The compression program for and 3457# extension of said files 3458# 3459wx_check_backup() { 3460 typeset _new _b_new _renamed _b_renamed _active _b_active \ 3461 _local_nt _b_local_nt found bad 3462 3463 _version=$1 3464 clear=$_version.clear.tar 3465 sdot=$_version.sdot.tar 3466 pdot=$_version.pdot.tar 3467 not=$_version.not.tar 3468 _renamed=$_version.renamed 3469 _b_renamed=$backup_dir/$_renamed 3470 _new=$_version.new 3471 _b_new=$backup_dir/$_new 3472 _active=$_version.active 3473 _b_active=$backup_dir/$_active 3474 _local_nt=$_version.local_nametable 3475 _b_local_nt=$backup_dir/$_local_nt 3476 _sort=$_version.sort_active 3477 _b_sort=$backup_dir/$_sort 3478 found=false 3479 bad=false 3480 # 3481 # these arrays must be in sync with: 3482 # 1. the immediately following _count variable 3483 # 2. wx_find_last_backup's egrep expression 3484 # 3. wx_backup's "$args" handling. 3485 # 4. wx_find_compression_progs's programs 3486 # 3487 set -A _comps "" "$gzip" "$bzip2" 3488 set -A _extns "" ".gz" ".bz2" 3489 _count=3 3490 3491 idx=0 3492 while [[ $idx -lt $_count ]] ; do 3493 _ext=${_extns[$idx]} 3494 _comp=${_comps[$idx]} 3495 _clear=$clear$_ext 3496 _sdot=$sdot$_ext 3497 _pdot=$pdot$_ext 3498 _b_clear=$backup_dir/$_clear 3499 _b_sdot=$backup_dir/$_sdot 3500 _b_pdot=$backup_dir/$_pdot 3501 3502 if [[ -f $_b_clear || -f $_b_sdot ]]; then 3503 if $found; then 3504 echo "$backup_dir: both $_version.*.tar$ext "\ 3505 "and $_version.*.tar$_ext exist" 3506 bad=true 3507 else 3508 ext=$_ext 3509 comp=$_comp 3510 found=true 3511 fi 3512 fi 3513 3514 if [[ -f $_b_clear && ! -f $_b_sdot ]]; then 3515 echo "$backup_dir: $_clear exists; $_sdot does not" 3516 bad=true 3517 elif [[ ! -f $_b_clear && -f $_b_sdot ]]; then 3518 echo "$backup_dir: $_sdot exists; $_clear does not" 3519 bad=true 3520 elif [[ ! -f $_b_sdot && -f $_b_pdot ]]; then 3521 echo "$backup_dir: $_pdot exists; $_sdot does not" 3522 bad=true 3523 fi 3524 idx=`expr $idx + 1` 3525 done 3526 3527 if [[ ! -f $_b_renamed && -f $_b_active ]]; then 3528 # Can determine compression only 3529 return 1 3530 fi 3531 3532 if [[ -f $_b_renamed && -f $_b_active && -f $_b_new && 3533 -f $_b_local_nt ]]; then 3534 found=true 3535 else 3536 bad=true 3537 fi 3538 3539 $bad && return 2 3540 $found || return 1 3541 3542 b_renamed=$_b_renamed 3543 b_new=$_b_new 3544 b_active=$_b_active 3545 b_local_nt=$_b_local_nt 3546 3547 if [[ -f $backup_dir/$clear$ext && -f $backup_dir/$sdot$ext ]]; then 3548 b_clear=$backup_dir/$clear$ext 3549 b_sdot=$backup_dir/$sdot$ext 3550 else 3551 b_clear= 3552 b_sdot= 3553 fi 3554 3555 # It's not an error if this doesn't exist. 3556 if [[ -f $backup_dir/$pdot$ext ]]; then 3557 b_pdot=$backup_dir/$pdot$ext 3558 else 3559 b_pdot= 3560 fi 3561 # It's not an error if this doesn't exist. 3562 if [[ -f $backup_dir/$not ]]; then 3563 b_not_files=$backup_dir/$not 3564 else 3565 b_not_files= 3566 fi 3567 # It's not an error if this doesn't exist. 3568 if [[ -f $_b_sort ]]; then 3569 b_sort=$_b_sort 3570 else 3571 b_sort= 3572 fi 3573 3574 return 0 3575} 3576 3577# 3578# finds the number of the last backup. 3579# 3580# Returned in $result, which is -1 if no backups are found 3581# 3582wx_find_last_backup() { 3583 # 3584 # The list of extensions in the egrep expression must be in sync 3585 # with wx_check_backup's arrays 3586 # 3587 result=`ls -1 $backup_dir | egrep \ 3588 '^[0-9][0-9]*\.((pdot|sdot|clear)\.tar($|\.gz$|\.bz2$)|active|renamed|new|local_nametable$)'| \ 3589 sed 's/^\([0-9][0-9]*\)\..*$/\1/'| sort -rn | head -1` 3590 3591 [[ -n "$result" ]] # fail if result is empty 3592} 3593 3594# 3595# wx_do_backup 3596# Returns 0 on successful backup, 1 if nothing to backup, 2 any other 3597# error. 3598# 3599 3600wx_do_backup() { 3601 _type=$1 # type of files (for user) 3602 _out=$2 # file to write to 3603 _comp="$3" # compression program, or empty for no compression 3604 _evalarg=$4 # arg to wx_eval to get the correct file list 3605 typeset backupfiles=$(wx_eval "$_evalarg") 3606 3607 echo 3608 echo "Saving $_type files to $_out" 3609 echo 3610 3611 if [[ -z $backupfiles ]]; then 3612 echo "Note, nothing to backup." 3613 return 1 3614 fi 3615 3616 if [[ -n "$_comp" ]]; then 3617 ( tar cvf - $backupfiles 2>$BACKUP_ERRORS || \ 3618 rm -f $_out ) | $_comp -9 -c > $_out || rm -f $_out 3619 else 3620 tar cvf $_out $backupfiles 2>$BACKUP_ERRORS || 3621 rm -f $_out 3622 fi 3623 3624 [[ -f "$_out" ]] || return 2 # $_out is removed on any error 3625 3626 return 0 3627} 3628 3629wx_do_restore() { 3630 _type=$1 # type of files (for user) 3631 _in=$2 # file to read from 3632 _comp="$3" # uncompressing program 3633 echo 3634 echo "Restoring $_type files from $_in" 3635 echo 3636 3637 if [[ -n "$_comp" ]]; then 3638 # 3639 # if decompression fails, echo a bad value to make tar fail 3640 # 3641 ($_comp -dc < $_in || echo "fail") | tar xvpf - || return 1 3642 else 3643 tar xvpf $_in || return 1 3644 fi 3645 return 0 3646} 3647 3648# 3649# do renames in a workspace from a backup set 3650# 3651 3652wx_do_renames() { 3653 typeset _in=$1 # file to read from 3654 3655 if [[ ! -f $wsdata/nametable ]]; then 3656 echo "$wsdata/nametable not found, not doing renames." 3657 return 0 3658 fi 3659 3660 echo 3661 echo "Restoring renamed files from $_in" 3662 echo 3663 3664 # Note this assumes we're staring in $workspace 3665 3666 while read new hash1 hash2 hash3 hash4; do 3667 # get current local file name 3668 current=$(grep " $hash1 $hash2 $hash3 $hash4$" \ 3669 $wsdata/nametable | cut -f1 -d' ') 3670 3671 if [[ -z $current ]]; then 3672 # nothing to rename 3673 continue 3674 fi 3675 3676 if [[ "$new" == "$current" ]]; then 3677 # rename not needed 3678 continue 3679 fi 3680 3681 if [[ ! -f $new ]]; then 3682 if [[ ! -d $(dirname $new) ]]; then 3683 mkdir -p $(dirname $new) || 3684 fail "Error: cannot create dir $(dirname $new)" 3685 fi 3686 echo "Renaming current workspace file $current to $new" 3687 workspace filemv $current $new 3688 else 3689 if [[ -f $current ]]; then 3690 ring_bell 3691 cat >&2 <<-EOF 3692 3693Warning: $current 3694and $new 3695files both exist in current workspace with the 3696same hash. The restored renamed list should be recreated by running: 3697'$ME update -r' 3698Skipping rename of $current 3699to $new 3700 EOF 3701 3702 fi 3703 fi 3704 done < $_in 3705 3706 return 0 3707} 3708 3709wx_backup() { 3710 typeset orig_file_list ws_file back_file 3711 typeset newer=false 3712 typeset origdir=$PWD 3713 3714 case $1 in 3715 -i) wx_get_backup_dir 3716 echo "Backup dir is $backup_dir" 3717 ls -ltr $backup_dir 3718 echo "Backup dir is $backup_dir" 3719 cd $origdir 3720 return ;; 3721 -t) newer=true 3722 # backup if wx files are newer than last backup. 3723 # Implies use of default compression and no 3724 # interaction. Doing shift so case further down 3725 # won't see -t. 3726 shift;; 3727 esac 3728 # save state in case wx_backup called from another command. 3729 orig_file_list=$file_list 3730 3731 # we always backup the active files. 3732 file_list=$(wx_active) 3733 3734 if [[ ! -s $wxdir/renamed && -z $file_list ]]; then 3735 echo "There isn't anything to backup." 3736 file_list=$orig_file_list 3737 return 0 3738 fi 3739 3740 # must be in workspace to do backup 3741 cd $workspace || fail "Error: cannot cd $workspace" 3742 3743 if $newer; then 3744 # get latest wx state files and active files but skip 3745 # wx/tmp and wx/*.old files. 3746 ws_file=$(ls -1t $wxdir/!(tmp|*.old) $file_list|head -1) 3747 # get latest backup. 3748 wx_get_backup_dir 3749 back_file=$(ls -1t $backup_dir/*|head -1) 3750 if [[ ( -z "$back_file" && -n "$ws_file" ) || \ 3751 (( -n "$back_file" && -n "$ws_file" ) && \ 3752 $ws_file -nt $back_file ) ]] 3753 then 3754 : # continue with backup 3755 else 3756 print "Skipping backup, last backup newer than wx"\ 3757 "files." 3758 file_list=$orig_file_list 3759 cd $origdir 3760 return 0 3761 fi 3762 fi 3763 3764 wx_find_compression_progs 3765 wx_get_backup_dir 3766 3767 if [[ ! -w $backup_dir ]]; then 3768 fail "$backup_dir: not writable" 3769 fi 3770 3771 if wx_find_last_backup; then 3772 prev_backup=$result 3773 version=`expr $result + 1` 3774 else 3775 prev_backup= 3776 version=0 3777 fi 3778 3779 # 3780 # This must be in sync with wx_check_backup's arrays 3781 # 3782 case $1 in 3783 -n) ext=; comp=;; 3784 -z) ext=.gz; comp=$gzip;; 3785 -b) ext=.bz2; comp=$bzip2;; 3786 "-") shift;; # treat this as use default compression 3787 "") ;; # treat this as use default compression 3788 -??*) fail "$ME $command: only accepts a single argument";; 3789 *) fail "$ME $command: unrecognized argument";; 3790 esac 3791 3792 if [[ -z "$1" ]]; then 3793 # 3794 # default to the compression of the previous backup 3795 # 3796 if [[ -z "$prev_backup" ]]; then 3797 ext= 3798 comp= 3799 else 3800 wx_check_backup $prev_backup 3801 # A return of 1 is okay 3802 if [ $? -gt 1 ]; then 3803 echo "$backup_dir/$prev_backup.*: "\ 3804 "cannot determine previous "\ 3805 "compression." 3806 if $newer; then 3807 # Assume we want backup. 3808 answer="yes" 3809 else 3810 yesno "Proceed with no "\ 3811 "compression?" 3812 fi 3813 if [[ $answer == "no" ]]; then 3814 echo "No backup done." 3815 file_list=$orig_file_list 3816 cd $origdir 3817 return 3818 fi 3819 ext= 3820 comp= 3821 fi 3822 fi 3823 fi 3824 3825 if [[ -n "$comp" && ! -x "$comp" ]]; then 3826 echo "${comp}: missing. defaulting to no compression" 3827 ext= 3828 comp= 3829 fi 3830 3831 b_clear=$backup_dir/$version.clear.tar$ext 3832 b_sdot=$backup_dir/$version.sdot.tar$ext 3833 b_pdot=$backup_dir/$version.pdot.tar$ext 3834 b_local_nt=$backup_dir/$version.local_nametable 3835 b_active=$backup_dir/$version.active 3836 b_renamed=$backup_dir/$version.renamed 3837 b_new=$backup_dir/$version.new 3838 b_not_files=$backup_dir/$version.not.tar 3839 b_sort=$backup_dir/$version.sort_active 3840 3841 # 3842 # If anything goes wrong, clean up after ourselves 3843 # 3844 trap "/usr/bin/rm -f $b_clear $b_sdot $b_pdot $b_active $b_renamed $b_new $b_local_nt $b_not_files $b_sort; exit 1" 0 1 2 3 15 3845 3846 fail_msg='failed. Cleaning up. ' 3847 3848 # 3849 # It is not a hard error for the SCCS/s.file to be missing. We just 3850 # let the user know what's going on. 3851 # 3852 sdot_cmd=' 3853_sdot="SCCS/s.$file"; 3854_file="$dir/$_sdot"; 3855if [[ -f $_sdot ]]; then 3856 echo "$_file"; 3857else 3858 echo "$_file: not found" >&2; 3859fi 3860' 3861 pdot_cmd=' 3862_pdot="SCCS/p.$file"; 3863_sdot="SCCS/s.$file"; 3864_file="$dir/$_pdot"; 3865if [[ -f $_pdot ]]; then 3866 echo "$_file"; 3867elif [[ ! -f $_sdot ]]; then 3868 echo "$_file: not checked in" >&2; 3869elif [[ -w $file ]]; then 3870 echo "$_file: not found but $file is writable!" >&2; 3871fi 3872' 3873 # Do this first in case there are no active files 3874 echo 3875 echo "Saving renamed file list to $b_renamed" 3876 echo 3877 cp $wxdir/renamed $b_renamed || fail "$b_renamed: $fail_msg" 3878 3879 if [[ -f $wxdir/local_nametable ]]; then 3880 echo 3881 echo "Saving local_nametable to $b_local_nt" 3882 echo 3883 cp $wxdir/local_nametable $b_local_nt || \ 3884 fail "$b_local_nt: $fail_msg" 3885 fi 3886 3887 if [[ -f $wxdir/sort_active ]]; then 3888 print 3889 print "Saving sort_active to $b_active" 3890 print 3891 cp $wxdir/sort_active $b_sort || fail "$b_sort: $fail_msg" 3892 fi 3893 3894 if ls wx/*.NOT >/dev/null 2>&1; then 3895 echo 3896 echo "Saving .NOT files to $b_not_files" 3897 echo 3898 tar -cf $b_not_files wx/*.NOT || fail "$b_not_files: $fail_msg" 3899 fi 3900 3901 # Are there any active files to backup? 3902 if [[ -n $file_list ]]; then 3903 wx_do_backup 'clear' $b_clear "$comp" 'echo $filepath' || 3904 fail "$b_clear: $fail_msg" 3905 3906 wx_do_backup 'sdot' $b_sdot "$comp" "$sdot_cmd" || 3907 fail "$b_sdot: $fail_msg" 3908 3909 echo 3910 echo "Saving new list to $b_new" 3911 echo 3912 cp $wxdir/new $b_new || fail "$b_new: $fail_msg" 3913 3914 # It's not fatal if the backup error for pdot files is 3915 # 'no files to backup'. This is because it's possible 3916 # that the active files aren't checked out so there 3917 # won't be any pdot files. 3918 wx_do_backup 'pdot (if any)' $b_pdot "$comp" "$pdot_cmd" 3919 if [[ $? -gt 1 ]]; then 3920 fail "$b_pdot: $fail_msg $(cat $BACKUP_ERRORS)" 3921 fi 3922 fi 3923 3924 echo 3925 echo "Saving active file list to $b_active" 3926 echo 3927 cp $wxdir/active $b_active || fail "$b_active: $fail_msg" 3928 3929 trap - 0 1 2 3 15 3930 3931 rm -f $BACKUP_ERRORS 3932 3933 # restore file_list state. 3934 file_list=$orig_file_list 3935 3936 cd $origdir 3937 return 0 3938} 3939 3940wx_restore() { 3941 typeset force=0 3942 3943 case $1 in 3944 -f) force=1;; 3945 -*) fail "Invalid flag $1. See 'wx help' for more info.";; 3946 esac 3947 3948 if [[ $force -eq 0 ]]; then 3949 cat <<-EOF 3950 3951Warning, the restore command will overwrite several files including the 3952active and renamed lists. This could be a problem if you have made 3953changes to your workspace and $ME related files following the last 3954backup. It may be a good idea to run: 3955 3956$ME update 3957 3958after the restore so that the active and renamed lists are updated with 3959the new changes in the workspace. 3960 3961Also, restore may perform workspace renames in this workspace if it 3962finds that the existing file has a pathname that differs from that in 3963the backup being restored. 3964 3965 EOF 3966 ok_to_proceed "Do you really want to do the restore?" 3967 fi 3968 3969 wx_find_compression_progs 3970 wx_get_backup_dir 3971 3972 if wx_find_last_backup; then 3973 version=$result 3974 else 3975 fail "$backup_dir: no backups found" 3976 fi 3977 3978 if [[ $force -eq 0 ]]; then 3979 ask 'Version to restore from' $version 3980 version=$answer 3981 fi 3982 3983 # 3984 # wx_check_backup sets $comp, $b_clear, and $b_sdot when successful 3985 # 3986 if wx_check_backup $version; then 3987 : 3988 else 3989 if [[ $? -eq 2 ]]; then 3990 fail "$backup_dir/$version.*: unable to restore"\ 3991 "inconsistent version" 3992 else 3993 fail "$backup_dir: Unable to find version $version" 3994 fi 3995 fi 3996 3997 b_active=$backup_dir/$version.active 3998 3999 if [[ -n "$comp" && ! -x "$comp" ]]; then 4000 fail "${comp}: missing -- cannot decompress $b_clear" 4001 fi 4002 4003 # must be in workspace to do restore 4004 cd $workspace || fail "Error: cannot cd $workspace" 4005 4006 [[ -f $b_renamed ]] || fail "$b_renamed: missing" 4007 [[ -f $b_new ]] || fail "$b_new: missing" 4008 [[ -f $b_active ]] || fail "$b_active: missing" 4009 4010 [[ -r $b_renamed ]] || fail "$b_renamed: not readable" 4011 [[ -r $b_new ]] || fail "$b_new: not readable" 4012 [[ -r $b_active ]] || fail "$b_active: not readable" 4013 4014 if [[ -f $b_clear ]]; then 4015 [[ -r $b_clear ]] || fail "$b_clear: not readable" 4016 fi 4017 if [[ -f $b_sdot ]]; then 4018 [[ -r $b_sdot ]] || fail "$b_sdot: not readable" 4019 fi 4020 if [[ -f $b_pdot ]]; then 4021 [[ -r $b_pdot ]] || fail "$b_pdot: not readable" 4022 fi 4023 if [[ -f $b_local_nt ]]; then 4024 [[ -r $b_local_nt ]] || fail "$b_local_nt: not readable" 4025 fi 4026 if [[ -f $b_not_files ]]; then 4027 [[ -r $b_not_files ]] || fail "$b_not_files: not readable" 4028 fi 4029 if [[ -f $b_sort ]]; then 4030 [[ -r $b_sort ]] || fail "$b_sort: not readable" 4031 fi 4032 4033 # 4034 # If something goes wrong, we need to make sure they notice, so 4035 # we make the message quite visible, and echo a BELL. 4036 # 4037 fail_msg='Extraction failed. 4038 4039 *DANGER* *DANGER* workspace could be corrupted *DANGER* *DANGER*' 4040 4041 cp $b_renamed $wxdir/renamed || fail "$wxdir/renamed: $fail_msg" 4042 cp $b_new $wxdir/new || fail "$wxdir/new: $fail_msg" 4043 cp $b_active $wxdir/active || fail "$wxdir/active: $fail_msg" 4044 cp $b_local_nt $wxdir/local_nametable || 4045 fail "$wxdir/local_nametable: $fail_msg" 4046 if [[ -n $b_sort ]]; then 4047 cp $b_sort $wxdir/sort_active || \ 4048 fail "$wxdir/sort_active: $fail_msg" 4049 fi 4050 4051 # Need to move active files that are renamed in current ws back to 4052 # their name in the active list to avoid two copies of the file 4053 # occuring when the clear files are restored below. 4054 wx_do_renames $wxdir/local_nametable || 4055 fail "$wxdir/local_nametable: $fail_msg" 4056 4057 if [[ -n $b_not_files ]]; then 4058 tar -xf $b_not_files || fail "$wx/*.NOT: $fail_msg" 4059 fi 4060 # It's not an error if there is no clear backup. 4061 if [[ -f $b_clear ]]; then 4062 wx_do_restore "clear" $b_clear "$comp" || 4063 fail "$b_clear: $fail_msg" 4064 fi 4065 # It's not an error if there is no sdot backup. 4066 if [[ -f $b_sdot ]]; then 4067 wx_do_restore "sdot" $b_sdot "$comp" || 4068 fail "$b_sdot: $fail_msg" 4069 fi 4070 # It's not an error if there is no pdot backup. 4071 if [[ -f $b_pdot ]]; then 4072 wx_do_restore "pdot" $b_pdot "$comp" || 4073 fail "$b_pdot: $fail_msg" 4074 fi 4075 4076 # Do some integrity checking 4077 for filepath in $(wx_active); do 4078 if cd ${workspace}/$(dirname $filepath); then 4079 file=$(basename $filepath) 4080 4081 # If file is not writable then assume the 4082 # SCCS/p.file is bogus. This can happen if a 4083 # file is checked out and a wx restore is done 4084 # and the restored file was not checked out when 4085 # it was backed up. 4086 4087 if [[ ! -w $file && -f SCCS/p.$file ]]; then 4088 ring_bell 4089 cat <<-EOF 4090 4091Warning! $filepath is in inconsistent state. 4092$filepath is not writable and SCCS/p.$file exists. 4093Removing SCCS/p.$file 4094To edit the file run '$ME edit $filepath' 4095 EOF 4096 rm -f SCCS/p.$file 4097 elif [[ -w $file && ! -f SCCS/p.$file ]]; then 4098 ring_bell 4099 cat <<-EOF 4100 4101Warning! $filepath is in inconsistent state. 4102$filepath is writable 4103but there is no SCCS/p.$file 4104 4105 EOF 4106 yesno "Should this file be checked out?" 4107 if [[ "$answer" == 'yes' ]]; then 4108 if mv $file $wxtmp; then 4109 if sccs edit $file; then 4110 update_active $filepath 4111 fi 4112 mv -f $wxtmp/$file $file 4113 fi 4114 else 4115 ask_remove_active_entry 4116 echo "Setting $filepath read only" 4117 chmod ugo-w $file 4118 fi 4119 fi 4120 else 4121 ring_bell 4122 echo "\nWarning! Could not check sccs state of "\ 4123 "$filepath" 4124 fi 4125 done 4126} 4127 4128wx_fullreview() { 4129 if wx_pnt_filepath; then 4130 : 4131 else 4132 parentfilepath=/dev/null 4133 fi 4134 if $show_comments && wx_show_comment > $wxdir/comment; then 4135 comm=-y"`cat $wxdir/comment`" 4136 codereview "$comm" $args $parentfilepath $workspace/$filepath 4137 else 4138 codereview $args $parentfilepath $workspace/$filepath 4139 fi 4140} 4141 4142# 4143# Check on RTI status for bug ID's found in active list comments. 4144# 4145 4146wx_rtichk() { 4147 # gate contains the gate dir, not full path 4148 typeset gate=${parent##*/} 4149 typeset -i rc=0 4150 typeset nolookup opt 4151 4152 if [[ -f $wxdir/rtichk.NOT ]]; then 4153 print "\nSkipping RTI check:" 4154 return 4155 else 4156 print "\nDoing RTI check:" 4157 fi 4158 4159 while getopts :N opt; do 4160 case $opt in 4161 N) nolookup='-N' ;; 4162 *) fail "Invalid flag -$OPTARG." ;; 4163 esac 4164 done 4165 4166 # Note, rtichk needs a gate arg to correctly determine status. 4167 if [[ -z $gate ]]; then 4168 cat >&2 <<-EOF 4169Warning: cannot find a parent gate, skipping RTI checking. 4170 EOF 4171 fi 4172 4173 # Use wx_summary to output bug ID's in active list comments, 4174 # redirecting warnings about non-bug ID's to file for later use. 4175 set -A bugs $(wx_summary -ao $nolookup 2>$wxtmp/bugwarnings|cut -f1 -d' ') 4176 rtichk -g $gate ${bugs[@]} 4177 rc=$? 4178 4179 if [[ -s $wxtmp/bugwarnings ]]; then 4180 cat <<-EOF 4181 4182There are issues with the bug ID format in the 4183$wxdir/active file. 4184Please fix the following and run rtichk again: 4185 4186 EOF 4187 cat $wxtmp/bugwarnings 4188 ((rc = 1)) 4189 fi 4190 if [[ ${#bugs} -eq 0 ]]; then 4191 print "\nWarning: no bug ID's in active list." 4192 fi 4193 return $rc 4194} 4195 4196# 4197# Do a Teamware putback of active and renamed files. 4198# 4199wx_putback() { 4200 # Use pbargs array to store Teamware putback args. 4201 # verbatim is for -v verbatim flag which doesn't get passed to 4202 # putback. 4203 set -A pbargs 4204 typeset i verbatim pbfiles narg=false force=false 4205 typeset nolookup=false 4206 4207 if $FILES_PASSED; then 4208 # use the user specified files 4209 pbfiles=$file_list 4210 else 4211 # use the pblist (active and renamed) 4212 pbfiles=$(wx_active -p) 4213 fi 4214 4215 while getopts :fnp:qvN i; do 4216 case $i in 4217 # Force the putback (no user interaction) 4218 f) force=true;; 4219 4220 n) narg=true 4221 pbargs[${#pbargs[@]}]="-$i" ;; 4222 4223 q) pbargs[${#pbargs[@]}]="-$i" ;; 4224 4225 p) pbargs[${#pbargs[@]}]="-$i" 4226 pbargs[${#pbargs[@]}]="$OPTARG" 4227 # setting parent for user prompt below 4228 parent="$OPTARG" ;; 4229 4230 # -v doesn't get passed to putback. 4231 v) verbatim='-v';; 4232 4233 N) nolookup='-N';; 4234 4235 *) fail "Invalid flag -$OPTARG. See 'wx help'"\ 4236 "for more info.";; 4237 esac 4238 done 4239 4240 if ! $narg; then 4241 # real putback 4242 4243 # get pb comments, will be used later. 4244 if ! wx_summary -p $verbatim $nolookup >$wxtmp/pb_comments; then 4245 # Fail if comments have problems. 4246 fail "\nError, improper comments found. Use -v"\ 4247 "to bypass this check." 4248 fi 4249 4250 if ! $force; then 4251 # not force so give more warning. 4252 ( # using subshell to capture stdout to file. 4253 cat <<-EOF 4254Remember to run '$ME pbchk' before doing a final putback (esp. if 4255doing a putback to an official ON gate). Make sure your workspace 4256parent ($parent) is correct. 4257It's a good idea to check your code diffs before putback ('$ME pdiffs'). 4258 4259Also, run '$ME $command -n' and check for conflicts before doing the 4260final putback. 4261 EOF 4262 4263 if [[ -z "$(wx_summary -bo 2>/dev/null)" ]]; then 4264 cat <<-EOF 4265 4266Don't forget the ARC ID info in your active list comments if there is an 4267ARC case associated with your putback. 4268 EOF 4269 fi 4270 4271 echo "\nThe putback comment will be:" 4272 cat $wxtmp/pb_comments 4273 print "========== End of putback comments =======" 4274 4275 # Output warning if RTI isn't approved. 4276 wx_rtichk $nolookup 4277 print "========== End of RTI check output =======" 4278 4279 cat <<-EOF 4280 4281The following files will be used for putback: 4282$pbfiles 4283 4284 EOF 4285 ) | ${PAGER:-more} 4286 4287 ok_to_proceed "Do you really want to"\ 4288 "'$PUTBACK ${pbargs[@]}' to $parent?" 4289 fi 4290 fi 4291 4292 # Do the putback, passing in active list comments if required. 4293 # putback both active and renamed/deleted files. 4294 cd $workspace 4295 if $narg; then 4296 # Don't use putback comment if -n is given (trial putback) 4297 $PUTBACK "${pbargs[@]}" $pbfiles 4298 else 4299 # feed active list comments into real putback 4300 wx_summary $verbatim $nolookup |$PUTBACK "${pbargs[@]}" $pbfiles 4301 fi 4302 return 4303} 4304 4305outchk() { 4306 4307 # List files that are checked out but not in active list. 4308 typeset outfile do_header=true 4309 4310 wx_checked_out >/dev/null 4311 # if $wxtmp/checked_out is 0 bytes then return 4312 [[ -s $wxtmp/checked_out ]] || return 4313 4314 sort $wxtmp/checked_out > $wxtmp/co_sort 4315 wx_active | sort > $wxtmp/active_sort 4316 for outfile in $(comm -12 $wxtmp/active_sort $wxtmp/co_sort); do 4317 if $do_header; then 4318 echo "\nWarning, the following active list files are"\ 4319 "checked out:" 4320 do_header=false 4321 fi 4322 echo "$outfile" 4323 done 4324 do_header=true 4325 for outfile in $(comm -13 $wxtmp/active_sort $wxtmp/co_sort); do 4326 if $do_header; then 4327 cat <<-EOF 4328 4329Warning, the following files are checked out but not in active list 4330(Run "$ME update -q" to add them to the active list): 4331 EOF 4332 do_header=false 4333 fi 4334 echo "$outfile" 4335 done 4336 rm -f $wxtmp/co_sort $wxtmp/active_sort 4337} 4338 4339# 4340# run Teamware resolve and do reedit only on merged files. 4341# 4342wx_resolve() { 4343 typeset merged_file 4344 4345 # clear the file_list, will be set below 4346 file_list= 4347 4348 grep -v '^VERSION ' $wsdata/conflicts > $wxtmp/conflicts 4349 [[ ! -f $wxtmp/conflicts ]] && fail "Error: cannot create $wxtmp/conflicts" 4350 4351 # run Teamware resolve 4352 resolve $* || fail "Teamware resolve failed." 4353 4354 # resolve will remove files from $wsdata/conflicts when 4355 # successfully merged. 4356 4357 # set file_list to files that were merged. 4358 for merged_file in $(cat $wxtmp/conflicts); do 4359 if ! grep -q '^'"$(escape_re $merged_file)"'$' \ 4360 $wsdata/conflicts; then 4361 # set file_list for wx_eval later. 4362 file_list="$file_list $merged_file" 4363 fi 4364 done 4365 4366 if [[ -n $file_list ]]; then 4367 ok_to_proceed "Re-edit merged files to collapse merge deltas?" 4368 echo "Re-editing merged files" 4369 echo 4370 wx_eval wx_reedit_file 4371 echo 4372 echo "Re-edit complete" 4373 echo 4374 else 4375 echo "No merged files to re-edit." 4376 fi 4377} 4378 4379######################################################################### 4380# 4381# Main 4382# 4383 4384# 4385# Do some initial sanity checking and set up. 4386# 4387 4388# Set the lang to standard English so wx doesn't get confused. 4389export LC_ALL=C 4390 4391# Turn on debugging output early 4392if [[ "$*" == *' -D'*( *) ]]; then 4393 typeset -ft $(typeset +f) 4394 set -x 4395fi 4396 4397ME=$(basename $0) 4398export ME 4399 4400if [[ -d /usr/xpg4/bin ]]; then 4401 # Want to use xpg4 versions of fgrep and grep 4402 PATH=/usr/xpg4/bin:/usr/bin:/usr/sbin:/usr/ccs/bin:$PATH 4403else 4404 fail "Error: directory /usr/xpg4/bin not found." 4405fi 4406 4407unset CDPATH # if set "cd" will print the new directory on stdout 4408 # which screws up wx_eval. 4409 4410DEFAULT_SRCDIR=usr 4411 4412if [[ $# -eq 0 || "$1" == help ]]; then 4413 # output usage now to avoid unnecessary checking below. 4414 wx_usage 4415fi 4416 4417if [[ "$1" == version ]]; then 4418 # output version now to avoid unnecessary checking below. 4419 version 4420 exit 0 4421fi 4422 4423# 4424# Check to make sure we're not being run from within a Mercurial repo 4425# 4426if hg root >/dev/null 2>&1; then 4427 fail "Error: wx does not support Mercurial repositories.\n"\ 4428"Please see http://opensolaris.org/os/community/tools/hg" 4429fi 4430 4431whence workspace >/dev/null || fail "Error: cannot find workspace command in \$PATH." 4432 4433# Note, PUTBACK can be set to "cm_env -g -o putback" to use Casper Dik's 4434# turbo-dir.flp scripts to speed up thorough updates. 4435PUTBACK=${PUTBACK:='putback'} 4436BRINGOVER=${BRINGOVER:='bringover'} 4437 4438dot=$PWD 4439 4440if [[ -n "$CODEMGR_WS" ]]; then 4441 # ws was used. 4442 # normalize the workspace name. 4443 workspace=$(cd $CODEMGR_WS && workspace name) 4444 4445 # If the current dir is in a workspace check that it is the same 4446 # as CODEMGR_WS. 4447 if [[ -n "$(workspace name)" ]]; then 4448 if [[ "$(/bin/pwd)/" != "$workspace/"* ]]; then 4449 cat <<-EOF 4450 4451Warning, $ME will use $ME files in workspace $workspace (the current 4452directory is not in this workspace). 4453 EOF 4454 ok_to_proceed "Okay to proceed?" 4455 fi 4456 fi 4457else 4458 # If current dir is in a workspace then use output of workspace 4459 # name as current ws. 4460 workspace=$(workspace name) 4461 if [[ -n "$workspace" ]]; then 4462 CODEMGR_WS=$workspace 4463 export CODEMGR_WS 4464 fi 4465fi 4466 4467if [[ -z "$workspace" ]]; then 4468 fail "No active workspace, run \"ws <workspace>\" or"\ 4469 "\"cd <workspace>\"." 4470fi 4471 4472workspace_basename=`basename $workspace` 4473wxdir=${WXDIR:-$workspace/wx} 4474wxtmp=$wxdir/tmp 4475wsdata=$workspace/Codemgr_wsdata 4476node=`uname -n` 4477 4478if [ -f $wsdata/parent ]; then 4479 parent=`tail -1 $wsdata/parent` 4480else 4481 parent= 4482fi 4483if [[ $parent == *:* ]]; then 4484 parentdir=${parent#*:} 4485 parentnode=${parent%%:*} 4486 if [[ $parentnode == $node ]]; then 4487 parent=$parentdir 4488 else 4489 parent=/net/$parentnode$parentdir 4490 fi 4491fi 4492 4493# Store backup state 4494backup_done=0 4495 4496# store state if new files are deleted 4497NEED_WS_CLEAN='n' 4498 4499# XXX doing this because keywords doesn't work on new files 4500# Note doing the echo so the tabs are apparent, 4501# % is escaped to prevent keyword expansion by sccs commands on this file. 4502SCCSKEYWORD=$(echo "ident\t+\"(\%Z\%\%M\%\t+\%I\%|\%W\%)\t+\%E\% SMI\"") 4503 4504# file that contains comments for use in create and checkin 4505comment_file= 4506# mode for updating comments in active list 4507comment_mode="replace" 4508 4509CSTYLE_FLAGS=${CSTYLE_FLAGS:='-P -p -c'} 4510JSTYLE_FLAGS=${JSTYLE_FLAGS:='-p'} 4511 4512BACKUP_ERRORS=/tmp/${ME}_berrors_$(/usr/xpg4/bin/id -un)_$$ 4513 4514# global for reedit command, don't checkin by default 4515CHECKIN=false 4516 4517# Indicates that the parent nametable cache needs refreshing 4518need_pnt_refresh=true 4519 4520# Indicate whether file args were specified 4521FILES_PASSED=false 4522 4523# Used to store files that have more than one delta compared to parent 4524multi_delta_list= 4525 4526# Used to bringover any files just before exit of wx 4527bofilelist= 4528 4529# should codereviews include delta comments? 4530show_comments=true 4531 4532# Determines if active list should be sorted by default 4533# If sort_active contains true then we sort the active list on updates. 4534if [[ -r $wxdir/sort_active && "$(cat $wxdir/sort_active)" == "true" ]]; then 4535 ACTSORT=sort 4536else 4537 ACTSORT=cat 4538fi 4539 4540# These are set depending on what needs sorting 4541do_renamed_sort=false 4542do_active_sort=false 4543 4544# Places to search for approved RTIs 4545RTIDIRS="/net/wizard.eng/export/consolidation/rtiroute/newrtis 4546 /net/wizard.eng/export/consolidation/rtiroute/oldrtis 4547 /net/onstc.eng/export/stc/Rtitool/consolidation/rtiroute/newrtis 4548 /net/onstc.eng/export/stc/Rtitool/consolidation/rtiroute/oldrtis" 4549 4550# Places to search for approved Patch RTIs 4551PRTIDIRS="/net/wizard.eng/export/consolidation/rtiroute/newprtis 4552 /net/wizard.eng/export/consolidation/rtiroute/oldprtis" 4553 4554export workspace parent wxdir file dir filepath backup_done DEFAULT_SRCDIR 4555 4556# 4557# main section 4558# 4559 4560# Get wx command 4561command=$1 4562comlist=$command 4563shift 4564# throw away -D flag after command assigned as this flag was processed earlier 4565[[ "$1" == '-D' ]] && shift 4566 4567case $command in 4568 apply|eval) subcommand=$1; shift;; 4569 grep|egrep|sed|nawk) pattern=$1; shift;; 4570 nits) comlist="cstyle jstyle hdrchk copyright cddlchk keywords"; 4571 echo "Note, nits is a subset of pbchk checks.";; 4572 pbchk) comlist="cstyle jstyle hdrchk copyright cddlchk keywords" 4573 comlist="$comlist rmdelchk deltachk comchk rtichk outchk";; 4574esac 4575 4576orig_args="$@" 4577silent= 4578args= 4579file_list= 4580typeset tmp_file_list tmp_args 4581 4582# 4583# Some subcommands pass through all arguments. 4584# 4585case $command in 4586 webrev) args="$orig_args"; shift $#;; 4587esac 4588 4589# Parse args 4590while [ $# -gt 0 ]; do 4591 case $1 in 4592 -c|-C) 4593 if [[ $command == @(delget|checkin|ci|create) ]]; then 4594 # set global comment_file 4595 [[ "$1" == "-C" ]] && comment_mode="append" 4596 comment_file=$2; 4597 if [[ $comment_file != '/'* ]]; then 4598 comment_file="$(pwd)/$comment_file" 4599 fi 4600 if [[ -z "$comment_file" ]]; then 4601 fail "Missing comment file."\ 4602 "Run 'wx help' for info." 4603 fi 4604 [[ ! -r "$comment_file" ]] && 4605 fail "Can not read comment file"\ 4606 "$comment_file." 4607 echo "Using comment file $comment_file"\ 4608 "for comments." 4609 # shift past the comment_file arg 4610 shift 4611 elif [[ $1 == '-C' && $command == 'diffs' || 4612 $command == 'tdiffs' && 4613 -z $WXDIFFCMD ]]; then 4614 if [[ $2 != +([0-9]) ]]; then 4615 # provide default context value for 4616 # compat with old wx 4617 args="$args -C5" 4618 else 4619 args="$args -C$2" 4620 # shift past context lines arg 4621 shift 4622 fi 4623 else 4624 args="$args $1" 4625 fi;; 4626 -p) if [[ $command == @(putback|pb) ]]; then 4627 if workspace access $2 >/dev/null; then 4628 # 2nd arg is a workspace 4629 args="$args $1 $2" 4630 else 4631 fail "$2 not a workspace."\ 4632 "Run 'wx help' for info." 4633 fi 4634 # shift past the parent ws arg 4635 shift 4636 else 4637 # for other commands -p doesn't have a arg 4638 args="$args $1" 4639 fi;; 4640 -r) if [[ $command == @(get|extract) ]]; then 4641 # 2nd arg is the version # 4642 args="$args $1 $2" 4643 # shift past 2nd arg 4644 shift 4645 else 4646 # for other commands -r doesn't have a arg 4647 args="$args $1" 4648 fi;; 4649 -s) if [[ "$command" == @(update|init) ]]; then 4650 args="$args $1" 4651 else 4652 silent=-s 4653 fi;; 4654 -N) if [[ "$command" == @(codereview|fullreview) ]]; then 4655 show_comments=false 4656 else 4657 args="$args $1" 4658 fi ;; 4659 -*) args="$args $1";; 4660 *) if [[ -z "$file_list" ]]; then 4661 file_list="$1" 4662 else 4663 file_list="$file_list $1" 4664 fi;; 4665 esac 4666 shift 4667done 4668 4669if [[ "$command" == "init" ]]; then 4670 if [ -z "$file_list" ]; then 4671 file_list=$DEFAULT_SRCDIR 4672 fi 4673 wx_init $file_list $args 4674 exit 4675fi 4676 4677if [ ! -d $wxdir/tmp ]; then 4678 echo "Workspace does not appear to be initialized for $ME." 4679 echo "The initialization process will create a few files under" 4680 echo "$wxdir but will not otherwise affect your workspace." 4681 ok_to_proceed 'OK to proceed?' 4682 4683 ask "Where is the root of the source code in this workspace?" \ 4684 $DEFAULT_SRCDIR 4685 # wx_init modifies file_list so save current value 4686 tmp_file_list=$file_list 4687 file_list= 4688 # save off args and set to null to avoid side effects 4689 tmp_args=$args 4690 args= 4691 wx_init $answer 4692 # restore original file list and cd to original dir in case there's 4693 # a command to execute. 4694 file_list=$tmp_file_list 4695 args=$tmp_args 4696 cd $dot 4697fi 4698 4699if [[ ! -f $wxdir/local_nametable ]]; then 4700 touch $wxdir/local_nametable 4701fi 4702 4703# Doing this for backward compat since old wx doesn't have a renamed list 4704if [[ ! -f $wxdir/renamed ]]; then 4705 # if 'wx update' or 'wx update -r' is the command then skip 4706 # renamed list creation since it will happen anyway. 4707 if [[ "$command" != "update" ]] || [[ "$args" == *'-q'* ]]; then 4708 ring_bell 4709 cat <<-EOF 4710 4711$ME needs to create a renamed file list. If you are sure that no files 4712were renamed or deleted in the current workspace then answer no to the 4713following question. 4714 4715 EOF 4716 yesno "Okay to search for renamed files (can be slow)?" 4717 if [[ "$answer" == "yes" ]] 4718 then 4719 wx_update -r 4720 else 4721 touch $wxdir/renamed 4722 fi 4723 fi 4724fi 4725 4726# Doing this for backward compat since old wx doesn't have a new list 4727if [[ ! -f $wxdir/new ]]; then 4728 ring_bell 4729 cat <<-EOF 4730 4731$ME needs to create a new-file list (cache names of newly created 4732files). Please be patient. 4733 EOF 4734 # Avoid a putback -n which is slow, just use lookup_parent() 4735 touch $wxdir/new || fail "Error: cannot create $wxdir/new list" 4736 wx_active | 4737 while read filepath; do 4738 if ! lookup_parent $filepath; then 4739 add_new $filepath 4740 fi 4741 done 4742 echo "\nNew files:" 4743 cat $wxdir/new 4744 echo 4745fi 4746 4747if [[ "$command" == @(restore|backup|bu) ]]; then 4748 # If the backup dir was specified as a file arg... 4749 if [ -n "$file_list" ]; then 4750 backup_dir=$(echo "$file_list"|cut -f1 -d' ') 4751 fi 4752 # unset file_list since this file arg has been processed here. 4753 unset file_list 4754elif [[ "$command" == "ea" ]]; then 4755 # Do this command before wx_active is run because the active list 4756 # may be corrupt. 4757 cd $wxdir 4758 exec ${EDITOR-vi} active 4759elif [[ "$command" == @(unedit|uncheckout|unco) ]]; then 4760 if [[ -z "$file_list" && $args != *-f ]]; then 4761 echo "$ME will $command all active files which may remove"\ 4762 "them from the active list." 4763 ok_to_proceed 'Do you REALLY want to do this?' 4764 fi 4765 cp $wxdir/active $wxdir/active.old 4766elif [[ "$command" == @(bugs|arcs) ]]; then 4767 # -v verbatim is not valid for these commands 4768 if [[ "$args" == *'-v'* ]]; then 4769 fail "Invalid flag -v. Run 'wx help' for info." 4770 fi 4771elif [[ "$command" == "create" ]]; then 4772 if [ -z "$file_list" ]; then 4773 fail "$command missing file arg(s). Run 'wx help' for info." 4774 fi 4775 4776 cp $wxdir/active $wxdir/active.old || 4777 fail "Error could not backup $wxdir/active" 4778elif [[ "$command" == @(delget|checkin|ci) && -n "$comment_file" ]]; then 4779 cp $wxdir/active $wxdir/active.old || 4780 fail "Error could not backup $wxdir/active" 4781elif [[ "$command" == @(mv) ]]; then 4782 if [[ $(echo "$file_list"|wc -w) -ne 2 ]]; then 4783 fail "$command requires two args. Run 'wx help' for info." 4784 fi 4785 4786 cp $wxdir/active $wxdir/active.old || 4787 fail "Error could not backup $wxdir/active" 4788 cp $wxdir/renamed $wxdir/renamed.old || 4789 fail "Error could not backup $wxdir/renamed" 4790elif [[ "$command" == @(delete|rm) ]]; then 4791 4792 if [ -z "$file_list" ]; then 4793 echo "$ME will try to delete all active files which may "\ 4794 "remove them from the active list." 4795 ok_to_proceed 'Do you REALLY want to do this?' 4796 fi 4797 4798 cp $wxdir/active $wxdir/active.old || 4799 fail "Error: could not backup $wxdir/active" 4800 cp $wxdir/renamed $wxdir/renamed.old || 4801 fail "Error: could not backup $wxdir/renamed" 4802elif [[ "$command" == reset ]]; then 4803 cp $wsdata/nametable $wxtmp/nametable.orig || \ 4804 fail "Error: cp $wsdata/nametable $wxtmp/nametable.orig failed." 4805fi 4806 4807if [ -z "$file_list" ]; then 4808 basedir=$workspace 4809 file_list=$(wx_active) || fail 4810else 4811 base_file_list=$file_list 4812 file_list= 4813 for basefile in $base_file_list; do 4814 # normalize the filepaths 4815 if [[ -d $basefile ]]; then 4816 basedir=$(cd $basefile && /bin/pwd) 4817 abspath=$basedir 4818 else 4819 basedir=$(cd $(dirname $basefile) && /bin/pwd) 4820 abspath=$basedir/$(basename $basefile) 4821 fi 4822 if [[ ! -d $basedir ]]; then 4823 fail "Error: Path to $basefile does not exist." 4824 elif [[ $(cd $basedir; workspace name) != $workspace ]]; then 4825 fail "Error: $basefile isn't in current workspace: $workspace." 4826 4827 fi 4828 filepath=${abspath##$workspace/} 4829 if [[ -z "$file_list" ]]; then 4830 file_list="$filepath" 4831 else 4832 file_list="$file_list $filepath" 4833 fi 4834 done 4835 FILES_PASSED=true 4836fi 4837 4838if [[ "$command" == @(nits|pbchk) ]]; then 4839 tmp_list= 4840 # skip nits/pbchk checks for files listed in $command.NOT 4841 if [[ -f $wxdir/${command}.NOT ]]; then 4842 for _a_file in $file_list; do 4843 if grep -q "^$(escape_re $_a_file)$" \ 4844 $wxdir/${command}.NOT 4845 then 4846 echo "skipping $command checks for "\ 4847 "$_a_file (skipping)" 4848 else 4849 tmp_list="$tmp_list $_a_file" 4850 fi 4851 done 4852 file_list=${tmp_list# } 4853 fi 4854 [[ -z $file_list ]] && exit 0 4855fi 4856 4857# This is where the commands are executed. 4858for command in $comlist; do 4859cd $dot 4860case $command in 4861 list|active) wx_active $args ;; 4862 pblist) wx_active -p;; 4863 renamed) list_renamed $args ;; 4864 new) list_new $args;; 4865 update) wx_update $args;; 4866 out) wx_checked_out; cat $wxtmp/checked_out;; 4867 diffs) wx_eval -r 'print -- "\n------- $filepath -------\n"; 4868 sccs get -s -p -k $filepath | 4869 ${WXDIFFCMD:-diff} $args - $filepath';; 4870 tdiffs) ## As diffs but also shows new files. 4871 if [[ -r $wxdir/new ]]; then 4872 ## Read names of new files into space separated list. 4873 while read new_file 4874 do 4875 new_files="${new_files}${new_file} " 4876 done < $wxdir/new 4877 else 4878 new_files="" 4879 fi 4880 ## For new files a comparison is made with /dev/null thus 4881 ## all lines will appear to have been added. 4882 wx_eval -r 'print -- "\n------- $filepath -------\n"; 4883 if [[ ${new_files} == *"${filepath} "* ]]; then 4884 ${WXDIFFCMD:-diff} $args /dev/null $filepath; 4885 else 4886 sccs get -s -p -k $filepath | 4887 ${WXDIFFCMD:-diff} $args - $filepath; 4888 fi';; 4889 pdiffs|tpdiffs) 4890 ## Parent Diffs - Compare with parent file. For 4891 ## 'tpdiffs' when the parent file does not exist the 4892 ## child file is assumed new and compared to 4893 ## /dev/null; thus all lines will appear to have been 4894 ## added. 4895 wx_eval ' 4896 print -- "\n------- $filepath -------\n"; 4897 if wx_pnt_filepath; then 4898 echo "Index: $filepath"; 4899 ${WXDIFFCMD:-diff} $args $parentfilepath 4900 $workspace/$filepath; 4901 elif [[ $command == 'tpdiffs' ]]; then 4902 ${WXDIFFCMD:-diff} $args /dev/null 4903 $workspace/$filepath; 4904 else 4905 print "New file (does not exist in parent)."; 4906 fi';; 4907 pvi) wx_eval ' 4908 echo $filepath; 4909 if wx_pnt_filepath; then 4910 ${EDITOR-vi} $args $parentfilepath; 4911 else 4912 echo "New file (does not exist in parent)"; 4913 fi';; 4914 edit|checkout|co) wx_eval wx_edit;; 4915 unedit|uncheckout|unco) wx_eval wx_unedit;; 4916 create) wx_eval wx_create $args;; 4917 uncreate) wx_eval wx_uncreate $args;; 4918 delete|rm) wx_eval wx_delete $args;; 4919 mv) wx_mv $file_list;; 4920 delget|checkin|ci) wx_eval wx_delget $args;; 4921 get|extract) wx_eval wx_get;; 4922 reset) wx_eval wx_reset $args;; 4923 putback|pb) wx_putback $args;; 4924 resolve) wx_resolve $args;; 4925 prt) wx_eval 'sccs prt $args $file';; 4926 comments) wx_eval 'echo $filepath; echo; wx_show_comment; echo';; 4927 bugs) wx_summary -ao $args;; 4928 arcs) wx_summary -bo $args;; 4929 pbcom) wx_summary -po $args;; 4930 info) wx_eval wx_info;; 4931 reedit|recheckout|reco) wx_reedit $args;; 4932 redelget|recheckin|reci) CHECKIN=true; wx_reedit $args;; 4933 cstyle) echo "\nDoing cstyle check:" 4934 rm -f $wxtmp/wx.cstyle.*; 4935 export CSTYLE_INDEX=0; 4936 wx_eval wx_cstyle; 4937 wait; 4938 sort -k 1,1 -k 2,2n $wxtmp/wx.cstyle.* 2> /dev/null 4939 ;; 4940 jstyle) echo "\nDoing jstyle check:" 4941 rm -f $wxtmp/wx.jstyle.*; 4942 export JSTYLE_INDEX=0; 4943 wx_eval wx_jstyle; 4944 wait; 4945 sort -k 1,1 -k 2,2n $wxtmp/wx.jstyle.* 2> /dev/null 4946 ;; 4947 hdrchk) echo "\nDoing header format check:"; 4948 cd $workspace; 4949 hdrchk_files=; 4950 for filepath in $file_list ; do 4951 if [[ "$filepath" == *.h ]]; then 4952 if [[ -s $wxdir/${command}.NOT ]] && 4953 grep -q "^$(escape_re $filepath)$" \ 4954 $wxdir/${command}.NOT 4955 then 4956 echo "$filepath (skipping)" 4957 else 4958 hdrchk_files="$hdrchk_files $filepath" 4959 fi 4960 fi 4961 done 4962 hdrchk -a $args $hdrchk_files ;; 4963 makestyle) echo "\nDoing makestyle check:"; 4964 cd $workspace; mlist=$(wx_active | grep '[Mm]akefile'); 4965 [[ -n "$mlist" ]] && makestyle $args $mlist;; 4966 4967 keywords) 4968 echo "\nDoing keywords check:"; 4969 cd $workspace; 4970 keyword_files=; 4971 for filepath in $file_list ; do 4972 if [[ -s $wxdir/${command}.NOT ]] && 4973 grep -q "^$(escape_re $filepath)$" \ 4974 $wxdir/${command}.NOT 4975 then 4976 echo "$filepath (skipping)" 4977 else 4978 keyword_files="$keyword_files $filepath" 4979 fi 4980 done 4981 keywords -p $args $keyword_files;; 4982 4983 rmdelchk) echo "\nDoing sccs rmdel check:"; wx_eval rmdelchk;; 4984 4985 rtichk) wx_rtichk;; 4986 4987 deltachk) echo "\nDoing multi delta check:"; wx_eval deltachk;; 4988 copyright) echo "\nDoing copyright check:"; 4989 cd $workspace; 4990 copyright_files=; 4991 for filepath in $file_list; do 4992 if [[ -s $wxdir/${command}.NOT ]] && 4993 grep -q "^$(escape_re $filepath)$" \ 4994 $wxdir/${command}.NOT 4995 then 4996 echo "$filepath (skipping)" 4997 else 4998 copyright_files="$copyright_files $filepath" 4999 fi 5000 done 5001 copyrightchk $copyright_files;; 5002 5003 cddlchk) 5004 echo "\nDoing CDDL block check:"; 5005 cd $workspace; 5006 cddlnot=""; 5007 if [[ -s $wxdir/${command}.NOT ]]; then 5008 cddlnot="-x $wxdir/${command}.NOT" 5009 fi 5010 5011 # 5012 # Split the file list into new files and existing files. 5013 # New files must have a CDDL block whereas existing files don't 5014 # necessarily have to have a block, but if they do it must be 5015 # valid. Both sets of files are subject to cddlchk.NOT 5016 # exception processing. 5017 # 5018 old="" 5019 new="" 5020 for filepath in $file_list; do 5021 if wx_pnt_filepath $filepath; then 5022 old="$old $filepath" 5023 else 5024 new="$new $filepath" 5025 fi 5026 done 5027 [[ ! -z $new ]] && cddlchk $cddlnot $args -a $new 5028 [[ ! -z $old ]] && cddlchk $cddlnot $args $old 5029 ;; 5030 comchk) echo "\nDoing comments check:"; wx_summary -n 2>&1;; 5031 outchk) echo "\nDoing out check:"; outchk;; 5032 backup|bu) wx_backup $args;; 5033 restore) wx_restore $args;; 5034 apply) wx_eval "$subcommand \$file";; 5035 eval) wx_eval "$subcommand";; 5036 grep|egrep) 5037 wx_eval ' 5038 if egrep -s '\'$pattern\'' $file; 5039 then 5040 echo $filepath; 5041 $command $args '\'$pattern\'' $file; 5042 fi';; 5043 nawk|sed) 5044 wx_eval 'echo $filepath; $command $args '\'$pattern\'' $file';; 5045 codereview) args="-e $args"; wx_eval wx_fullreview;; 5046 fullreview) wx_eval wx_fullreview;; 5047 webrev) wx_webrev $args;; 5048 dir) echo $wxdir;; 5049 e) cd $wxdir; exec ${EDITOR-vi} $orig_args;; 5050 ws) cd $wsdata; cat $orig_args;; 5051 args) cat $wsdata/args;; 5052 access) cat $wsdata/access_control;; 5053 *) ring_bell; 5054 echo "Command not found. Run 'wx help' for command list."; 5055 exit 1;; 5056esac 5057 5058done 5059 5060if [[ $NEED_WS_CLEAN == 'y' ]]; then 5061 # clean up the nametable 5062 print -u2 "Running workspace updatenames to clean up nametable, may"\ 5063 "take a while." 5064 workspace updatenames >&2 5065fi 5066 5067if [[ -n $bofilelist ]]; then 5068 $BRINGOVER $bofilelist 5069fi 5070 5071# save sorting for last for some speed up. 5072if [[ $ACTSORT == sort ]]; then 5073 if $do_renamed_sort; then 5074 sort_renamed 5075 fi 5076 if $do_active_sort; then 5077 sort_active 5078 fi 5079fi 5080