51 branding regression for boot menu
[illumos-gate.git] / usr / src / tools / scripts / wx.sh
blobd8dc0203d007906810967ff653552e141db72bb2
1 #!/bin/ksh -p
3 # CDDL HEADER START
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.
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.
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]
20 # CDDL HEADER END
25 # Copyright 2009 Sun Microsystems, Inc. All rights reserved.
26 # Use is subject to license terms.
29 # wx -- workspace extensions. Jeff Bonwick, December 1992.
31 # The bugster cat/subcat = consolidation/os-net-tools
33 version() {
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
42 ring_bell() {
43 # Sound bell to stderr, no newline
44 print -u2 "\007\c"
47 fail() {
48 ring_bell
49 # output error message to stderr
50 print -u2 "$@ Aborting $command."
51 exit 1
54 ask() {
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"
61 read answer
62 [ -z "$answer" ] && answer="$default_answer"
65 yesno() {
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
78 ok_to_proceed() {
79 yesno "$*"
80 if [[ "$answer" == no ]]; then
81 echo "Exiting, no action performed"
82 exit 1
86 escape_re() {
87 # Escape the . so they are treated as literals in greps.
88 echo "$1"|sed 's{\.{\\.{g'
91 remove_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."
101 remove_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"
111 add_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"
121 return 0
124 remove_active_entry() {
125 # Remove entry from active list
126 # $1 is the filepath to remove
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;
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
156 An error occured trying to remove $1 from the active list.
157 The active list may be corrupt. You should check it out and
158 possibly run '$ME update' to fix.
160 fail
164 rename_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."
172 is_active() {
173 # Return 0 if filepath arg is found in active list.
174 wx_active|grep -q "^$(escape_re $1)$"
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.
181 ask_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
189 if [[ ! -f $file ]]; then
190 echo "Cannot find $file"
191 return 1
195 if is_active $filepath; then
196 if wx_pnt_filepath $filepath; then
197 if ! cmp -s $file $parentfilepath; then
198 cat <<-EOF
200 The file $filepath
201 differs from parent file:
202 $parentfilepath
203 and will remain in the active list.
205 return
207 else
208 # New file, leave in active list.
209 cat <<-EOF
210 $filepath
211 is new and will remain in active list. Use:
212 '$ME uncreate $filepath'
213 to remove from active list.
215 return
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
228 refresh_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.
233 # no parent so nothing to update.
234 [[ -z $parent ]] && return 0
236 if [[ ! -r $parent/Codemgr_wsdata/nametable ]]; then
237 fail "Error: cannot read $parent/Codemgr_wsdata/nametable"
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
246 if [[ ! -f $wxtmp/hash_list ]]; then
247 fail "Error: cannot create $wxtmp/hash_list."
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
260 # There aren't any files to search for so just
261 # update the timestamp.
263 touch $wxtmp/parent_nametable
268 # add an active file to the new list
269 add_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."
275 if is_active $1 && ! grep -q "^$efp$" $wxdir/new; then
276 echo "$1" >> $wxdir/new || fail "Error: cannot update $wxdir/new."
280 # remove a file from the new list
281 remove_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."
291 update_active() {
292 # Try to add an entry to the active list
293 typeset efp=$(escape_re $1)
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')."
308 add_local_nt_entry $1
309 fi # End if not in active list
312 sort_active() {
313 typeset origfp=$filepath
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"
323 filepath=$origfp
326 sort_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"
333 update_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;
343 #print 1 blank (delimit)
344 print "";
345 # Get past blank lines
346 while(NF == 0){
347 getline;
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;
357 } else {
358 # get past existing comments
359 while(NF > 0) getline;
362 # output new comments
363 while (getline < comments){
364 # do not print blank lines
365 if (NF > 0)
366 print $0
368 close comments
369 # print delimiting blank line
370 printf "\n"
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;
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
391 An error occured trying to update comments for $1 in the active list.
392 The active list ($wxdir/active) may be corrupt. You should check it out
393 and possilbly run '$ME ea' to fix.
396 fail
400 lookup_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.
407 typeset efp parententry localfile hash1 hash2 hash3 hash4 \
408 local_nt pnt_nt
410 parentfile=
411 parenthash=
413 if [[ -z $parent ]]; then
414 cat >&2 <<-EOF
416 Warning: there is no parent for the current workspace so local file:
418 is assumed to be new.
420 return 1
422 if [[ ! -f $wsdata/nametable ]]; then
423 # Nothing has been brought over so assuming new file.
424 cat >&2 <<-EOF
426 Warning: the $wsdata/nametable
427 doesn't exist so
429 is assumed to be new.
431 return 1
434 if [[ ! -r $parent/Codemgr_wsdata/nametable ]]; then
435 fail "Error: cannot read $parent/Codemgr_wsdata/nametable."
437 if [[ ! -f $wxtmp/parent_nametable ]] || $need_pnt_refresh; then
438 refresh_pnt_nt_cache
439 need_pnt_refresh=false
441 if [[ ! -f $wxdir/local_nametable ]]; then
442 touch $wxdir/local_nametable ||
443 fail "Error: cannot create $wxdir/local_nametable."
446 efp=$(escape_re $1)
448 for local_nt in $wxdir/local_nametable $wsdata/nametable; do
450 # May be multiple entries in nametable, see if one
451 # matches parent.
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
469 # Update the local nt
470 # hash cache if parent
471 # found and local
472 # workspace nt used.
474 add_local_nt_entry $localfile
476 if [[ $pnt_nt == \
477 $parent/Codemgr_wsdata/nametable ]]
478 then
480 # Update the parent nt
481 # hash cache if actual
482 # parent nt used.
484 echo $parententry >>\
485 $wxtmp/parent_nametable
488 # break out of all the loops if
489 # parent found
491 break 3
493 done # for pnt_nt
494 done # while read active file
495 done # for local_nt
497 if [[ -z "$parentfile" ]]; then
498 # parent filepath not found.
499 return 1
500 else
501 # parent filepath found.
502 return 0
507 # Detect if a file was locally renamed
509 renamed() {
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)
514 if [[ ! -f $wxdir/renamed ]]; then
515 update_renamed_dir
518 # new is the new filename in the current ws, old is the previous
519 # filename that should exist in parent ws.
521 if grep -q "^$(escape_re $filepath) " $wxdir/renamed; then
522 if lookup_parent $filepath; then
523 return 0
524 else
526 # New files aren't in $wxdir/renamed so no
527 # parent is a problem
529 fail "Error: renamed $filepath but no matching parent"\
530 "file in $parent"
532 else
533 # not locally renamed
534 return 1
538 wx_pnt_filepath() {
539 # return 0 if parent file found. Side effect: sets parentfilepath
540 # and parentsdot. parentfile and parenthash are set via lookup_parent.
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
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."
564 # wasn't found
565 return 1
568 get_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
576 cat <<-EOF
577 Doing a '$PUTBACK -n $*' to find diffs between workspaces.
578 Please be patient as this can take several minutes.
581 cd $workspace
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."
591 trap - HUP INT QUIT TERM
592 cd $origdir
593 return 0
596 wx_usage() {
597 version
599 cat << EOF
601 See <http://www.opensolaris.org/os/community/on/wx/> for usage tips.
603 Usage: $ME command [-D] [args]
605 -D turn on debugging for any command (output to stderr)
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).
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.
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).
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
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"
680 $ME tdiffs [file ...]
681 Similar to diffs but new files are also displayed.
682 New files are those listed by '$ME new'.
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.
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.
695 $ME prt [-y] show sccs history for all active files
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
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.
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.
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.
750 NOTE: use redelget to reset new file's version to 1.1.
752 $ME checkin Alias for delget command.
753 $ME ci Alias for delget command.
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.
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.
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.
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.
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.
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.
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.
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
819 $ME recheckout Alias for reedit command.
820 $ME reco Alias for reedit command.
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.
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)
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.
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)
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).
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.
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.
881 $ME resolve [Teamware resolve args]
882 resolve bringover conflicts and reedit merged
883 files. See 'man resolve' for args.
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.
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
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.
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.
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.
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.
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
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.
990 $ME ea shorthand for "$ME e active" (edit active list).
991 Note, the format for each entry in the active
992 list is:
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.
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.
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"
1009 $ME help print this usage message
1010 $ME version print current version of this program
1012 exit 1
1015 list_putback() {
1016 (wx_active; list_renamed -n)|nawk '!seen[$0]++'
1019 list_new() {
1020 # list new files (not found in parent ws)
1021 typeset new
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"
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"
1039 done < $wxdir/new
1043 list_renamed() {
1044 typeset active current old
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"
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."
1083 list_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"
1091 done
1094 wx_webrev() {
1095 typeset origdir=$PWD
1097 cd $workspace
1098 # skip files listed in .NOT files
1099 cat -s $wxdir/$command.NOT >$wxtmp/NOT
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
1107 if renamed; then
1108 echo "$filepath $parentfile"
1109 else
1110 echo "$filepath"
1112 echo "\n$(wx_show_comment)\n"
1113 done
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
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"
1133 done
1134 # End of subshell
1135 ) > $wxtmp/webrev.list
1137 # Note that the file list must come last.
1138 ${WXWEBREV:-webrev} -w "$@" $wxtmp/webrev.list
1140 cd $origdir
1144 # list all active files
1146 wx_active() {
1147 # do not print hash by default
1148 typeset rc hash=0
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
1160 if [[ ! -r $wxdir/active ]]; then
1161 fail "Error: cannot read $wxdir/active"
1164 nawk '
1166 # skip blank lines
1167 while (NF == 0) {
1168 if (getline == 0)
1169 next;
1171 if (NF > 0){
1172 # print the active filepath
1173 print $1;
1174 getline;
1176 # skip blank lines
1177 while (NF == 0) {
1178 if (getline == 0){
1179 # Error, corrupt active list (missing comment)
1180 exit 1
1183 # skip comment
1184 while (NF > 0) {
1185 if (getline == 0){
1186 # Error, blank line after comment missing
1187 exit 2
1190 }' $wxdir/active
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)."
1201 # show the comment for $filepath
1203 wx_show_comment() {
1204 if [[ -f $wxdir/active ]]; then
1205 nawk '
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
1217 found = 1
1218 print
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"
1233 bugdb_lookup_monaco() {
1234 typeset buglist=$1
1235 typeset monaco=/net/monaco.sfbay/export/bin/monaco
1237 if [[ ! -x $monaco ]]; then
1238 return 1
1241 $monaco -text <<-EOF
1242 set What =
1243 substr(cr.cr_number, 1, 7), synopsis
1245 set Which =
1246 cr.cr_number in ($buglist)
1248 set FinalClauses =
1249 order by cr.cr_number
1251 do query/CR
1255 bugdb_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)
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
1285 # Summarize all comments listing, in order:
1286 # - free-form comments
1287 # - ARC case comments
1288 # - Bug comments
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.
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.
1305 function 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
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
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
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
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
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][^ ]'
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)
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"
1378 if $pbcom && ! $verbatim; then
1380 # Don't want to output anything to
1381 # stdout for a pbcom if there is an
1382 # error.
1384 return 1
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
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
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)"
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
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
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)"
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
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
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
1481 grep -n "^$comment" $wxdir/active >&2
1482 done < $wxtmp/error
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
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
1498 Warning, the following comments are found in your active list
1499 that are neither bug or arc cases:
1502 cat $wxtmp/other_comments
1503 print -- "\n---- End of active list comment warnings ----"
1504 fi > $wxtmp/comment_warning
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
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."
1527 # Add blank line to active comments so following cmp will
1528 # work properly.
1529 (wx_show_comment; print) | sort > $wxtmp/com2
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
1538 done
1539 # Just output warnings for pbchk
1540 return 0
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
1555 if $show_arcs; then
1556 egrep "^$arc" $wxtmp/comments | $cmd
1559 if $show_bugs; then
1560 egrep "^$bug" $wxtmp/comments | $cmd
1562 return 0
1565 update_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.
1570 # ofp: old filepath, nfp: new filepath
1571 typeset ofp=$1 nfp=$2
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."
1580 # remove old entries from local nt cache
1581 remove_local_nt_entry $ofp
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."
1590 [[ $ACTSORT == sort ]] && do_renamed_sort=true
1593 return 0
1596 update_renamed_dir() {
1597 typeset append pb_files new orig
1598 typeset -i rc
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
1609 else
1610 # Assuming one or more filepaths as args
1611 append=true
1612 pb_files="$*"
1614 echo "Updating $ME renamed list... this may take several minutes."
1616 # Get output of putback -n to detect renames elsewhere in
1617 # this script.
1619 get_pb_output $pb_files
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."
1627 cp $wxdir/renamed $wxdir/renamed.old ||
1628 fail "Error: cannot create $wxdir/renamed.old."
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."
1641 [[ $ACTSORT == sort ]] && do_renamed_sort=true
1644 # returns 0 if a pattern in patternfile matches input path arg
1645 pathcheck() {
1646 typeset pattern path=$1 patternfile=$2
1648 while read pattern; do
1649 if [[ $path == $pattern ]]; then
1650 return 0 # pattern matched path
1652 done < $patternfile
1653 return 1 # file path not matched by pattern
1657 # Evaluate a command for all listed files. This is the basic building
1658 # block for most wx functionality.
1661 wx_eval() {
1662 typeset -i changedir=1
1664 if [[ $# -gt 1 && "$1" == "-r" ]]; then
1665 changedir=0
1666 shift
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
1682 done
1686 # Initialize a workspace for wx.
1689 wx_init() {
1690 typeset srcroot_dir force=false
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="."
1703 else
1704 fail "Source root '$1' does not exist in workspace"\
1705 "($workspace)."
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?'
1713 else
1714 mkdir -p $wxtmp
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.
1721 rm -f $wxdir/srcroot_dir
1722 echo $srcroot_dir >$wxdir/srcroot_dir
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."
1731 touch $wxdir/renamed
1732 touch $wxdir/active
1733 touch $wxdir/new
1734 touch $wxdir/local_nametable
1736 if [[ -z "$2" ]]; then
1737 # Interactive mode
1738 cat << EOF
1739 Pick one of the following update methods:
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.
1748 2) Quick: Only update the active list with files that are currently
1749 checked out. Will not update the renamed list.
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.
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
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
1788 print
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
1801 else
1802 echo "Active list empty, not doing backup."
1803 echo
1806 echo "$ME initialization complete"
1810 # Find all checked out files
1813 wx_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
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
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
1839 deal_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' ')
1859 [[ -z $newfp ]] && continue
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
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"
1878 done
1879 if [[ -n $notrenamed_list ]]; then
1880 ring_bell
1881 cat <<-EOF
1882 Warning, active file(s):
1883 $(echo $notrenamed_list)
1884 not found and cannot be renamed. Use "$ME ea" to edit the active list to
1885 remove these entries if they do not exist in this workspace.
1888 cd $origdir
1892 # Old style update the active file list (by appending all checked out files).
1893 # This is what the original wx update did.
1895 wx_update_quick() {
1897 # Sort active if requested.
1898 [[ "$1" == "-s" ]] && ACTSORT=sort
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"
1915 mv -f active active.old
1916 mv -f active.new active
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 =========================="
1928 # Do new file processing after active list is updated.
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
1944 done < tmp/files.new
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 =========================="
1959 # Update various lists (active, renamed, new)
1962 wx_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
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
1979 deal_ws_renames
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
1988 if [[ -z $parent ]]; then
1989 fail "Error: cannot do thorough update, no parent. Use 'update -q'"\
1990 "instead."
1992 if [[ ! -r $parent/Codemgr_wsdata/nametable ]]; then
1993 fail "Error: cannot read $parent/Codemgr_wsdata/nametable"
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
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
2008 cd $wxdir
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."
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"
2026 for filepath in $(cut -f1 -d' ' renamed); do
2027 add_local_nt_entry $filepath
2028 done
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 =========================="
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"
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"
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."
2063 # clear the tmp active file
2064 print -n > tmp/active.new || fail "Error: cannot create tmp/active.new."
2066 # store current active list
2067 wx_active > tmp/files.old ||
2068 fail "Error: cannot create $wxtmp/files.old"
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
2076 efp=$(escape_re $filepath)
2078 if grep -q "^$efp$" tmp/conflict_nawk_out; then
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
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' ')"
2091 # continue if empty string
2092 [[ -z "$local_file" ]] && continue
2094 if ! grep -q "^$local_file" tmp/active.new; then
2095 filepath=$local_file
2096 else
2097 continue
2100 add_local_nt_entry $filepath
2101 (echo $filepath; echo; wx_show_comment; echo)\
2102 >> tmp/active.new
2103 done
2105 rm -f tmp/active_nawk_out
2107 mv -f active active.old
2108 mv -f tmp/active.new active
2109 wx_active > tmp/files.new
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
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."
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 =========================="
2148 wx_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."
2160 else
2161 ring_bell
2162 echo "Warning. file $filepath not found."
2165 [[ $ACTSORT == sort ]] && do_active_sort=true
2168 wx_unedit() {
2169 # Must be called via wx_eval
2170 typeset -i force=0
2171 typeset arg msg
2173 # set positional args to contents of global $args
2174 set -- $args
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
2184 msg="differs from parent file, will remain in active list."
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."
2195 else
2196 # only backup if necessary
2197 print "Will backup wx and active files if necessary"
2198 wx_backup -t || fail "Backup failed."
2200 backup_done=1;
2202 # cd to the dir where the file is in case
2203 # wx_backup took us somewhere else.
2205 cd ${workspace}/$dir
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"
2220 else
2221 ask_remove_active_entry
2227 wx_create() {
2228 # Must be called via wx_eval
2229 typeset -i checkout=0 force=0
2230 typeset arg
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
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
2248 Error: a deleted version of $filepath exists.
2249 You must undelete the file and edit that version.
2250 Run:
2251 'cd $workspace'
2252 '$ME mv deleted_files/$filepath $filepath'
2253 '$ME edit $filepath'
2255 return 1
2256 elif [[ -n $parent && -f $parent/$filepath ]]; then
2257 ring_bell
2258 cat >&2 <<-EOF
2259 Error! $filepath exists in the parent workspace $parent.
2260 Choose a different name.
2262 return 1
2263 elif [[ -n $parent && -f $parent/deleted_files/$filepath ]]; then
2264 ring_bell
2265 cat >&2 <<-EOF
2266 Error! a deleted version of $filepath exists in the parent workspace
2267 You must undelete the file and edit that version.
2268 Run:
2269 'cd $workspace'
2270 'bringover deleted_files/$filepath'
2271 '$ME mv deleted_files/$filepath $filepath'
2272 '$ME edit $filepath'
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
2284 Warning!!!
2285 $filepath
2286 is missing SCCS keywords. See
2287 /net/wizard.eng/export/misc/general_docs/keyword_info.txt
2288 for more info. Note, pay attention to the tabs.
2290 if [[ $force -ne 1 ]]; then
2291 yesno "Continue with create?"
2292 if [[ "$answer" != 'yes' ]]; then
2293 echo "Aborting create $filepath"
2294 return 1
2299 if ! copyrightchk $file; then
2300 # Sound bell
2301 ring_bell
2302 cat >&2 <<-EOF
2304 Warning!!!
2305 $filepath
2306 has copyright problems. See
2307 /net/wizard.eng/export/misc/general_docs/golden_rules.txt
2308 for more info.
2310 if [[ $force -ne 1 ]]; then
2311 yesno "Continue with create?"
2312 if [[ "$answer" != 'yes' ]]; then
2313 echo "Aborting create $filepath"
2314 return 1
2319 if ! cddlchk -a $file; then
2320 # Sound bell
2321 ring_bell
2322 cat >&2 <<-EOF
2324 Warning!!!
2325 $filepath
2326 has CDDL block problems. See
2327 http://www.opensolaris.org/os/community/onnv/devref_toc/devref_7/#7_2_3_nonformatting_considerations
2328 for more info.
2330 if [[ $force -ne 1 ]]; then
2331 yesno "Continue with create?"
2332 if [[ "$answer" != 'yes' ]]; then
2333 echo "Aborting create $filepath"
2334 return 1
2339 if [[ ! -d SCCS ]]; then
2340 mkdir SCCS || fail "Error: cannot create SCCS dir."
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."
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."
2358 [[ $ACTSORT == sort ]] && do_active_sort=true
2362 wx_uncreate() {
2363 # Must be called via wx_eval
2364 # undoes a 'wx create'
2366 typeset efp
2367 typeset -i force=0
2369 case $1 in
2370 -f) force=1;;
2371 -*) fail "$ME $command: unrecognized argument";;
2372 esac
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."
2380 else
2381 # only backup if necessary
2382 print "Will backup wx and active files if necessary"
2383 wx_backup -t || fail "Backup failed."
2385 backup_done=1;
2386 cd $workspace/$dir
2389 if [[ ! -f $file ]]; then
2390 echo "$filepath not found, skipping"
2391 return 1
2394 efp=$(escape_re $filepath)
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
2402 $filepath appears to be a new file.
2403 Note, $command will remove its SCCS info from your
2404 workspace and entry in the active list but will leave
2405 the file in your workspace.
2408 # yesno sets answer
2409 yesno "Continue $command $filepath?"
2410 else
2411 # forced to yes
2412 answer='yes'
2415 if [[ "$answer" == 'yes' ]]; then
2416 if [[ ! -f SCCS/p.$file ]]; then
2417 sccs edit $file ||
2418 fail "sccs edit $filepath failed."
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'
2426 if is_active $filepath; then
2427 remove_active_entry $filepath
2429 remove_new $filepath
2430 else
2431 echo "skipping $filepath"
2433 else
2434 echo "Not new, skipping $filepath"
2435 fi # if ! wx_pnt_filepath
2438 wx_reset() {
2439 # Must be called via wx_eval
2440 # resets a local file to the parent version
2442 typeset efp
2443 typeset -i force=0
2445 case $1 in
2446 -f) force=1;;
2447 -*) fail "$ME $command: unrecognized argument";;
2448 esac
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."
2456 else
2457 # only backup if necessary
2458 print "Will backup wx and active files if necessary"
2459 wx_backup -t || fail "Backup failed."
2461 backup_done=1;
2464 if [[ ! -f $file ]]; then
2465 print "$filepath not found, skipping"
2466 return 1
2469 efp=$(escape_re $filepath)
2471 if wx_pnt_filepath; then
2472 if [[ $force -ne 1 ]]; then
2473 answer='no' # safe default
2474 cat <<-EOF
2476 Regarding: $filepath
2477 $command will reset the file contents and sccs history to that of the parent:
2478 $parentfilepath
2479 and remove the entry from the active and renamed lists.
2482 if [[ $filepath != $parentfile ]]; then
2483 print "Note: local file will be reset to parent filepath."
2485 # yesno sets answer
2486 yesno "Continue $command $filepath?"
2487 else
2488 # forced to yes
2489 answer='yes'
2492 if [[ "$answer" == 'yes' ]]; then
2493 if is_active $filepath; then
2494 remove_active_entry $filepath
2496 if renamed; then
2497 remove_renamed_entry $filepath
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."
2505 # add to bringover list for more efficient bringover
2506 bofilelist="$bofilelist $parentfile"
2507 else
2508 print -u2 "Skipping $filepath"
2510 else
2511 cat >&2 <<-EOF
2513 Warning: skipping $filepath
2514 as it appears to be new. Use 'uncreate' to remove this new file from the
2515 workspace.
2517 fi # if ! wx_pnt_filepath
2521 cyclic_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
2528 while read prev_new prev_old; do
2529 if [[ "deleted_files/$new_filepath" == $prev_new &&
2530 $old_filepath != $prev_new ]]; then
2532 # Cyclic rename
2533 return 0
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
2544 elif [[ $old_filepath == $prev_new &&
2545 $new_filepath != $prev_old ]]; then
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)
2552 found_old=true
2553 if $found_new; then
2554 # Cyclic rename
2555 return 0
2558 done < $wxdir/renamed
2560 # Not a cyclic rename
2561 return 1
2564 wx_delete() {
2565 # Must be called via wx_eval
2566 typeset efp
2567 typeset -i force=0
2569 case $1 in
2570 -f) force=1;;
2571 -*) fail "$ME $command: unrecognized argument";;
2572 esac
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."
2580 else
2581 # only backup if necessary
2582 print "Will backup wx and active files if necessary"
2583 wx_backup -t || fail "Backup failed."
2585 backup_done=1;
2586 cd $workspace/$dir
2589 if [[ ! -f $file ]]; then
2590 fail "$filepath isn't a file."
2593 # this is used a couple times so save escape_re value
2594 efp=$(escape_re $filepath)
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
2602 Warning! $filepath
2603 is in active list. You should run
2604 "$ME reedit $filepath"
2605 "$ME unedit $filepath"
2606 which should remove it from the active list then run
2607 "$ME $command $filepath".
2608 Note, if you have made changes to this file that you want to keep, back
2609 it up first.
2611 $filepath not deleted.
2614 return 1
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
2621 Warning: $filepath
2622 has already been deleted.
2623 Check for deleted_files/$filepath
2624 in $wxdir/renamed .
2626 else
2627 cat >&2 <<-EOF
2628 Warning! the $ME renamed list appears to be corrupt.
2630 fail "Please run '$ME update -r' and try this"\
2631 "command again."
2634 if workspace filerm $file; then
2635 # we know filerm renames files under deleted_files/
2636 update_renamed_file $filepath deleted_files/$filepath
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"
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
2652 Warning: $filepath
2653 is in active list. You should run
2654 "$ME uncreate $filepath"
2655 which should remove it from the active list
2656 then run "$ME $command $filepath".
2658 $filepath not deleted.
2661 return 1
2664 answer='no'
2665 if [[ $force -ne 1 ]]; then
2666 cat <<-EOF
2668 Warning: $filepath
2669 appears to be a new file.
2671 Do you want to completely remove the file and SCCS info from
2672 your workspace? (If you answer no, the file will just be
2673 removed from the active list if it's in there. If you answer
2674 yes, the file and associated SCCS history files will removed
2675 from the active list and also removed entirely from the
2676 workspace.)
2679 # yesno sets answer
2680 yesno "Completely remove $filepath?"
2681 else
2682 # forced to yes
2683 answer='yes'
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'
2695 remove_new $filepath
2699 wx_mv() {
2700 # create some local variables to avoid side effects
2701 typeset efp old_filepath new_filepath
2703 cd $workspace
2705 old_filepath=$1
2706 new_filepath=$2
2708 if [[ -d $old_filepath && ( -d $new_filepath || ! -f $new_filepath ) ]]
2709 then
2711 if [[ $(basename $old_filepath) == "SCCS" ]]; then
2712 return
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=
2724 sccsmv $old_filepath $new_filepath ||
2725 fail "sccsmv $old_filepath $new_filepath failed."
2727 # remove previous renamed entry
2728 remove_renamed_entry $old_filepath
2730 update_renamed_dir $new_filepath/$base
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'
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."
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."
2758 wx_mv_file() {
2759 # store literal filepath in local var. to avoid side effects
2760 typeset efp old_filepath new_filepath
2762 cd $workspace
2764 old_filepath=$1
2765 new_filepath=$2
2767 if [[ ! -f $old_filepath ]]; then
2768 fail "Error! $old_filepath does not exist."
2770 elif [[ -f $new_filepath ]]; then
2771 fail "Error! $new_filepath already exists."
2773 else
2774 if cyclic_rename $new_filepath $old_filepath; then
2775 fail "Cyclic renamed detected. See 'man workspace'"\
2776 "for more info."
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
2787 if grep -q "^$efp$" $wxdir/new; then
2788 remove_new $old_filepath
2789 add_new $new_filepath
2791 if grep -q "^$efp " $wsdata/nametable 2>/dev/null; then
2792 NEED_WS_CLEAN=y
2794 else
2795 echo "There was an error renaming $old_filepath to "\
2796 "$new_filepath"
2801 sccs_rmdel_done() {
2802 # Note there are literal tabs in the []'s below so be careful when
2803 # editing.
2805 # file not in SCCS so return false (1)
2806 [[ ! -f SCCS/s.$file ]] && return 1
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"
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
2838 rmdelchk() {
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
2845 Warning, it looks like 'sccs rmdel' was run on $filepath
2846 This will cause a problem for Teamware. Please fix this.
2847 Note, this can be fixed by doing '$ME reedit $filepath'
2849 return 0
2850 else
2851 return 1
2855 wx_delget() {
2856 typeset -i force=0
2857 typeset arg comment_found=false
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
2867 if [[ (! -f SCCS/s.$file && ! -f SCCS/p.$file) ||
2868 (-f SCCS/s.$file && -f SCCS/p.$file) ]]; then
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
2877 ring_bell
2878 cat <<-EOF
2880 The keywords check has detected a problem with $filepath
2881 If this check should be skipped for this file, put the filepath in
2882 ${wxdir}/keywords.NOT.
2883 See /net/wizard.eng/export/misc/general_docs/keyword_info.txt
2884 for more info about keywords. Note, pay attention to the tabs.
2887 yesno "Continue with $command for $filepath?"
2888 if [[ "$answer" != 'yes' ]]; then
2889 echo "Aborting $command $filepath\n"
2890 return
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
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
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."
2931 else
2932 fail "Edit $wxdir/active and try again."
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 ."
2942 wx_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"
2951 wx_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.)"
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)"
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
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."
2986 else
2987 echo "New file (does not exist in parent ws)."
2989 echo
2992 get_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"
3000 wx_reedit() {
3001 typeset -i numkids=`workspace children | wc -l`
3002 typeset i newfiles only_multideltas=false
3004 case $1 in
3005 -m) only_multideltas=true;;
3006 -*) fail "Invalid flag $1. See 'wx help' for more"\
3007 "info.";;
3008 esac
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."
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
3024 cd $workspace
3026 for i in $file_list; do
3027 if [[ ! -f $i ]]; then
3028 fail "$i does not exist."
3030 if ! lookup_parent $i; then
3031 if [[ -z $newfiles ]]; then
3032 newfiles="$i"
3033 else
3034 newfiles="$newfiles\n$i"
3037 done
3039 if [[ -n $newfiles ]]; then
3040 # If there are some new files, give user a warning
3041 cat <<-EOF | ${PAGER:-more}
3043 $ME thinks following files are new (not in parent workspace) and will
3044 reset their file histories to version 1.1 (exit if this list isn't correct):
3045 $(echo $newfiles)
3048 ok_to_proceed "Okay to continue with $command?"
3049 if ! $CHECKIN; then
3050 cat <<-EOF
3052 Hint, use '$ME redelget' to collapse/reset new file histories to version
3053 1.1 since '$ME $command' will check out the file and '$ME delget' always
3054 increments the file version doing the check in.
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?'
3069 echo
3070 yesno "Do you want to backup files first?"
3071 if [[ "$answer" == 'yes' ]]; then
3072 wx_backup || fail "Backup failed."
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
3084 wx_reedit_file() {
3085 # Must be called via wx_eval
3086 typeset comment_found=false
3088 if [[ ! -f $file ]]; then
3089 echo "$file does not exist. Can not reedit $file"
3090 return
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 ."
3100 # get the latest parent delta and comment and filter out
3101 # certain fields removing trailing spaces
3103 p_delta="$(sccs prt -y $parentsdot|expand -1|grep 'SCCS'|\
3104 cut -f'4,5,6,9-' -d' '|sed 's/ *$//')"
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
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;
3123 delta=sprintf("%s %s %s %s ",$3, $4, $5, $8);
3124 comment = "";
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 = " ";
3136 } else {
3137 if (NF > 0) {
3138 comment = comment " " $0;
3139 } else {
3140 comment = comment " ";
3144 END {
3145 if (delta != "") {
3146 # print last delta info
3147 print delta comment;
3149 }' | sed 's/ *$//' > $wxtmp/l_deltas ||
3150 fail "Error: cannot create $wxtmp/l_deltas."
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
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."
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."
3180 if sccs edit $silent $file; then
3181 update_active $filepath
3182 else
3183 fail "sccs edit $file failed."
3186 mv -f ${file}.wx_reedit $file ||
3187 fail "mv -f ${file}.wx_reedit $file failed."
3189 if $CHECKIN; then
3190 wx_delget
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."
3201 # clean up SCCS since we are going to create again.
3202 rm -f SCCS/s.$file
3204 # clean up SCCS since we are going to create again.
3205 [[ -f SCCS/p.$file ]] && rm -f SCCS/p.$file
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."
3230 else
3231 fail "Edit $wxdir/active and try again."
3235 if $CHECKIN; then
3236 # No need to check out file.
3237 return
3240 if sccs edit $silent $file; then
3241 update_active $filepath
3242 add_new $filepath
3243 else
3244 fail "sccs edit $file failed."
3250 # Warn if there are sccs delta issues
3252 deltachk() {
3253 # must be run via wx_eval
3254 typeset -i numdeltas
3255 typeset newfile checkedout=false
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 '^\x01d D' SCCS/s.$file|wc -l) - \
3262 $(grep '^\x01d 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 '^\x01d D' SCCS/s.$file|wc -l)
3268 newfile=true
3271 if [[ -z $numdeltas ]]; then
3272 cat <<-EOF
3274 Warning: the local file:
3275 $filepath
3276 does not appear to have a sccs delta history file or the sccs delta
3277 history file is corrupt. If the local file is new try using:
3278 "cd $dir"
3279 "$ME create $file"
3281 If the file is not new (exists in parent):
3282 "cd $dir"
3283 Save a copy of the local file
3284 Remove the SCCS/[ps].$file history files
3285 "bringover $filepath"
3286 "$ME edit $file"
3287 Then carefuly merge the saved copy of local file with the
3288 file brought over from parent. Hint: twmerge is a good merge
3289 tool.
3291 return 1
3294 [[ -f SCCS/p.$file ]] && checkedout=true
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
3307 Warning: the local file:
3308 $filepath
3309 and the parent file:
3310 $parentfilepath
3311 content are identical. There are no new deltas in the local file.
3312 If this file is no longer required in the active list use:
3313 "cd $dir"
3314 "$ME reset $file"
3315 to remove file from the wx state files (active list, etc...)
3317 else
3318 cat <<-EOF
3320 Warning: the local file:
3321 $filepath
3322 and the parent file:
3323 $parentfilepath
3324 have the same number of deltas but contents differ. A bringover may be
3325 required before putback.
3328 else
3329 cat <<-EOF
3331 Warning: the local file:
3332 $filepath
3333 is new but doesn't appear to contain any deltas. The SCCS delta history file
3334 may need to be recreated. If so:
3335 "cd $dir"
3336 "rm SCCS/s.$file"
3337 "$ME create $file"
3340 return 1
3341 fi ;;
3343 1) if $checkedout; then
3344 cat <<-EOF
3346 Regarding $filepath
3347 Warning! 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
3349 the deltas and check in with 1 delta unless putting back > 1 bug.
3351 return 1
3352 else
3353 return 0
3354 fi ;;
3356 -*) # a negative number means the parent has more deltas
3358 cat <<-EOF
3360 Regarding $filepath
3361 Warning! The parent file has more deltas than the local file.
3362 You should bringover the local file to fix this.
3366 *) if $newfile && $checkedout; then
3367 cat <<-EOF
3369 Regarding $filepath
3370 Warning! 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
3372 the deltas and check in with 1 delta unless putting back > 1 bug.
3374 else
3375 cat <<-EOF
3377 Regarding $filepath
3378 Warning! There is more than 1 delta. Run:
3379 'cd $dir; $ME redelget $file'
3380 to collapse the deltas on this file and check in with 1 delta unless
3381 putting back > 1 bug.
3384 return 1;;
3385 esac
3388 wx_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) &
3399 wx_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) &
3410 wx_find_compression_progs() {
3411 gzip=/usr/bin/gzip
3412 if [[ ! -x $gzip && -n "$GZIPBIN" ]]; then
3413 gzip=$GZIPBIN
3416 bzip2=/usr/bin/bzip2
3417 if [[ ! -x $bzip2 && -n "$BZIP2BIN" ]]; then
3418 bzip2=$BZIP2BIN
3422 wx_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"
3432 backup_dir=`cat $backup_dir_file`
3434 if [[ ! ( -d $backup_dir && -x $backup_dir && -r $backup_dir ) ]]; then
3435 fail "$backup_dir: missing, not a directory, or bad permissions"
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)
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.
3449 # Takes one argument, the version number.
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
3459 wx_check_backup() {
3460 typeset _new _b_new _renamed _b_renamed _active _b_active \
3461 _local_nt _b_local_nt found bad
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
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
3487 set -A _comps "" "$gzip" "$bzip2"
3488 set -A _extns "" ".gz" ".bz2"
3489 _count=3
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
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
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
3524 idx=`expr $idx + 1`
3525 done
3527 if [[ ! -f $_b_renamed && -f $_b_active ]]; then
3528 # Can determine compression only
3529 return 1
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
3539 $bad && return 2
3540 $found || return 1
3542 b_renamed=$_b_renamed
3543 b_new=$_b_new
3544 b_active=$_b_active
3545 b_local_nt=$_b_local_nt
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=
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=
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=
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=
3574 return 0
3578 # finds the number of the last backup.
3580 # Returned in $result, which is -1 if no backups are found
3582 wx_find_last_backup() {
3584 # The list of extensions in the egrep expression must be in sync
3585 # with wx_check_backup's arrays
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`
3591 [[ -n "$result" ]] # fail if result is empty
3595 # wx_do_backup
3596 # Returns 0 on successful backup, 1 if nothing to backup, 2 any other
3597 # error.
3600 wx_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")
3607 echo
3608 echo "Saving $_type files to $_out"
3609 echo
3611 if [[ -z $backupfiles ]]; then
3612 echo "Note, nothing to backup."
3613 return 1
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
3624 [[ -f "$_out" ]] || return 2 # $_out is removed on any error
3626 return 0
3629 wx_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
3637 if [[ -n "$_comp" ]]; then
3639 # if decompression fails, echo a bad value to make tar fail
3641 ($_comp -dc < $_in || echo "fail") | tar xvpf - || return 1
3642 else
3643 tar xvpf $_in || return 1
3645 return 0
3649 # do renames in a workspace from a backup set
3652 wx_do_renames() {
3653 typeset _in=$1 # file to read from
3655 if [[ ! -f $wsdata/nametable ]]; then
3656 echo "$wsdata/nametable not found, not doing renames."
3657 return 0
3660 echo
3661 echo "Restoring renamed files from $_in"
3662 echo
3664 # Note this assumes we're staring in $workspace
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' ')
3671 if [[ -z $current ]]; then
3672 # nothing to rename
3673 continue
3676 if [[ "$new" == "$current" ]]; then
3677 # rename not needed
3678 continue
3681 if [[ ! -f $new ]]; then
3682 if [[ ! -d $(dirname $new) ]]; then
3683 mkdir -p $(dirname $new) ||
3684 fail "Error: cannot create dir $(dirname $new)"
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
3693 Warning: $current
3694 and $new
3695 files both exist in current workspace with the
3696 same hash. The restored renamed list should be recreated by running:
3697 '$ME update -r'
3698 Skipping rename of $current
3699 to $new
3704 done < $_in
3706 return 0
3709 wx_backup() {
3710 typeset orig_file_list ws_file back_file
3711 typeset newer=false
3712 typeset origdir=$PWD
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
3731 # we always backup the active files.
3732 file_list=$(wx_active)
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
3740 # must be in workspace to do backup
3741 cd $workspace || fail "Error: cannot cd $workspace"
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
3764 wx_find_compression_progs
3765 wx_get_backup_dir
3767 if [[ ! -w $backup_dir ]]; then
3768 fail "$backup_dir: not writable"
3771 if wx_find_last_backup; then
3772 prev_backup=$result
3773 version=`expr $result + 1`
3774 else
3775 prev_backup=
3776 version=0
3780 # This must be in sync with wx_check_backup's arrays
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
3792 if [[ -z "$1" ]]; then
3794 # default to the compression of the previous backup
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?"
3813 if [[ $answer == "no" ]]; then
3814 echo "No backup done."
3815 file_list=$orig_file_list
3816 cd $origdir
3817 return
3819 ext=
3820 comp=
3825 if [[ -n "$comp" && ! -x "$comp" ]]; then
3826 echo "${comp}: missing. defaulting to no compression"
3827 ext=
3828 comp=
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
3842 # If anything goes wrong, clean up after ourselves
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
3846 fail_msg='failed. Cleaning up. '
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.
3852 sdot_cmd='
3853 _sdot="SCCS/s.$file";
3854 _file="$dir/$_sdot";
3855 if [[ -f $_sdot ]]; then
3856 echo "$_file";
3857 else
3858 echo "$_file: not found" >&2;
3861 pdot_cmd='
3862 _pdot="SCCS/p.$file";
3863 _sdot="SCCS/s.$file";
3864 _file="$dir/$_pdot";
3865 if [[ -f $_pdot ]]; then
3866 echo "$_file";
3867 elif [[ ! -f $_sdot ]]; then
3868 echo "$_file: not checked in" >&2;
3869 elif [[ -w $file ]]; then
3870 echo "$_file: not found but $file is writable!" >&2;
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"
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"
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"
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"
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"
3906 wx_do_backup 'sdot' $b_sdot "$comp" "$sdot_cmd" ||
3907 fail "$b_sdot: $fail_msg"
3909 echo
3910 echo "Saving new list to $b_new"
3911 echo
3912 cp $wxdir/new $b_new || fail "$b_new: $fail_msg"
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)"
3924 echo
3925 echo "Saving active file list to $b_active"
3926 echo
3927 cp $wxdir/active $b_active || fail "$b_active: $fail_msg"
3929 trap - 0 1 2 3 15
3931 rm -f $BACKUP_ERRORS
3933 # restore file_list state.
3934 file_list=$orig_file_list
3936 cd $origdir
3937 return 0
3940 wx_restore() {
3941 typeset force=0
3943 case $1 in
3944 -f) force=1;;
3945 -*) fail "Invalid flag $1. See 'wx help' for more info.";;
3946 esac
3948 if [[ $force -eq 0 ]]; then
3949 cat <<-EOF
3951 Warning, the restore command will overwrite several files including the
3952 active and renamed lists. This could be a problem if you have made
3953 changes to your workspace and $ME related files following the last
3954 backup. It may be a good idea to run:
3956 $ME update
3958 after the restore so that the active and renamed lists are updated with
3959 the new changes in the workspace.
3961 Also, restore may perform workspace renames in this workspace if it
3962 finds that the existing file has a pathname that differs from that in
3963 the backup being restored.
3966 ok_to_proceed "Do you really want to do the restore?"
3969 wx_find_compression_progs
3970 wx_get_backup_dir
3972 if wx_find_last_backup; then
3973 version=$result
3974 else
3975 fail "$backup_dir: no backups found"
3978 if [[ $force -eq 0 ]]; then
3979 ask 'Version to restore from' $version
3980 version=$answer
3984 # wx_check_backup sets $comp, $b_clear, and $b_sdot when successful
3986 if wx_check_backup $version; then
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"
3997 b_active=$backup_dir/$version.active
3999 if [[ -n "$comp" && ! -x "$comp" ]]; then
4000 fail "${comp}: missing -- cannot decompress $b_clear"
4003 # must be in workspace to do restore
4004 cd $workspace || fail "Error: cannot cd $workspace"
4006 [[ -f $b_renamed ]] || fail "$b_renamed: missing"
4007 [[ -f $b_new ]] || fail "$b_new: missing"
4008 [[ -f $b_active ]] || fail "$b_active: missing"
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"
4014 if [[ -f $b_clear ]]; then
4015 [[ -r $b_clear ]] || fail "$b_clear: not readable"
4017 if [[ -f $b_sdot ]]; then
4018 [[ -r $b_sdot ]] || fail "$b_sdot: not readable"
4020 if [[ -f $b_pdot ]]; then
4021 [[ -r $b_pdot ]] || fail "$b_pdot: not readable"
4023 if [[ -f $b_local_nt ]]; then
4024 [[ -r $b_local_nt ]] || fail "$b_local_nt: not readable"
4026 if [[ -f $b_not_files ]]; then
4027 [[ -r $b_not_files ]] || fail "$b_not_files: not readable"
4029 if [[ -f $b_sort ]]; then
4030 [[ -r $b_sort ]] || fail "$b_sort: not readable"
4034 # If something goes wrong, we need to make sure they notice, so
4035 # we make the message quite visible, and echo a BELL.
4037 fail_msg='Extraction failed.
4039 *DANGER* *DANGER* workspace could be corrupted *DANGER* *DANGER*'
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"
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"
4057 if [[ -n $b_not_files ]]; then
4058 tar -xf $b_not_files || fail "$wx/*.NOT: $fail_msg"
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"
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"
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"
4076 # Do some integrity checking
4077 for filepath in $(wx_active); do
4078 if cd ${workspace}/$(dirname $filepath); then
4079 file=$(basename $filepath)
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.
4087 if [[ ! -w $file && -f SCCS/p.$file ]]; then
4088 ring_bell
4089 cat <<-EOF
4091 Warning! $filepath is in inconsistent state.
4092 $filepath is not writable and SCCS/p.$file exists.
4093 Removing SCCS/p.$file
4094 To edit the file run '$ME edit $filepath'
4096 rm -f SCCS/p.$file
4097 elif [[ -w $file && ! -f SCCS/p.$file ]]; then
4098 ring_bell
4099 cat <<-EOF
4101 Warning! $filepath is in inconsistent state.
4102 $filepath is writable
4103 but there is no SCCS/p.$file
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
4112 mv -f $wxtmp/$file $file
4114 else
4115 ask_remove_active_entry
4116 echo "Setting $filepath read only"
4117 chmod ugo-w $file
4120 else
4121 ring_bell
4122 echo "\nWarning! Could not check sccs state of "\
4123 "$filepath"
4125 done
4128 wx_fullreview() {
4129 if wx_pnt_filepath; then
4131 else
4132 parentfilepath=/dev/null
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
4143 # Check on RTI status for bug ID's found in active list comments.
4146 wx_rtichk() {
4147 # gate contains the gate dir, not full path
4148 typeset gate=${parent##*/}
4149 typeset -i rc=0
4150 typeset nolookup opt
4152 if [[ -f $wxdir/rtichk.NOT ]]; then
4153 print "\nSkipping RTI check:"
4154 return
4155 else
4156 print "\nDoing RTI check:"
4159 while getopts :N opt; do
4160 case $opt in
4161 N) nolookup='-N' ;;
4162 *) fail "Invalid flag -$OPTARG." ;;
4163 esac
4164 done
4166 # Note, rtichk needs a gate arg to correctly determine status.
4167 if [[ -z $gate ]]; then
4168 cat >&2 <<-EOF
4169 Warning: cannot find a parent gate, skipping RTI checking.
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=$?
4179 if [[ -s $wxtmp/bugwarnings ]]; then
4180 cat <<-EOF
4182 There are issues with the bug ID format in the
4183 $wxdir/active file.
4184 Please fix the following and run rtichk again:
4187 cat $wxtmp/bugwarnings
4188 ((rc = 1))
4190 if [[ ${#bugs} -eq 0 ]]; then
4191 print "\nWarning: no bug ID's in active list."
4193 return $rc
4197 # Do a Teamware putback of active and renamed files.
4199 wx_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
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)
4215 while getopts :fnp:qvN i; do
4216 case $i in
4217 # Force the putback (no user interaction)
4218 f) force=true;;
4220 n) narg=true
4221 pbargs[${#pbargs[@]}]="-$i" ;;
4223 q) pbargs[${#pbargs[@]}]="-$i" ;;
4225 p) pbargs[${#pbargs[@]}]="-$i"
4226 pbargs[${#pbargs[@]}]="$OPTARG"
4227 # setting parent for user prompt below
4228 parent="$OPTARG" ;;
4230 # -v doesn't get passed to putback.
4231 v) verbatim='-v';;
4233 N) nolookup='-N';;
4235 *) fail "Invalid flag -$OPTARG. See 'wx help'"\
4236 "for more info.";;
4237 esac
4238 done
4240 if ! $narg; then
4241 # real putback
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."
4250 if ! $force; then
4251 # not force so give more warning.
4252 ( # using subshell to capture stdout to file.
4253 cat <<-EOF
4254 Remember to run '$ME pbchk' before doing a final putback (esp. if
4255 doing a putback to an official ON gate). Make sure your workspace
4256 parent ($parent) is correct.
4257 It's a good idea to check your code diffs before putback ('$ME pdiffs').
4259 Also, run '$ME $command -n' and check for conflicts before doing the
4260 final putback.
4263 if [[ -z "$(wx_summary -bo 2>/dev/null)" ]]; then
4264 cat <<-EOF
4266 Don't forget the ARC ID info in your active list comments if there is an
4267 ARC case associated with your putback.
4271 echo "\nThe putback comment will be:"
4272 cat $wxtmp/pb_comments
4273 print "========== End of putback comments ======="
4275 # Output warning if RTI isn't approved.
4276 wx_rtichk $nolookup
4277 print "========== End of RTI check output ======="
4279 cat <<-EOF
4281 The following files will be used for putback:
4282 $pbfiles
4285 ) | ${PAGER:-more}
4287 ok_to_proceed "Do you really want to"\
4288 "'$PUTBACK ${pbargs[@]}' to $parent?"
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
4302 return
4305 outchk() {
4307 # List files that are checked out but not in active list.
4308 typeset outfile do_header=true
4310 wx_checked_out >/dev/null
4311 # if $wxtmp/checked_out is 0 bytes then return
4312 [[ -s $wxtmp/checked_out ]] || return
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
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
4329 Warning, the following files are checked out but not in active list
4330 (Run "$ME update -q" to add them to the active list):
4332 do_header=false
4334 echo "$outfile"
4335 done
4336 rm -f $wxtmp/co_sort $wxtmp/active_sort
4340 # run Teamware resolve and do reedit only on merged files.
4342 wx_resolve() {
4343 typeset merged_file
4345 # clear the file_list, will be set below
4346 file_list=
4348 grep -v '^VERSION ' $wsdata/conflicts > $wxtmp/conflicts
4349 [[ ! -f $wxtmp/conflicts ]] && fail "Error: cannot create $wxtmp/conflicts"
4351 # run Teamware resolve
4352 resolve $* || fail "Teamware resolve failed."
4354 # resolve will remove files from $wsdata/conflicts when
4355 # successfully merged.
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"
4364 done
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."
4379 #########################################################################
4381 # Main
4385 # Do some initial sanity checking and set up.
4388 # Set the lang to standard English so wx doesn't get confused.
4389 export LC_ALL=C
4391 # Turn on debugging output early
4392 if [[ "$*" == *' -D'*( *) ]]; then
4393 typeset -ft $(typeset +f)
4394 set -x
4397 ME=$(basename $0)
4398 export ME
4400 if [[ -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
4403 else
4404 fail "Error: directory /usr/xpg4/bin not found."
4407 unset CDPATH # if set "cd" will print the new directory on stdout
4408 # which screws up wx_eval.
4410 DEFAULT_SRCDIR=usr
4412 if [[ $# -eq 0 || "$1" == help ]]; then
4413 # output usage now to avoid unnecessary checking below.
4414 wx_usage
4417 if [[ "$1" == version ]]; then
4418 # output version now to avoid unnecessary checking below.
4419 version
4420 exit 0
4424 # Check to make sure we're not being run from within a Mercurial repo
4426 if 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"
4431 whence workspace >/dev/null || fail "Error: cannot find workspace command in \$PATH."
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.
4435 PUTBACK=${PUTBACK:='putback'}
4436 BRINGOVER=${BRINGOVER:='bringover'}
4438 dot=$PWD
4440 if [[ -n "$CODEMGR_WS" ]]; then
4441 # ws was used.
4442 # normalize the workspace name.
4443 workspace=$(cd $CODEMGR_WS && workspace name)
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
4451 Warning, $ME will use $ME files in workspace $workspace (the current
4452 directory is not in this workspace).
4454 ok_to_proceed "Okay to proceed?"
4457 else
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
4467 if [[ -z "$workspace" ]]; then
4468 fail "No active workspace, run \"ws <workspace>\" or"\
4469 "\"cd <workspace>\"."
4472 workspace_basename=`basename $workspace`
4473 wxdir=${WXDIR:-$workspace/wx}
4474 wxtmp=$wxdir/tmp
4475 wsdata=$workspace/Codemgr_wsdata
4476 node=`uname -n`
4478 if [ -f $wsdata/parent ]; then
4479 parent=`tail -1 $wsdata/parent`
4480 else
4481 parent=
4483 if [[ $parent == *:* ]]; then
4484 parentdir=${parent#*:}
4485 parentnode=${parent%%:*}
4486 if [[ $parentnode == $node ]]; then
4487 parent=$parentdir
4488 else
4489 parent=/net/$parentnode$parentdir
4493 # Store backup state
4494 backup_done=0
4496 # store state if new files are deleted
4497 NEED_WS_CLEAN='n'
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.
4502 SCCSKEYWORD=$(echo "ident\t+\"(\%Z\%\%M\%\t+\%I\%|\%W\%)\t+\%E\% SMI\"")
4504 # file that contains comments for use in create and checkin
4505 comment_file=
4506 # mode for updating comments in active list
4507 comment_mode="replace"
4509 CSTYLE_FLAGS=${CSTYLE_FLAGS:='-P -p -c'}
4510 JSTYLE_FLAGS=${JSTYLE_FLAGS:='-p'}
4512 BACKUP_ERRORS=/tmp/${ME}_berrors_$(/usr/xpg4/bin/id -un)_$$
4514 # global for reedit command, don't checkin by default
4515 CHECKIN=false
4517 # Indicates that the parent nametable cache needs refreshing
4518 need_pnt_refresh=true
4520 # Indicate whether file args were specified
4521 FILES_PASSED=false
4523 # Used to store files that have more than one delta compared to parent
4524 multi_delta_list=
4526 # Used to bringover any files just before exit of wx
4527 bofilelist=
4529 # should codereviews include delta comments?
4530 show_comments=true
4532 # Determines if active list should be sorted by default
4533 # If sort_active contains true then we sort the active list on updates.
4534 if [[ -r $wxdir/sort_active && "$(cat $wxdir/sort_active)" == "true" ]]; then
4535 ACTSORT=sort
4536 else
4537 ACTSORT=cat
4540 # These are set depending on what needs sorting
4541 do_renamed_sort=false
4542 do_active_sort=false
4544 # Places to search for approved RTIs
4545 RTIDIRS="/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"
4550 # Places to search for approved Patch RTIs
4551 PRTIDIRS="/net/wizard.eng/export/consolidation/rtiroute/newprtis
4552 /net/wizard.eng/export/consolidation/rtiroute/oldprtis"
4554 export workspace parent wxdir file dir filepath backup_done DEFAULT_SRCDIR
4557 # main section
4560 # Get wx command
4561 command=$1
4562 comlist=$command
4563 shift
4564 # throw away -D flag after command assigned as this flag was processed earlier
4565 [[ "$1" == '-D' ]] && shift
4567 case $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";;
4574 esac
4576 orig_args="$@"
4577 silent=
4578 args=
4579 file_list=
4580 typeset tmp_file_list tmp_args
4583 # Some subcommands pass through all arguments.
4585 case $command in
4586 webrev) args="$orig_args"; shift $#;;
4587 esac
4589 # Parse args
4590 while [ $# -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"
4600 if [[ -z "$comment_file" ]]; then
4601 fail "Missing comment file."\
4602 "Run 'wx help' for info."
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
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."
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
4667 done
4669 if [[ "$command" == "init" ]]; then
4670 if [ -z "$file_list" ]; then
4671 file_list=$DEFAULT_SRCDIR
4673 wx_init $file_list $args
4674 exit
4677 if [ ! -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?'
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
4699 if [[ ! -f $wxdir/local_nametable ]]; then
4700 touch $wxdir/local_nametable
4703 # Doing this for backward compat since old wx doesn't have a renamed list
4704 if [[ ! -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
4711 $ME needs to create a renamed file list. If you are sure that no files
4712 were renamed or deleted in the current workspace then answer no to the
4713 following question.
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
4726 # Doing this for backward compat since old wx doesn't have a new list
4727 if [[ ! -f $wxdir/new ]]; then
4728 ring_bell
4729 cat <<-EOF
4731 $ME needs to create a new-file list (cache names of newly created
4732 files). Please be patient.
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
4741 done
4742 echo "\nNew files:"
4743 cat $wxdir/new
4744 echo
4747 if [[ "$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' ')
4752 # unset file_list since this file arg has been processed here.
4753 unset file_list
4754 elif [[ "$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
4759 elif [[ "$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?'
4765 cp $wxdir/active $wxdir/active.old
4766 elif [[ "$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."
4771 elif [[ "$command" == "create" ]]; then
4772 if [ -z "$file_list" ]; then
4773 fail "$command missing file arg(s). Run 'wx help' for info."
4776 cp $wxdir/active $wxdir/active.old ||
4777 fail "Error could not backup $wxdir/active"
4778 elif [[ "$command" == @(delget|checkin|ci) && -n "$comment_file" ]]; then
4779 cp $wxdir/active $wxdir/active.old ||
4780 fail "Error could not backup $wxdir/active"
4781 elif [[ "$command" == @(mv) ]]; then
4782 if [[ $(echo "$file_list"|wc -w) -ne 2 ]]; then
4783 fail "$command requires two args. Run 'wx help' for info."
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"
4790 elif [[ "$command" == @(delete|rm) ]]; then
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?'
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"
4802 elif [[ "$command" == reset ]]; then
4803 cp $wsdata/nametable $wxtmp/nametable.orig || \
4804 fail "Error: cp $wsdata/nametable $wxtmp/nametable.orig failed."
4807 if [ -z "$file_list" ]; then
4808 basedir=$workspace
4809 file_list=$(wx_active) || fail
4810 else
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)
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."
4828 filepath=${abspath##$workspace/}
4829 if [[ -z "$file_list" ]]; then
4830 file_list="$filepath"
4831 else
4832 file_list="$file_list $filepath"
4834 done
4835 FILES_PASSED=true
4838 if [[ "$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"
4851 done
4852 file_list=${tmp_list# }
4854 [[ -z $file_list ]] && exit 0
4857 # This is where the commands are executed.
4858 for command in $comlist; do
4859 cd $dot
4860 case $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
4875 new_files="${new_files}${new_file} "
4876 done < $wxdir/new
4877 else
4878 new_files=""
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
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
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"
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;;
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"
4980 done
4981 keywords -p $args $keyword_files;;
4983 rmdelchk) echo "\nDoing sccs rmdel check:"; wx_eval rmdelchk;;
4985 rtichk) wx_rtichk;;
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"
5000 done
5001 copyrightchk $copyright_files;;
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"
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.
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"
5026 done
5027 [[ ! -z $new ]] && cddlchk $cddlnot $args -a $new
5028 [[ ! -z $old ]] && cddlchk $cddlnot $args $old
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;;
5056 esac
5058 done
5060 if [[ $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
5067 if [[ -n $bofilelist ]]; then
5068 $BRINGOVER $bofilelist
5071 # save sorting for last for some speed up.
5072 if [[ $ACTSORT == sort ]]; then
5073 if $do_renamed_sort; then
5074 sort_renamed
5076 if $do_active_sort; then
5077 sort_active