diff options
author | mjnelson <none@none> | 2008-07-10 19:11:48 -0700 |
---|---|---|
committer | mjnelson <none@none> | 2008-07-10 19:11:48 -0700 |
commit | cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0 (patch) | |
tree | c1b10cec006b1a248eca473c6dddc63d5c720208 /usr/src | |
parent | 84db2a68825c1a672f664432101f6f0b443679e3 (diff) | |
download | illumos-gate-cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0.tar.gz |
6538468 add Mercurial support to ON developer tools
6658967 /etc/publickey entries get removed on upgrade
Portions of 6538468 contributed by Rich Lowe.
Portions of 6538468 contributed by Mike Gerdts.
--HG--
rename : usr/src/pkgdefs/common_files/i.confupdate => deleted_files/usr/src/pkgdefs/common_files/i.confupdate
rename : usr/src/pkgdefs/common_files/i.pcicconf => deleted_files/usr/src/pkgdefs/common_files/i.pcicconf
rename : usr/src/tools/scripts/cddlchk.pl => deleted_files/usr/src/tools/scripts/cddlchk.pl
rename : usr/src/tools/scripts/hdrchk.pl => deleted_files/usr/src/tools/scripts/hdrchk.pl
rename : usr/src/tools/findunref/exception_list => usr/src/tools/findunref/exception_list.open
Diffstat (limited to 'usr/src')
101 files changed, 8488 insertions, 2303 deletions
diff --git a/usr/src/Makefile.master b/usr/src/Makefile.master index f230b99d16..c05542ecf1 100644 --- a/usr/src/Makefile.master +++ b/usr/src/Makefile.master @@ -177,6 +177,7 @@ CTFFINDMOD= $(ONBLD_TOOLS)/bin/ctffindmod XREF= $(ONBLD_TOOLS)/bin/xref FIND= /usr/bin/find PERL= /usr/bin/perl +PYTHON= /usr/bin/python SORT= /usr/bin/sort TOUCH= /usr/bin/touch WC= /usr/bin/wc @@ -209,11 +210,11 @@ $(PATCH_BUILD)PMTMO_FILE=$(SRC)/patch_makeup_table.mo # Note that the X and C checks are not used at this time and may need # modification when they are actually used. # -CSTYLE= cstyle +CSTYLE= $(ONBLD_TOOLS)/bin/cstyle CSTYLE_TAIL= -HDRCHK= hdrchk +HDRCHK= $(ONBLD_TOOLS)/bin/hdrchk HDRCHK_TAIL= -JSTYLE= jstyle +JSTYLE= $(ONBLD_TOOLS)/bin/jstyle DOT_H_CHECK= \ @$(ECHO) "checking $<"; $(CSTYLE) $< $(CSTYLE_TAIL); \ @@ -240,6 +241,14 @@ INS.rename= $(INS.file); $(MV) $(@D)/$(<F) $@ # install a link INSLINKTARGET= $< INS.link= $(RM) $@; $(LN) $(INSLINKTARGET) $@ +# +# Python bakes the mtime of the .py file into the compiled .pyc and +# rebuilds if the baked-in mtime != the mtime of the source file +# (rather than only if it's less than), thus when installing python +# files we must make certain to not adjust the mtime of the source +# (.py) file. +# +INS.pyfile= $(INS.file); $(TOUCH) -r $< $@ # MACH must be set in the shell environment per uname -p on the build host # More specific architecture variables should be set in lower makefiles. @@ -998,7 +1007,7 @@ PKGARCHIVE=$(SRC)/../../packages/$(MACH)/nightly$(PKGARCHIVESUFFIX) # Note that Python i18n isn't supported by this rule set yet, # as it requires a special build tool (pygettext.py). # -.SUFFIXES: .pl .pm .py +.SUFFIXES: .pl .pm .py .pyc .pl: $(RM) $@; @@ -1008,6 +1017,11 @@ PKGARCHIVE=$(SRC)/../../packages/$(MACH)/nightly$(PKGARCHIVESUFFIX) .py: $(RM) $@; $(CAT) $< > $@; $(CHMOD) +x $@ +.py.pyc: + $(RM) $@ + $(PYTHON) -mpy_compile $< + @[ $(<)c = $@ ] || $(MV) $(<)c $@ + .pl.po .pm.po: $(XGETTEXT) $(XGETFLAGS) -d $(<F) $< ; $(RM) $@ ; diff --git a/usr/src/pkgdefs/SUNWpcmci/Makefile b/usr/src/pkgdefs/SUNWpcmci/Makefile index e854503ac5..6cf6a1e4ca 100644 --- a/usr/src/pkgdefs/SUNWpcmci/Makefile +++ b/usr/src/pkgdefs/SUNWpcmci/Makefile @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 1994, 1997, 2002 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -28,7 +27,7 @@ include ../Makefile.com -DATAFILES += depend i.preserve i.pcicconf i.initd +DATAFILES += depend i.initd CHKINSTALLSRC=checkinstall.initd .KEEP_STATE: diff --git a/usr/src/pkgdefs/SUNWpcmci/pkginfo.tmpl b/usr/src/pkgdefs/SUNWpcmci/pkginfo.tmpl index afa2d9c96b..da672e6bac 100644 --- a/usr/src/pkgdefs/SUNWpcmci/pkginfo.tmpl +++ b/usr/src/pkgdefs/SUNWpcmci/pkginfo.tmpl @@ -20,7 +20,7 @@ # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -44,7 +44,7 @@ DESC="kernel modules and start-up files for PCMCIA card services" VENDOR="Sun Microsystems, Inc." HOTLINE="Please contact your local service provider" EMAIL="" -CLASSES="none preserve initd pcicconf" +CLASSES="none initd" BASEDIR=/ SUNW_PKGVERS="1.0" SUNW_PKG_ALLZONES="true" diff --git a/usr/src/pkgdefs/SUNWpcmci/prototype_i386 b/usr/src/pkgdefs/SUNWpcmci/prototype_i386 index 6ccf25b071..ae965c3a52 100644 --- a/usr/src/pkgdefs/SUNWpcmci/prototype_i386 +++ b/usr/src/pkgdefs/SUNWpcmci/prototype_i386 @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -44,8 +43,6 @@ # # List files which are i386 specific here # -i i.pcicconf -i i.preserve # # source locations relative to the prototype file # diff --git a/usr/src/pkgdefs/SUNWpcmci/prototype_sparc b/usr/src/pkgdefs/SUNWpcmci/prototype_sparc index 6425c56018..8ead5f465f 100644 --- a/usr/src/pkgdefs/SUNWpcmci/prototype_sparc +++ b/usr/src/pkgdefs/SUNWpcmci/prototype_sparc @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -21,7 +20,7 @@ # # ident "%Z%%M% %I% %E% SMI" # -# Copyright 1999,2001,2003 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # This required package information file contains a list of package contents. @@ -43,7 +42,6 @@ # # List files which are SPARC specific here # -i i.pcicconf # # source locations relative to the prototype file # diff --git a/usr/src/pkgdefs/SUNWpsdcr/Makefile b/usr/src/pkgdefs/SUNWpsdcr/Makefile index 083dd0b020..d331f6a51e 100644 --- a/usr/src/pkgdefs/SUNWpsdcr/Makefile +++ b/usr/src/pkgdefs/SUNWpsdcr/Makefile @@ -26,7 +26,7 @@ include ../Makefile.com -DATAFILES += i.preserve i.confupdate +DATAFILES += i.preserve LICENSEFILES += $(OSBL) .KEEP_STATE: diff --git a/usr/src/pkgdefs/SUNWpsdcr/pkginfo.tmpl b/usr/src/pkgdefs/SUNWpsdcr/pkginfo.tmpl index 81b99723ea..3f623226d2 100644 --- a/usr/src/pkgdefs/SUNWpsdcr/pkginfo.tmpl +++ b/usr/src/pkgdefs/SUNWpsdcr/pkginfo.tmpl @@ -20,7 +20,7 @@ # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -45,7 +45,7 @@ DESC="Platform Support, Bus-independent Device Drivers, (Root)" VENDOR="Sun Microsystems, Inc." HOTLINE="Please contact your local service provider" EMAIL="" -CLASSES="none preserve confupdate" +CLASSES="none preserve" BASEDIR=/ SUNW_PKG_ALLZONES="true" SUNW_PKG_HOLLOW="true" diff --git a/usr/src/pkgdefs/SUNWpsdcr/prototype_i386 b/usr/src/pkgdefs/SUNWpsdcr/prototype_i386 index 345b187edd..4b65d8b532 100644 --- a/usr/src/pkgdefs/SUNWpsdcr/prototype_i386 +++ b/usr/src/pkgdefs/SUNWpsdcr/prototype_i386 @@ -18,7 +18,7 @@ # # CDDL HEADER END # -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #pragma ident "%Z%%M% %I% %E% SMI" @@ -34,7 +34,6 @@ #!<param>=<value> # puts parameter in pkg environment i i.preserve -i i.confupdate # # List bus-independent (common) drivers here # diff --git a/usr/src/pkgdefs/SUNWrmodr/i.master b/usr/src/pkgdefs/SUNWrmodr/i.master index 75d136574f..26ed8172d4 100644 --- a/usr/src/pkgdefs/SUNWrmodr/i.master +++ b/usr/src/pkgdefs/SUNWrmodr/i.master @@ -33,13 +33,6 @@ # t=/tmp/mstr$$ -cannot_merge() -{ - echo "EXISTING_FILE_RENAMED: $dest $dest.prev" >> /tmp/CLEANUP - mv $dest $dest.prev - cp $src $dest -} - while read src dest do if [ ! -f $dest ] ; then @@ -47,37 +40,14 @@ do cp $src $dest else # - # If the installed version of the master file is too old - # we're going to just have to punt on merging, and use the - # install version. - # - existvers=`grep \#ident $dest | awk '{ print $3 }'` - exmaj=`echo $existvers | awk 'BEGIN {FS="."} {print $1}'` - exmin=`echo $existvers | awk 'BEGIN {FS="."} {print $2}'` - - majormatch=`expr $exmaj = "1"` - tooold=`expr $exmin \< "156"` - - if [ "$majormatch" != "1" ] - then - cannot_merge - continue - elif [ "$tooold" = "1" ] - then - cannot_merge - continue - fi - - # # Preserve the installed version of # /boot/solaris/devicedb/master during upgrade # - # Master file entries added after the release of - # Solaris 2.6 need to be duplicated here so that upgrade - # of an installed version of the master file include any - # changes while preserving any user applied changes. - # (Which would most likely come from third-party driver - # additions.) + # New master file entries need to be duplicated here so + # that upgrade of an installed version of the master file + # includes any changes while preserving any user applied + # changes, which would most likely come from third-party driver + # additions. # # @@ -620,16 +590,6 @@ PNP0FFF mouse ptr all none "Reserved by Microsoft Systems" SYN010B mouse ptr all none "Synaptics mouse pad" EOF - # - # Replace Copyright year and SCCS id if it seems appropriate - # - if grep '^#ident' $dest > /dev/null 2>&1 - then - sed -n -e '1,/^#ident/p' $src > $t - sed -e '1,/^#ident/d' $dest >> $t - cp $t $dest - fi - rm -f $t fi done diff --git a/usr/src/pkgdefs/common_files/i.confupdate b/usr/src/pkgdefs/common_files/i.confupdate deleted file mode 100644 index aa4317ec36..0000000000 --- a/usr/src/pkgdefs/common_files/i.confupdate +++ /dev/null @@ -1,85 +0,0 @@ -#!/bin/sh -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -#ident "%Z%%M% %I% %E% SMI" -# -# Copyright (c) 1996 by Sun Microsystems, Inc. -# All Rights Reserved. -# - -while read src dest -do - # - # First preserve any existing version, excepting the SCCS - # ident and copyright, which we'll take from the new version. - # - if [ ! -f $dest ] ; then - # no existing version, just copy in new one - cp $src $dest - else - # update the SCCS id and copyright line(s) - newident=`grep '^#ident[ ]*"@(#)' $src` - newcr=`grep '^#[ ]*Copyright (c)' $src` - newall=`grep '^#[ ]*All Rights Reserved' $src` - d=`basename $dest` - - while read line - do - case "$line" in - "#ident"*) - echo "$newident" - ;; - - "#pragma ident"*) - echo "$newident" - ;; - - "# Copyright"*) - echo "$newcr" - echo "$newall" - ;; - - "# All Rights"*) - ;; - - *) - echo "$line" - ;; - esac - done < $dest > /tmp/tmp.$d.$$ - mv /tmp/tmp.$d.$$ $dest - fi - - # Now add 'ignore-hardware-nodes' line if necessary - grep 'ignore-hardware-nodes' $dest > /dev/null - if [ $? -ne 0 ] ; then - cat >> $dest <<EOT - -# This is an old-style, non-conformant, driver.conf file. -# This file is not meant to be modified in the field. -ignore-hardware-nodes=1; - -EOT - fi -done -exit 0 diff --git a/usr/src/pkgdefs/common_files/i.cronroot b/usr/src/pkgdefs/common_files/i.cronroot index f87165ccdc..86651827e0 100644 --- a/usr/src/pkgdefs/common_files/i.cronroot +++ b/usr/src/pkgdefs/common_files/i.cronroot @@ -21,7 +21,7 @@ # #ident "%Z%%M% %I% %E% SMI" # -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. PATH="/usr/bin:/usr/sbin:${PATH}" @@ -44,11 +44,6 @@ do echo "$rtc" >> $dest fi else - grep '^#ident[ ]*\"@(#)root' $src \ - > /tmp/newident.$$ 2>/dev/null - grep -v '^#ident[ ]*\"@(#)root' $dest \ - > /tmp/rest.$$ 2>/dev/null - cat /tmp/newident.$$ /tmp/rest.$$ > $dest # # 2.1 version of this file had a trailing blank line. # Remove it. @@ -99,7 +94,6 @@ do fi fi -# rm -f /tmp/d.$$ /tmp/newident.$$ /tmp/rest.$$ # # take nptdate out of crontab. It was added in Beta 2.6. # Make sure it is gone evermore. diff --git a/usr/src/pkgdefs/common_files/i.devallocdefs b/usr/src/pkgdefs/common_files/i.devallocdefs index a776b0e360..4042087c4a 100644 --- a/usr/src/pkgdefs/common_files/i.devallocdefs +++ b/usr/src/pkgdefs/common_files/i.devallocdefs @@ -1,3 +1,4 @@ +#!/bin/sh # # CDDL HEADER START # @@ -18,11 +19,9 @@ # # CDDL HEADER END # -#!/bin/sh -# #ident "%Z%%M% %I% %E% SMI" # -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # class action script for devalloc_defaults installed by pkgadd @@ -56,17 +55,6 @@ sort_cmd=/usr/bin/sort # dbmerge() { # -# If the new file has an ident string, remove the ident string from the old -# file. -# - newident=`${egrep_cmd} '^#[pragma ]*ident' $2 \ - 2>/dev/null` - if [ -n "${newident}" ]; then - ${egrep_cmd} -v '^#[pragma ]*ident' $1 > $3.old 2>/dev/null - else - $cp_cmd $1 $3.old - fi -# # If the new file has a Sun copyright, remove the Sun copyright from the old # file. # @@ -76,8 +64,9 @@ dbmerge() { $sed_cmd -e '/^# Copyright.*Sun Microsystems, Inc./d' \ -e '/^# All rights reserved./d' \ -e '/^# Use is subject to license terms./d' \ - $3.old > $3.$$ 2>/dev/null - $mv_cmd $3.$$ $3.old + $1 > $3.old 2>/dev/null + else + $cp_cmd $1 $3.old fi # # Remove empty lines and multiple instances of these comments: diff --git a/usr/src/pkgdefs/common_files/i.devlinktab_i386 b/usr/src/pkgdefs/common_files/i.devlinktab_i386 index 3202d1eb1f..428a3669a3 100644 --- a/usr/src/pkgdefs/common_files/i.devlinktab_i386 +++ b/usr/src/pkgdefs/common_files/i.devlinktab_i386 @@ -3,9 +3,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -23,8 +22,8 @@ # #pragma ident "%Z%%M% %I% %E% SMI" # -# Copyright (c) 1998-2000 by Sun Microsystems, Inc. -# All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. # PATH="/usr/bin:/usr/sbin:${PATH}" @@ -35,13 +34,6 @@ do if [ ! -f $dest ] ; then cp $src $dest else - # update the SCCS id - grep '^#ident[ ]*"@(#)devlink.tab' $src \ - > /tmp/newident.$$ 2>/dev/null - egrep -v '^#(pragma ident|ident)[ ]*"@\(#\)devlink.tab' $dest \ - > /tmp/rest.$$ 2>/dev/null - cat /tmp/newident.$$ /tmp/rest.$$ > $dest - # begin updates sed -e '/^type=ddi_pseudo;name=app /d' \ -e '/^type=ddi_pseudo;name=sw /d' \ @@ -200,4 +192,3 @@ do done exit 0 - diff --git a/usr/src/pkgdefs/common_files/i.devlinktab_sparc b/usr/src/pkgdefs/common_files/i.devlinktab_sparc index 570a44481b..84802aa861 100644 --- a/usr/src/pkgdefs/common_files/i.devlinktab_sparc +++ b/usr/src/pkgdefs/common_files/i.devlinktab_sparc @@ -3,9 +3,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -23,7 +22,7 @@ # #ident "%Z%%M% %I% %E% SMI" # -# Copyright 1998-2002 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # @@ -35,11 +34,6 @@ do if [ ! -f $dest ] ; then cp $src $dest else - grep '^#ident[ ]*"@(#)devlink.tab' $src \ - > /tmp/newident.$$ 2>/dev/null - egrep -v '^#(pragma ident|ident)[ ]*"@\(#\)devlink.tab' $dest \ - > /tmp/rest.$$ 2>/dev/null - cat /tmp/newident.$$ /tmp/rest.$$ > $dest sed -e '/^type=ddi_pseudo;name=app /d' \ -e '/^type=ddi_pseudo;name=sw /d' \ -e '/^type=ddi_pseudo;name=consfb;minor=consfb /d' \ @@ -145,9 +139,8 @@ do -e '/^type=ddi_pseudo;name=se /d' \ -e 's,sys/obpdefs.h,<sys/sunddi.h>,' $dest > /tmp/d.$$ cp /tmp/d.$$ $dest - rm -f /tmp/d.$$ /tmp/newident.$$ /tmp/rest.$$ + rm -f /tmp/d.$$ fi done exit 0 - diff --git a/usr/src/pkgdefs/common_files/i.dialers b/usr/src/pkgdefs/common_files/i.dialers index ec8f1d568d..587b041a88 100644 --- a/usr/src/pkgdefs/common_files/i.dialers +++ b/usr/src/pkgdefs/common_files/i.dialers @@ -3,9 +3,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -23,7 +22,8 @@ # #ident "%Z%%M% %I% %E% SMI" # -# Copyright (c) 1993 by Sun Microsystems, Inc. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. # while read src dest @@ -31,13 +31,6 @@ do if [ ! -f $dest ] ; then cp $src $dest else - # update version string - grep '^#ident[ ]*\"@(#)Dialers' $src \ - > /tmp/newident.$$ 2>/dev/null - grep -v '^#ident[ ]*\"@(#)Dialers' $dest \ - > /tmp/rest.$$ 2>/dev/null - cat /tmp/newident.$$ /tmp/rest.$$ > $dest - # add USR Courier entry grep '^usrv32-ec[ ]' $dest > /dev/null 2>&1 if [ $? != 0 ] ; then diff --git a/usr/src/pkgdefs/common_files/i.etcprofile b/usr/src/pkgdefs/common_files/i.etcprofile index 92e1a88d3c..ec021d3535 100644 --- a/usr/src/pkgdefs/common_files/i.etcprofile +++ b/usr/src/pkgdefs/common_files/i.etcprofile @@ -3,9 +3,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -23,8 +22,8 @@ # #pragma ident "%Z%%M% %I% %E% SMI" # -# Copyright (c) 1999,2001 by Sun Microsystems, Inc. -# All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. # PATH="/usr/bin:/usr/sbin:${PATH}" export PATH @@ -34,19 +33,12 @@ do if [ ! -f $dest ] ; then cp $src $dest else - ( - # Get the SCCS ID from the source. - grep '^#.*ident.*@(#)profile' $src - - # Remove the SCCS ID from the destination. - # Solaris/Intel console type now "sun-color". - # Add -bash to shell case - SHELLS='-sh | -ksh | -jsh' - sed -e '/^#.*ident.*@(#)profile/d' \ - -e "s/^${SHELLS})$/${SHELLS} | -bash)/" \ - -e 's/TERM=AT386/TERM=sun-color/' \ - $dest - ) > /tmp/prof.$$ + # Solaris/Intel console type now "sun-color". + # Add -bash to shell case + SHELLS='-sh | -ksh | -jsh' + sed -e "s/^${SHELLS})$/${SHELLS} | -bash)/" \ + -e 's/TERM=AT386/TERM=sun-color/' \ + $dest > /tmp/prof.$$ cp /tmp/prof.$$ $dest rm -f /tmp/prof.$$ fi diff --git a/usr/src/pkgdefs/common_files/i.etcrpc b/usr/src/pkgdefs/common_files/i.etcrpc index 6a6f62ddd3..a9fd7bf084 100644 --- a/usr/src/pkgdefs/common_files/i.etcrpc +++ b/usr/src/pkgdefs/common_files/i.etcrpc @@ -3,9 +3,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -21,7 +20,7 @@ # CDDL HEADER END # # -# Copyright 1994-2002 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -35,25 +34,9 @@ do if [ ! -f $dest ] ; then cp $src $dest else - # - # determine whether existing /etc/rpc file is based on - # the same one being installed. If so, no need to update it. - # - newrev=`sed -n 's/^.*\(@(#)rpc.*\)\".*/\1/p' $src` - oldrev=`sed -n 's/^.*\(@(#)rpc.*\)\".*/\1/p' $dest` - if [ "$oldrev" != "$newrev" ] ; then - grep '^#ident[ ]*\"@(#)rpc' $src \ - > /tmp/newident.$$ 2>/dev/null - grep -v '^#ident[ ]*\"@(#)rpc' $dest \ - > /tmp/rest.$$ 2>/dev/null - cat /tmp/newident.$$ /tmp/rest.$$ > $dest - rm -f /tmp/newident.$$ /tmp/rest.$$ - fi - - # add the entry for nispasswd used by rpc.nispasswdd - # even if sccsid is wrong it might still be there - # we do not get fancy and try to add it at the "right" - # location. putting it on the end works just fine. + # Add the entry for nispasswd used by rpc.nispasswdd. + # We do not get fancy and try to add it at the "right" + # location. Putting it on the end works just fine. grep 'nispasswd' $dest > /dev/null 2>&1 if [ $? -ne 0 ] ; then diff --git a/usr/src/pkgdefs/common_files/i.etcsystem b/usr/src/pkgdefs/common_files/i.etcsystem index 5e398ddef9..77d887770e 100644 --- a/usr/src/pkgdefs/common_files/i.etcsystem +++ b/usr/src/pkgdefs/common_files/i.etcsystem @@ -3,9 +3,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -21,7 +20,7 @@ # CDDL HEADER END # # -# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -177,48 +176,6 @@ do # Comment out obsolete System V IPC Tunables eolipc $dest - - # - # determine whether existing etc/system file is based on - # the same one being installed. If so, no need to update it. - # - newrev=`sed -n 's/^.*\(@(#)system.*\)\".*/\1/p' $src` - oldrev=`sed -n 's/^.*\(@(#)system.*\)\".*/\1/p' $dest` - if [ "$oldrev" != "$newrev" ] ; then - # - # existing /etc/system file is based on a different - # original installed version of etc/system. Determine - # whether it has been modified by looking for non-blank, - # non-comment lines in the file. If it has been - # modified, preserve it and install the new one as - # /etc/system.new. - # - egrep -v '(^[ ]*$)|(^\*)' $dest >/dev/null 2>&1 - if [ $? = 0 ] ; then - realdest=`expr $dest : "/a\(.*\)"` - if [ "$realdest" = "" ] ; then - realdest=$dest - fi - cp $src $dest.${TAG} - # - # Checking for the existance of "rootfs:cachefs" from - # an AutoClient installation in the existing /etc/system. - # Transfer it to /etc/system.new if it does. - # - grep 'rootfs:cachefs' $dest > /dev/null 2>&1 - if [ $? = 0 ] ; then - grep 'rootfs:cachefs' $dest >> $dest.${TAG} - fi - echo "EXISTING_FILE_PRESERVED: ${realdest} ${realdest}.${TAG}" \ - >> ${CLEANUP_FILE} - else - - # existing file hasn't been modified, so - # install over it. - - cp $src $dest - fi - fi fi done exit 0 diff --git a/usr/src/pkgdefs/common_files/i.hosts b/usr/src/pkgdefs/common_files/i.hosts index 14697282ba..e6902398ac 100755 --- a/usr/src/pkgdefs/common_files/i.hosts +++ b/usr/src/pkgdefs/common_files/i.hosts @@ -20,7 +20,7 @@ # CDDL HEADER END # # -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -441,8 +441,7 @@ deliver_hosts() { # Remove redundant header lines from ipnodes file /usr/bin/sed -e ' /^# CDDL HEADER START$/,/^# CDDL HEADER END$/ d - /^# ident[ \t]*/ d - /^# Copyright 1999 Sun Microsystems, Inc/ d + /^# Copyright .* Sun Microsystems, Inc/ d /^# Use is subject to license terms/ d /^# Internet host table$/ d ' $saved_ipnodes_file | /usr/bin/sed -e ' /^#$/ { diff --git a/usr/src/pkgdefs/common_files/i.ibnexconf b/usr/src/pkgdefs/common_files/i.ibnexconf index f73e2fe27a..4c1a666e3a 100644 --- a/usr/src/pkgdefs/common_files/i.ibnexconf +++ b/usr/src/pkgdefs/common_files/i.ibnexconf @@ -21,7 +21,7 @@ # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -52,28 +52,14 @@ search_ibconf() } # -# Update ib.conf does two things : -# 1. Replace the old ident with new ident -# 2. Add the line containing : +# Update ib.conf just adds the line containing : # name="ib" class="root"; # and the adjoining comments in target ib.conf file. # update_ibconf() { - PKG_IBCONFFILE=$1 TGT_IBCONFFILE=$2 - # Replace old ident with new ident - ident_pattern="^#.*ident.*SMI\"$" - ident_var=`grep $ident_pattern $PKG_IBCONFFILE` - ed -s $TGT_IBCONFFILE <<-EOF - /$ident_pattern/c - $ident_var - . - w - q - EOF - echo $IB_STR1 >> $TGT_IBCONFFILE echo $IB_STR2 >> $TGT_IBCONFFILE echo $IB_STR3 >> $TGT_IBCONFFILE diff --git a/usr/src/pkgdefs/common_files/i.inetdconf b/usr/src/pkgdefs/common_files/i.inetdconf index eeecfc3e40..8fe041803f 100644 --- a/usr/src/pkgdefs/common_files/i.inetdconf +++ b/usr/src/pkgdefs/common_files/i.inetdconf @@ -20,7 +20,7 @@ # CDDL HEADER END # # -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -64,8 +64,7 @@ inetsedhdr=/tmp/inetd.sedhdr.$$ # The header editing is built separately so that we only apply it when needed cat >$inetsedhdr <<EOF -/^#ident/d -/^# Copyright/d +/^# Copyright .* Sun Microsystems/d /^# Use is subject to license terms/d EOF diff --git a/usr/src/pkgdefs/common_files/i.inittab b/usr/src/pkgdefs/common_files/i.inittab index ce5e5486b4..a8bea6a0d2 100644 --- a/usr/src/pkgdefs/common_files/i.inittab +++ b/usr/src/pkgdefs/common_files/i.inittab @@ -3,9 +3,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -23,7 +22,7 @@ # #ident "%Z%%M% %I% %E% SMI" # -# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # @@ -152,18 +151,12 @@ while read src dest; do -e /^sp:/d ' cp -p $src /tmp/d1.$$ - sed $PRMVALCUR $dest | sed $PRMVALOLD >/tmp/d2.$$ - if grep '^#ident' $dest >/dev/null 2>&1; then - awk ' - /^#/ { if (end_sun_comments) print $0 } - !/^#/ { end_sun_comments = 1; print $0 } - /^#ident/ { end_sun_comments = 1 } - ' /tmp/d2.$$ >>/tmp/d1.$$ - else - cat /tmp/d2.$$ >>/tmp/d1.$$ - fi + sed $PRMVALCUR $dest | sed $PRMVALOLD | awk ' + /^#/ { if (end_sun_comments) print $0 } + !/^#/ { end_sun_comments = 1; print $0 } + ' >>/tmp/d1.$$ cp -p /tmp/d1.$$ $dest - rm -f /tmp/d1.$$ /tmp/d2.$$ + rm -f /tmp/d1.$$ fi done diff --git a/usr/src/pkgdefs/common_files/i.kclasses_i386 b/usr/src/pkgdefs/common_files/i.kclasses_i386 index 5bb023e2f9..2c179c26a7 100644 --- a/usr/src/pkgdefs/common_files/i.kclasses_i386 +++ b/usr/src/pkgdefs/common_files/i.kclasses_i386 @@ -45,7 +45,6 @@ do cp /tmp/odc.$$.tmp $dest rm -f /dev/odc.$$.tmp - grep '^#pragma' $src > /tmp/newident.$$ 2>/dev/null sed -e '/^aha[ ].*scsi/d' \ -e '/^aic[ ].*scsi/d' \ -e '/^blogic[ ].*scsi/d' \ @@ -68,15 +67,9 @@ do -e '/^pci_to_i2o[ ].*i2o/d' \ -e '/^i2o_scsi[ ].*scsi/d' \ $dest > /tmp/c.$$ - if cmp -s /tmp/c.$$ $dest > /dev/null 2>&1 - then - : - else - cat /tmp/newident.$$ > /tmp/rest.$$ - sed '/^#pragma.*/d' /tmp/c.$$ >> /tmp/rest.$$ - cp /tmp/rest.$$ $dest - fi - rm -f /tmp/rest.$$ /tmp/newident.$$ /tmp/c.$$ + cmp -s /tmp/c.$$ $dest > /dev/null 2>&1 || + cp /tmp/c.$$ $dest + rm -f /tmp/c.$$ grep '^pci[ ].*pci' $dest > /dev/null 2>&1 if [ $? != 0 ] ; then diff --git a/usr/src/pkgdefs/common_files/i.kclasses_sparc b/usr/src/pkgdefs/common_files/i.kclasses_sparc index 77bd25476c..041da84777 100644 --- a/usr/src/pkgdefs/common_files/i.kclasses_sparc +++ b/usr/src/pkgdefs/common_files/i.kclasses_sparc @@ -45,16 +45,13 @@ do cp /tmp/odc.$$.tmp $dest rm -f /dev/odc.$$.tmp - grep '^#ident[ ]*\"@(#)driver_classes' $src \ - > /tmp/newident.$$ 2>/dev/null - sed -e '/^#ident[ ]*\"@(#)driver_classes.*$/d' \ - -e '/^\"QLGC,isp\"[ ]*scsi$/d' \ + sed -e '/^\"QLGC,isp\"[ ]*scsi$/d' \ -e '/^\"SUNW,isp\"[ ]*scsi$/d' \ -e '/^ncr[ ]*scsi$/d' \ -e '/^vme[ ]*vme$/d' \ -e '/^pci[ ]*pci$/d' \ $dest > /tmp/rest.$$ 2>/dev/null - cat /tmp/newident.$$ /tmp/rest.$$ > $dest + cp /tmp/rest.$$ $dest grep '^isp scsi' $dest > /dev/null 2>&1 if [ $? != 0 ] ; then echo 'isp scsi' >> $dest @@ -105,6 +102,6 @@ do fi fi done -rm -f /tmp/newident.$$ /tmp/rest.$$ +rm -f /tmp/rest.$$ exit 0 diff --git a/usr/src/pkgdefs/common_files/i.locallogin b/usr/src/pkgdefs/common_files/i.locallogin index 0581bf909a..165e5fcb00 100644 --- a/usr/src/pkgdefs/common_files/i.locallogin +++ b/usr/src/pkgdefs/common_files/i.locallogin @@ -3,9 +3,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -23,8 +22,8 @@ # #pragma ident "%Z%%M% %I% %E% SMI" # -# Copyright (c) 1999 by Sun Microsystems, Inc. -# All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. # PATH="/usr/bin:/usr/sbin:${PATH}" @@ -59,15 +58,6 @@ do cp /tmp/d.$$ $dest rm -f /tmp/d.$$ fi - # - # preserve the SCCS id string - # - ( - grep '^# @(#)' $src - grep -v '^# @(#)local.login' $dest - ) > /tmp/d.$$ - cp /tmp/d.$$ $dest - rm -f /tmp/d.$$ fi done diff --git a/usr/src/pkgdefs/common_files/i.localprofile b/usr/src/pkgdefs/common_files/i.localprofile index e14a3ff910..66e8b5bfd8 100644 --- a/usr/src/pkgdefs/common_files/i.localprofile +++ b/usr/src/pkgdefs/common_files/i.localprofile @@ -3,9 +3,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -23,8 +22,8 @@ # #pragma ident "%Z%%M% %I% %E% SMI" # -# Copyright (c) 1999 by Sun Microsystems, Inc. -# All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. # PATH="/usr/bin:/usr/sbin:${PATH}" @@ -59,16 +58,6 @@ do cp /tmp/d.$$ $dest rm -f /tmp/d.$$ fi - - # - # preserve the SCCS id string - # - ( - grep '^# @(#)' $src - grep -v '^# @(#)local.profile' $dest - ) > /tmp/d.$$ - cp /tmp/d.$$ $dest - rm -f /tmp/d.$$ fi done diff --git a/usr/src/pkgdefs/common_files/i.mailxrc b/usr/src/pkgdefs/common_files/i.mailxrc index 6e5dd51d93..93aa6cd390 100644 --- a/usr/src/pkgdefs/common_files/i.mailxrc +++ b/usr/src/pkgdefs/common_files/i.mailxrc @@ -3,9 +3,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -23,8 +22,8 @@ # #ident "%Z%%M% %I% %E% SMI" # -# Copyright (c) 1995 by Sun Microsystems, Inc. -# All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. # txtfile=/tmp/mailx-txt.$$ scrfile=/tmp/mailx-scratch.$$ @@ -40,7 +39,6 @@ do # based on the same one being installed. If so, no need # to update it. # - newrev="`sed -n 's/^.*\(@(#)mailx\.rc.*\)\".*/\1/p' $src`" sed -n -e 's/^\([^#]*\).*$/\1/p' < $dest > $scrfile # # if either of the following is defined, no need to update. @@ -55,11 +53,16 @@ do # existing /etc/mail/mailx.rc file is based on # the original installed version # - echo "# The following 3 settings produce the familiar Solaris behavior." > $txtfile - echo "set appenddeadletter" >> $txtfile - echo "unset pipeignore" >> $txtfile - echo "unset replyall" >> $txtfile - printf "1 c\n# \"%s\"\n.\n1 r %s\nw\nq\n" "$newrev" $txtfile | ed -s $dest + ( + cat <<EOF +# The following 3 settings produce the familiar Solaris behavior. +set appenddeadletter +unset pipeignore +unset replyall +EOF + cat $dest + ) > $txtfile + cp $txtfile $dest fi fi done diff --git a/usr/src/pkgdefs/common_files/i.mptconf b/usr/src/pkgdefs/common_files/i.mptconf index e3ba1f7602..51158b03cc 100644 --- a/usr/src/pkgdefs/common_files/i.mptconf +++ b/usr/src/pkgdefs/common_files/i.mptconf @@ -19,7 +19,7 @@ # # CDDL HEADER END # -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -107,17 +107,6 @@ update_mptconf() fi fi - # replace old ident with new ident - HEADER="^#.*ident.*SMI\"$" - if grep "$HEADER" $1 > $NEWHDR1 2>/dev/null; then - # replace / by \/ - sed "s/\\//\\\\\\//g" $NEWHDR1 > $NEWHDR2 2>/dev/null - if sed "s/$HEADER/`cat $NEWHDR2`/" $2 > $TMPFILE 2>/dev/null - then - cp $TMPFILE $2 - fi - fi - if [ "$ARCH" = "i386" ]; then # remove useless property flow_control and queue # check the property named tape and that the property is diff --git a/usr/src/pkgdefs/common_files/i.pcicconf b/usr/src/pkgdefs/common_files/i.pcicconf deleted file mode 100644 index 30ef2b2aa5..0000000000 --- a/usr/src/pkgdefs/common_files/i.pcicconf +++ /dev/null @@ -1,86 +0,0 @@ -#!/bin/sh -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# ident "%Z%%M% %I% %E% SMI" -# -# Copyright (c) 1993-1997,2001 by Sun Microsystems, Inc. -# All rights reserved. -# -# SUNWpcmci i.pcicconf script -# - -while read src dest -do - if [ "`basename $src`" = "pcic.conf" ] - then - TMP=/tmp/SUNWpcmci.pcic.$$ - - # - # strip out all the old cruft in pcic.conf and add any - # user-supplied lines to the new pcic.conf - # be careful about the egrep [ ] regexp - it should be - # [<SAPCE><TAB>] - # - if [ -f $dest ] && egrep -s 'res-*=|ioaddr=|the "smi" prop' $dest - then - OLD_CMT1="with the pcmcia\/pcic enumerator and the PCI devices" - OLD_CMT2="there is not much need for this file other than to" - OLD_CMT3="get the correct interrupt priorities" - OLD_CMT4="force attach driver to support hotplug activity" - egrep -iv 'Copyright|All |ident |interrupt-priorities=|ddi-forceattach=' $dest | \ - egrep -v "$OLD_CMT1|$OLD_CMT2|$OLD_CMT3|$OLD_CMT4" | \ - egrep -v '^[ ]*$|^[ ]*#[ ]*$|^[ ]*;[ ]*$' | \ - nawk '{print "# "$0}' > $TMP - PCIC_WCL="`cat $TMP | wc -l`" - if [ "$PCIC_WCL" -gt 0 ] - then - PCIC_WCL="`expr $PCIC_WCL`" - ( cat $src - echo '#' - echo "# The following $PCIC_WCL lines were\c" - echo ' extracted from your old /kernel/drv/pcic.conf' - echo '# file. Please edit your new pcic.conf file\c' - echo ' if necessary to include some or' - echo '# all of these lines.' - echo '#' - echo '# ======== start of extracted lines from\c' - echo ' old /kernel/drv/pcic.conf ========' - cat $TMP - echo '# ========= end of extracted lines from\c' - echo ' old /kernel/drv/pcic.conf =========' ) >$dest - fi - rm -f $TMP - else - if [ ! -f $dest ] - then - cp $src $dest - fi - fi - else - if [ ! -f $dest ] - then - cp $src $dest - fi - fi -done -exit 0 diff --git a/usr/src/pkgdefs/common_files/i.powerconf b/usr/src/pkgdefs/common_files/i.powerconf index 5507bc5a89..a579f432d1 100644 --- a/usr/src/pkgdefs/common_files/i.powerconf +++ b/usr/src/pkgdefs/common_files/i.powerconf @@ -3,9 +3,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -23,8 +22,8 @@ # #pragma ident "%Z%%M% %I% %E% SMI" # -# Copyright (c) 1996-2001 by Sun Microsystems, Inc. -# All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. # # @@ -33,7 +32,6 @@ PATH="/usr/bin:/usr/sbin:${PATH}" export PATH write_sed_script() { cat > /tmp/power.sed.$$ << EOF -/^#ident.*$/d /^# Putting an entry in this file will only be effective if the driver$/d /^# for the device supports device power management. After the file is$/d /^# modified, pmconfig(1M) command must be executed to activate the new$/d @@ -60,9 +58,8 @@ do if [ ! -f $dest ] ; then cp $src $dest else - grep '@(#)power.conf' $src > /tmp/p.$$ write_sed_script - sed -f /tmp/power.sed.$$ < $dest >> /tmp/p.$$ + sed -f /tmp/power.sed.$$ < $dest > /tmp/p.$$ cp -f /tmp/p.$$ $dest rm -f /tmp/power.sed.$$ /tmp/p.$$ grep -w 'autopm' $dest > /dev/null 2>&1 diff --git a/usr/src/pkgdefs/common_files/i.publickey b/usr/src/pkgdefs/common_files/i.publickey index 08e0690476..0e29745991 100644 --- a/usr/src/pkgdefs/common_files/i.publickey +++ b/usr/src/pkgdefs/common_files/i.publickey @@ -3,9 +3,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -23,7 +22,8 @@ # #ident "%Z%%M% %I% %E% SMI" # -# Copyright (c) 1993 by Sun Microsystems, Inc. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. # PATH="/usr/bin:/usr/sbin:${PATH}" @@ -34,22 +34,36 @@ do if [ ! -f $dest ] ; then cp $src $dest else + # This updates the header information. Note that there's a + # long-standing bug that was introduced by the fix for CR + # 1094626. All systems that have been upgraded at least once + # since 1993 are missing the "nobody" entry. There's no good + # way to know, though, whether a missing entry is due to that + # bug or due to intentional configuration, so we don't + # correct it here. We just don't make it worse. # - # determine whether existing etc/system file is based on - # the same one being installed. If so, no need to update it. - # - newrev=`sed -n 's/^.*\(@(#)publickey.*\)\".*/\1/p' $src` - oldrev=`sed -n 's/^.*\(@(#)publickey.*\)\".*/\1/p' $dest` - if [ "$oldrev" != "$newrev" ] ; then - grep '^[ ]*#' $src > /tmp/newcomment.$$ \ - 2>/dev/null - sed '1,/# a new one/d' $dest > /tmp/oldcontent.$$ \ - 2>/dev/null - cat /tmp/newcomment.$$ /tmp/oldcontent.$$ > $dest - rm -f /tmp/newcomment.$$ /tmp/oldcontent.$$ - fi + # From the source file, take everything before the "nobody" + # line. If there's no "nobody" line, take the whole thing. + # From the destination, take everything after the initial + # comment block. The "netname" comment is the end of the + # traditional comment block, so start after there if present + # (keeping the user's added comments, if any), or with the + # first non-comment line. + tmpfile=/tmp/policyconf.$$ + ( + cat $src + echo SWITCH + cat $dest + ) | nawk ' + /^nobody / && state == 0 { state=1 } + /^SWITCH$/ { state=2; next } + /^[^#]/ && state == 2 { state=3 } + /^# netname / && state == 2 { state=3; next } + state == 0 || state == 3 { print $0 } + ' > $tmpfile + cmp -s $tmpfile $dest || cp $tmpfile $dest + rm -f $tmpfile fi done exit 0 - diff --git a/usr/src/pkgdefs/common_files/i.rbac b/usr/src/pkgdefs/common_files/i.rbac index fb5eed988a..85f8c486e4 100644 --- a/usr/src/pkgdefs/common_files/i.rbac +++ b/usr/src/pkgdefs/common_files/i.rbac @@ -24,7 +24,7 @@ # # i.rbac # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # class action script for "rbac" class files @@ -65,17 +65,6 @@ sort_cmd=sort # dbmerge() { # -# If the new file has an ident string, remove the ident string from the old -# file. -# - newident=`${egrep_cmd} '^#[pragma ]*ident' $3 \ - 2>/dev/null` - if [ -n "${newident}" ]; then - ${egrep_cmd} -v '^#[pragma ]*ident' $2 > $4.old 2>/dev/null - else - $cp_cmd $2 $4.old - fi -# # If the new file has a Sun copyright, remove the Sun copyright from the old # file. # @@ -85,8 +74,9 @@ dbmerge() { $sed_cmd -e '/^# Copyright.*Sun Microsystems, Inc./d' \ -e '/^# All rights reserved./d' \ -e '/^# Use is subject to license terms./d' \ - $4.old > $4.$$ 2>/dev/null - $mv_cmd $4.$$ $4.old + $2 > $4.old + else + $cp_cmd $2 $4.old fi # # If the new file has the CDDL, remove it from the old file. diff --git a/usr/src/pkgdefs/common_files/i.scsivhciconf b/usr/src/pkgdefs/common_files/i.scsivhciconf index 00c2784018..6a84603574 100644 --- a/usr/src/pkgdefs/common_files/i.scsivhciconf +++ b/usr/src/pkgdefs/common_files/i.scsivhciconf @@ -186,21 +186,11 @@ update_scsi_vhci() { TMPSCSIVHCI=$PREFIX.conf SEDSCRIPT=$PREFIX.sed - NEWIDENT1=$PREFIX.ident1 - NEWIDENT2=$PREFIX.ident2 FMBFILE=$PREFIX.fb # make sed script to do most of the work of upgrading make_sed_script $1 $2 - # make sed script to replace old ident with new ident - IDENT="^#.*ident.*SMI\"$" - if grep "$IDENT" $1 > $NEWIDENT1 2>/dev/null; then - # replace / by \/ - sed "s/\\//\\\\\\//g" $NEWIDENT1 > $NEWIDENT2 2>/dev/null - echo "s/$IDENT/`cat $NEWIDENT2`/" >> $SEDSCRIPT - fi - sed -f $SEDSCRIPT $2 > $TMPSCSIVHCI 2>/dev/null retval=$? if [ $retval -eq 0 ]; then @@ -212,7 +202,7 @@ update_scsi_vhci() fi fi - rm -f $NEWIDENT1 $NEWIDENT2 $SEDSCRIPT $TMPSCSIVHCI $FMBFILE + rm -f $SEDSCRIPT $TMPSCSIVHCI $FMBFILE return $retval } diff --git a/usr/src/pkgdefs/common_files/i.sdconf_i386 b/usr/src/pkgdefs/common_files/i.sdconf_i386 index 555847596f..f6f6ca2bbd 100644 --- a/usr/src/pkgdefs/common_files/i.sdconf_i386 +++ b/usr/src/pkgdefs/common_files/i.sdconf_i386 @@ -45,13 +45,6 @@ do if [ ! -f $dest ] ; then cp $src $dest else - # update the SCCS id - grep '^#pragma ident[ ]*"@(#)sd.conf' $src \ - > /tmp/newident.$$ 2>/dev/null - egrep -v '^#(pragma ident|ident)[ ]*"@\(#\)sd.conf' \ - $dest > /tmp/rest.$$ 2>/dev/null - cat /tmp/newident.$$ /tmp/rest.$$ > /tmp/d.$$ - # # remove entries for eol'ed blogic drivers # remove entries for eol'ed flashpt drivers @@ -104,9 +97,9 @@ do -e '/^name="sd" parent="ahci";$/d' \ -e '/^name="sd" parent="si3124";$/d' \ -e '/^name="sd" parent="marvell88sx";$/d' \ - /tmp/d.$$ > /tmp/d2.$$ + $dest > /tmp/d2.$$ - if cmp -s /tmp/d.$$ /tmp/d2.$$ > /dev/null 2>&1 + if cmp -s $dest /tmp/d2.$$ > /dev/null 2>&1 then : # Do not modify file unless changes are required. else @@ -117,8 +110,8 @@ do if [ $? -ne 0 ]; then add_self_identifying_entry fi - # remove temporary files - rm -f /tmp/d.$$ /tmp/d2.$$ /tmp/newident.$$ /tmp/rest.$$ + # remove temporary file + rm -f /tmp/d2.$$ fi done diff --git a/usr/src/pkgdefs/common_files/i.syslogconf b/usr/src/pkgdefs/common_files/i.syslogconf index 86aa09392e..62a6a3acda 100644 --- a/usr/src/pkgdefs/common_files/i.syslogconf +++ b/usr/src/pkgdefs/common_files/i.syslogconf @@ -3,9 +3,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -23,7 +22,8 @@ # #ident "%Z%%M% %I% %E% SMI" # -# Copyright (c) 1993, by Sun Microsystems, Inc. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. # PATH="/usr/bin:/usr/sbin:${PATH}" @@ -34,12 +34,6 @@ do if [ ! -f $dest ] ; then cp $src $dest else - grep '^#ident[ ]*\"@(#)syslog.conf' $src \ - > /tmp/newident.$$ 2>/dev/null - grep -v '^#ident[ ]*\"@(#)syslog.conf' $dest \ - > /tmp/rest.$$ 2>/dev/null - cat /tmp/newident.$$ /tmp/rest.$$ > $dest - newline=`grep '^# Copyright.*Sun Microsystems, Inc.$' $src \ 2>/dev/null` if [ $? != 0 ]; then @@ -79,6 +73,6 @@ do cp /tmp/work.$$ $dest fi done -rm -f /tmp/newident.$$ /tmp/rest.$$ /tmp/work.$$ +rm -f /tmp/work.$$ exit 0 diff --git a/usr/src/pkgdefs/common_files/i.ttysrch b/usr/src/pkgdefs/common_files/i.ttysrch index 2b2ed34cf8..8cd0e4444e 100644 --- a/usr/src/pkgdefs/common_files/i.ttysrch +++ b/usr/src/pkgdefs/common_files/i.ttysrch @@ -3,9 +3,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -23,7 +22,8 @@ # #ident "%Z%%M% %I% %E% SMI" # -# Copyright (c) 1994 by Sun Microsystems, Inc. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. # PATH="/usr/bin:/usr/sbin:${PATH}" @@ -38,14 +38,6 @@ do awk '/^\/dev/ { print $1 }' $dest > /tmp/i.$$ if [ "`cat /tmp/i.$$`" != "/dev/pts" ]; then - - # update the SCCS id - grep '@(#)ttysrch' $src \ - > /tmp/newident.$$ 2>/dev/null - grep -v '@(#)ttysrch' $dest \ - > /tmp/rest.$$ 2>/dev/null - cat /tmp/newident.$$ /tmp/rest.$$ > $dest - sed '/^\/dev\/pts$/d' $dest > /tmp/i.$$ ed -s /tmp/i.$$ << EOF /^\/dev/i diff --git a/usr/src/tools/Makefile b/usr/src/tools/Makefile index 85f2def0f0..d3bebf23b1 100644 --- a/usr/src/tools/Makefile +++ b/usr/src/tools/Makefile @@ -44,6 +44,7 @@ COMMON_SUBDIRS= \ fastfs \ findunref \ ndrgen \ + onbld \ pmodes \ gk \ install.bin \ @@ -103,6 +104,11 @@ ROOTDIRS= \ $(ROOTONBLD)/bin/$(MACH) \ $(ROOTONBLD)/lib \ $(ROOTONBLD)/lib/$(MACH) \ + $(ROOTONBLD)/lib/python \ + $(ROOTONBLD)/lib/python/onbld \ + $(ROOTONBLD)/lib/python/onbld/Checks \ + $(ROOTONBLD)/lib/python/onbld/hgext \ + $(ROOTONBLD)/lib/python/onbld/Scm \ $(ROOTONBLD)/env \ $(ROOTONBLD)/etc \ $(ROOTONBLD)/etc/abi \ diff --git a/usr/src/tools/Makefile.tools b/usr/src/tools/Makefile.tools index 216e7ba31b..28155f068e 100644 --- a/usr/src/tools/Makefile.tools +++ b/usr/src/tools/Makefile.tools @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -37,6 +37,7 @@ ROOTONBLDBIN= $(ROOTONBLD)/bin ROOTONBLDBINMACH= $(ROOTONBLD)/bin/$(MACH) ROOTONBLDLIB= $(ROOTONBLD)/lib ROOTONBLDLIBMACH= $(ROOTONBLD)/lib/$(MACH) +ROOTONBLDLIBPY= $(ROOTONBLD)/lib/python ROOTONBLDENV= $(ROOTONBLD)/env ROOTONBLDGK= $(ROOTONBLD)/gk ROOTONBLDMAN= $(ROOTONBLD)/man diff --git a/usr/src/tools/README.tools b/usr/src/tools/README.tools index 587a8fbba8..5bc04a889c 100644 --- a/usr/src/tools/README.tools +++ b/usr/src/tools/README.tools @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -54,6 +54,15 @@ Layout of /opt/onbld /opt/onbld/env build environment files. +/opt/onbld/lib + libraries used by the build tools. + +/opt/onbld/lib/python + python modules used by the build tools. + +/opt/onbld/lib/python/onbld/hgext + Mercurial extensions. + /opt/onbld/man rudimentary man pages for some of the tools. @@ -87,6 +96,10 @@ build_cscope builds cscope databases in the uts, the platform subdirectories of uts, and in usr/src. Uses cscope-fast. +cdm + A Mercurial extension providing various commands useful for ON + development + check_rtime checks ELF attributes used by ELF dynamic objects in the proto area. Used by 'nightly's -r option, to check a number of ELF runtime @@ -115,6 +128,10 @@ codesign server. The codesign_server code is not used on an ON build machine but is kept here for source control purposes. +copyrightchk + Checks that files have appropriate SMI copyright notices. + Primarily used by wx + cscope-fast The fast version of cscope that we use internally. Seems to work, but may need more testing before it's placed in the gate. The source @@ -182,6 +199,13 @@ hdrchk checks headers for compliance with OS/Net standards (form, includes, C++ guards). +hgsetup + creates a basic Mercurial configuration for the user. + +hg-active + helper used by webrev to generate file lists for Mercurial + workspaces. + install.bin binary version of /usr/sbin/install. Used to be vastly faster (since /usr/sbin/install is a shell script), but may only be a bit @@ -233,6 +257,10 @@ protocmp.terse protolist create a list of what's in the proto area, to feed to protocmp. +rtichk + checks that a set of CRs have approved RTIs. Primarily used + by wx + sccscp copy a file under SCCS control to another location in a workspace. also updates teamware's nametable. @@ -261,6 +289,10 @@ wx A great workspace tool by bonwick. See wx.README for information and warnings. +wx2hg + Converts a TeamWare workspace under the control of wx to a + Mercurial workspace, discarding intermediate deltas. + tokenize Used to build the sun4u boot block. @@ -271,6 +303,10 @@ webrev manually-generated list; knows how to use wx's active file for lists of checked-out files and proposed SCCS comments. +which_scm + Reports the current Source Code Management (SCM) system in use + and the top-level directory of the workspace. + wsdiff Detect object differences between two ON proto areas. Used by nightly(1) to determine what changed between two builds. Handy diff --git a/usr/src/tools/SUNWonbld/Makefile b/usr/src/tools/SUNWonbld/Makefile index f0e41a72e0..ae5c612b5c 100644 --- a/usr/src/tools/SUNWonbld/Makefile +++ b/usr/src/tools/SUNWonbld/Makefile @@ -28,7 +28,7 @@ include ../../Makefile.master include $(PKGDEFS)/Makefile.com include ../Makefile.tools -LICENSEFILES += ../ctf/dwarf/THIRDPARTYLICENSE +LICENSEFILES += ../ctf/dwarf/THIRDPARTYLICENSE $(GPLV2) .KEEP_STATE: diff --git a/usr/src/tools/SUNWonbld/prototype_com b/usr/src/tools/SUNWonbld/prototype_com index 102bc25f53..409fafd801 100644 --- a/usr/src/tools/SUNWonbld/prototype_com +++ b/usr/src/tools/SUNWonbld/prototype_com @@ -63,6 +63,7 @@ f none opt/onbld/bin/cddlchk 555 root bin f none opt/onbld/bin/check_rtime 555 root bin f none opt/onbld/bin/checkpaths 555 root bin f none opt/onbld/bin/checkproto 555 root bin +f none opt/onbld/bin/copyrightchk 555 root bin f none opt/onbld/bin/cstyle 555 root bin f none opt/onbld/bin/ctffindmod 555 root bin f none opt/onbld/bin/ctfcvtptbl 555 root bin @@ -72,6 +73,8 @@ f none opt/onbld/bin/flg.flp 555 root bin f none opt/onbld/bin/genoffsets 555 root bin f none opt/onbld/bin/get_depend_info 555 root bin f none opt/onbld/bin/hdrchk 555 root bin +f none opt/onbld/bin/hg-active 555 root bin +f none opt/onbld/bin/hgsetup 555 root bin f none opt/onbld/bin/intf_check 555 root bin f none opt/onbld/bin/jstyle 555 root bin f none opt/onbld/bin/keywords 555 root bin @@ -85,6 +88,7 @@ f none opt/onbld/bin/mktpl 555 root bin f none opt/onbld/bin/nightly 555 root bin f none opt/onbld/bin/onblddrop 555 root bin f none opt/onbld/bin/protocmp.terse 555 root bin +f none opt/onbld/bin/rtichk 555 root bin f none opt/onbld/bin/sccscheck 555 root bin f none opt/onbld/bin/sccscp 555 root bin f none opt/onbld/bin/sccshist 555 root bin @@ -97,12 +101,55 @@ f none opt/onbld/bin/validate_flg 555 root bin f none opt/onbld/bin/validate_paths 555 root bin f none opt/onbld/bin/wdiff 555 root bin f none opt/onbld/bin/webrev 555 root bin +f none opt/onbld/bin/which_scm 555 root bin f none opt/onbld/bin/ws 555 root bin f none opt/onbld/bin/wsdiff 555 root bin f none opt/onbld/bin/wx 555 root bin +f none opt/onbld/bin/wx2hg 555 root bin f none opt/onbld/bin/xref 555 root bin f none opt/onbld/bin/xref.mk 644 root bin d none opt/onbld/lib 755 root bin +d none opt/onbld/lib/python 755 root bin +d none opt/onbld/lib/python/onbld 755 root bin +f none opt/onbld/lib/python/onbld/__init__.py 444 root bin +f none opt/onbld/lib/python/onbld/__init__.pyc 444 root bin +d none opt/onbld/lib/python/onbld/Checks 755 root bin +f none opt/onbld/lib/python/onbld/Checks/__init__.py 444 root bin +f none opt/onbld/lib/python/onbld/Checks/__init__.pyc 444 root bin +f none opt/onbld/lib/python/onbld/Checks/CStyle.py 444 root bin +f none opt/onbld/lib/python/onbld/Checks/CStyle.pyc 444 root bin +f none opt/onbld/lib/python/onbld/Checks/Cddl.py 444 root bin +f none opt/onbld/lib/python/onbld/Checks/Cddl.pyc 444 root bin +f none opt/onbld/lib/python/onbld/Checks/Comments.py 444 root bin +f none opt/onbld/lib/python/onbld/Checks/Comments.pyc 444 root bin +f none opt/onbld/lib/python/onbld/Checks/Copyright.py 444 root bin +f none opt/onbld/lib/python/onbld/Checks/Copyright.pyc 444 root bin +f none opt/onbld/lib/python/onbld/Checks/DbLookups.py 444 root bin +f none opt/onbld/lib/python/onbld/Checks/DbLookups.pyc 444 root bin +f none opt/onbld/lib/python/onbld/Checks/HdrChk.py 444 root bin +f none opt/onbld/lib/python/onbld/Checks/HdrChk.pyc 444 root bin +f none opt/onbld/lib/python/onbld/Checks/JStyle.py 444 root bin +f none opt/onbld/lib/python/onbld/Checks/JStyle.pyc 444 root bin +f none opt/onbld/lib/python/onbld/Checks/Keywords.py 444 root bin +f none opt/onbld/lib/python/onbld/Checks/Keywords.pyc 444 root bin +f none opt/onbld/lib/python/onbld/Checks/ProcessCheck.py 444 root bin +f none opt/onbld/lib/python/onbld/Checks/ProcessCheck.pyc 444 root bin +f none opt/onbld/lib/python/onbld/Checks/Rti.py 444 root bin +f none opt/onbld/lib/python/onbld/Checks/Rti.pyc 444 root bin +d none opt/onbld/lib/python/onbld/hgext 755 root bin +f none opt/onbld/lib/python/onbld/hgext/__init__.py 444 root bin +f none opt/onbld/lib/python/onbld/hgext/__init__.pyc 444 root bin +f none opt/onbld/lib/python/onbld/hgext/cdm.py 444 root bin +f none opt/onbld/lib/python/onbld/hgext/cdm.pyc 444 root bin +d none opt/onbld/lib/python/onbld/Scm 755 root bin +f none opt/onbld/lib/python/onbld/Scm/__init__.py 444 root bin +f none opt/onbld/lib/python/onbld/Scm/__init__.pyc 444 root bin +f none opt/onbld/lib/python/onbld/Scm/Backup.py 444 root bin +f none opt/onbld/lib/python/onbld/Scm/Backup.pyc 444 root bin +f none opt/onbld/lib/python/onbld/Scm/Version.py 444 root bin +f none opt/onbld/lib/python/onbld/Scm/Version.pyc 444 root bin +f none opt/onbld/lib/python/onbld/Scm/WorkSpace.py 444 root bin +f none opt/onbld/lib/python/onbld/Scm/WorkSpace.pyc 444 root bin d none opt/onbld/env 755 root bin f none opt/onbld/env/developer 644 root bin f none opt/onbld/env/gatekeeper 644 root bin @@ -129,6 +176,9 @@ f none opt/onbld/man/man1/cw.1 644 root bin f none opt/onbld/man/man1/flg.flp.1 644 root bin f none opt/onbld/man/man1/get_depend_info.1 644 root bin f none opt/onbld/man/man1/intf_check.1 644 root bin +f none opt/onbld/man/man1/hdrchk.1 644 root bin +f none opt/onbld/man/man1/hgsetup.1 644 root bin +f none opt/onbld/man/man1/jstyle.1 644 root bin f none opt/onbld/man/man1/lintdump.1 644 root bin f none opt/onbld/man/man1/make_pkg_db.1 644 root bin f none opt/onbld/man/man1/mkacr.1 644 root bin @@ -140,7 +190,9 @@ f none opt/onbld/man/man1/sccsrm.1 644 root bin f none opt/onbld/man/man1/signit.1 644 root bin f none opt/onbld/man/man1/signproto.1 644 root bin f none opt/onbld/man/man1/webrev.1 644 root bin +f none opt/onbld/man/man1/which_scm.1 644 root bin f none opt/onbld/man/man1/ws.1 644 root bin f none opt/onbld/man/man1/wsdiff.1 644 root bin f none opt/onbld/man/man1/wx.1 644 root bin +f none opt/onbld/man/man1/wx2hg.1 644 root bin f none opt/onbld/man/man1/xref.1 644 root bin diff --git a/usr/src/tools/findunref/Makefile b/usr/src/tools/findunref/Makefile index d38cd3fef9..bd11b6169e 100644 --- a/usr/src/tools/findunref/Makefile +++ b/usr/src/tools/findunref/Makefile @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -19,14 +18,13 @@ # # CDDL HEADER END # + # -# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" # -# tools/findunref/Makefile -# PROG = findunref CFLAGS += $(CCVERBOSE) @@ -34,14 +32,24 @@ LINTFLAGS += -ux include ../Makefile.tools +EXCEPTION_SRC= $(SCM_TYPE) common open +$(CLOSED_BUILD)EXCEPTION_SRC += closed +EXCEPTION_LISTS= $(EXCEPTION_SRC:%=exception_list.%) + +CLOBBERFILES += exception_list + .KEEP_STATE: -all: $(PROG) +all: $(PROG) exception_list install: all .WAIT $(ROOTONBLDMACHPROG) lint: lint_PROG +exception_list: $(EXCEPTION_LISTS) + -$(RM) $@ + $(CAT) $(EXCEPTION_LISTS) > $@ + clean: include ../Makefile.targ diff --git a/usr/src/tools/findunref/README.exception_lists b/usr/src/tools/findunref/README.exception_lists new file mode 100644 index 0000000000..2f8c4bb8ff --- /dev/null +++ b/usr/src/tools/findunref/README.exception_lists @@ -0,0 +1,55 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +Exception lists for the findunref tool + +Files in these lists are by definition intentionally never used during a +standard nightly build. + +Most files in this category should be matched by the existing filename globs, so +if you find yourself adding exceptions, please check with your advocate and/or +the gatekeepers to be sure you're doing the right thing. + +The actual exception_list file used during a nightly build is generated during +the build (see usr/src/tools/findunref/Makefile for details), based on various +input files as follows: + + Filename globs, applicable regardless of location in the source tree, + and regardless of SCM: + + exception_list.common + + Filename globs and specific files to ignore, based on the SCM in use: + + exception_list.teamware + exception_list.mercurial + + Specific files to ignore, divided by location in the source tree: + + exception_list.open + exception_list.closed diff --git a/usr/src/tools/findunref/exception_list.closed b/usr/src/tools/findunref/exception_list.closed new file mode 100644 index 0000000000..df70b10427 --- /dev/null +++ b/usr/src/tools/findunref/exception_list.closed @@ -0,0 +1,62 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +# +# closed-tree exception list +# +# See README.exception_lists for details +# + +# +# Ignore internal packages, scripts, and tools that are intentionally not +# built or used during a nightly. +# +./closed/cmd/zic/makefile.tzpkg +./closed/cmd/zic/tzpkg.awk + +# +# Ignore files that get used during a EXPORT_SRC or CRYPT_SRC build only. +# +./closed/uts/sun4v/io/n2cp/Makefile +./closed/uts/sun4v/io/ncp/Makefile + +# +# Ignore files that are only used for warlock +# +./closed/uts/sparc/marvell88sx/Makefile + +# +# An unfortunate artifact of the bridged, split gate is that closed-source +# deleted files go where findunref can accidentally find them... +# +# And an unfortunate artifact of using these tools with both full Teamware +# and split, non-Teamware workspaces is that sometimes closed/deleted_files +# won't exist, so we need the ISUSED directive here. +# +# ISUSED - let checkpaths know that the next entry is good. +./closed/deleted_files diff --git a/usr/src/tools/findunref/exception_list.common b/usr/src/tools/findunref/exception_list.common new file mode 100644 index 0000000000..c0ffd9ead6 --- /dev/null +++ b/usr/src/tools/findunref/exception_list.common @@ -0,0 +1,91 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +# +# common exception list +# +# See README.exception_lists for details +# + +# +# Ignore text files. +# +*.[1-9] +*.memo +*.mm +*.txt +*/*[Rr][Ee][Aa][Dd][Mm][Ee]* +*/BUGS +*/COMPATIBILITY +*/COPYRIGHT +*/CREDITS +*/ChangeLog +*/DESIGN +*/HISTORY +*/NOTES +*/OBSOLETE +*/READ_ME +*/RELEASE* +*/TODO + +# +# Ignore warlock-related goop; not used during a nightly. +# +*.wlc +*.wlcmd +*/wlcmd +*/warlock + +# +# Ignore internal test directories and test programs. +# +*/tests +*/test +*Test.java +*_test.[ch] + +# +# Ignore internal packages, scripts, and tools that are intentionally not +# built or used during a nightly. +# +*/tools + +# +# Ignore license files. This should be temporary, and these lines +# should be removed once we start generating the opensolaris.org +# deliverables from the nightly gate builds. +# +*/COPYING* +*/LICENSE* +*/THIRDPARTYLICENSE* +*/OPENSOLARIS.LICENSE + +# +# Ignore file list generators +# +*.flg diff --git a/usr/src/tools/findunref/exception_list.mercurial b/usr/src/tools/findunref/exception_list.mercurial new file mode 100644 index 0000000000..17e5cefad2 --- /dev/null +++ b/usr/src/tools/findunref/exception_list.mercurial @@ -0,0 +1,42 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +# +# Mercurial-specific exception list +# +# See README.exception_lists for details +# + +# +# Without nested repositories, this list could be empty, because ON +# checks for unref relative to usr, and the hg files are all in the +# root of the repository. +# + +*/.hg +*/.hgtags diff --git a/usr/src/tools/findunref/exception_list b/usr/src/tools/findunref/exception_list.open index 5eb6f9ca01..cf07dbd7ed 100644 --- a/usr/src/tools/findunref/exception_list +++ b/usr/src/tools/findunref/exception_list.open @@ -25,32 +25,12 @@ # # ident "%Z%%M% %I% %E% SMI" # -# Exception list for the findunref tool. Files in this list are by definition -# intentionally never used during a standard nightly build. Since very few -# files fall into this category (that will not match the existing filename -# globs), you should clear any additions to this file with the gatekeepers. -# # -# Ignore text files. -# -*.[1-9] -*.memo -*.mm -*.txt -*/*[Rr][Ee][Aa][Dd][Mm][Ee]* -*/BUGS -*/COMPATIBILITY -*/COPYRIGHT -*/CREDITS -*/ChangeLog -*/DESIGN -*/HISTORY -*/NOTES -*/OBSOLETE -*/READ_ME -*/RELEASE* -*/TODO +# open-tree exception list +# +# See README.exception_lists for details +# # # Ignore oddly-named text files scattered about -- someday these should be @@ -59,7 +39,7 @@ ./src/cmd/oawk/EXPLAIN ./src/cmd/rpcsvc/nis/rpc.nisd/resolv_server/DNS_FWD ./src/cmd/vi/port/ex.news -./src/cmd/ssh/doc/* +./src/cmd/ssh/doc # # Ignore everything under trees that may be resynched from outside ON. @@ -76,24 +56,24 @@ # Ignore ksh93/ast-related files that are only used to resync our build # configuration with upstream. # -./src/lib/libast/*/src/lib/libast/FEATURE/* +./src/lib/libast/*/src/lib/libast/FEATURE ./src/lib/libast/common/comp/conf.* -./src/lib/libast/common/features/* +./src/lib/libast/common/features ./src/lib/libast/common/include/ast_windows.h ./src/lib/libast/common/port/lc.tab ./src/lib/libast/common/port/lcgen.c -./src/lib/libcmd/*/src/lib/libcmd/FEATURE/* -./src/lib/libcmd/common/features/* -./src/lib/libdll/*/src/lib/libdll/FEATURE/* -./src/lib/libdll/common/features/* +./src/lib/libcmd/*/src/lib/libcmd/FEATURE +./src/lib/libcmd/common/features +./src/lib/libdll/*/src/lib/libdll/FEATURE +./src/lib/libdll/common/features ./src/lib/libpp/*/pp.* ./src/lib/libpp/common/gentab.sh ./src/lib/libpp/common/ppsym.c ./src/lib/libpp/i386/ppdebug.h ./src/lib/libpp/sparc/ppdebug.h -./src/lib/libshell/*/src/cmd/ksh93/FEATURE/* +./src/lib/libshell/*/src/cmd/ksh93/FEATURE ./src/lib/libshell/common/data/math.tab -./src/lib/libshell/common/features/* +./src/lib/libshell/common/features ./src/lib/libshell/misc/buildksh93.ksh ./src/lib/libshell/misc/buildksh93.readme @@ -130,10 +110,6 @@ # # Ignore warlock-related goop; not used during a nightly. # -*.wlc -*.wlcmd -*/wlcmd -*/warlock ./src/uts/sparc/amsrc*/main.c # @@ -167,10 +143,7 @@ ./src/cmd/mdb/packages ./src/cmd/sgs/packages ./src/cmd/sgs/rtld.4.x -./closed/cmd/zic/makefile.tzpkg -./closed/cmd/zic/tzpkg.awk ./src/prototypes -*/tools ./src/cmd/pools/poold/com/sun/solaris/*/*/package.html ./src/uts/intel/io/acpica/cmp_ca.sh @@ -182,8 +155,6 @@ # # Ignore files that get used during a EXPORT_SRC or CRYPT_SRC build only. # -./closed/uts/sun4v/io/n2cp/Makefile -./closed/uts/sun4v/io/ncp/Makefile ./src/common/crypto/aes/Makefile ./src/common/crypto/arcfour/Makefile ./src/common/crypto/blowfish/Makefile @@ -262,12 +233,11 @@ ./src/common/bignum/mont_mulf.c # -# Ignore the sparc Makefiles for sata, si3124, marvell88sx, nv_sata, ahci -# and audioixp. These are used for warlock purposes only. +# Ignore the sparc Makefiles for x86-only drivers; +# they're used to build warlock only. # ./src/uts/sparc/sata/Makefile ./src/uts/sparc/si3124/Makefile -./closed/uts/sparc/marvell88sx/Makefile ./src/uts/sparc/nv_sata/Makefile ./src/uts/sparc/ahci/Makefile ./src/uts/sparc/audioixp/Makefile @@ -284,13 +254,3 @@ ./src/cmd/fps/fptest/singdoub* ./src/pkgdefs/SUNWfsu/prototype_gcc_sparc ./src/pkgdefs/SUNWfsu/prototype_cc_sparc - -# -# Ignore license files. This should be temporary, and these lines -# should be removed once we start generating the opensolaris.org -# deliverables from the nightly gate builds. -# -*/COPYING* -*/LICENSE* -*/THIRDPARTYLICENSE* -*/OPENSOLARIS.LICENSE diff --git a/usr/src/tools/findunref/exception_list.teamware b/usr/src/tools/findunref/exception_list.teamware new file mode 100644 index 0000000000..de12b68d95 --- /dev/null +++ b/usr/src/tools/findunref/exception_list.teamware @@ -0,0 +1,36 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +# +# Teamware-specific exception list +# +# See README.exception_lists for details +# + +*/SCCS +*/.del-* diff --git a/usr/src/tools/findunref/findunref.c b/usr/src/tools/findunref/findunref.c index a1aab7eca8..f40690fa75 100644 --- a/usr/src/tools/findunref/findunref.c +++ b/usr/src/tools/findunref/findunref.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -19,11 +18,11 @@ * * CDDL HEADER END */ + /* - * Copyright (c) 2001 by Sun Microsystems, Inc. - * All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. */ - #pragma ident "%Z%%M% %I% %E% SMI" /* @@ -156,22 +155,12 @@ make_exset(const char *exceptfile) char *newline; pnset_t *pnsetp; unsigned int i; - char *builtin[] = { "*/SCCS", "*/.del-*", "*/.make.*", - "*.flg", NULL }; pnsetp = calloc(sizeof (pnset_t), 1); if (pnsetp == NULL) return (NULL); /* - * Add the built-in exceptions. - */ - for (i = 0; builtin[i] != NULL; i++) { - if (pnset_add(pnsetp, builtin[i]) == 0) - goto fail; - } - - /* * Add any exceptions from the file. */ fp = fopen(exceptfile, "r"); diff --git a/usr/src/tools/onbld/Checks/CStyle.py b/usr/src/tools/onbld/Checks/CStyle.py new file mode 100644 index 0000000000..25847f4e6f --- /dev/null +++ b/usr/src/tools/onbld/Checks/CStyle.py @@ -0,0 +1,63 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +# +# CStyle, wrap the cstyle tool in a pythonic API +# + +import sys +from onbld.Checks.ProcessCheck import processcheck + +def cstyle(fh, filename=None, output=sys.stderr, **opts): + opttrans = {'check_continuation': '-c', + 'heuristic': '-h', + 'picky': '-p', + 'verbose': '-v', + 'ignore_hdr_comment': '-C', + 'check_posix_types': '-P', + 'doxygen_comments': '-o doxygen', + 'splint_comments': '-o splint'} + + for x in filter(lambda x: x not in opttrans, opts): + raise TypeError('cstyle() got an unexpected keyword ' + 'argument %s' % x) + + options = [opttrans[x] for x in opts if opts[x]] + + if not filename: + filename = fh.name + + ret, tmpfile = processcheck('cstyle', options, fh, output) + + if tmpfile: + for line in tmpfile: + line = line.replace('<stdin>', filename) + output.write(line) + + tmpfile.close() + return ret diff --git a/usr/src/tools/onbld/Checks/Cddl.py b/usr/src/tools/onbld/Checks/Cddl.py new file mode 100644 index 0000000000..dad098b731 --- /dev/null +++ b/usr/src/tools/onbld/Checks/Cddl.py @@ -0,0 +1,125 @@ +#! /usr/bin/python + +CDDL = ''' +CDDL HEADER START + +The contents of this file are subject to the terms of the +Common Development and Distribution License (the "License"). +You may not use this file except in compliance with the License. + +You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +or http://www.opensolaris.org/os/licensing. +See the License for the specific language governing permissions +and limitations under the License. + +When distributing Covered Code, include this CDDL HEADER in each +file and include the License file at usr/src/OPENSOLARIS.LICENSE. +If applicable, add the following below this CDDL HEADER, with the +fields enclosed by brackets "[]" replaced with your own identifying +information: Portions Copyright [yyyy] [name of copyright owner] + +CDDL HEADER END +''' + +# +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +# +# Check source files contain a valid CDDL block +# + +import re, sys + +CDDL = CDDL.splitlines()[1:] # Don't include initial \n + +CmntChrs = r'#*!/\\";. ' +CDDLStartRE = re.compile(r'^[%s ]*CDDL HEADER START' % CmntChrs) +CDDLEndRE = re.compile(r'^[%s ]*CDDL HEADER END' % CmntChrs) + +class CddlError(Exception): + def __init__(self, lineno, seen, shouldbe): + Exception.__init__(self) + self.lineno = lineno + self.seen = seen + self.shouldbe = shouldbe + +def checkblock(block): + line = block['start'] + lictxt = block['block'] + + for actual, valid in map(lambda x, y: (x and x.lstrip(CmntChrs), y), + lictxt, CDDL): + if actual != valid: + raise CddlError(line, actual, valid) + line += 1 + +def cddlchk(fh, filename=None, lenient=False, verbose=False, output=sys.stderr): + ret = 0 + blocks = [] + lic = [] + in_cddl = False + start = 0 + lineno = 0 + + if not filename: + filename = fh.name + + for line in fh: + line = line.rstrip('\r\n') + lineno += 1 + + if CDDLStartRE.search(line): + in_cddl = True + lic.append(line) + start = lineno + elif in_cddl and CDDLEndRE.search(line): + in_cddl = False + lic.append(line) + blocks.append({'start':start, 'block':lic}) + start = 0 + lic = [] + elif in_cddl: + lic.append(line) + + if in_cddl: + output.write('Error: Incomplete CDDL block in file %s\n' + ' at line %s\n''' % (filename, start)) + + # Check for no CDDL, warn if we're not being lenient + if not len(blocks) and not lenient: + if not ret: + ret = 2 + output.write("Warning: No CDDL block in file %s\n" % filename) + + # Check for multiple CDDL blocks + if len(blocks) > 1: + ret = 1 + output.write('Error: Multiple CDDL blocks in file %s\n' + ' at lines %s\n''' % + (filename, ', '.join([str(x['start']) + for x in blocks]))) + + # Validate each CDDL block + for b in blocks: + try: + checkblock(b) + except CddlError, e: + ret = 1 + output.write( + "Error: Invalid line in CDDL block in file %s\n" + " at line %d, should be\n" + " '%s'\n" + " is\n" + " '%s'\n" % (filename, e.lineno, + e.shouldbe, e.seen)) + break + + if verbose and not ret: + output.write("Message: Valid CDDL block in file %s\n" % + filename) + + return ret diff --git a/usr/src/tools/onbld/Checks/Comments.py b/usr/src/tools/onbld/Checks/Comments.py new file mode 100644 index 0000000000..986c1c4ad0 --- /dev/null +++ b/usr/src/tools/onbld/Checks/Comments.py @@ -0,0 +1,203 @@ +#! /usr/bin/python +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +# +# Check delta comments: +# - Have the correct form. +# - Have a synopsis matching that of the CR or ARC case. +# - Appear only once. +# + +import re, sys +from onbld.Checks.DbLookups import BugDB, ARC + +arcre = re.compile(r'^([A-Z][A-Z]*ARC[/ \t][12]\d{3}/\d{3}) (.*)$') +bugre = re.compile(r'^(\d{7}) (.*)$') +def isARC(comment): + return arcre.match(comment) + +def isBug(comment): + return bugre.match(comment) + +# +# Translate any acceptable case number format into "<ARC> <YEAR>/<NUM>" +# format. +# +def normalize_arc(caseid): + return re.sub(r'^([A-Z][A-Z]*ARC)[/ \t]', '\\1 ', caseid) + +def comchk(comments, check_db=True, output=sys.stderr): + bugnospcre = re.compile(r'^(\d{7})([^ ].*)') + ignorere = re.compile(r'^(Contributed by .*|backout \d{7})') + + errors = { 'bugnospc': [], + 'mutant': [], + 'dup': [], + 'nomatch': [], + 'nonexistent': [] } + bugs = {} + arcs = {} + ret = blanks = 0 + + for com in comments: + # Ignore valid comments we can't check + if ignorere.search(com): + continue + + if not com or com.isspace(): + blanks += 1 + continue + + match = bugre.search(com) + if match: + if match.group(1) not in bugs: + bugs[match.group(1)] = [] + bugs[match.group(1)].append(match.group(2)) + continue + + # + # Bugs missing a space after the ID are still bugs + # for the purposes of the duplicate ID and synopsis + # checks. + # + match = bugnospcre.search(com) + if match: + if match.group(1) not in bugs: + bugs[match.group(1)] = [] + bugs[match.group(1)].append(match.group(2)) + errors['bugnospc'].append(com) + continue + + # ARC case + match = arcre.search(com) + if match: + case = normalize_arc(match.group(1)) + if case not in arcs: arcs[case] = [] + arcs[case].append(match.group(2)) + continue + + # Anything else is bogus + errors['mutant'].append(com) + + if len(bugs) > 0 and check_db: + bugdb = BugDB() + results = bugdb.lookup(bugs.keys()) + + for crid, insts in bugs.iteritems(): + if len(insts) > 1: + errors['dup'].append(crid) + + if not check_db: + continue + + if crid not in results: + errors['nonexistent'].append(crid) + continue + + for entered in insts: + synopsis = results[crid]["synopsis"] + if not re.search(re.escape(synopsis) + + r'( \([^)]+\))?$', entered): + errors['nomatch'].append([crid, synopsis, + entered]) + + for case, insts in arcs.iteritems(): + if len(insts) > 1: + errors['dup'].append(case) + + if not check_db: + continue + + com, id = case.split(' ') + arc = ARC(com, id) + + if not arc.valid(): + errors['nonexistent'].append(case) + continue + + # + # The opensolaris.org ARC interfaces only give us the + # first 40 characters of the case name, so we must limit + # our checking similarly. + # + # We first try a direct match between the actual case name + # and the entered comment. If that fails we remove a possible + # trailing (fix nit)-type comment, and re-try. + # + for entered in insts: + if entered[0:40] == arc.name(): + continue + else: + dbcom = re.sub(r' \([^)]+\)$', '', entered) + if dbcom[0:40] != arc.name(): + errors['nomatch'].append([case, + arc.name(), + entered]) + + if blanks: + output.write("WARNING: Blank line(s) in comments\n") + ret = 1 + + if errors['dup']: + ret = 1 + output.write("These IDs appear more than once in your " + "comments:\n") + for err in errors['dup']: + output.write(" %s\n" % err) + + if errors['bugnospc']: + ret = 1 + output.write("These bugs are missing a single space following " + "the ID:\n") + for com in errors['bugnospc']: + output.write(" %s\n" % com) + + if errors['mutant']: + ret = 1 + output.write("These comments are neither bug nor ARC case:\n") + for com in errors['mutant']: + output.write(" %s\n" % com) + + if errors['nonexistent']: + ret = 1 + output.write("These bugs/ARC cases were not found in the " + "databases:\n") + for id in errors['nonexistent']: + output.write(" %s\n" % id) + + if errors['nomatch']: + ret = 1 + output.write("These bugs/ARC case synopsis/names don't match " + "the database entries:\n") + for err in errors['nomatch']: + output.write("Synopsis/name of %s is wrong:\n" % err[0]) + output.write(" should be: '%s'\n" % err[1]) + output.write(" is: '%s'\n" % err[2]) + + return ret diff --git a/usr/src/tools/onbld/Checks/Copyright.py b/usr/src/tools/onbld/Checks/Copyright.py new file mode 100644 index 0000000000..79e312cdeb --- /dev/null +++ b/usr/src/tools/onbld/Checks/Copyright.py @@ -0,0 +1,132 @@ +#! /usr/bin/python +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +# +# Make sure there is a correctly formed copyright message containing +# the current year. +# +# We treat extant but incorrect copyrights of known format as present +# for the purposes of the "no copyright found" messages to avoid +# treating every otherwise incorrect copyright as also not present +# + +import time, re, sys + +def err(stream, msg, fname, line=None): + if line: + stream.write("%s: %d: %s\n" % (fname, line, msg)) + else: + stream.write("%s: %s\n" % (fname, msg)) + +# pre-2002 copyright with '(c)' +oldcopyright = re.compile(r'Copyright \(c\) .* Sun Microsystems, Inc\.') + +# pre-2002 copyright with 'by' +oldcopyright1 = re.compile(r'Copyright .* by Sun Microsystems, Inc\.') + +# Valid, current copyright +goodcopyright = re.compile(r'Copyright ([\d, -]+) Sun Microsystems, Inc\.' + + r'(\s+)(All rights reserved\.)?') + +licterms = 'Use is subject to license terms.' + +def copyright(fh, filename=None, output=sys.stderr): + ret = lineno = rights = 0 + # Are we expecting the license terms message on this line? + expecting_license = False + + if not filename: + filename = fh.name + + for line in fh: + lineno += 1 + + if expecting_license: + expecting_license = False + + if licterms not in line: + err(output, "'%s' message missing" % licterms, + filename, lineno) + ret = 1 + continue + elif rights > 0 and ret == 0: + return 0 + continue + + if oldcopyright.search(line): + err(output, "old copyright with '(c)'", filename, + lineno) + rights += 1 + ret = 1 + elif oldcopyright1.search(line): + err(output, "old copyright with 'by'", filename, lineno) + rights += 1 + ret = 1 + + # + # group 1 = year + # group 2 = spacing + # group 3 = All rights reserved message. + # + match = goodcopyright.search(line) + if match: + expecting_license = True + rights += 1 + + year = time.strftime('%Y') + if match.group(1) != year: + err(output, "wrong copyright year %s, should " + "be %s" % + (match.group(1), year), filename, lineno) + ret = 1 + + if not match.group(3): + err(output, "'All rights reserved.' message " + "missing", + filename, lineno) + ret = 1 + elif match.group(2) != ' ': + err(output, "need two spaces between copyright " + "and all rights reserved phrases", + filename, lineno) + ret = 1 + # + # If the last line left us expecting the license message, + # we're pretty sure it isn't going to be there. + # + if expecting_license: + err(output, "'Use is subject to license terms.' message " + "missing", filename, lineno) + ret = 1 + + if rights == 0: + err(output, "no copyright message found", filename) + ret = 1 + + return ret diff --git a/usr/src/tools/onbld/Checks/DbLookups.py b/usr/src/tools/onbld/Checks/DbLookups.py new file mode 100644 index 0000000000..672160b88e --- /dev/null +++ b/usr/src/tools/onbld/Checks/DbLookups.py @@ -0,0 +1,477 @@ +#! /usr/bin/python +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +# +# Various database lookup classes/methods, i.e.: +# * monaco +# * bugs.opensolaris.org (b.o.o.) +# * opensolaris.org/cgi/arc.py (for ARC) +# + +import re +import urllib +import htmllib +import os +from socket import socket, AF_INET, SOCK_STREAM + +from onbld.Checks import onSWAN + +class BugException(Exception): + def __init__(self, data=''): + self.data = data + Exception.__init__(self, data) + + def __str__(self): + return "Unknown error: %s" % self.data + +class NonExistentBug(BugException): + def __str__(self): + return "Bug %s does not exist" % self.data + +class Monaco(object): + """ + Query bug database. + + Methods: + queryBugs() + expertQuery() + """ + + def __init__(self): + self.__baseURL = "http://hestia.sfbay.sun.com/cgi-bin/expert?" + + def expertQuery(self, cmd, format="Normal+text", header=False): + """Return results of user-supplied bug query. + + Argument: + cmd: query to run + + Keyword arguments: + format: desired output format (default="Normal+text") + header: include headers in output? (default=False) + + Returns: + List of lines representing the output from Monaco + """ + + url = self.__baseURL + "format=" + format + ";Go=2;" + if not header: url += "no_header=on;" + url += "cmds=" + urllib.quote_plus("\n".join(cmd)) + myMonaco = urllib.urlopen(url) + return myMonaco.readlines() + + def queryBugs(self, crs): + """Return all info for requested change reports. + + Argument: + crs: list of change request ids + + Returns: + Dictionary, mapping CR=>dictionary, where the nested dictionary + is a mapping of field=>value + """ + monacoFields = [ "cr_number", "synopsis", "category", "sub_category", + "area", "release", "build", "responsible_manager", + "responsible_engineer", "priority", "status", "sub_status", + "submitted_by", "date_submitted" ] + cmd = [] + cmd.append("set What = cr." + ', cr.'.join(monacoFields)) + cmd.append("") + cmd.append("set Which = cr.cr_number in (" + ','.join(crs) +")") + cmd.append("") + cmd.append("set FinalClauses = order by cr.cr_number") + cmd.append("") + cmd.append("doMeta genQuery cr") + output = self.expertQuery(cmd, "Pipe-delimited+text") + results = {} + for line in output: + values = line.split('|') + v = 0 + cr = values[0] + results[cr] = {} + for field in monacoFields: + results[cr][field] = values[v] + v += 1 + return results + +class BooBug(object): + """Look up a single bug on bugs.opensolaris.org.""" + def __init__(self, cr): + cr = str(cr) + url = "http://bugs.opensolaris.org/view_bug.do?bug_id="+cr + data = urllib.urlopen(url).readlines() + self.__fields = {} + self.__fields["cr_number"] = cr + htmlParser = htmllib.HTMLParser(None) + metaHtmlRe = re.compile(r'^<meta name="([^"]+)" content="([^"]*)">$') + for line in data: + m = metaHtmlRe.search(line) + if not m: + continue + val = urllib.unquote(m.group(2)) + htmlParser.save_bgn() + htmlParser.feed(val) + self.__fields[m.group(1)] = htmlParser.save_end() + htmlParser.close() + if "synopsis" not in self.__fields: + raise NonExistentBug(cr) + + def synopsis(self): + return self.__fields["synopsis"] + def product(self): + return self.__fields["product"] + def cat(self): + return self.__fields["category"] + def subcat(self): + return self.__fields["subcategory"] + def keywords(self): + return self.__fields["keywords"] + def state(self): + return self.__fields["state"] + def submit_date(self): + return self.__fields["submit_date"] + def type(self): + return self.__fields["type"] + def date(self): + return self.__fields["date"] + def number(self): + return self.__fields["cr_number"] + +class BugDB(object): + """Lookup change requests. + + Object can be used on or off of SWAN, using either monaco or + bugs.opensolaris.org as a database. + + Usage: + bdb = BugDB() + r = bdb.lookup("6455550") + print r["6455550"]["synopsis"] + r = bdb.lookup(["6455550", "6505625"]) + print r["6505625"]["synopsis"] + """ + + def __init__(self, forceBoo = False): + """Create a BugDB object. + + Keyword argument: + forceBoo: use b.o.o even from SWAN (default=False) + """ + if forceBoo: + self.__onSWAN = False + else: + self.__onSWAN = onSWAN() + if self.__onSWAN: + self.__m = Monaco() + + def lookup(self, crs): + """Return all info for requested change reports. + + Argument: + crs: one change request id (may be integer, string, or list), + or multiple change request ids (must be a list) + + Returns: + Dictionary, mapping CR=>dictionary, where the nested dictionary + is a mapping of field=>value + """ + if not isinstance(crs, list): + crs = [str(crs)] + if self.__onSWAN: + results = self.__m.queryBugs(crs) + return self.__m.queryBugs(crs) + # else we're off-swan and querying via boo, which we can + # only do one bug at a time + results = {} + for cr in crs: + cr = str(cr) + try: + b = BooBug(cr) + except NonExistentBug: + continue + + results[cr] = {} + results[cr]["cr_number"] = cr + results[cr]["product"] = b.product() + results[cr]["synopsis"] = b.synopsis() + results[cr]["category"] = b.cat() + results[cr]["sub_category"] = b.subcat() + results[cr]["keywords"] = b.keywords() + results[cr]["status"] = b.state() + results[cr]["date_submitted"] = b.submit_date() + results[cr]["type"] = b.type() + results[cr]["date"] = b.date() + + return results + +#################################################################### + +class ARC(object): + """Lookup an ARC case on opensolaris.org. + + Usage: + a = ARC("PSARC", "2008/002") + if a.valid(): + print a.name() + """ + def __init__(self, arc, case): + self.__valid = False + q = "http://opensolaris.org/cgi/arc.py?n=1" + q += "&arc0=" + arc + q += "&case0=" + case + data = urllib.urlopen(q).readlines() + self.__fields = {} + for line in data: + line = line.rstrip('\n') + fields = line.split('|') + validity = fields[0] + + if validity != "0": + return + else: + self.__fields["Name"] = fields[2] + + self.__valid = True + + def valid(self): + return self.__valid + def name(self): + return self.__fields["Name"] + def status(self): + return self.__fields["Status"] + def type(self): + return self.__fields["Type"] + +#################################################################### + +# Pointers to the webrti server hostname & port to use +# Using it directly is probably not *officially* supported, so we'll +# have a pointer to the official `webrticli` command line interface +# if using a direct socket connection fails for some reason, so we +# have a fallback +WEBRTI_HOST = 'webrti.sfbay.sun.com' +WEBRTI_PORT = 9188 +WEBRTICLI = '/net/webrti.sfbay.sun.com/export/home/bin/webrticli' + + +class RtiException(Exception): + def __init__(self, data=''): + self.data = data + Exception.__init__(self, data) + + def __str__(self): + return "Unknown error: %s" % self.data + +# RtiInvalidOutput & RtiCallFailed are our "own" failures +# The other exceptions are triggered from WebRTI itself +class RtiInvalidOutput(RtiException): + def __str__(self): + return "Invalid output from WebRTI: %s" % self.data + +class RtiCallFailed(RtiException): + def __str__(self): + return "Unable to call webrti: %s" % self.data + +class RtiSystemProblem(RtiException): + def __str__(self): + return "RTI status cannot be determined: %s" % self.data + +class RtiIncorrectCR(RtiException): + def __str__(self): + return "Incorrect CR number specified: %s" % self.data + +class RtiNotFound(RtiException): + def __str__(self): + return "RTI not found: %s" % self.data + +class RtiNeedConsolidation(RtiException): + def __str__(self): + return "More than one consolidation has this CR: %s" % self.data + +class RtiBadGate(RtiException): + def __str__(self): + return "Incorrect gate name specified: %s" % self.data + +class RtiOffSwan(RtiException): + def __str__(self): + return "RTI status checks need SWAN access: %s" % self.data + +WEBRTI_ERRORS = { + '1': RtiSystemProblem, + '2': RtiIncorrectCR, + '3': RtiNotFound, + '4': RtiNeedConsolidation, + '5': RtiBadGate, +} + +# Our Rti object which we'll use to represent an Rti query +# It's really just a wrapper around the Rti connection, and attempts +# to establish a direct socket connection and query the webrti server +# directly (thus avoiding a system/fork/exec call). If it fails, it +# falls back to the webrticli command line client. + +returnCodeRe = re.compile(r'.*RETURN_CODE=(\d+)') +class Rti: + """Lookup an RTI. + + Usage: + r = Rti("6640538") + print r.rtiNumber(); + """ + + def __init__(self, cr, gate=None, consolidation=None): + """Create an Rti object for the specified change request. + + Argument: + cr: change request id + + Keyword arguments, to limit scope of RTI search: + gate: path to gate workspace (default=None) + consolidation: consolidation name (default=None) + """ + + bufSz = 1024 + addr = (WEBRTI_HOST, WEBRTI_PORT) + # If the passed 'cr' was given as an int, then wrap it + # into a string to make our life easier + if isinstance(cr, int): + cr = str(cr) + self.__queryCr = cr + self.__queryGate = gate + self.__queryConsolidation = consolidation + + try: + # try to use a direct connection to the + # webrti server first + sock = socket(AF_INET, SOCK_STREAM) + sock.connect(addr) + command = "WEBRTICLI/1.0\nRTIstatus\n%s\n" % cr + if consolidation: + command += "-c\n%s\n" % consolidation + if gate: + command += "-g\n%s\n" % gate + command += "\n" + sock.send(command) + dataList = [] + # keep receiving data from the socket until the + # server closes the connection + stillReceiving = True + while stillReceiving: + dataPiece = sock.recv(bufSz) + if dataPiece: + dataList.append(dataPiece) + else: + stillReceiving = False + # create the lines, skipping the first + # ("WEBRTCLI/1.0\n") + data = '\n'.join(''.join(dataList).split('\n')[1:]) + except: + if not onSWAN(): + raise RtiOffSwan(cr) + + if not os.path.exists(WEBRTICLI): + raise RtiCallFailed('not found') + + # fallback to the "supported" webrticli interface + command = WEBRTICLI + if consolidation: + command += " -c " + consolidation + if gate: + command += " -g " + gate + command += " RTIstatus " + cr + + try: + cliPipe = os.popen(command) + except: + # we couldn't call the webrticli for some + # reason, so return a failure + raise RtiCallFailed('unknown') + + data = cliPipe.readline() + + # parse the data to see if we got a return code + # if we did, then that's bad. if we didn't, + # then our call was successfully + m = returnCodeRe.search(data) + if m: + # we got a return code, set it in our + # object, set the webRtiOutput for debugging + # or logging, and return a failure + if m.group(1) in WEBRTI_ERRORS: + exc = WEBRTI_ERRORS[m.group(1)] + else: + exc = RtiException + raise exc(data) + + if data.count('\n') != 1: + # there shouldn't be more than one line in + # the output. if we got more than one line, + # then let's be paranoid, and abort. + raise RtiInvalidOutput(data) + + # At this point, we should have valid data + data = data.rstrip('\r\n') + self.__webRtiOutput = data + self.__fields = data.split(':') + self.__mainCR = self.__fields[0] + self.__rtiNumber = self.__fields[1] + self.__consolidation = self.__fields[2] + self.__project = self.__fields[3] + self.__status = self.__fields[4] + self.__rtiType = self.__fields[5] + + # accessors in case callers need the raw data + def mainCR(self): + return self.__mainCR + def rtiNumber(self): + return self.__rtiNumber + def consolidation(self): + return self.__consolidation + def project(self): + return self.__project + def status(self): + return self.__status + def rtiType(self): + return self.__rtiType + def queryCr(self): + return self.__queryCr + def queryGate(self): + return self.__queryGate + def queryConsolidation(self): + return self.__queryConsolidation + + # in practice, most callers only care about the following + def accepted(self): + return (self.__status == "S_ACCEPTED") + + # for logging/debugging in case the caller wants the raw webrti output + def webRtiOutput(self): + return self.__webRtiOutput + + diff --git a/usr/src/tools/onbld/Checks/HdrChk.py b/usr/src/tools/onbld/Checks/HdrChk.py new file mode 100644 index 0000000000..32a700a4eb --- /dev/null +++ b/usr/src/tools/onbld/Checks/HdrChk.py @@ -0,0 +1,320 @@ +#! /usr/bin/python +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +# +# Check that header files conform to our standards +# +# Standards for all header files (lenient): +# +# 1) Begin with a comment containing a copyright message +# +# 2) Enclosed in a guard of the form: +# +# #ifndef GUARD +# #define GUARD +# #endif /* [!]GUARD */ +# +# The preferred form is without the bang character, but either is +# acceptable. +# +# 3) Has a valid ident declaration +# +# Additional standards for system header files: +# +# 1) The file guard must take the form '_FILENAME_H[_]', where FILENAME +# matches the basename of the file. If it is installed in a +# subdirectory, it must be of the form _DIR_FILENAME_H. The form +# without the trailing underscore is preferred. +# +# 2) All #include directives must use the <> form. +# +# 3) If the header file contains anything besides comments and +# preprocessor directives, then it must be enclosed in a C++ guard of +# the form: +# +# #ifdef __cplusplus +# extern "C" { +# #endif +# +# #ifdef __cplusplus +# } +# #endif +# + +import re, os, sys + +class HeaderFile(object): + def __init__(self, fh, filename=None, lenient=False): + self.file = fh + self.lenient = lenient + self.lineno = 0 + self.has_copyright = False + self.eof = False + + if filename: + self.filename = filename + else: + self.filename = fh.name + + def getline(self): + for line in self.file: + self.lineno += 1 + if not line or line.isspace(): + continue + else: + line = line.rstrip('\r\n') + + # Recursively join continuation lines + if line.endswith('\\'): + line = line[0:-1] + self.getline() + + return line + else: + self.eof = True + return '' + + # + # Optionally take a line to start skipping/processing with + # + def skipcomments(self, curline=None): + line = curline or self.getline() + while line: + # When lenient, allow C++ comments + if self.lenient and re.search(r'^\s*//', line): + line = self.getline() + continue + + if not re.search(r'^\s*/\*', line): + return line + + while not re.search(r'\*/', line): + # + # We explicitly exclude the form used in the + # CDDL header rather than attempting to craft + # a match for every possibly valid copyright + # notice + # + if re.search(r'Copyright (?!\[yyyy\])', line): + self.has_copyright = True + line = self.getline() + + if re.search(r'Copyright (?!\[yyyy\])', line): + self.has_copyright = True + line = self.getline() + + return line + + +def err(stream, msg, hdr): + if not hdr.eof: + stream.write("%s: line %d: %s\n" % + (hdr.filename, hdr.lineno, msg)) + else: + stream.write("%s: %s\n" % (hdr.filename, msg)) + + +# +# Keyword strings (both expanded and literal) for the various SCMs +# Be certain to wrap each full expression in parens. +# +idents = [ + # SCCS + r'((\%Z\%(\%M\%)\t\%I\%|\%W\%)\t\%E\% SMI)', + r'(@\(#\)(\w[-\.\w]+\.h)\t\d+\.\d+(\.\d+\.\d+)?\t\d\d/\d\d/\d\d SMI)', +] + +IDENT = re.compile(r'(%s)' % '|'.join(idents)) + + +def hdrchk(fh, filename=None, lenient=False, output=sys.stderr): + found_ident = False + guard = None + ret = 0 + + hdr = HeaderFile(fh, filename=filename, lenient=lenient) + + # + # Step 1: + # + # Headers must begin with a comment containing a copyright notice. We + # don't validate the contents of the copyright, only that it exists + # + line = hdr.skipcomments() + + if not hdr.has_copyright: + err(output, "Missing copyright in opening comment", hdr) + ret = 1 + + # + # Step 2: + # + # For application header files only, allow the ident string to appear + # before the header guard. + if lenient and line.startswith("#pragma ident") and IDENT.search(line): + found_ident = 1 + line = hdr.skipcomments() + + # + # Step 3: Header guards + # + match = re.search(r'^#ifndef\s([a-zA-Z0-9_]+)$', line) + if not match: + err(output, "Invalid or missing header guard", hdr) + ret = 1 + else: + guard = match.group(1) + + if not lenient: + guardname = os.path.basename(hdr.filename) + + # + # If we aren't being lenient, validate the name of the + # guard + # + + guardname = guardname.upper() + guardname = guardname.replace('.', '_').replace('-','_') + guardname = guardname.replace('+', "_PLUS") + + if not re.search(r'^_.*%s[_]?$' % guardname, guard): + err(output, "Header guard does not match " + "suggested style (_FILEPATH_H_)", hdr) + ret = 1 + + line = hdr.getline() + if not re.search(r'#define\s%s$' % guard, line): + err(output, "Invalid header guard", hdr) + ret = 1 + if not line: + line = hdr.skipcomments() + else: + line = hdr.skipcomments() + + + # + # Step 4: ident string + # + # We allow both the keyword and extracted versions + # + if (not found_ident and line.startswith("#pragma ident") and + not IDENT.search(line)): + err(output, "Invalid #pragma ident", hdr) + ret = 1 + else: + line = hdr.skipcomments(line) + + # + # Main processing loop + # + in_cplusplus = False + found_endguard = False + found_cplusplus = False + found_code = False + + while line: + if not (line.startswith('#') or line.startswith('using')): + found_code = True + line = hdr.getline() + continue + + match = re.search(r'^#include(.*)$', line) + if match: + # + # For system files, make sure #includes are of the form: + # '#include <file>' + # + if not lenient and not re.search(r'\s<.*>', + match.group(1)): + err(output, "Bad include", hdr) + ret = 1 + elif not in_cplusplus and re.search(r'^#ifdef\s__cplusplus$', + line): + # + # Start of C++ header guard. + # Make sure it is of the form: + # + # #ifdef __cplusplus + # extern "C" { + # #endif + # + line = hdr.getline() + if line == 'extern "C" {': + line = hdr.getline() + if line != '#endif': + err(output, "Bad __cplusplus clause", + hdr) + ret = 1 + else: + in_cplusplus = True + found_cplusplus = True + else: + continue + elif in_cplusplus and re.search(r'^#ifdef\s__cplusplus$', line): + # + # End of C++ header guard. Make sure it is of the form: + # + # #ifdef __cplusplus + # } + # #endif + # + line = hdr.getline() + if line == '}': + line = hdr.getline() + if line != '#endif': + err(output, "Bad __cplusplus clause", + hdr) + ret = 1 + else: + in_cplusplus = False + else: + continue + elif re.search(r'^#endif\s/\* [!]?%s \*/$' % guard, line): + # + # Ending header guard + # + found_endguard = True + + line = hdr.skipcomments() + + # + # Check for missing end clauses + # + if (not lenient) and (not found_cplusplus) and found_code: + err(output, "Missing __cplusplus guard", hdr) + ret = 1 + + if in_cplusplus: + err(output, "Missing closing #ifdef __cplusplus", hdr) + ret = 1 + + if not found_endguard: + err(output, "Missing or invalid ending header guard", hdr) + ret = 1 + + return ret diff --git a/usr/src/tools/onbld/Checks/JStyle.py b/usr/src/tools/onbld/Checks/JStyle.py new file mode 100644 index 0000000000..3941966840 --- /dev/null +++ b/usr/src/tools/onbld/Checks/JStyle.py @@ -0,0 +1,63 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +# +# JStyle, wrap the jstyle tool in a pythonic API +# + +import sys +from onbld.Checks.ProcessCheck import processcheck + + +def jstyle(fh, filename=None, output=sys.stderr, **opts): + opttrans = {'check_continuation': '-c', + 'heuristic': '-h', + 'picky': '-p', + 'ignore_hdr_comment': '-C', + 'verbose': '-v', + 'tabs': '-t'} + + for x in filter(lambda x: x not in opttrans, opts): + raise TypeError('jstyle() got an unexpected keyword ' + 'argument %s' % x) + + options = [opttrans[x] for x in opts if opts[x]] + + if not filename: + filename = fh.name + + ret, tmpfile = processcheck('jstyle', options, fh, output) + + if tmpfile: + for line in tmpfile: + line = line.replace('<stdin>', filename) + output.write(line) + + tmpfile.close() + + return ret diff --git a/usr/src/tools/onbld/Checks/Keywords.py b/usr/src/tools/onbld/Checks/Keywords.py new file mode 100644 index 0000000000..5c374c3abb --- /dev/null +++ b/usr/src/tools/onbld/Checks/Keywords.py @@ -0,0 +1,75 @@ +#! /usr/bin/python +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +# +# Mercurial (lack of) keyword checks +# + +import re, sys + +# A general 'ident'-style decleration, to allow for leniency. +ident = re.compile(r'((\%Z\%(\%M\%)\s+\%I\%|\%W\%)\s+\%E\% SMI)') + +# +# Absolutely anything that appears to be an SCCS keyword. +# It's impossible to programatically differentiate between these +# and other, legitimate, uses of matching strings. +# +anykword = re.compile(r'%[A-ILMP-UWYZ]%') + +def keywords(fh, filename=None, lenient=False, verbose=False, + output=sys.stderr): + '''Search FH for SCCS keywords, which should not be present when + Mercurial is in use. + + If LENIENT, accept #ident-style declarations, for the purposes of + migration''' + + if not filename: + filename = fh.name + + ret = 0 + lineno = 0 + + for line in fh: + line = line.rstrip('\r\n') + lineno += 1 + + if lenient and ident.search(line): + continue + + match = anykword.findall(line) + if match: + ret = 1 + output.write('%s: %d: contains SCCS keywords "%s"\n' % + (filename, lineno, ', '.join(match))) + if verbose: + output.write(" %s\n" % line) + + return ret diff --git a/usr/src/tools/onbld/Checks/Makefile b/usr/src/tools/onbld/Checks/Makefile new file mode 100644 index 0000000000..961a1875be --- /dev/null +++ b/usr/src/tools/onbld/Checks/Makefile @@ -0,0 +1,64 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +include $(SRC)/Makefile.master +include ../../Makefile.tools + +PYSRCS= \ + CStyle.py \ + Cddl.py \ + Comments.py \ + Copyright.py \ + DbLookups.py \ + HdrChk.py \ + JStyle.py \ + Keywords.py \ + ProcessCheck.py \ + Rti.py \ + __init__.py + +PYOBJS = $(PYSRCS:%.py=%.pyc) + +PYFILES= $(PYSRCS) $(PYOBJS) + +ROOTONBLDCHECKSFILES= $(PYFILES:%=$(ROOTONBLDLIBPY)/onbld/Checks/%) +$(ROOTONBLDCHECKSFILES) := FILEMODE = 0444 + +.KEEP_STATE: + +all: $(PYOBJS) + +install: $(ROOTONBLDCHECKSFILES) + +clean: + $(RM) $(PYOBJS) + +$(ROOTONBLDLIBPY)/onbld/Checks/%: % + $(INS.pyfile) + +include ../../Makefile.targ diff --git a/usr/src/tools/onbld/Checks/ProcessCheck.py b/usr/src/tools/onbld/Checks/ProcessCheck.py new file mode 100644 index 0000000000..52ebabd002 --- /dev/null +++ b/usr/src/tools/onbld/Checks/ProcessCheck.py @@ -0,0 +1,70 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +# +# Wrap a command-line check tool in a pythonic API +# + +import subprocess +import tempfile + +def processcheck(command, args, inpt, output): + '''Run a checking command, command, with arguments as args. + Input is provided by inpt (an iterable), error output is + written to output (a stream-like entity). + + Return a tuple (error, handle), where handle is a file handle + (you must close it), containing output from the command.''' + + # + # We use a tempfile for output, rather than a pipe, so we + # don't deadlock with the child if both pipes fill. + # + try: + tmpfile = tempfile.TemporaryFile(prefix=command) + except EnvironmentError, e: + output.write("Could not create temporary file: %s\n" % e) + return (3, None) + + try: + p = subprocess.Popen([command] + args, + stdin=subprocess.PIPE, stdout=tmpfile, + stderr=subprocess.STDOUT, close_fds=False) + except OSError, e: + output.write("Could not execute %s: %s\n" % (command, e)) + return (3, None) + + for line in inpt: + p.stdin.write(line) + + p.stdin.close() + + ret = p.wait() + tmpfile.seek(0) + + return (ret < 0 and 1 or ret, tmpfile) diff --git a/usr/src/tools/onbld/Checks/Rti.py b/usr/src/tools/onbld/Checks/Rti.py new file mode 100644 index 0000000000..a0a1035d37 --- /dev/null +++ b/usr/src/tools/onbld/Checks/Rti.py @@ -0,0 +1,135 @@ +#! /usr/bin/python +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +# +# Check on RTI status for bug IDs passed. +# +# How we obtain the bug IDs will vary per SCM. +# - For Teamware, we want to check the active list comments. +# - For Mercurial, we can check the incoming changegroup (via the +# pretxnchangegroup hook) and abort if necessary +# +# This module is implemented as a generic checking module given a list of +# bug IDs. It can then be wrapped or hooked into whatever SCM with an +# SCM-specific hook to parse and pass the requisite bug IDs +# + +import re, os, sys +from onbld.Checks.DbLookups import Rti, RtiException, RtiNotFound, RtiOffSwan + +patchGateRe = re.compile(r'.*-patch.*') +testGateRe = re.compile(r'.*-(stc2|test)$') + +def rti(bugids, gatePath=None, consolidation=None, + output=sys.stderr): + """Return True iff each of the specified bugids has an approved RTI. + + Required argument: + bugids: list of seven-digit bug ids + + Keyword arguments, used to limit the scope of the RTI search: + gatePath: fully qualified path to gate + consolidation: name of the consolidation + """ + + rtiType = "MarketingRelease" + gateType = "MarketingRelease" + + # Check to see if we were given a gate to lookup with + if gatePath != None: + # strip any trailing / + gatePath.rstrip('/') + gateName = os.path.split(gatePath)[1] + + # Is this a patch gate? + if patchGateRe.search(gatePath): + rtiType = "Patch" + gateType = "Patch" + + # Is this a test gate? + if testGateRe.search(gatePath): + rtiType = "RTI" + gateType = "RTI" + else: + gateName = None + + # Query RTI if there's a gate + # Check the RTIs, caching them in the 'rtis' dictionary + # We do our error checking/handling here + rtis = {} + badRtis = [] + for cr in bugids: + # If we don't already have an Rti object for this cr cached, + # then go create/query it + if cr not in rtis.keys() + badRtis: + try: + rtis[cr] = Rti(cr, gateName, consolidation) + except RtiOffSwan, e: + output.write("%s\n" % e) + return False + except RtiNotFound, e: + output.write("Error: no RTI found for bug %s\n" + % cr) + badRtis.append(cr) + continue + except RtiException, e: + output.write("%s\n" % e) + badRtis.append(cr) + continue + + crRti = rtis[cr] + + # If we've reached this point, then the Rti query succeeded, + # and we didn't get an error back from webrti. There is still + # some sanity checking to be done, however + rtiNumber = crRti.rtiNumber() + rtiType = crRti.rtiType() + + # check to make sure the RTI type matches the gate type + if rtiType != gateType: + output.write( + "Error: for bug %s the RTI %s is of %s type " + "but the parent gate %s is a %s gate.\n" + "A %s RTI must be submitted to putback bug %s " + "to %s.\n" % (cr, rtiNumber, rtiType, gateName, + gateType, gateType, cr, gateName)) + badRtis.append(cr) + continue + + if not crRti.accepted(): + output.write("Error: RTI %s for CR %s is not in " + "the accepted state.\n" % (rtiNumber, cr)) + badRtis.append(cr) + continue + + if len(badRtis) > 0: + return False + + return True + diff --git a/usr/src/tools/onbld/Checks/__init__.py b/usr/src/tools/onbld/Checks/__init__.py new file mode 100644 index 0000000000..d9eae7a9e3 --- /dev/null +++ b/usr/src/tools/onbld/Checks/__init__.py @@ -0,0 +1,58 @@ +#! /usr/bin/python +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +# +# The 'checks' package contains various checks that may be run +# + +__all__ = [ + 'Cddl', + 'Comments', + 'Copyright', + 'CStyle', + 'HdrChk', + 'JStyle', + 'Keywords', + 'Rti', + 'onSWAN'] + + +import socket + +# +# Generic check to test if a host is on SWAN +# +def onSWAN(): + try: + if socket.gethostbyname("sunweb.central.sun.com."): + return True + else: + return False + except: + return False diff --git a/usr/src/tools/onbld/Makefile b/usr/src/tools/onbld/Makefile new file mode 100644 index 0000000000..3da4d86b3e --- /dev/null +++ b/usr/src/tools/onbld/Makefile @@ -0,0 +1,68 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +include $(SRC)/Makefile.master +include ../Makefile.tools + +SUBDIRS= \ + Checks \ + hgext \ + Scm + +PYSRCS= \ + __init__.py + +PYOBJS= $(PYSRCS:%.py=%.pyc) + +PYFILES= $(PYSRCS) $(PYOBJS) + +all := TARGET = all +install := TARGET = install +clean := TARGET = clean + +ROOTONBLDBASEFILES= $(PYFILES:%=$(ROOTONBLDLIBPY)/onbld/%) +$(ROOTONBLDBASEFILES) := FILEMODE = 0444 + +.KEEP_STATE: + +all: $(PYOBJS) $(SUBDIRS) + +install: $(ROOTONBLDBASEFILES) $(SUBDIRS) + +clean: $(SUBDIRS) + $(RM) $(PYOBJS) + +$(ROOTONBLDLIBPY)/onbld/%: % + $(INS.pyfile) + +$(SUBDIRS): FRC + @cd $@; pwd; $(MAKE) $(TARGET) + +FRC: + +include ../Makefile.targ diff --git a/usr/src/tools/onbld/Scm/Backup.py b/usr/src/tools/onbld/Scm/Backup.py new file mode 100644 index 0000000000..bd69bc0a1f --- /dev/null +++ b/usr/src/tools/onbld/Scm/Backup.py @@ -0,0 +1,707 @@ +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 +# as published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# + +# +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +''' +Workspace backup + +Backup format is: + backupdir/ + wsname/ + generation#/ + dirstate (handled by CdmUncommittedBackup) + File containing dirstate nodeid (the tip we expect to be at + after applying the bundle). + + bundle (handled by CdmCommittedBackup) + An Hg bundle containing outgoing committed changes. + + nodes (handled by CdmCommittedBackup) + A text file listing the full (hex) nodeid of all nodes in + bundle, used by need_backup. + + diff (handled by CdmUncommittedBackup) + A Git-formatted diff containing uncommitted changes. + + renames (handled by CdmUncommittedBackup) + A list of renames in the working copy that have to be + applied manually, rather than by the diff. + + metadata.tar.gz (handled by CdmMetadataBackup) + $CODEMGR_WS/.hg/hgrc + $CODEMGR_WS/.hg/localtags + $CODEMGR_WS/.hg/patches (Mq data) + + latest -> generation# + Newest backup generation. + +All files in a given backup generation, with the exception of +dirstate, are optional. +''' + +import os, pwd, shutil, traceback, tarfile, time +from mercurial import changegroup, patch, node, util +from cStringIO import StringIO + + +class CdmCommittedBackup(object): + '''Backup of committed changes''' + + def __init__(self, backup, ws): + self.ws = ws + self.bu = backup + self.files = ('bundle', 'nodes') + + def _outgoing_nodes(self, parent): + '''Return a list of all outgoing nodes in hex format''' + + if parent: + outgoing = self.ws.findoutgoing(parent) + nodes = self.ws.repo.changelog.nodesbetween(outgoing)[0] + return map(node.hex, nodes) + else: + return [] + + def backup(self): + '''Backup committed changes''' + parent = self.ws.parent() + + if not parent: + self.ws.ui.warn('Workspace has no parent, committed changes will ' + 'not be backed up\n') + return + + out = self.ws.findoutgoing(parent) + if not out: + return + + cg = self.ws.repo.changegroup(out, 'bundle') + changegroup.writebundle(cg, self.bu.backupfile('bundle'), 'HG10BZ') + + outnodes = self._outgoing_nodes(parent) + if outnodes: + fp = None + try: + try: + fp = open(self.bu.backupfile('nodes'), 'w') + fp.write('%s\n' % '\n'.join(outnodes)) + except EnvironmentError, e: + raise util.Abort("couldn't store outgoing nodes: %s" % e) + finally: + if fp and not fp.closed: + fp.close() + + def restore(self): + '''Restore committed changes from backup''' + bfile = self.bu.backupfile('bundle') + + if os.path.exists(bfile): + f = None + try: + try: + f = open(bfile, 'r') + bundle = changegroup.readbundle(f, bfile) + self.ws.repo.addchangegroup(bundle, 'strip', + 'bundle:%s' % bfile) + except EnvironmentError, e: + raise util.Abort("couldn't restore committed changes: %s\n" + " %s" % (bfile, e)) + finally: + if f and not f.closed: + f.close() + + def need_backup(self): + '''Compare backup of committed changes to workspace''' + + if os.path.exists(self.bu.backupfile('nodes')): + f = None + try: + try: + f = open(self.bu.backupfile('nodes')) + bnodes = set([line.rstrip('\r\n') + for line in f.readlines()]) + f.close() + except EnvironmentError, e: + raise util.Abort("couldn't open backup node list: %s" % e) + finally: + if f and not f.closed: + f.close() + else: + bnodes = set() + + outnodes = set(self._outgoing_nodes(self.ws.parent())) + if outnodes != bnodes: + return True + + return False + + def cleanup(self): + '''Remove backed up committed changes''' + + for fname in self.files: + if os.path.exists(self.bu.backupfile(fname)): + os.unlink(self.bu.backupfile(fname)) + + +class CdmUncommittedBackup(object): + '''Backup of uncommitted changes''' + + def __init__(self, backup, ws): + self.ws = ws + self.bu = backup + + def _clobbering_renames(self): + '''Return a list of pairs of files representing renames/copies + that clobber already versioned files. [(oldname newname)...]''' + + # + # Note that this doesn't handle uncommitted merges + # as CdmUncommittedBackup itself doesn't. + # + wctx = self.ws.repo.workingctx() + parent = wctx.parents()[0] + + ret = [] + for fname in wctx.added() + wctx.modified(): + rn = wctx.filectx(fname).renamed() + if rn and fname in parent: + ret.append((rn[0], fname)) + return ret + + def backup(self): + '''Backup uncommitted changes''' + + if self.ws.merged(): + raise util.Abort("Unable to backup an uncommitted merge.\n" + "Please complete your merge and commit") + + dirstate = node.hex(self.ws.repo.changectx().node()) + + fp = None + try: + try: + fp = open(self.bu.backupfile('dirstate'), 'w') + fp.write(dirstate + '\n') + except EnvironmentError, e: + raise util.Abort("couldn't save working copy parent: %s" % e) + finally: + if fp and not fp.closed: + fp.close() + + try: + try: + fp = open(self.bu.backupfile('renames'), 'w') + for cons in self._clobbering_renames(): + fp.write("%s %s\n" % cons) + except EnvironmentError, e: + raise util.Abort("couldn't save clobbering copies: %s" % e) + finally: + if fp and not fp.closed: + fp.close() + + try: + try: + fp = open(self.bu.backupfile('diff'), 'w') + patch.diff(self.ws.repo, fp=fp, + opts=patch.diffopts(self.ws.ui, opts={'git': True})) + except EnvironmentError, e: + raise util.Abort("couldn't save working copy diff: %s" % e) + finally: + if fp and not fp.closed: + fp.close() + + def _dirstate(self): + '''Return the current working copy node''' + fp = None + try: + try: + fp = open(self.bu.backupfile('dirstate')) + dirstate = fp.readline().strip() + return dirstate + except EnvironmentError, e: + raise util.Abort("couldn't read saved parent: %s" % e) + finally: + if fp and not fp.closed: + fp.close() + + def restore(self): + '''Restore uncommitted changes''' + diff = self.bu.backupfile('diff') + dirstate = self._dirstate() + + try: + self.ws.clean(rev=dirstate) + except util.Abort, e: + raise util.Abort("couldn't update to saved node: %s" % e) + + if not os.path.exists(diff): + return + + # + # There's a race here whereby if the patch (or part thereof) + # is applied within the same second as the clean above (such + # that mtime doesn't change) and if the size of that file + # does not change, Hg may not see the change. + # + # We sleep a full second to avoid this, as sleeping merely + # until the next second begins would require very close clock + # synchronization on network filesystems. + # + time.sleep(1) + + files = {} + try: + try: + fuzz = patch.patch(diff, self.ws.ui, strip=1, + cwd=self.ws.repo.root, files=files) + if fuzz: + raise util.Abort('working copy diff applied with fuzz') + except Exception, e: + raise util.Abort("couldn't apply working copy diff: %s\n" + " %s" % (diff, e)) + finally: + patch.updatedir(self.ws.ui, self.ws.repo, files) + + if not os.path.exists(self.bu.backupfile('renames')): + return + + # + # We need to re-apply name changes where the new name + # (rename/copy destination) is an already versioned file, as + # Hg would otherwise ignore them. + # + try: + fp = open(self.bu.backupfile('renames')) + for line in fp: + source, dest = line.strip().split() + self.ws.repo.copy(source, dest) + except EnvironmentError, e: + raise util.Abort('unable to open renames file: %s' % e) + except ValueError: + raise util.Abort('corrupt renames file: %s' % + self.bu.backupfile('renames')) + + def need_backup(self): + '''Compare backup of uncommitted changes to workspace''' + if self._dirstate() != node.hex(self.ws.repo.changectx().node()): + return True + + curdiff = StringIO() + diff = self.bu.backupfile('diff') + fd = None + + patch.diff(self.ws.repo, fp=curdiff, + opts=patch.diffopts(self.ws.ui, opts={'git': True})) + + if os.path.exists(diff): + try: + try: + fd = open(diff) + backdiff = fd.read() + except EnvironmentError, e: + raise util.Abort("couldn't open backup diff %s\n" + " %s" % (diff, e)) + finally: + if fd and not fd.closed: + fd.close() + else: + backdiff = '' + + if backdiff != curdiff.getvalue(): + return True + + + currrenamed = self._clobbering_renames() + bakrenamed = None + + if os.path.exists(self.bu.backupfile('renames')): + try: + try: + fd = open(self.bu.backupfile('renames')) + bakrenamed = [line.strip().split(' ') for line in fd] + except EnvironmentError, e: + raise util.Abort("couldn't open renames file %s: %s\n" % + (self.bu.backupfile('renames'), e)) + finally: + if fd and not fd.closed: + fd.close() + + if currrenamed != bakrenamed: + return True + + return False + + def cleanup(self): + '''Remove backed up uncommitted changes''' + for fname in ('dirstate', 'diff', 'renames'): + if os.path.exists(self.bu.backupfile(fname)): + os.unlink(self.bu.backupfile(fname)) + + +class CdmMetadataBackup(object): + '''Backup of workspace metadata''' + + def __init__(self, backup, ws): + self.bu = backup + self.ws = ws + self.files = ('hgrc', 'localtags', 'patches') + + def backup(self): + '''Backup workspace metadata''' + + tar = None + + try: + try: + tar = tarfile.open(self.bu.backupfile('metadata.tar.gz'), + 'w:gz') + tar.errorlevel = 2 + except (EnvironmentError, tarfile.TarError), e: + raise util.Abort("couldn't open %s for writing: %s" % + (self.bu.backupfile('metadata.tar.gz'), e)) + + try: + for elt in self.files: + fpath = self.ws.repo.join(elt) + if os.path.exists(fpath): + tar.add(fpath, elt) + except (EnvironmentError, tarfile.TarError), e: + # + # tarfile.TarError doesn't include the tar member or file + # in question, so we have to do so ourselves. + # + if isinstance(e, tarfile.TarError): + error = "%s: %s" % (elt, e) + else: + error = str(e) + + raise util.Abort("couldn't backup metadata to %s:\n" + " %s" % + (self.bu.backupfile('metadata.tar.gz'), + error)) + finally: + if tar and not tar.closed: + tar.close() + + def old_restore(self): + '''Restore workspace metadata from an pre-tar backup''' + + for fname in self.files: + bfile = self.bu.backupfile(fname) + wfile = self.ws.repo.join(fname) + + if os.path.exists(bfile): + try: + shutil.copy2(bfile, wfile) + except EnvironmentError, e: + raise util.Abort("couldn't restore metadata from %s:\n" + " %s" % (bfile, e)) + + def tar_restore(self): + '''Restore workspace metadata (from a tar-style backup)''' + + if os.path.exists(self.bu.backupfile('metadata.tar.gz')): + tar = None + + try: + try: + tar = tarfile.open(self.bu.backupfile('metadata.tar.gz')) + tar.errorlevel = 2 + except (EnvironmentError, tarfile.TarError), e: + raise util.Abort("couldn't open %s: %s" % + (self.bu.backupfile('metadata.tar.gz'), e)) + + try: + for elt in tar: + tar.extract(elt, path=self.ws.repo.path) + except (EnvironmentError, tarfile.TarError), e: + # Make sure the member name is in the exception message. + if isinstance(e, tarfile.TarError): + error = "%s: %s" % (elt.name, e) + else: + error = str(e) + + raise util.Abort("couldn't restore metadata from %s:\n" + " %s" % + (self.bu.backupfile('metadata.tar.gz'), + error)) + finally: + if tar and not tar.closed: + tar.close() + + def restore(self): + '''Restore workspace metadata''' + + if os.path.exists(self.bu.backupfile('hgrc')): + self.old_restore() + else: + self.tar_restore() + + def need_backup(self): + '''Compare backed up workspace metadata to workspace''' + + if os.path.exists(self.bu.backupfile('metadata.tar.gz')): + try: + tar = tarfile.open(self.bu.backupfile('metadata.tar.gz')) + tar.errorlevel = 2 + except (EnvironmentError, tarfile.TarError), e: + raise util.Abort("couldn't open metadata tarball: %s\n" + " %s" % + (self.bu.backupfile('metadata.tar.gz'), e)) + + for elt in tar: + fpath = self.ws.repo.join(elt.name) + if not os.path.exists(fpath): + return True # File in tar, not workspace + + if elt.isdir(): # Don't care about directories + continue + + if (elt.mtime != os.path.getmtime(fpath) or + elt.size != os.path.getsize(fpath)): + return True + + tarnames = tar.getnames() + tar.close() + else: + tarnames = [] + + for mfile in self.files: + fpath = self.ws.repo.join(mfile) + + if os.path.isdir(fpath): + # Directories in tarfile always end with a '/' + if not mfile.endswith('/'): + mfile += '/' + + if mfile not in tarnames: + return True + + for root, dirs, files in os.walk(fpath, topdown=True): + for elt in files: + path = os.path.join(root, elt) + + rpath = self.ws.repo.path + if not rpath.endswith('/'): + rpath += '/' + + path = path.replace(rpath, '', 1) + if path not in tarnames: + return True # In workspace not tar + else: + if os.path.exists(fpath) and mfile not in tarnames: + return True + + return False + + def cleanup(self): + '''Remove backed up workspace metadata''' + if os.path.exists(self.bu.backupfile('metadata.tar.gz')): + os.unlink(self.bu.backupfile('metadata.tar.gz')) + + +class CdmBackup(object): + '''A backup of a given workspace''' + + def __init__(self, ui, ws, name): + self.ws = ws + self.ui = ui + self.backupdir = self._find_backup_dir(name) + + # + # The order of instances here controls the order the various operations + # are run. + # + # There's some inherent dependence, in that on restore we need + # to restore committed changes prior to uncommitted changes + # (as the parent revision of any uncommitted changes is quite + # likely to not exist until committed changes are restored). + # Metadata restore can happen at any point, but happens last + # as a matter of convention. + # + self.modules = [x(self, ws) for x in [CdmCommittedBackup, + CdmUncommittedBackup, + CdmMetadataBackup]] + + + if os.path.exists(os.path.join(self.backupdir, 'latest')): + generation = os.readlink(os.path.join(self.backupdir, 'latest')) + self.generation = int(os.path.split(generation)[1]) + else: + self.generation = 0 + + def _find_backup_dir(self, name): + '''Find the path to an appropriate backup directory based on NAME''' + backupdir = None + backupbase = None + + if os.path.isabs(name): + return name + + if self.ui.config('cdm', 'backupdir'): + backupbase = os.path.expanduser(self.ui.config('cdm', 'backupdir')) + else: + home = None + + try: + home = os.getenv('HOME') or pwd.getpwuid(os.getuid()).pw_dir + except KeyError: + pass # Handled anyway + + if not home: + raise util.Abort('Could not determine your HOME directory to ' + 'find backup path') + + backupbase = os.path.join(home, 'cdm.backup') + + backupdir = os.path.join(backupbase, name) + + # If backupdir exists, it must be a directory. + if (os.path.exists(backupdir) and not os.path.isdir(backupdir)): + raise util.Abort('%s exists but is not a directory' % backupdir) + + return backupdir + + def backupfile(self, path): + '''return full path to backup file FILE at GEN''' + return os.path.join(self.backupdir, str(self.generation), path) + + def update_latest(self, gen): + '''Update latest symlink to point to the current generation''' + linkpath = os.path.join(self.backupdir, 'latest') + + if os.path.lexists(linkpath): + os.unlink(linkpath) + + os.symlink(str(gen), linkpath) + + def create_gen(self, gen): + '''Create a new backup generation''' + try: + os.makedirs(os.path.join(self.backupdir, str(gen))) + self.update_latest(gen) + except EnvironmentError, e: + raise util.Abort("Couldn't create backup generation %s: %s" % + (os.path.join(self.backupdir, str(gen)), e)) + + def need_backup(self): + '''Compare backed up changes to workspace''' + # + # If there's no current backup generation, or the last backup was + # invalid (lacking the dirstate file), we need a backup regardless + # of anything else. + # + if (not self.generation or + not os.path.exists(self.backupfile('dirstate'))): + return True + + for x in self.modules: + if x.need_backup(): + return True + + return False + + def backup(self): + '''Take a backup of the current workspace''' + + if not os.path.exists(self.backupdir): + try: + os.makedirs(self.backupdir) + except EnvironmentError, e: + raise util.Abort('Could not create backup directory %s: %s' % + (self.backupdir, e)) + + self.generation += 1 + self.create_gen(self.generation) + + # + # Lock the repo, so the backup can be consistent. We need the + # wlock too to make sure the dirstate parent doesn't change + # underneath us. + # + + lock = self.ws.repo.lock() + wlock = self.ws.repo.lock() + + try: + for x in self.modules: + x.backup() + except Exception, e: + if isinstance(e, KeyboardInterrupt): + self.ws.ui.warn("Interrupted\n") + else: + self.ws.ui.warn("Error: %s\n" % e) + + # + # If it's not a 'normal' error, we want to print a stack + # trace now in case the attempt to remove the partial + # backup also fails, and raises a second exception. + # + if (not isinstance(e, (EnvironmentError, util.Abort)) + or self.ws.ui.traceback): + traceback.print_exc() + + for x in self.modules: + x.cleanup() + + os.rmdir(os.path.join(self.backupdir, str(self.generation))) + self.generation -= 1 + + if self.generation != 0: + self.update_latest(self.generation) + else: + os.unlink(os.path.join(self.backupdir, 'latest')) + + raise util.Abort('Backup failed') + + def restore(self, gen=None): + '''Restore workspace from backup + + Restores from backup generation GEN (defaulting to the latest) + into workspace WS.''' + + wlock = self.ws.repo.wlock() + lock = self.ws.repo.lock() + + if not os.path.exists(self.backupdir): + raise util.Abort('Backup directory does not exist: %s' % + (self.backupdir)) + + if gen: + if not os.path.exists(os.path.join(self.backupdir, str(gen))): + raise util.Abort('Backup generation does not exist: %s' % + (os.path.join(self.backupdir, str(gen)))) + self.generation = int(gen) + + if not self.generation: # This is ok, 0 is not a valid generation + raise util.Abort('Backup has no generations: %s' % self.backupdir) + + if not os.path.exists(self.backupfile('dirstate')): + raise util.Abort('Backup %s/%s is incomplete (dirstate missing)' % + (self.backupdir, self.generation)) + + try: + for x in self.modules: + x.restore() + except util.Abort, e: + raise util.Abort('Error restoring workspace:\n' + '%s\n' + 'Workspace will be partially restored' % e) diff --git a/usr/src/tools/onbld/Scm/Makefile b/usr/src/tools/onbld/Scm/Makefile new file mode 100644 index 0000000000..4466ab539c --- /dev/null +++ b/usr/src/tools/onbld/Scm/Makefile @@ -0,0 +1,58 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +include $(SRC)/Makefile.master +include ../../Makefile.tools + +PYSRCS= \ + __init__.py \ + Backup.py \ + Version.py \ + WorkSpace.py + +PYOBJS = $(PYSRCS:%.py=%.pyc) + +PYFILES = $(PYSRCS) $(PYOBJS) + +ROOTONBLDSCMFILES= $(PYFILES:%=$(ROOTONBLDLIBPY)/onbld/Scm/%) + +$(ROOTONBLDSCMFILES) := FILEMODE = 0444 + +.KEEP_STATE: + +all: $(PYOBJS) + +install: all .WAIT $(ROOTONBLDSCMFILES) + +clean: + $(RM) $(PYOBJS) + +$(ROOTONBLDLIBPY)/onbld/Scm/%: % + $(INS.pyfile) + +include ../../Makefile.targ diff --git a/usr/src/tools/onbld/Scm/Version.py b/usr/src/tools/onbld/Scm/Version.py new file mode 100644 index 0000000000..0cb8e6e842 --- /dev/null +++ b/usr/src/tools/onbld/Scm/Version.py @@ -0,0 +1,58 @@ +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 +# as published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# + +# +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" + +''' +Minimal amount of code to check the version of Mercurial in use +against our expectations. +''' + +# +# It is important that this rely on as little of Mercurial as is possible. +# + +from mercurial import version + + +class VersionMismatch(Exception): + "Exception used to indicate a mis-match between Scm tools and Mercurial" + pass + +# +# List of versions that are explicitly acceptable to us +# +GOOD_VERSIONS = ['1.0'] + + +def check_version(): + '''Check that we're running on a suitable version of Mercurial''' + + def versionstring(versions): + '''return the list, versions, as a vaguely grammatical string''' + if len(versions) > 1: + return "%s or %s" % (', '.join(versions[0:-1]), versions[-1]) + else: + return versions[0] + + if version.get_version() not in GOOD_VERSIONS: + raise VersionMismatch("Scm expects Mercurial version %s, " + "actual version is %s" % + (versionstring(GOOD_VERSIONS), + version.get_version())) diff --git a/usr/src/tools/onbld/Scm/WorkSpace.py b/usr/src/tools/onbld/Scm/WorkSpace.py new file mode 100644 index 0000000000..99feb24840 --- /dev/null +++ b/usr/src/tools/onbld/Scm/WorkSpace.py @@ -0,0 +1,830 @@ +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 +# as published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# + +# +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +# +# Theory: +# +# Workspaces have a non-binding parent/child relationship. +# All important operations apply to the changes between the two. +# +# However, for the sake of remote operation, the 'parent' of a +# workspace is not seen as a literal entity, instead the figurative +# parent contains the last changeset common to both parent and child, +# as such the 'parent tip' is actually nothing of the sort, but instead a +# convenient imitation. +# +# Any change made to a workspace is a change to a file therein, such +# changes can be represented briefly as whether the file was +# modified/added/removed as compared to the parent workspace, whether +# the file has a different name in the parent and if so, whether it +# was renamed or merely copied. Each changed file has an +# associated ActiveEntry. +# +# The ActiveList being a list ActiveEntrys can thus present the entire +# change in workspace state between a parent and its child, and is the +# important bit here (in that if it is incorrect, everything else will +# be as incorrect, or more) +# + +import cStringIO +import os +from mercurial import hg, patch, cmdutil, util, node, repo +from mercurial import revlog, repair +from hgext import mq + + +class ActiveEntry(object): + '''Representation of the changes made to a single file. + + MODIFIED - Contents changed, but no other changes were made + ADDED - File is newly created + REMOVED - File is being removed + + Copies are represented by an Entry whose .parentname is non-nil + + Truly copied files have non-nil .parentname and .renamed = False + Renames have non-nil .parentname and .renamed = True + + Do not access any of this information directly, do so via the + + .is_<change>() methods.''' + + MODIFIED = 1 + ADDED = 2 + REMOVED = 3 + + def __init__(self, name): + self.name = name + self.change = None + self.parentname = None + # As opposed to copied (or neither) + self.renamed = False + self.comments = [] + + # + # ActiveEntrys sort by the name of the file they represent. + # + def __cmp__(self, other): + return cmp(self.name, other.name) + + def is_added(self): + return self.change == self.ADDED + + def is_modified(self): + return self.change == self.MODIFIED + + def is_removed(self): + return self.change == self.REMOVED + + def is_renamed(self): + return self.parentname and self.renamed + + def is_copied(self): + return self.parentname and not self.renamed + + +class ActiveList(object): + '''Complete representation of workspace change. + + In practice, a container for ActiveEntrys, and methods to build them, + update them, and deal with them en masse.''' + + def __init__(self, ws, parenttip, revs=None): + self._active = {} + self.ws = ws + + self.revs = revs + + self.base = None + self.parenttip = parenttip + + # + # If we couldn't find a parenttip, the two repositories must + # be unrelated (Hg catches most of this, but this case is valid for it + # but invalid for us) + # + if self.parenttip == None: + raise util.Abort('repository is unrelated') + self.localtip = None + + if revs: + self.base = revs[0] + self.localtip = revs[-1] + + self._comments = [] + + self._build(revs) + + def _build(self, revs): + if not revs: + return + + status = self.ws.status(self.parenttip.node(), self.localtip.node()) + + files = [] + for ctype in status.values(): + files.extend(ctype) + + # + # When a file is renamed, two operations actually occur. + # A file copy from source to dest and a removal of source. + # + # These are represented as two distinct entries in the + # changectx and status (one on the dest file for the + # copy, one on the source file for the remove). + # + # Since these are unconnected in both the context and + # status we can only make the association by explicitly + # looking for it. + # + # We deal with this thusly: + # + # We maintain a dict dest -> source of all copies + # (updating dest as appropriate, but leaving source alone). + # + # After all other processing, we mark as renamed any pair + # where source is on the removed list. + # + copies = {} + + # + # Walk revs looking for renames and adding files that + # are in both change context and status to the active + # list. + # + for ctx in revs: + desc = ctx.description().splitlines() + + self._comments.extend(desc) + + for fname in ctx.files(): + # + # We store comments per-entry as well, for the sake of + # webrev and similar. We store twice to avoid the problems + # of uniquifying comments for the general list (and possibly + # destroying multi-line entities in the process). + # + if fname not in self: + self._addentry(fname) + self[fname].comments.extend(desc) + + try: + fctx = ctx.filectx(fname) + except revlog.LookupError: + continue + + # + # NB: .renamed() is a misnomer, this actually checks + # for copies. + # + rn = fctx.renamed() + if rn: + # + # If the source file is a known copy we know its + # ancestry leads us to the parent. + # Otherwise make sure the source file is known to + # be in the parent, we need not care otherwise. + # + # We detect cycles at a later point. There is no + # reason to continuously handle them. + # + if rn[0] in copies: + copies[fname] = copies[rn[0]] + elif rn[0] in self.parenttip.manifest(): + copies[fname] = rn[0] + + # + # Walk the copy list marking as copied any non-cyclic pair + # where the destination file is still present in the local + # tip (to avoid ephemeral changes) + # + # Where source is removed, mark as renamed, and remove the + # AL entry for the source file + # + for fname, oldname in copies.iteritems(): + if fname == oldname or fname not in self.localtip.manifest(): + continue + + self[fname].parentname = oldname + + if oldname in status['removed']: + self[fname].renamed = True + if oldname in self: + del self[oldname] + + # + # Walk the active list setting the change type for each active + # file. + # + # In the case of modified files that are not renames or + # copies, we do a content comparison, and drop entries that + # are not actually modified. + # + # We walk a copy of the AL such that we can drop entries + # within the loop. + # + for entry in self._active.values(): + if entry.name not in files: + del self[entry.name] + continue + + if entry.name in status['added']: + entry.change = ActiveEntry.ADDED + elif entry.name in status['removed']: + entry.change = ActiveEntry.REMOVED + elif entry.name in status['modified']: + entry.change = ActiveEntry.MODIFIED + + # + # There are cases during a merge where a file will be in + # the status return as modified, but in reality be an + # addition (ie, not in the parenttip). + # + # We need to check whether the file is actually present + # in the parenttip, and set it as an add, if not. + # + if entry.name not in self.parenttip.manifest(): + entry.change = ActiveEntry.ADDED + elif entry.is_modified() and not entry.parentname: + if not self.filecmp(entry): + del self[entry.name] + continue + + assert entry.change + + def __contains__(self, fname): + return fname in self._active + + def __getitem__(self, key): + return self._active[key] + + def __setitem__(self, key, value): + self._active[key] = value + + def __delitem__(self, key): + del self._active[key] + + def __iter__(self): + for entry in self._active.values(): + yield entry + + def _addentry(self, fname): + if fname not in self: + self[fname] = ActiveEntry(fname) + + # + # Return list of files represented in this AL, + # including the parent file of a rename + # + def files(self): + ret = self._active.keys() + + ret.extend([x.parentname for x in self + if x.parentname and x.parentname not in ret]) + return ret + + def comments(self): + return self._comments + + # + # It's not uncommon for a child workspace to itself contain the + # merge of several other children, with initial branch points in + # the parent (possibly from the cset a project gate was created + # from, for instance). + # + # Immediately after recommit, this leaves us looking like this: + # + # * <- recommitted changeset (real tip) + # | + # | * <- Local tip + # |/| + # * | <- parent tip + # | |\ + # | | | + # | | |\ + # | | | | + # | * | | <- Base + # |/_/__/ + # + # [left-most is parent, next is child, right two being + # branches in child, intermediate merges parent->child + # omitted] + # + # Obviously stripping base (the first child-specific delta on the + # main child workspace line) doesn't remove the vestigial branches + # from other workspaces (or in-workspace branches, or whatever) + # + # In reality, what we need to strip in a recommit is any + # child-specific branch descended from the parent (rather than + # another part of the child). Note that this by its very nature + # includes the branch representing the 'main' child workspace. + # + # We calculate these by walking from base (which is guaranteed to + # be the oldest child-local cset) to localtip searching for + # changesets with only one parent cset, and where that cset is not + # part of the active list (and is therefore outgoing). + # + def bases(self): + '''Find the bases that in combination define the "old" + side of a recommitted set of changes, based on AL''' + + get = util.cachefunc(lambda r: self.ws.repo.changectx(r).changeset()) + + # We don't rebuild the AL So the AL local tip is the old tip + revrange = "%s:%s" % (self.base.rev(), self.localtip.rev()) + + changeiter = cmdutil.walkchangerevs(self.ws.repo.ui, self.ws.repo, + [], get, {'rev': [revrange]})[0] + + hold = [] + ret = [] + alrevs = [x.rev() for x in self.revs] + for st, rev, fns in changeiter: + n = self.ws.repo.changelog.node(rev) + if st == 'add': + if rev in alrevs: + hold.append(n) + elif st == 'iter': + if n not in hold: + continue + + p = self.ws.repo.changelog.parents(n) + if p[1] != node.nullid: + continue + + if self.ws.repo.changectx(p[0]).rev() not in alrevs: + ret.append(n) + return ret + + def tags(self): + '''Find tags that refer to a changeset in the ActiveList, + returning a list of 3-tuples (tag, node, is_local) for each. + + We return all instances of a tag that refer to such a node, + not just that which takes precedence.''' + + if os.path.exists(self.ws.repo.join('localtags')): + l = self.ws.repo.opener('localtags').readlines() + ltags = [x.rstrip().split(' ') for x in l] + else: + ltags = [] + + # We want to use the tags file from the localtip + if '.hgtags' in self.localtip.manifest(): + f = self.localtip.filectx('.hgtags') + rtags = [x.rstrip().split(' ') for x in f.data().splitlines()] + else: + rtags = [] + + nodes = [node.hex(n.node()) for n in self.revs] + tags = [] + + for nd, name in rtags: + if nd in nodes: + tags.append((name, self.ws.repo.lookup(nd), False)) + + for nd, name in ltags: + if nd in nodes: + tags.append((name, self.ws.repo.lookup(nd), True)) + + return tags + + def filecmp(self, entry): + '''Compare two revisions of two files + + Return True if file changed, False otherwise. + + The fast path compares file metadata, slow path is a + real comparison of file content.''' + + parentfile = self.parenttip.filectx(entry.parentname or entry.name) + localfile = self.localtip.filectx(entry.name) + + # + # NB: Keep these ordered such as to make every attempt + # to short-circuit the more time consuming checks. + # + if parentfile.size() != localfile.size(): + return True + + if parentfile.fileflags() != localfile.fileflags(): + return True + + if parentfile.cmp(localfile.data()): + return True + + +class WorkSpace(object): + + def __init__(self, repository): + self.repo = repository + self.ui = self.repo.ui + self.name = self.repo.root + + parent = self.repo.ui.expandpath('default') + if parent == 'default': + parent = None + self.parentrepo = parent + + self.activecache = {} + self.outgoingcache = {} + + def parent(self, spec=None): + '''Return canonical workspace parent, either SPEC if passed, + or default parent otherwise''' + return spec or self.parentrepo + + def _localtip(self, bases, heads): + '''Return a tuple (changectx, workingctx) representing the most + representative head to act as the local tip. + + If the working directory is modified, the changectx is its + tipmost local parent (or tipmost parent, if neither is + local), and the workingctx is non-null. + + If the working directory is clean, the workingctx is null. + The changectx is the tip-most local head on the current branch. + If this can't be determined for some reason (e.g., the parent + repo is inacessible), changectx is the tip-most head on the + current branch. + + If the workingctx is non-null it is the actual local tip (and would + be the local tip in any generated ActiveList, for instance), + the better parent revision is returned also to aid callers needing + a real changeset to act as a surrogate for an uncommitted change.''' + + def tipmost_of(nodes): + return sorted(nodes, cmp=lambda x, y: cmp(x.rev(), y.rev()))[-1] + + # + # We need a full set of outgoing nodes such that we can limit + # local branch heads to those which are outgoing + # + outnodes = self.repo.changelog.nodesbetween(bases, heads)[0] + wctx = self.repo.workingctx() + + # + # A modified working context is seen as a proto-branch, where + # the 'heads' from our view are the parent revisions of that + # context. + # (and the working head is it) + # + if (wctx.files() or len(wctx.parents()) > 1 or + wctx.branch() != wctx.parents()[0].branch()): + heads = wctx.parents() + else: + heads = [self.repo.changectx(n) for n in heads] + wctx = None + + localchoices = [n for n in heads if n.node() in outnodes] + return (tipmost_of(localchoices or heads), wctx) + + def _parenttip(self, localtip, parent=None): + '''Find the closest approximation of the parents tip, as best + as we can. + + In parent-less workspaces returns our tip (given the best + we can do is deal with uncommitted changes)''' + + def tipmost_shared(head, outnodes): + '''Return the tipmost node on the same branch as head that is not + in outnodes. + + We walk from head to the bottom of the workspace (revision + 0) collecting nodes not in outnodes during the add phase + and return the first node we see in the iter phase that + was previously collected. + + See the docstring of mercurial.cmdutil.walkchangerevs() + for the phased approach to the iterator returned. The + important part to note is that the 'add' phase gathers + nodes, which the 'iter' phase then iterates through.''' + + get = util.cachefunc(lambda r: self.repo.changectx(r).changeset()) + changeiter = cmdutil.walkchangerevs(self.repo.ui, self.repo, [], + get, {'rev': ['%s:0' % head], + 'follow': True})[0] + seen = [] + for st, rev, fns in changeiter: + n = self.repo.changelog.node(rev) + if st == 'add': + if n not in outnodes: + seen.append(n) + elif st == 'iter': + if n in seen: + return rev + return None + + tipctx, wctx = localtip + parent = self.parent(parent) + outgoing = None + + if parent: + outgoing = self.findoutgoing(parent) + + if wctx: + possible_branches = wctx.parents() + else: + possible_branches = [tipctx] + + nodes = self.repo.changelog.nodesbetween(outgoing)[0] + ptips = map(lambda x: tipmost_shared(x.rev(), nodes), possible_branches) + return self.repo.changectx(sorted(ptips)[-1]) + + def status(self, base=None, head=None): + '''Translate from the hg 6-tuple status format to a hash keyed + on change-type''' + states = ['modified', 'added', 'removed', 'deleted', 'unknown', + 'ignored'] + chngs = self.repo.status(base, head) + return dict(zip(states, chngs)) + + # + # Cache findoutgoing results + # + def findoutgoing(self, parent): + ret = [] + if parent in self.outgoingcache: + ret = self.outgoingcache[parent] + else: + self.ui.pushbuffer() + try: + pws = hg.repository(self.ui, parent) + ret = self.repo.findoutgoing(pws) + except repo.RepoError: + self.ui.warn( + "Warning: Parent workspace %s is not accessible\n" % parent) + self.ui.warn("active list will be incomplete\n\n") + + self.outgoingcache[parent] = ret + self.ui.popbuffer() + + return ret + + def modified(self): + '''Return a list of files modified in the workspace''' + wctx = self.repo.workingctx() + return sorted(wctx.files() + wctx.deleted()) or None + + def merged(self): + '''Return boolean indicating whether the workspace has an uncommitted + merge''' + wctx = self.repo.workingctx() + return len(wctx.parents()) > 1 + + def branched(self): + '''Return boolean indicating whether the workspace has an + uncommitted named branch''' + + wctx = self.repo.workingctx() + return wctx.branch() != wctx.parents()[0].branch() + + def active(self, parent=None): + '''Return an ActiveList describing changes between workspace + and parent workspace (including uncommitted changes). + If workspace has no parent ActiveList will still describe any + uncommitted changes''' + + parent = self.parent(parent) + if parent in self.activecache: + return self.activecache[parent] + + if parent: + outgoing = self.findoutgoing(parent) + else: + outgoing = [] # No parent, no outgoing nodes + + branchheads = self.repo.heads(start=self.repo.dirstate.parents()[0]) + ourhead, workinghead = self._localtip(outgoing, branchheads) + + if len(branchheads) > 1: + self.ui.warn('The current branch has more than one head, ' + 'using %s\n' % ourhead.rev()) + + if workinghead: + parents = workinghead.parents() + ctxs = [self.repo.changectx(n) for n in + self.repo.changelog.nodesbetween(outgoing, + [h.node() for h in + parents])[0]] + ctxs.append(workinghead) + else: + ctxs = [self.repo.changectx(n) for n in + self.repo.changelog.nodesbetween(outgoing, + [ourhead.node()])[0]] + + act = ActiveList(self, self._parenttip((ourhead, workinghead), parent), + ctxs) + + self.activecache[parent] = act + return act + + def pdiff(self, parent=None): + 'Return diffs relative to PARENT, as best as we can make out' + + parent = self.parent(parent) + act = self.active(parent) + + # + # act.localtip maybe nil, in the case of uncommitted local + # changes. + # + if not act.revs: + return + + ret = cStringIO.StringIO() + patch.diff(self.repo, act.parenttip.node(), act.localtip.node(), + fp=ret) + return ret.getvalue() + + # + # Theory: + # + # We wish to go from a single series of consecutive changesets + # (possibly including merges with the parent) to a single + # changeset faithfully representing contents and copy history. + # + # We achieve this in a somewhat confusing fashion. + # + # - Sanity check the workspace + # - Update the workspace to tip + # - Enter into the dirstate the sum total of file contents in the + # to-be-squished changesets + # - Commit this in-progress change (which has no changes at all, + # in reality) On top of the effective parent tip. + # - Strip the child-local branch(es) (see ActiveList.bases()) + # + def squishdeltas(self, active, message, user=None): + '''Create a single conglomerate changeset, with log message MESSAGE + containing the changes from ACTIVE. USER, if set, is used + as the author name. + + The old changes are removed.''' + + def strip_tags(nodes): + '''Remove any tags referring to the specified nodes.''' + + if os.path.exists(self.repo.join('localtags')): + fh = self.repo.opener('localtags').readlines() + tags = [t for t in fh if t.split(' ')[0] not in nodes] + fh = self.repo.opener('localtags', 'w', atomictemp=True) + fh.writelines(tags) + fh.rename() + + if os.path.exists(self.repo.wjoin('.hgtags')): + fh = self.repo.wopener('.hgtags', 'rb').readlines() + tags = [t for t in fh if t.split(' ')[0] not in nodes] + fh = self.repo.wopener('.hgtags', 'wb', atomictemp=True) + fh.writelines(tags) + fh.rename() + + wlock = self.repo.wlock() + lock = self.repo.lock() + + # + # The files involved need to be present in the workspace and + # not otherwise molested, rather than the workspace not being + # modified we also need to prevent files being deleted (but + # left versioned) too. + # + # The easiest way to achieve this is to update the working + # copy to tip. + # + self.clean() + + try: + strip_tags([node.hex(ctx.node()) for ctx in active.revs]) + except EnvironmentError, e: + raise util.Abort('Could not recommit tags: %s\n' % e) + + # + # For copied files, we need to enter the copy into the + # dirstate before we force the commit such that the + # file logs of both branches (old and new) contain + # representation of the copy. + # + parentman = active.parenttip.manifest() + for entry in active: + if not entry.is_renamed() and not entry.is_copied(): + continue + + assert entry.parentname in parentman, \ + ("parentname '%s' (of '%s') not in parent" % + (entry.parentname, entry.name)) + + # + # If the source file exists, and used to be versioned + # this will cause this to become a true copy + # (re-introducing the source file) + # + # We bandaid this, by removing the source file in this + # case. If we're here, the user has already agreed to this + # from above. + # + if (entry.is_renamed() and + os.path.exists(self.repo.wjoin(entry.parentname))): + os.unlink(self.repo.wjoin(entry.parentname)) + + self.repo.copy(entry.parentname, entry.name) + + if active.files(): + extra = {'branch': active.localtip.branch()} + self.repo.commit(files=active.files(), text=message, + user=user, p1=active.parenttip.node(), p2=None, + extra=extra) + wsstate = "recommitted changeset" + self.clean() + else: + # + # If all we're doing is stripping the old nodes, we want to + # update the working copy such that we're not at a revision + # that's about to go away. + # + wsstate = "tip changeset" + self.clean(rev=active.parenttip.node()) + + # Silence all the strip and update fun + self.ui.pushbuffer() + + # + # We must strip away the old representation of the child + # branch(es). This may involve stripping a theoretically + # large number of branches in certain cases + # + bases = active.bases() + try: + try: + for basenode in bases: + repair.strip(self.ui, self.repo, basenode, backup=False) + except: + # + # If this fails, it may leave us in a surprising place in + # the history. + # + # We want to warn the user that something went wrong, + # and what will happen next, re-raise the exception, and + # bring the working copy back into a consistent state + # (which the finally block will do) + # + self.ui.warn("stripping failed, your workspace will have " + "superfluous heads.\n" + "your workspace has been updated to the " + "%s.\n" % wsstate) + raise # Re-raise the exception + finally: + # + # We need to remove Hg's undo information (used for rollback), + # since it refers to data that will probably not exist after + # the strip. + # + + self.clean() + self.repo.dirstate.write() # Flush the dirstate + self.repo.invalidate() # Invalidate caches + + if os.path.exists(self.repo.sjoin('undo')): + try: + os.unlink(self.repo.sjoin('undo')) + except EnvironmentError, e: + raise util.Abort('failed to remove undo data: %s\n' % e) + + self.ui.popbuffer() + + def filepath(self, path): + 'Return the full path to a workspace file.' + return self.repo.pathto(path) + + def clean(self, rev=None): + '''Bring workspace up to REV (or tip) forcefully (discarding in + progress changes)''' + if rev != None: + rev = self.repo.lookup(rev) + else: + rev = self.repo.changelog.tip() + + wlock = self.repo.wlock() + hg.clean(self.repo, rev, show_stats=False) + + def mq_applied(self): + '''True if the workspace has Mq patches applied''' + q = mq.queue(self.ui, self.repo.join('')) + return q.applied diff --git a/usr/src/tools/onbld/Scm/__init__.py b/usr/src/tools/onbld/Scm/__init__.py new file mode 100644 index 0000000000..f45ecbc95f --- /dev/null +++ b/usr/src/tools/onbld/Scm/__init__.py @@ -0,0 +1,28 @@ +#! /usr/bin/python +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# diff --git a/usr/src/tools/onbld/__init__.py b/usr/src/tools/onbld/__init__.py new file mode 100644 index 0000000000..7fb929ec5e --- /dev/null +++ b/usr/src/tools/onbld/__init__.py @@ -0,0 +1,26 @@ +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# diff --git a/usr/src/tools/onbld/hgext/Makefile b/usr/src/tools/onbld/hgext/Makefile new file mode 100644 index 0000000000..8295b93a63 --- /dev/null +++ b/usr/src/tools/onbld/hgext/Makefile @@ -0,0 +1,56 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +include $(SRC)/Makefile.master +include ../../Makefile.tools + +PYSRCS= \ + __init__.py \ + cdm.py \ + +PYOBJS = $(PYSRCS:%.py=%.pyc) + +PYFILES = $(PYSRCS) $(PYOBJS) + +ROOTONBLDHGEXTFILES= $(PYFILES:%=$(ROOTONBLDLIBPY)/onbld/hgext/%) + +$(ROOTONBLDHGEXTFILES) := FILEMODE = 0444 + +.KEEP_STATE: + +all: $(PYOBJS) + +install: all .WAIT $(ROOTONBLDHGEXTFILES) + +clean: + $(RM) $(PYOBJS) + +$(ROOTONBLDLIBPY)/onbld/hgext/%: % + $(INS.pyfile) + +include ../../Makefile.targ diff --git a/usr/src/tools/onbld/hgext/__init__.py b/usr/src/tools/onbld/hgext/__init__.py new file mode 100644 index 0000000000..f45ecbc95f --- /dev/null +++ b/usr/src/tools/onbld/hgext/__init__.py @@ -0,0 +1,28 @@ +#! /usr/bin/python +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# diff --git a/usr/src/tools/onbld/hgext/cdm.py b/usr/src/tools/onbld/hgext/cdm.py new file mode 100644 index 0000000000..144afd4c61 --- /dev/null +++ b/usr/src/tools/onbld/hgext/cdm.py @@ -0,0 +1,897 @@ +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 +# as published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# + +# +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +'''workspace extensions for mercurial + +This extension contains a number of commands to help you work within +the OpenSolaris consolidations. + +Common uses: + +Show diffs relative to parent workspace - pdiffs +Check source style rules - nits +Run pre-putback checks - pbchk +Collapse all your changes into a single changeset - recommit''' + + +# +# NB: This assumes the normal directory structure, with this +# extension 2 levels below .../lib/python. +# +# If you change that, change this +# +import sys, os +sys.path.insert(1, "%s/../../" % os.path.dirname(__file__)) + +from onbld.Scm import Version +from mercurial import util + +try: + Version.check_version() +except Version.VersionMismatch, badversion: + raise util.Abort("Version Mismatch:\n %s\n" % badversion) + +import ConfigParser +from mercurial import cmdutil, node + +from onbld.Scm.WorkSpace import WorkSpace, ActiveEntry +from onbld.Scm.Backup import CdmBackup +from onbld.Checks import Cddl, Comments, Copyright, CStyle, HdrChk +from onbld.Checks import JStyle, Keywords, Rti, onSWAN + + +def yes_no(ui, msg, default): + if default: + prompt = ' [Y/n]:' + defanswer = 'y' + else: + prompt = ' [y/N]:' + defanswer = 'n' + + if ui.interactive and sys.stdin.isatty(): + resp = ui.prompt(msg + prompt, r'([Yy(es)?|[Nn]o?)?', + default=defanswer) + if not resp: + return default + elif resp[0] in ['Y', 'y']: + return True + else: + return False + else: + return default + +# +# Adding a reference to WorkSpace from a repo causes a circular reference +# repo <-> WorkSpace. +# +# This prevents repo, WorkSpace and members thereof from being garbage +# collected. Since transactions are aborted when the transaction object +# is collected, and localrepo holds a reference to the most recently created +# transaction, this prevents transactions from cleanly aborting. +# +# Instead, we hold the repo->WorkSpace association in a dictionary, breaking +# that dependence. +# +wslist = {} + + +def reposetup(ui, repo): + if repo.local() and repo not in wslist: + wslist[repo] = WorkSpace(repo) + + +def cdm_pdiffs(ui, repo, parent=None): + '''list workspace diffs relative to parent workspace + + The parent tip is taken to be the latest revision shared between + us and the parent workspace.''' + diffs = wslist[repo].pdiff(parent) + if diffs: + ui.write(diffs) + + +def cdm_list(ui, repo, **opts): + '''list files changed relative to parent workspace + + The parent tip is taken to be the latest revision shared between + us and the parent workspace.''' + + wanted = [] + + if opts['added']: + wanted.append(ActiveEntry.ADDED) + if opts['modified']: + wanted.append(ActiveEntry.MODIFIED) + if opts['removed']: + wanted.append(ActiveEntry.REMOVED) + + act = wslist[repo].active(opts['parent']) + chngmap = {ActiveEntry.MODIFIED: 'modified', + ActiveEntry.ADDED: 'added', + ActiveEntry.REMOVED: 'removed'} + + lst = {} + for entry in act: + if wanted and (entry.change not in wanted): + continue + + chngstr = chngmap[entry.change] + if chngstr not in lst: + lst[chngstr] = [] + lst[chngstr].append(entry) + + for chng in sorted(lst.keys()): + ui.write(chng + ':\n') + for elt in sorted(lst[chng]): + if elt.is_renamed(): + ui.write('\t%s (renamed from %s)\n' % (elt.name, + elt.parentname)) + elif elt.is_copied(): + ui.write('\t%s (copied from %s)\n' % (elt.name, + elt.parentname)) + else: + ui.write('\t%s\n' % elt.name) + + +def cdm_arcs(ui, repo, parent=None): + 'show all ARC cases in checkin comments' + act = wslist[repo].active(parent) + + # We take a set of the appropriate comments to eliminate duplicates. + for elt in set(filter(Comments.isARC, act.comments())): + ui.write(elt + '\n') + + +def cdm_bugs(ui, repo, parent=None): + 'show all bug IDs in checkin comments' + act = wslist[repo].active(parent) + + for elt in set(filter(Comments.isBug, act.comments())): + ui.write(elt + '\n') + + +def cdm_comments(ui, repo, parent=None): + 'show checkin comments for active files' + act = wslist[repo].active(parent) + + for elt in act.comments(): + ui.write(elt + '\n') + + +def cdm_renamed(ui, repo, parent=None): + '''show renamed active files + + Renamed files are shown in the format + + newname oldname + + One pair per-line.''' + + act = wslist[repo].active(parent) + + for entry in sorted(filter(lambda x: x.is_renamed(), act)): + ui.write('%s %s\n' % (entry.name, entry.parentname)) + + +def cdm_comchk(ui, repo, **opts): + '''check checkin comments for active files + + Check that checkin comments conform to O/N rules.''' + + active = opts.get('active') or wslist[repo].active(opts['parent']) + + ui.write('Comments check:\n') + + check_db = not opts['nocheck'] + return Comments.comchk(active.comments(), check_db=check_db, output=ui) + + +def cdm_cddlchk(ui, repo, **opts): + '''check for a valid CDDL block in active files + + See http://www.opensolaris.org/os/community/on/devref_toc/devref_7/#7_2_3_nonformatting_considerations + for more info.''' + + active = opts.get('active') or wslist[repo].active(opts['parent']) + + ui.write('CDDL block check:\n') + + lenient = True + ret = 0 + + for entry in sorted(active): + if entry.is_removed(): + continue + elif entry.is_added(): + lenient = False + else: + lenient = True + + path = wslist[repo].filepath(entry.name) + fh = open(path, 'r') + ret |= Cddl.cddlchk(fh, lenient=lenient, output=ui) + fh.close() + return ret + + +def cdm_copyright(ui, repo, **opts): + '''check active files for valid copyrights + + Check that all active files have a valid copyright containing the + current year (and *only* the current year). + See http://www.opensolaris.org/os/project/muskoka/on_dev/golden_rules.txt + for more info.''' + + active = opts.get('active') or wslist[repo].active(opts['parent']) + + ui.write('Copyright check:\n') + + ret = 0 + + for entry in sorted(active): + if entry.is_removed(): + continue + + path = wslist[repo].filepath(entry.name) + + fh = open(path, 'r') + ret |= Copyright.copyright(fh, output=ui) + fh.close() + return ret + + +def cdm_hdrchk(ui, repo, **opts): + '''check active header files conform to O/N rules''' + + active = opts.get('active') or wslist[repo].active(opts['parent']) + + ui.write('Header format check:\n') + + ret = 0 + + for entry in sorted(active): + if entry.is_removed(): + continue + + path = wslist[repo].filepath(entry.name) + + if entry.name.endswith('.h'): + fh = open(path, 'r') + ret |= HdrChk.hdrchk(fh, lenient=True, output=ui) + fh.close() + return ret + + +def cdm_cstyle(ui, repo, **opts): + '''check active C source files conform to the C Style Guide + + See http://opensolaris.org/os/community/documentation/getting_started_docs/cstyle.ms.pdf''' + + active = opts.get('active') or wslist[repo].active(opts['parent']) + + ui.write('C style check:\n') + + ret = 0 + + for entry in sorted(active): + if entry.is_removed(): + continue + + path = wslist[repo].filepath(entry.name) + + if entry.name.endswith('.c') or entry.name.endswith('.h'): + fh = open(path, 'r') + ret |= CStyle.cstyle(fh, output=ui, + picky=True, check_posix_types=True, + check_continuation=True) + fh.close() + return ret + + +def cdm_jstyle(ui, repo, **opts): + 'check active Java source files for common stylistic errors' + + active = opts.get('active') or wslist[repo].active(opts['parent']) + + ui.write('Java style check:\n') + + ret = 0 + + for entry in sorted(active): + if entry.is_removed(): + continue + + path = wslist[repo].filepath(entry.name) + + if entry.name.endswith('.java'): + fh = open(path, 'r') + ret |= JStyle.jstyle(fh, output=ui, picky=True) + fh.close() + return ret + + +def cdm_permchk(ui, repo, **opts): + '''check active files permission - warn +x (execute) mode''' + + active = opts.get('active') or wslist[repo].active(opts['parent']) + + ui.write('File permission check:\n') + + exeFiles = [] + for entry in sorted(active): + if entry.is_removed(): + continue + + path = wslist[repo].filepath(entry.name) + + if active.localtip.manifest().execf(path): + exeFiles.append(path) + + if len(exeFiles) > 0: + ui.write('Warning: the following active file(s) have executable mode ' + '(+x) permission set,\nremove unless intentional:\n') + for fname in exeFiles: + ui.write(" %s\n" % fname) + + return len(exeFiles) > 0 + + +def cdm_tagchk(ui, repo, **opts): + '''check if .hgtags is active and issue warning + + Tag sharing among repositories is restricted to gatekeepers''' + + active = opts.get('active') or wslist[repo].active(opts['parent']) + + ui.write('Checking for new tags:\n') + + if ".hgtags" in active: + tfile = wslist[repo].filepath('.hgtags') + ptip = active.parenttip.rev() + + ui.write('Warning: Workspace contains new non-local tags.\n' + 'Only gatekeepers should add or modify such tags.\n' + 'Use the following commands to revert these changes:\n' + ' hg revert -r%d %s\n' + ' hg commit %s\n' + 'You should also recommit before integration\n' % + (ptip, tfile, tfile)) + + return 1 + + return 0 + + +def cdm_branchchk(ui, repo, **opts): + '''check if multiple heads (or branches) are present, or if + branch changes are made''' + + active = opts.get('active') or wslist[repo].active(opts['parent']) + + ui.write('Checking for multiple heads (or branches):\n') + + heads = set(repo.heads()) + parents = set([x.node() for x in repo.workingctx().parents()]) + + # + # We care if there's more than one head, and those heads aren't + # identical to the dirstate parents (if they are identical, it's + # an uncommitted merge which mergechk will catch, no need to + # complain twice). + # + if len(heads) > 1 and heads != parents: + ui.write('Workspace has multiple heads (or branches):\n') + for head in [repo.changectx(head) for head in heads]: + ui.write(" %d:%s\t%s\n" % + (head.rev(), str(head), head.description().splitlines()[0])) + ui.write('You must merge and recommit.\n') + return 1 + + ui.write('\nChecking for branch changes:\n') + + if active.localtip.branch() != 'default': + ui.write("Warning: Workspace tip has named branch: '%s'\n" + "Only gatekeepers should push new branches.\n" + "Use the following commands to restore the branch name:\n" + " hg branch [-f] default\n" + " hg commit\n" + "You should also recommit before integration\n" % + (active.localtip.branch())) + return 1 + + branches = repo.branchtags().keys() + if len(branches) > 1: + ui.write('Warning: Workspace has named branches:\n') + for t in branches: + if t == 'default': + continue + ui.write("\t%s\n" % t) + + ui.write("Only gatekeepers should push new branches.\n" + "Use the following commands to remove extraneous branches.\n" + " hg branch [-f] default\n" + " hg commit" + "You should also recommit before integration\n") + return 1 + + return 0 + + +def cdm_rtichk(ui, repo, **opts): + '''check active bug/RFEs for approved RTIs + + Only works on SWAN.''' + + if opts['nocheck']: + ui.status('Skipping RTI checks...\n') + return 0 + + if not onSWAN(): + ui.write('RTI checks only work on SWAN, skipping...\n') + return 0 + + active = opts.get('active') or wslist[repo].active(opts['parent']) + + ui.write('RTI check:\n') + + bugs = [] + + for com in active.comments(): + match = Comments.isBug(com) + if match and match.group(1) not in bugs: + bugs.append(match.group(1)) + + # RTI normalizes the gate path for us + return int(not Rti.rti(bugs, gatePath=opts['parent'], output=ui)) + + +def cdm_keywords(ui, repo, **opts): + '''check source files do not contain SCCS keywords''' + + active = opts.get('active') or wslist[repo].active(opts['parent']) + + ui.write('Keywords check:\n') + + ret = 0 + for entry in sorted(active): + if entry.is_removed(): + continue + + path = wslist[repo].filepath(entry.name) + fh = open(path, 'r') + ret |= Keywords.keywords(fh, output=ui) + fh.close() + return ret + + +# +# NB: +# There's no reason to hook this up as an invokable command, since +# we have 'hg status', but it must accept the same arguments. +# +def cdm_outchk(ui, repo, **opts): + '''Warn the user if they have uncommitted changes''' + + ui.write('Checking for uncommitted changes:\n') + + st = wslist[repo].modified() + if st: + ui.write('Warning: the following files have uncommitted changes:\n') + for elt in st: + ui.write(' %s\n' % elt) + return 1 + return 0 + + +def cdm_mergechk(ui, repo, **opts): + '''Warn the user if their workspace contains merges''' + + active = opts.get('active') or wslist[repo].active(opts['parent']) + + ui.write('Checking for merges:\n') + + merges = filter(lambda x: len(x.parents()) == 2 and x.parents()[1], + active.revs) + + if merges: + ui.write('Workspace contains the following merges:\n') + for rev in merges: + desc = rev.description().splitlines() + ui.write(' %s:%s\t%s\n' % + (rev.rev() or "working", str(rev), + desc and desc[0] or "*** uncommitted change ***")) + return 1 + return 0 + + +def run_checks(ws, cmds, **opts): + '''Run CMDS (with OPTS) over active files in WS''' + active = ws.active(opts['parent']) + + ret = 0 + + for cmd in cmds: + name = cmd.func_name.split('_')[1] + if not ws.ui.configbool('cdm', name, True): + ws.ui.status('Skipping %s check...\n' % name) + else: + ws.ui.pushbuffer() + + result = cmd(ws.ui, ws.repo, active=active, **opts) + ret |= result + + output = ws.ui.popbuffer() + if not ws.ui.quiet or result != 0: + ws.ui.write(output, '\n') + return ret + + +def cdm_nits(ui, repo, **opts): + '''check for stylistic nits in active files + + Run cddlchk, copyright, cstyle, hdrchk, jstyle, permchk, and + keywords checks.''' + + cmds = [cdm_cddlchk, + cdm_copyright, + cdm_cstyle, + cdm_hdrchk, + cdm_jstyle, + cdm_permchk, + cdm_keywords] + + return run_checks(wslist[repo], cmds, **opts) + + +def cdm_pbchk(ui, repo, **opts): + '''pre-putback check all active files + + Run cddlchk, comchk, copyright, cstyle, hdrchk, jstyle, permchk, tagchk, + branchchk, keywords and rtichk checks. Additionally, warn about + uncommitted changes.''' + + # + # The current ordering of these is that the commands from cdm_nits + # run first in the same order as they would in cdm_nits. Then the + # pbchk specifics run + # + cmds = [cdm_cddlchk, + cdm_copyright, + cdm_cstyle, + cdm_hdrchk, + cdm_jstyle, + cdm_permchk, + cdm_keywords, + cdm_comchk, + cdm_tagchk, + cdm_branchchk, + cdm_rtichk, + cdm_outchk, + cdm_mergechk] + + return run_checks(wslist[repo], cmds, **opts) + + +def cdm_recommit(ui, repo, **opts): + '''compact outgoing deltas into a single, conglomerate delta''' + + if not os.getcwd().startswith(repo.root): + raise util.Abort('recommit is not safe to run with -R') + + if wslist[repo].modified(): + raise util.Abort('workspace has uncommitted changes') + + if wslist[repo].merged(): + raise util.Abort('workspace contains uncommitted merge') + + if wslist[repo].branched(): + raise util.Abort('workspace contains uncommitted branch') + + if wslist[repo].mq_applied(): + raise util.Abort("workspace has Mq patches applied") + + wlock = repo.wlock() + lock = repo.lock() + + heads = repo.heads() + if len(heads) > 1: + ui.warn('Workspace has multiple heads (or branches):\n') + for head in heads: + ui.warn('\t%d\n' % repo.changelog.rev(head)) + raise util.Abort('you must merge before recommitting') + + active = wslist[repo].active(opts['parent']) + + if len(active.revs) <= 0: + raise util.Abort("no changes to recommit") + + if len(active.files()) <= 0: + ui.warn("Recommitting %d active changesets, but no active files\n" % + len(active.revs)) + + # + # During the course of a recommit, any file bearing a name matching the + # source name of any renamed file will be clobbered by the operation. + # + # As such, we ask the user before proceeding. + # + bogosity = [f.parentname for f in active if f.is_renamed() and + os.path.exists(repo.wjoin(f.parentname))] + + if bogosity: + ui.warn("The following file names are the original name of a rename " + "and also present\n" + "in the working directory:\n") + for fname in bogosity: + ui.warn(" %s\n" % fname) + if not yes_no(ui, "These files will be removed by recommit. Continue?", + False): + raise util.Abort("recommit would clobber files") + + user = opts['user'] or ui.username() + + message = cmdutil.logmessage(opts) or ui.edit('\n'.join(active.comments()), + user) + if not message: + raise util.Abort('empty commit message') + + name = backup_name(repo.root) + bk = CdmBackup(ui, wslist[repo], name) + if bk.need_backup(): + if yes_no(ui, 'Do you want to backup files first?', True): + bk.backup() + + oldtags = repo.tags() + clearedtags = [(name, nd, repo.changelog.rev(nd), local) + for name, nd, local in active.tags()] + + wslist[repo].squishdeltas(active, message, user=user) + + if clearedtags: + ui.write("Removed tags:\n") + for name, nd, rev, local in clearedtags: + ui.write(" %s %s:%s%s\n" % (name, rev, node.short(nd), + (local and ' (local)') or '')) + + for ntag, nnode in repo.tags().items(): + if ntag in oldtags and ntag != "tip": + if oldtags[ntag] != nnode: + ui.write("tag %s now refers to revision %d:%s\n" % + (ntag, repo.changelog.rev(nnode), node.short(nnode))) + + +def do_eval(cmd, files, root, changedir=True): + if not changedir: + os.chdir(root) + + for path in sorted(files): + dirn, base = os.path.split(path) + + if changedir: + os.chdir(os.path.join(root, dirn)) + + os.putenv('workspace', root) + os.putenv('filepath', path) + os.putenv('dir', dirn) + os.putenv('file', base) + os.system(cmd) + + +def cdm_eval(ui, repo, *command, **opts): + '''run cmd for each active file + + cmd can refer to: + $file - active file basename. + $dir - active file dirname. + $filepath - path from workspace root to active file. + $workspace - full path to workspace root. + + For example "hg eval 'echo $dir; hg log -l3 $file'" will show the last + the 3 log entries for each active file, preceded by its directory.''' + + act = wslist[repo].active(opts['parent']) + cmd = ' '.join(command) + files = [x.name for x in act if not x.is_removed()] + + do_eval(cmd, files, repo.root, not opts['remain']) + + +def cdm_apply(ui, repo, *command, **opts): + '''apply cmd to all active files + + For example 'hg apply wc -l' outputs a line count of active files.''' + + act = wslist[repo].active(opts['parent']) + + if opts['remain']: + appnd = ' $filepath' + else: + appnd = ' $file' + + cmd = ' '.join(command) + appnd + files = [x.name for x in act if not x.is_removed()] + + do_eval(cmd, files, repo.root, not opts['remain']) + + +def cdm_reparent(ui, repo, parent): + '''reparent your workspace + + Updates the 'default' path.''' + + filename = repo.join('hgrc') + + cp = util.configparser() + try: + cp.read(filename) + except ConfigParser.ParsingError, inst: + raise util.Abort('failed to parse %s\n%s' % (filename, inst)) + + try: + fh = open(filename, 'w') + except IOError, e: + raise util.Abort('Failed to open workspace configuration: %s' % e) + + if not cp.has_section('paths'): + cp.add_section('paths') + cp.set('paths', 'default', parent) + cp.write(fh) + fh.close() + + +def backup_name(fullpath): + '''Create a backup directory name based on the specified path. + + In most cases this is the basename of the path specified, but + certain cases are handled specially to create meaningful names''' + + special = ['usr/closed'] + + fullpath = fullpath.rstrip(os.path.sep).split(os.path.sep) + + # + # If a path is 'special', we append the basename of the path to + # the path element preceding the constant, special, part. + # + # Such that for instance: + # /foo/bar/onnv-fixes/usr/closed + # has a backup name of: + # onnv-fixes-closed + # + for elt in special: + elt = elt.split(os.path.sep) + pathpos = len(elt) + + if fullpath[-pathpos:] == elt: + return "%s-%s" % (fullpath[-pathpos - 1], elt[-1]) + else: + return fullpath[-1] + + +def cdm_backup(ui, repo, if_newer=False): + '''make backup copies of all workspace changes + + Backups will be stored in ~/cdm.backup/<basename of workspace>.''' + + name = backup_name(repo.root) + bk = CdmBackup(ui, wslist[repo], name) + + if if_newer and not bk.need_backup(): + ui.status('backup is up-to-date\n') + else: + bk.backup() + + +def cdm_restore(ui, repo, backup, **opts): + '''restore workspace from backup + + Restores a workspace from the specified backup directory and generation + (which defaults to the latest).''' + + if not os.getcwd().startswith(repo.root): + raise util.Abort('restore is not safe to run with -R') + if wslist[repo].modified(): + raise util.Abort('Workspace has uncommitted changes') + if wslist[repo].merged(): + raise util.Abort('Workspace has an uncommitted merge') + if wslist[repo].branched(): + raise util.Abort('Workspace has an uncommitted branch') + + if opts['generation']: + gen = int(opts['generation']) + else: + gen = None + + if os.path.exists(backup): + backup = os.path.abspath(backup) + + bk = CdmBackup(ui, wslist[repo], backup) + bk.restore(gen) + +cmdtable = { + 'apply': (cdm_apply, [('p', 'parent', '', 'parent workspace'), + ('r', 'remain', None, 'do not change directories')], + 'hg apply [-p PARENT] [-r] command...'), + 'arcs': (cdm_arcs, [('p', 'parent', '', 'parent workspace')], + 'hg arcs [-p PARENT]'), + '^backup|bu': (cdm_backup, [('t', 'if-newer', None, + 'only backup if workspace files are newer')], + 'hg backup [-t]'), + 'branchchk': (cdm_branchchk, [('p', 'parent', '', 'parent workspace')], + 'hg branchchk [-p PARENT]'), + 'bugs': (cdm_bugs, [('p', 'parent', '', 'parent workspace')], + 'hg bugs [-p PARENT]'), + 'cddlchk': (cdm_cddlchk, [('p', 'parent', '', 'parent workspace')], + 'hg cddlchk [-p PARENT]'), + 'comchk': (cdm_comchk, [('p', 'parent', '', 'parent workspace'), + ('N', 'nocheck', None, + 'do not compare comments with databases')], + 'hg comchk [-p PARENT]'), + 'comments': (cdm_comments, [('p', 'parent', '', 'parent workspace')], + 'hg comments [-p PARENT]'), + 'copyright': (cdm_copyright, [('p', 'parent', '', 'parent workspace')], + 'hg copyright [-p PARENT]'), + 'cstyle': (cdm_cstyle, [('p', 'parent', '', 'parent workspace')], + 'hg cstyle [-p PARENT]'), + 'eval': (cdm_eval, [('p', 'parent', '', 'parent workspace'), + ('r', 'remain', None, 'do not change directories')], + 'hg eval [-p PARENT] [-r] command...'), + 'hdrchk': (cdm_hdrchk, [('p', 'parent', '', 'parent workspace')], + 'hg hdrchk [-p PARENT]'), + 'jstyle': (cdm_jstyle, [('p', 'parent', '', 'parent workspace')], + 'hg jstyle [-p PARENT]'), + 'keywords': (cdm_keywords, [('p', 'parent', '', 'parent workspace')], + 'hg keywords [-p PARENT]'), + '^list|active': (cdm_list, [('p', 'parent', '', 'parent workspace'), + ('r', 'removed', None, 'show removed files'), + ('a', 'added', None, 'show added files'), + ('m', 'modified', None, 'show modified files')], + 'hg list [-amrRu] [-p PARENT]'), + '^nits': (cdm_nits, [('p', 'parent', '', 'parent workspace')], + 'hg nits [-p PARENT]'), + '^pbchk': (cdm_pbchk, [('p', 'parent', '', 'parent workspace'), + ('N', 'nocheck', None, 'skip RTI check')], + 'hg pbchk [-N] [-p PARENT]'), + 'permchk': (cdm_permchk, [('p', 'parent', '', 'parent workspace')], + 'hg permchk [-p PARENT]'), + '^pdiffs': (cdm_pdiffs, [('p', 'parent', '', 'parent workspace')], + 'hg pdiffs [-p PARENT]'), + '^recommit|reci': (cdm_recommit, [('p', 'parent', '', 'parent workspace'), + ('f', 'force', None, 'force operation'), + ('m', 'message', '', + 'use <text> as commit message'), + ('l', 'logfile', '', + 'read commit message from file'), + ('u', 'user', '', + 'record user as committer')], + 'hg recommit [-f] [-p PARENT]'), + 'renamed': (cdm_renamed, [('p', 'parent', '', 'parent workspace')], + 'hg renamed [-p PARENT]'), + 'reparent': (cdm_reparent, [], 'hg reparent PARENT'), + '^restore': (cdm_restore, [('g', 'generation', '', 'generation number')], + 'hg restore [-g GENERATION] BACKUP'), + 'rtichk': (cdm_rtichk, [('p', 'parent', '', 'parent workspace'), + ('N', 'nocheck', None, 'skip RTI check')], + 'hg rtichk [-N] [-p PARENT]'), + 'tagchk': (cdm_tagchk, [('p', 'parent', '', 'parent workspace')], + 'hg tagchk [-p PARENT]'), +} diff --git a/usr/src/tools/scripts/Makefile b/usr/src/tools/scripts/Makefile index f31b760cc5..d2cf5e8d3b 100644 --- a/usr/src/tools/scripts/Makefile +++ b/usr/src/tools/scripts/Makefile @@ -42,6 +42,7 @@ SHFILES= \ elfcmp \ flg.flp \ genoffsets \ + hgsetup \ keywords \ makebfu \ mkacr \ @@ -57,14 +58,14 @@ SHFILES= \ sccsrm \ sdrop \ webrev \ + which_scm \ ws \ wx \ + wx2hg \ xref PERLFILES= \ - cddlchk \ check_rtime \ - hdrchk \ jstyle \ mkreadme_osol \ mktpl \ @@ -73,6 +74,11 @@ PERLFILES= \ wdiff PYFILES= \ + cddlchk \ + copyrightchk \ + hdrchk \ + hg-active \ + rtichk \ wsdiff MAN1FILES= \ @@ -85,6 +91,8 @@ MAN1FILES= \ check_rtime.1 \ cstyle.1 \ flg.flp.1 \ + hdrchk.1 \ + hgsetup.1 \ jstyle.1 \ mkacr.1 \ nightly.1 \ @@ -93,15 +101,17 @@ MAN1FILES= \ sccsmv.1 \ sccsrm.1 \ webrev.1 \ + which_scm.1 \ ws.1 \ wsdiff.1 \ wx.1 \ + wx2hg.1 \ xref.1 MAKEFILES= \ xref.mk -CLEANFILES = $(SHFILES) $(PERLFILES) $(PYFILES) bldenv.1 cddlchk.1 +CLEANFILES = $(SHFILES) $(PERLFILES) $(PYFILES) bldenv.1 include ../Makefile.tools @@ -139,9 +149,5 @@ nightly: nightly.sh stdenv.sh sed -e '/# STDENV_START/ r stdenv.sh' nightly.sh > nightly $(CHMOD) +x "$@" -cddlchk.1: cddlchk.pl - /usr/perl5/bin/pod2man --center='User Commands' --name=cddlchk \ - --section=1 --release='SunOS $(RELEASE)' $? > "$@" - include ../Makefile.targ diff --git a/usr/src/tools/scripts/bldenv.sh b/usr/src/tools/scripts/bldenv.sh index 36ce588dfd..b9d09ec01d 100644 --- a/usr/src/tools/scripts/bldenv.sh +++ b/usr/src/tools/scripts/bldenv.sh @@ -324,6 +324,16 @@ if "${flags.s.o}" ; then SRC="${OPEN_SRCDIR}/usr/src" fi +# +# Keep track of this now, before we manipulate $PATH +# +WHICH_SCM=$(dirname $(whence $0))/which_scm +if [[ ! -x $WHICH_SCM ]]; then + WHICH_SCM=which_scm +fi +$WHICH_SCM | read SCM_TYPE junk + + # Set PATH for a build PATH="/opt/onbld/bin:/opt/onbld/bin/${MACH}:/opt/SUNWspro/bin:/usr/ccs/bin:/usr/bin:/usr/sbin:/usr/ucb:/usr/etc:/usr/openwin/bin:/usr/sfw/bin:/opt/sfw/bin:." if [[ "${SUNWSPRO}" != "" ]]; then @@ -416,7 +426,8 @@ export \ ENVCPPFLAGS3 \ ENVCPPFLAGS4 \ MAKEFLAGS \ - PARENT_ROOT + PARENT_ROOT \ + SCM_TYPE printf 'RELEASE is %s\n' "$RELEASE" printf 'VERSION is %s\n' "$VERSION" diff --git a/usr/src/tools/scripts/cddlchk.1 b/usr/src/tools/scripts/cddlchk.1 new file mode 100644 index 0000000000..f2c916adb6 --- /dev/null +++ b/usr/src/tools/scripts/cddlchk.1 @@ -0,0 +1,75 @@ +.\" CDDL HEADER START +.\" +.\" The contents of this file are subject to the terms of the +.\" Common Development and Distribution License (the "License"). +.\" You may not use this file except in compliance with the License. +.\" +.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +.\" or http://www.opensolaris.org/os/licensing. +.\" See the License for the specific language governing permissions +.\" and limitations under the License. +.\" +.\" When distributing Covered Code, include this CDDL HEADER in each +.\" file and include the License file at usr/src/OPENSOLARIS.LICENSE. +.\" If applicable, add the following below this CDDL HEADER, with the +.\" fields enclosed by brackets "[]" replaced with your own identifying +.\" information: Portions Copyright [yyyy] [name of copyright owner] +.\" +.\" CDDL HEADER END +.\" +.\" Copyright 2008 Sun Microsystems, Inc. All rights reserved. +.\" Use is subject to license terms. +.\" +.\" ident "%Z%%M% %I% %E% SMI" +.TH cddlchk 1 "1 June 2008" +.SH NAME +cddlchk \- Check for valid CDDL header blocks +.SH SYNOPSIS +.nf +\fBcddlchk \fR [\fB-av\fR] [\fB-x\fR \fIexceptions_file\fR] [\fIpath\fR...] +.fi +.LP +.SH DESCRIPTION +.IX "OS-Net build tools" "cddlchk" "" "\fBcddlchk\fP" +cddlchk inspects files for missing, obsolete, or corrupt Common +Development and Distribution License (CDDL) header blocks. +.LP +.SH OPTIONS +.LP +.TP 4 +.B \-a +Check that all the specified files have a CDDL block, and report a +warning if any do not. +If this flag is not specified, only files containing an existing CDDL +block are validated. +.LP +.TP 4 +.B \-v +Report on all files, not just those with invalid headers +.LP +.TP 4 +.B \-x \fIexceptions_file\fR +Load an exceptions file containing a list of files, directories and +file extensions to be ignored. +Exceptions may be one of three types: +.nf + * File paths + * Directories, specified with a trailing '/' + * File extensions, specified with a leading '*.' +.fi +.LP +.SH EXIT STATUS +.TP 4 +.B 0 +The command completed successfully. +No errors or warnings were reported +.LP +.TP 4 +.B 1 +The command completed unsuccessfully. +One or more errors or warnings were reported. +.LP +.TP 4 +.B 2 +Invalid command-line arguments were specified to the command, or one +of the command-line help functions was invoked. diff --git a/usr/src/tools/scripts/cddlchk.pl b/usr/src/tools/scripts/cddlchk.pl deleted file mode 100755 index 5e882f5288..0000000000 --- a/usr/src/tools/scripts/cddlchk.pl +++ /dev/null @@ -1,403 +0,0 @@ -#!/usr/perl5/bin/perl -# -# See the bottom of the file for the license, and for the reason why it is -# there and not here. -# - -# -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# ident "%Z%%M% %I% %E% SMI" -# - -# -# Check source files for a valid CDDL block. -# - -use strict; -use warnings; -use Getopt::Std; -use Pod::Usage; -use File::Find; - -# -# Global variables. -# - -our $VERSION = '%I%'; # Program version number. - -our $CmtChrs = q{#*!/\";.}; # Acceptable comment characters. -our %Opt; # Command-line flags. -our @CDDL; # Approved CDDL block. -our $CDDLStartRE; # RE to match the first line of a CDDL block. -our $CDDLEndRE; # RE to match the last line of a CDDL block. -our $Status = 0; # Exit status -our $CmtRE; # Comment regular expression. -our %IgnoreDir; # Directories to be ignored. -our %IgnoreFile; # Files to be ignored. -our $IgnoreExtnRE; # File extensions to be ignored. - -# -# Print a help message - see Getopt::Std. -# -sub HELP_MESSAGE -{ - my ($out, $opt_pkg, $ver, $sw) = @_; - pod2usage(-output => $out, -exitval => 2, -verbose => 2); -} - -# -# Print a version message - see Getopt::Std. -# -sub VERSION_MESSAGE -{ - my ($out, $opt_pkg, $ver, $sw) = @_; - print($out "cddlchk version $VERSION\n"); -} - -# -# Print a message. -# -sub message -{ - print("Message: ", join("\n ", @_), "\n"); -} - -# -# Print a warning message. -# -sub warning -{ - print("Warning: ", join("\n ", @_), "\n"); - $Status = 2 if ($Status == 0); -} - -# -# Print an error message. -# -sub error -{ - print("Error: ", join("\n ", @_), "\n"); - $Status = 1; -} - -# -# Load an exceptions file. $root, if specified, will be prepended to all -# relative file and directory paths. Exceptions may be one of three types: -# 1. File paths. -# 2. Directories, specified with a trailing '/'. -# 3. File extensions, specified with a leading '*.' -# Returns true if the file loaded OK, false otherwise. -# -sub load_exceptions -{ - my ($file, $root) = @_; - - # Fix up the $root prefix, if specified. - $root .= '/' if (defined($root) && substr($root, -1, 1) ne '/'); - - # Open the exception file. - my $fh; - if (! open($fh, '<', $file)) { - return(0); - } - - # Zero any existing exceptions, read the file. - %IgnoreDir = (); - %IgnoreFile = (); - $IgnoreExtnRE = undef; - my @ext; - while (defined(my $line = <$fh>)) { - chomp($line); - # File extension. - if ($line =~ m{^\*\.(.*)$}) { - push(@ext, quotemeta($1)); - - # Directory path. - } elsif (($_) = $line =~ m{^(.*)/$}) { - $_ = "$root$_" - if (defined($root) && substr($_, 0, 1) ne '/'); - $IgnoreDir{$_} = 1; - - # File path. - } else { - $line = "$root$line" - if (defined($root) && substr($line, 0, 1) ne '/'); - $IgnoreFile{$line} = 1; - } - } - - # Compose the extension exception RE if any were defined. - if (@ext > 0) { - $_ = '\.(?:' . join('|', @ext) . ')$'; - $IgnoreExtnRE = qr{$_}; - } - - return(close($fh)); -} - -# -# Check if the specified file or directory should be validated or not. -# $type is 'file' or 'dir'. -# -sub is_exception -{ - my($type, $path) = @_; - - if ($type eq 'file') { - return(exists($IgnoreFile{$path}) || - (defined($IgnoreExtnRE) && $path =~ $IgnoreExtnRE)); - } else { - return(exists($IgnoreDir{$path})); - } -} - -# -# Check a file for a valid CDDL block. If $Opt{a} is true an error will be -# reported if the file doesn't contain any CDDL at all, if it is false a -# warning will only be reported if the file has a CDDL block which is invalid. -# If $Opt{v} is true valid files will be listed, otherwise they will not. -# -sub cuddle -{ - my ($file) = @_; - - # Open the file. - my $fh; - if (! open($fh, '<', $file)) { - error("Can't open $file: $!"); - return; - } - - # Extract all the CDDL blocks. - my ($msg, $start, $block, @cddl); - $msg = 0; - $block = []; - while (defined($_ = <$fh>)) { - if (my $s = $_ =~ $CDDLStartRE ... $_ =~ $CDDLEndRE) { - chomp($_); - push(@$block, $_); - # First line of CDDL block. - if ($s == 1) { - $start = $.; - # Last line of CDDL block. - } elsif (substr($s, -2) eq 'E0') { - push(@cddl, - { start => $start, block => $block }); - $start = undef; - $block = []; - } - } - } - - # Close the file. - if (! close($fh)) { - warning("Can't close $file: $!"); - } - - # Check for unterminated blocks. - if (defined($start)) { - error("Unterminated CDDL block in file $file", - "at line $start"); - $msg++; - } - - # Check for no CDDL - may be a warning. - if (@cddl == 0 && $Opt{a}) { - warning("No CDDL block in file $file"); - return; - } - - # Check for multiple CDDL blocks. - if (@cddl > 1) { - error("Multiple CDDL blocks in file $file", - "at lines " . join(", ", map($_->{start}, @cddl))); - $msg++; - } - - # Validate each CDDL block. - foreach my $c (@cddl) { - my ($s, $b) = @$c{qw{start block}}; - - # Compare each line. - for (my $i = 0; $i < @CDDL; $i++) { - $_ = $i < @$b ? $b->[$i] : ''; - if ($_ !~ m{^$CmtRE\Q$CDDL[$i]\E$}) { - error( - "Invalid line in CDDL block in file $file", - "at line " . ($s + $i) . ", should be", - "'[$CmtChrs ]*$CDDL[$i]'", "is", "'$_'"); - $msg++; - last; # Just report the first error. - } - } - } - - # Report the file if required. - message("Valid CDDL block in file $file") if ($Opt{v} && ! $msg); -} - -# -# Main. -# - -# Check the command-line arguments. -$Getopt::Std::STANDARD_HELP_VERSION = 1; -pod2usage() unless (getopts('avx:M', \%Opt)); -pod2usage(-verbose => 2) if ($Opt{M}); - -# Read in the exception list. -if (exists($Opt{x})) { - if (! load_exceptions($Opt{x})) { - error("Can't load exceptions file $Opt{x}: $!"); - exit(2); - } -} - -# Read in the template CDDL block from the end of the file. -while (defined($_ = <DATA>)) { - chomp($_); - push(@CDDL, $_); -} -shift(@CDDL) while ($CDDL[0] =~ m{^\s*$}); -pop(@CDDL) while ($CDDL[$#CDDL] =~ m{^\s*$}); -$CmtRE = qr{[\Q$CmtChrs\E\s]*}; -$CDDLStartRE = qr{^$CmtRE\Q$CDDL[0]}; -$CDDLEndRE = qr{^$CmtRE\Q$CDDL[$#CDDL]}; - -# File::Find callback. -my $wanted = sub { - my $path = $File::Find::name; - if (-d $path && $path =~ m{SCCS$}) { - $File::Find::prune = 1; - } elsif (-f _) { - cuddle($path) unless (is_exception('file', $path)); - } -}; - -# Process each file and directory on the command-line. -foreach my $arg (@ARGV) { - if (-f $arg) { - # Explicitly listed files must have a CDDL block. - cuddle($arg, 1) unless (is_exception('file', $arg)); - } elsif (-d $arg) { - find({ wanted => $wanted, no_chdir => 1 }, $arg) - unless (is_exception('dir', $arg)); - } else { - error("Unrecognised file/directory argument $arg"); - } -} -exit($Status); - -# -# Inline documentation. -# - -=pod - -=head1 NAME - -cddlchk - Check for valid CDDL blocks - -=head1 SYNOPSIS - -cddlchk [B<-avxM> B<--help> B<--version>] [B<<file or directory>>...] - -=head1 DESCRIPTION - -cddlchk inspects files for missing, obsolete, or corrupt CDDL blocks. - -=head1 OPTIONS - -The following options are supported: - -=over - -=item B<-a> - -Check that all the specified files have a CDDL block, and report a warning if -they do not. If this flag is not specified, only files containing an existing -CDDL block are validated. - -=item B<-v> - -Report on all files, not just those with invalid headers. - -=item B<-x> - -Load an exceptions file containing a list of files, directories and file -extensions to be ignored. Exceptions may be one of three types: - -=over - -=item * B<File paths> - -=item * B<Directories>, specified with a trailing C</> - -=item * B<File extensions>, specified with a leading C<*.> - -=back - -=item B<-M> - -Display the manpage for the chkcddl command. - -=item B<--help> - -Display command-line help for the cddlchk command. - -=item B<--version> - -Display the program version number. - -=back - -=head1 EXIT STATUS - -The following exit status values are returned: - -=over - -=item B<0> - -The command completed sucessfully. No errors or warnings were reported. - -=item B<1> - -The command completed unsucessfully. One or more errors or warnings were -reported. - -=item B<2> - -Invalid command-line arguments were specified to the command, or one of the -command-line help functions was invoked. - -=back - -=cut - -# -# Put the CDDL at the end of the file so we can use it as a template. -# - -__DATA__ - -CDDL HEADER START - -The contents of this file are subject to the terms of the -Common Development and Distribution License (the "License"). -You may not use this file except in compliance with the License. - -You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -or http://www.opensolaris.org/os/licensing. -See the License for the specific language governing permissions -and limitations under the License. - -When distributing Covered Code, include this CDDL HEADER in each -file and include the License file at usr/src/OPENSOLARIS.LICENSE. -If applicable, add the following below this CDDL HEADER, with the -fields enclosed by brackets "[]" replaced with your own identifying -information: Portions Copyright [yyyy] [name of copyright owner] - -CDDL HEADER END diff --git a/usr/src/tools/scripts/cddlchk.py b/usr/src/tools/scripts/cddlchk.py new file mode 100644 index 0000000000..2450018976 --- /dev/null +++ b/usr/src/tools/scripts/cddlchk.py @@ -0,0 +1,150 @@ +#! /usr/bin/python +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +# +# Check for valid CDDL blocks in source files. +# + +import sys, os, getopt, fnmatch + +sys.path.append(os.path.join(os.path.dirname(__file__), '../lib/python')) +sys.path.append(os.path.join(os.path.dirname(__file__), '..')) + +from onbld.Checks.Cddl import cddlchk + +class ExceptionList(object): + def __init__(self): + self.dirs = [] + self.files = [] + self.extensions = [] + + def load(self, exfile): + fh = None + try: + fh = open(exfile, 'r') + except IOError, e: + sys.stderr.write('Failed to open exception list: ' + '%s: %s\n' % (e.filename, e.strerror)) + sys.exit(2) + + for line in fh: + line = line.strip() + + if line.strip().endswith('/'): + self.dirs.append(line[0:-1]) + elif line.startswith('*.'): + self.extensions.append(line) + else: + self.files.append(line) + + fh.close() + + def match(self, filename): + if os.path.isdir(filename): + return filename in self.dirs + else: + if filename in self.files: + return True + + for pat in self.extensions: + if fnmatch.fnmatch(filename, pat): + return True + + def __contains__(self, elt): + return self.match(elt) + +def usage(): + progname = os.path.split(sys.argv[0])[1] + sys.stderr.write('''Usage: %s [-av] [-x exceptions] paths... + -a check that all the specified files have a CDDL block. + -v report on all files, not just those with errors. + -x exceptions load an exceptions file +''' % progname) + sys.exit(2) + + +def check(filename, opts): + try: + fh = open(filename, 'r') + except IOError, e: + sys.stderr.write("failed to open '%s': %s\n" % + (e.filename, e.strerror)) + return 1 + else: + return cddlchk(fh, verbose=opts['verbose'], + lenient=opts['lenient'], + output=sys.stdout) + +def walker(opts, dirname, fnames): + for f in fnames: + path = os.path.join(dirname, f) + + if not os.path.isdir(path): + if not path in opts['exclude']: + opts['status'] |= check(path, opts) + else: + if path in opts['exclude']: + fnames.remove(f) + +def walkpath(path, opts): + if os.path.isdir(path): + os.path.walk(path, walker, opts) + else: + if not path in opts['exclude']: + opts['status'] |= check(path, opts) + +def main(args): + options = { + 'status': 0, + 'lenient': True, + 'verbose': False, + 'exclude': ExceptionList() + } + + try: + opts, args = getopt.getopt(sys.argv[1:], 'avx:') + except getopt.GetoptError: + usage() + sys.exit(2) + + for opt, arg in opts: + if opt == '-a': + options['lenient'] = False + elif opt == '-v': + options['verbose'] = True + elif opt == '-x': + options['exclude'].load(arg) + + for path in args: + walkpath(path, options) + + return options['status'] + +if __name__ == '__main__': + sys.exit(main(sys.argv[1:])) diff --git a/usr/src/tools/scripts/checkpaths.sh b/usr/src/tools/scripts/checkpaths.sh index 1ac842780f..0feb794aad 100644 --- a/usr/src/tools/scripts/checkpaths.sh +++ b/usr/src/tools/scripts/checkpaths.sh @@ -24,7 +24,8 @@ # Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -#ident "%Z%%M% %I% %E% SMI" +# ident "%Z%%M% %I% %E% SMI" +# # Quis custodiet ipsos custodies? @@ -93,12 +94,12 @@ done # disabling all checks of them. The assumption is that the entries # marked with ISUSED are always known to be good, thus the Latin quote # at the top of the file. +# +# The exception_list is generated from whichever input files are appropriate +# for this workspace, so checking it obviates the need to check the inputs. +elist="" if [ -r $SRC/tools/findunref/exception_list ]; then - # If the closed source is not present, then don't validate it. - if [ "$CLOSED_IS_PRESENT" = no ]; then - excl="-e ^\./closed" - fi - validate_paths -k ISUSED -r -e '^\*' $excl -b $SRC/.. \ + validate_paths -k ISUSED -r -e '^\*' -b $SRC/.. \ $SRC/tools/findunref/exception_list fi diff --git a/usr/src/tools/scripts/copyrightchk.py b/usr/src/tools/scripts/copyrightchk.py new file mode 100644 index 0000000000..2ffee80cac --- /dev/null +++ b/usr/src/tools/scripts/copyrightchk.py @@ -0,0 +1,53 @@ +#! /usr/bin/python +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +# +# Check for valid SMI copyright notices in source files. +# + +import sys, os + +sys.path.append(os.path.join(os.path.dirname(__file__), '../lib/python')) +sys.path.append(os.path.join(os.path.dirname(__file__), '..')) + +from onbld.Checks.Copyright import copyright + +ret = 0 +for filename in sys.argv[1:]: + try: + fin = open(filename, 'r') + except IOError, e: + sys.stderr.write("failed to open '%s': %s\n" % + (e.filename, e.strerror)) + continue + + ret |= copyright(fin, output=sys.stdout) + fin.close() + +sys.exit(ret) diff --git a/usr/src/tools/scripts/cstyle.pl b/usr/src/tools/scripts/cstyle.pl index 63ca0e2104..9f67b1d2e4 100644 --- a/usr/src/tools/scripts/cstyle.pl +++ b/usr/src/tools/scripts/cstyle.pl @@ -3,9 +3,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -21,7 +20,7 @@ # CDDL HEADER END # # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # @(#)cstyle 1.58 98/09/09 (from shannon) @@ -74,7 +73,7 @@ my %opts; if (!getopts("cho:pvCP", \%opts)) { print $usage; - exit 1; + exit 2; } my $check_continuation = $opts{'c'}; @@ -96,7 +95,7 @@ if (defined($opts{'o'})) { } else { print "cstyle: unrecognized construct \"$x\"\n"; print $usage; - exit 1; + exit 2; } } } @@ -170,6 +169,8 @@ my $warlock_re = qr/\/\*\s*(?: LOCK\ ORDER: )/x; +my $err_stat = 0; # exit status + if ($#ARGV >= 0) { foreach my $arg (@ARGV) { my $fh = new IO::File $arg, "r"; @@ -183,23 +184,33 @@ if ($#ARGV >= 0) { } else { &cstyle("<stdin>", *STDIN); } +exit $err_stat; my $no_errs = 0; # set for CSTYLED-protected lines sub err($) { my ($error) = @_; - printf $fmt, $filename, $., $error, $line unless ($no_errs); + unless ($no_errs) { + printf $fmt, $filename, $., $error, $line; + $err_stat = 1; + } } sub err_prefix($$) { my ($prevline, $error) = @_; my $out = $prevline."\n".$line; - printf $fmt, $filename, $., $error, $out unless ($no_errs); + unless ($no_errs) { + printf $fmt, $filename, $., $error, $out; + $err_stat = 1; + } } sub err_prev($) { my ($error) = @_; - printf $fmt, $filename, $. - 1, $error, $prev unless ($no_errs); + unless ($no_errs) { + printf $fmt, $filename, $. - 1, $error, $prev; + $err_stat = 1; + } } sub cstyle($$) { diff --git a/usr/src/tools/scripts/flg.flp.sh b/usr/src/tools/scripts/flg.flp.sh index 8c18c6c455..c2aa024fb5 100644 --- a/usr/src/tools/scripts/flg.flp.sh +++ b/usr/src/tools/scripts/flg.flp.sh @@ -3,9 +3,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -21,11 +20,12 @@ # CDDL HEADER END # # -# Copyright 1991, 2002-2003 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" # +# # Generates the list of source files that would get brought over with the # specified subtree as a result of inc.flg and req.flg files. If no subtree # is named, then the current directory is assumed. @@ -33,7 +33,10 @@ # Based loosely on ON's version of Teamware's def.dir.flp. # -PATH=/usr/bin export PATH +ONBLDDIR=$(dirname $(whence $0)) + +PATH=/usr/bin:${BUILD_TOOLS:-/opt}/teamware/bin:$ONBLDDIR +export PATH PROG=`basename $0` # @@ -61,7 +64,6 @@ fail() exit 1 } -# # Find the files matching the pattern specified by the first argument in the # directories named by the remaining arguments. Unlike def.dir.flp, print # the name of the source file since we want to make a list of source files, @@ -72,13 +74,27 @@ find_files() pat=$1 shift - for dir; do - if [ -d $CODEMGR_WS/$dir ]; then - cd $CODEMGR_WS - find $dir -name "$pat" | sed -n s:/SCCS/s.:/:p | prpath - cd - > /dev/null - fi - done + if [ "$SCM_MODE" = "teamware" ] ; then + for dir; do + if [ -d $CODEMGR_WS/$dir ]; then + cd $CODEMGR_WS + find $dir -name "$pat" | \ + sed -n s:/SCCS/s.:/:p | prpath + cd - > /dev/null + fi + done + elif [ "$SCM_MODE" = "mercurial" ]; then + dirs="" + for dir; do + if [ -d $CODEMGR_WS/$dir ]; then + dirs="$dirs|${dir%/}" + fi + done + + # Remove leading pipe before it can confuse egrep + dirs=${dirs#\|} + echo "$FILELIST" | egrep "^($dirs)/.*/${pat#s.}\$" | prpath + fi } # @@ -134,7 +150,14 @@ incflg() # prpath() { - reltree=${CURTREE##$CODEMGR_WS/} + # + # $CURTREE may be a subdirectory of $CODEMGR_WS, or it + # may be the root of $CODEMGR_WS. We want to strip it + # and end up with a relative path in either case, so the + # ?(/) pattern is important. If we don't do that, the + # dots/tree loop will go on forever. + # + reltree=${CURTREE##$CODEMGR_WS?(/)} while read srcfile; do if [ "$RELPATHS" != y ]; then @@ -152,7 +175,15 @@ prpath() done } -[ -z "$CODEMGR_WS" ] && fail "No active workspace; run \"ws <workspace_name>\"" +which_scm | read SCM_MODE CODEMGR_WS || exit 1 + +if [[ $SCM_MODE == "unknown" ]]; then + fail "Unable to determine SCM type currently in use." +elif [[ $SCM_MODE == "mercurial" ]]; then + FILELIST=`hg manifest` +elif [[ $SCM_MODE != "teamware" ]]; then + fail "Unsupported SCM in use: $SCM_MODE" +fi while getopts r flag; do case $flag in diff --git a/usr/src/tools/scripts/hdrchk.1 b/usr/src/tools/scripts/hdrchk.1 new file mode 100644 index 0000000000..0297d3e5b3 --- /dev/null +++ b/usr/src/tools/scripts/hdrchk.1 @@ -0,0 +1,100 @@ +.\" CDDL HEADER START +.\" +.\" The contents of this file are subject to the terms of the +.\" Common Development and Distribution License (the "License"). +.\" You may not use this file except in compliance with the License. +.\" +.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +.\" or http://www.opensolaris.org/os/licensing. +.\" See the License for the specific language governing permissions +.\" and limitations under the License. +.\" +.\" When distributing Covered Code, include this CDDL HEADER in each +.\" file and include the License file at usr/src/OPENSOLARIS.LICENSE. +.\" If applicable, add the following below this CDDL HEADER, with the +.\" fields enclosed by brackets "[]" replaced with your own identifying +.\" information: Portions Copyright [yyyy] [name of copyright owner] +.\" +.\" CDDL HEADER END +.\" +.\" Copyright 2008 Sun Microsystems, Inc. All rights reserved. +.\" Use is subject to license terms. +.\" +.\" ident "%Z%%M% %I% %E% SMI" +.\" +.TH hdrchk 1 "02 July 2008" +.SH NAME +hdrchk \- check that header files conform to ON standards +.SH SYNOPSIS +.nf +\fBhdrchk\fR [\fB-a\fP] \fIfile\fR [\fIfile ...\fR]\fP +.fi +.LP +.SH DESCRIPTION +.IX "OS-Net build tools" "hdrchk" "" "\fBhdrchk\fP" +.LP +.I hdrchk +verifies that C header files (*.h) conform to the standards of the ON +consolidation. +See HEADER STANDARDS for details. +.LP +.SH OPTIONS +.LP +.TP 10 +.B -a +Apply (more lenient) application header rules. +.LP +.SH HEADER STANDARDS +.LP +Standards for all header files: +.TP 4 +.B 1. +Begin with a comment containing a copyright message. +.LP +.TP 4 +.B 2. +Enclosed in a guard of the form: +.LP +.nf + #ifndef GUARD + #define GUARD + #endif /* [!]GUARD */ +.fi +.sp +.RS 4n +The preferred form is without the bang character, but either is +acceptable. +.RE +.LP +.TP 4 +.B 3. +Has a valid ident declaration. +.LP +Additional standards for system header files: +.TP 4 +.B 1. +The file guard must take the form '_\fBFILENAME\fP_H[_]', where +\fBFILENAME\fP matches the basename of the file. +If it is installed in a subdirectory, it should be of the +form '_\fBDIR\fP_\fBFILENAME\fP_H[_]', though this is not currently enforced. +The form without the trailing underscore is preferred in both cases. +.LP +.TP 4 +.B 2. +All #include directives must use the <> form. +.LP +.TP 4 +.B 3. +If the header file contains anything besides comments and preprocessor +directives, then it must be enclosed in a C++ guard of the form: +.LP +.nf + #ifdef __cplusplus + extern "C" { + #endif + + #ifdef __cplusplus + } + #endif +.fi + diff --git a/usr/src/tools/scripts/hdrchk.pl b/usr/src/tools/scripts/hdrchk.pl deleted file mode 100644 index 08a77cf02a..0000000000 --- a/usr/src/tools/scripts/hdrchk.pl +++ /dev/null @@ -1,371 +0,0 @@ -#!/usr/perl5/bin/perl -w -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - -#ident "%Z%%M% %I% %E% SMI" - -# Check that header files conform to our standards -# -# Usage: hdrck [-a] file [file ...] -# -# -a Apply (more lenient) application header rules -# -# Standards for all header files: -# -# 1) Begin with a comment containing a copyright message -# -# 2) Enclosed in a guard of the form: -# -# #ifndef GUARD -# #define GUARD -# #endif /* [!]GUARD */ -# -# The preferred form is without the bang character, but either is -# acceptable. -# -# 3) Has a valid ident declaration -# -# Additional standards for system header files: -# -# 1) The file guard must take the form '_FILENAME_H[_]', where FILENAME -# matches the basename of the file. If it is installed in a -# subdirectory, it must be of the form _DIR_FILENAME_H. The form -# without the trailing underscore is preferred. -# -# 2) All #include directives must use the <> form. -# -# 3) If the header file contains anything besides comments and -# preprocessor directives, then it must be enclosed in a C++ guard of -# the form: -# -# #ifdef __cplusplus -# extern "C" { -# #endif -# -# #ifdef __cplusplus -# } -# #endif -# - -use File::Basename; - -$do_system = 1; - -if ($#ARGV >= 0) { - if ($ARGV[0] eq "-a") { - $do_system = 0; - shift; - } -} - -# -# Global varibles keep track of what file we're processing and what line we're -# on. -# - -my $lineno; -my $filename; -my $feof; -my $exitval = 0; - -# -# Loop through each file on the command line and process it appropriately -# -while ($filename = shift) { - - if (!open FILE, $filename) { - print STDERR "failed to open '$filename': $!\n"; - next; - } - - $feof = 0; - $lineno = 0; - - process_file(); - - close FILE; -} - -exit $exitval; - -# -# Returns the next line from the file, skipping blank lines. -# -sub getline { - my $line; - - while ($line = <FILE>) { - $lineno++; - chop $line; - if ($line =~ /^.+$/) { - return $line; - } - } - - $feof = 1; - return $line; -} - -# -# Prints out an error message with the current file and line number -# -sub error { - my $msg = shift; - if ($feof) { - print STDERR "$filename: $msg\n"; - } else { - print STDERR "$filename: line $lineno: $msg\n"; - } - $exitval++; -} - -# -# The main verification process -# -sub process_file { - - my $eolcom = '(.*/\*\s.*\s\*/)?'; - my $found_ident = 0; - - my $ident = '(\%Z\%(\%M\%)\t\%I\%|\%W\%)\t\%E\% SMI'; - my $xident = '@\(#\)(\w[-\.\w]+\.h)\t\d+\.\d+(\.\d+\.\d+)?\t\d\d/'. - '\d\d/\d\d SMI'; - - # - # Step 1: - # - # Headers must begin with a comment containing a copyright notice. We - # don't validate the contents of the copyright, only that it exists. - # - $_ = skip_comments(); - if (!$found_copyright) { - error("Missing copyright in opening comment"); - } - - # - # Step 2: - # - # For application header files only, allow the ident string to appear - # before the header guard. - # - if (!$do_system && - /^#pragma ident\t\"(($xident)|($ident))\"$eolcom\s*$/) { - $found_ident = 1; - $_ = skip_comments(); - } - - # - # Step 3: Header guards - # - my $guard = "NOGUARD"; - if (!/^#ifndef\s([a-zA-Z_0-9]+)$/) { - error("Invalid or missing header guard"); - } else { - $guard = $1; - - if ($do_system) { - my $guardname = basename($filename); - - # - # For system headers, validate the name of the guard - # - $guardname =~ tr/a-z/A-Z/; - $guardname =~ tr/\./_/; - $guardname =~ tr/-/_/; - - if (!($1 =~ /^_.*$guardname[_]?$/)) { - error("Header guard does not match filename"); - } - - } - - $_ = getline(); - if (!/^#define\s$1$/) { - error("Invalid header guard"); - if (/^$/) { - $_ = skip_comments(); - } - } else { - $_ = skip_comments(); - } - } - - # - # Step 4: ident string - # - # We allow both the keyword and extracted versions. - # - if (!$found_ident) { - if (!/^#pragma ident\t\"(($xident)|($ident))\"$eolcom\s*$/) { - error("Invalid or missing #pragma ident"); - } else { - $_ = skip_comments(); - } - } - - # - # Main processing loop. - # - my $in_cplusplus = 0; - my $found_endguard = 0; - my $found_cplusplus = 0; - my $found_code = 0; - - while ($_) { - - if (!/^#/ && !/^using /) { - $found_code = 1; - } - - if (/^#include(.*)$/) { - # - # Validate #include directive. For system files, make - # sure its of the form '#include <>'. - # - if ($do_system && !($1 =~ /\s<.*>/)) { - error("Bad include"); - } - } elsif (!$in_cplusplus && /^#ifdef\s__cplusplus$/) { - - # - # Start of C++ header guard. Make sure it of the form: - # - # #ifdef __cplusplus - # extern "C" { - # endif - # - $_ = getline(); - if (/^extern "C" {$/) { - $_ = getline(); - if (!/^#endif$/) { - error("Bad _cplusplus clause"); - } else { - $in_cplusplus = 1; - $found_cplusplus = 1; - } - } else { - next; - } - } elsif ($in_cplusplus && /^#ifdef\s__cplusplus$/) { - - # - # End of C++ header guard. Make sure it's of the form: - # - # #ifdef __cplusplus - # } - # #endif - # - $_ = getline(); - if (/^}$/) { - $_ = getline(); - if (!/^#endif$/) { - error("Bad __cplusplus clause"); - } else { - $in_cplusplus = 0; - } - } else { - next; - } - } elsif (/^#endif\s\/\* [!]?$guard \*\/$/){ - - # - # Ending header guard - # - $found_endguard = 1; - - } - - $_ = skip_comments(); - } - - # - # Check for missing end clauses - # - if ($do_system && !$found_cplusplus && $found_code) { - error("Missing __cplusplus guard"); - } - - if ($in_cplusplus) { - error("Missing closing #ifdef __cplusplus"); - } - - if (!$found_endguard) { - error("Missing or invalid ending header guard"); - } -} - - -# -# Skips comments, returning the next line after the comment. This only avoids -# lines which begin with comments. Any other partial comment lines are returned -# unaltered. -# -# It can set one of the following global variables: -# -# found_copyright Comment contains copyright string -# -sub skip_comments { - my $sub = shift; - my $open_comment = '/\*'; - my $close_comment = '\*/'; - - $found_copyright = 0; - - while ($_ = getline()) { - - # For application headers, allow C++ comments - if (!$do_system && /^\s*\/\//) { - next; - } - - # Not a comment - if (!/^\s*\/\*/) { - return $_; - } - - while (!/\*\//) { - if (/Copyright/) { - $found_copyright = 1; - } - - $_ = getline(); - } - - if (/Copyright/) { - $found_copyright = 1; - } - } - - # Join continuation lines - if ($_) { - while (/\\$/) { - chop; - $_ .= getline(); - } - } - - return $_; -} diff --git a/usr/src/tools/scripts/hdrchk.py b/usr/src/tools/scripts/hdrchk.py new file mode 100644 index 0000000000..7a165a40e5 --- /dev/null +++ b/usr/src/tools/scripts/hdrchk.py @@ -0,0 +1,69 @@ +#! /usr/bin/python +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +# +# Check header files conform to ON standards. +# + +import sys, os, getopt + +sys.path.append(os.path.join(os.path.dirname(__file__), '../lib/python')) +sys.path.append(os.path.join(os.path.dirname(__file__), '..')) + +from onbld.Checks.HdrChk import hdrchk + +def usage(): + progname = os.path.split(sys.argv[0])[1] + msg = ['Usage: %s [-a] file [file...]\n' % progname, + ' -a\tApply (more lenient) application header rules\n'] + sys.stderr.writelines(msg) + + +try: + opts, args = getopt.getopt(sys.argv[1:], 'a') +except getopt.GetoptError: + usage() + sys.exit(2) + +lenient = False +for opt, arg in opts: + if opt == '-a': + lenient = True + +ret = 0 +for filename in args: + try: + fh = open(filename, 'r') + except IOError, e: + sys.stderr.write("failed to open '%s': %s\n" % + (e.filename, e.strerror)) + else: + ret |= hdrchk(fh, lenient=lenient, output=sys.stderr) + fh.close() +sys.exit(ret) diff --git a/usr/src/tools/scripts/hg-active.py b/usr/src/tools/scripts/hg-active.py new file mode 100644 index 0000000000..192cf3b7aa --- /dev/null +++ b/usr/src/tools/scripts/hg-active.py @@ -0,0 +1,109 @@ +#! /usr/bin/python +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 +# as published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# + +# +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +''' +Create a wx-style active list on stdout based on a Mercurial +workspace in support of webrev's Mercurial support. +''' + +# +# NB: This assumes the normal onbld directory structure +# +import sys, os +sys.path.insert(1, "%s/../lib/python" % os.path.dirname(__file__)) +sys.path.insert(1, "%s/.." % os.path.dirname(__file__)) + +from onbld.Scm import Version + +try: + Version.check_version() +except Version.VersionMismatch, e: + sys.stderr.write("Error: %s\n" % e) + sys.exit(1) + +import getopt, binascii +from mercurial import hg, repo +from onbld.Scm.WorkSpace import WorkSpace + +def usage(): + sys.stderr.write("usage: %s [-p parent] -w workspace\n" % + os.path.basename(__file__)) + sys.exit(2) + +def main(argv): + try: + opts, args = getopt.getopt(argv, 'w:p:') + except getopt.GetoptError, e: + sys.stderr.write(str(e) + '\n') + usage() + + parentpath = None + wspath = None + + for opt, arg in opts: + if opt == '-w': + wspath = arg + elif opt == '-p': + parentpath = arg + + if not wspath: + usage() + + try: + repository = hg.repository(None, wspath) + except repo.RepoError, e: + sys.stderr.write("failed to open repository: %s\n" % e) + sys.exit(1) + + ws = WorkSpace(repository) + act = ws.active(parentpath) + + node = act.parenttip.node() + parenttip = binascii.hexlify(node) + print "HG_PARENT=" + parenttip + + entries = [i for i in act] + entries.sort() + + for entry in entries: + if entry.is_renamed(): + print "%s %s" % (entry.name, entry.parentname) + else: + print entry.name + + # Strip blank lines. + comments = filter(lambda x: x and not x.isspace(), + entry.comments) + + print + if comments: + print '\n'.join(comments) + else: + print "*** NO COMMENTS ***" + print + +if __name__ == '__main__': + try: + main(sys.argv[1:]) + except KeyboardInterrupt: + sys.exit(1) diff --git a/usr/src/tools/scripts/hgsetup.1 b/usr/src/tools/scripts/hgsetup.1 new file mode 100644 index 0000000000..64b1f7c55d --- /dev/null +++ b/usr/src/tools/scripts/hgsetup.1 @@ -0,0 +1,71 @@ +.\" CDDL HEADER START +.\" +.\" The contents of this file are subject to the terms of the +.\" Common Development and Distribution License (the "License"). +.\" You may not use this file except in compliance with the License. +.\" +.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +.\" or http://www.opensolaris.org/os/licensing. +.\" See the License for the specific language governing permissions +.\" and limitations under the License. +.\" +.\" When distributing Covered Code, include this CDDL HEADER in each +.\" file and include the License file at usr/src/OPENSOLARIS.LICENSE. +.\" If applicable, add the following below this CDDL HEADER, with the +.\" fields enclosed by brackets "[]" replaced with your own identifying +.\" information: Portions Copyright [yyyy] [name of copyright owner] +.\" +.\" CDDL HEADER END +.\" +.\" Copyright 2008 Sun Microsystems, Inc. All rights reserved. +.\" Use is subject to license terms." +.\" +.\" ident "%Z%%M% %I% %E% SMI" +.TH hgsetup 1 "10 July 2008" +.SH NAME +.I hgsetup +\- sets up a user's ~/.hgrc for development of ON with Mercurial +.SH SYNOPSIS +\fBhgsetup [-f] [-c \fIcdm_path\fP] [-m \fImerge_path\fP] [-n \fIname\fP] [-e \fIemail\fP] [-p \fIproxy\fP] +.LP +.SH DESCRIPTION +.IX "OS-Net build tools" "hgsetup" "" "\fBhgsetup\fP" +.LP +The hgsetup script sets up a user's ~/.hgrc (hgrc(5)) file for development +of ON (OS/Net) with Mercurial. +.LP +It populates the author and email fields with the user's information. +It loads the Cadmium extension. +It aliases canonical repositories for onnv-gate. +It configures Mercurial to use appropriate merge tools. +.SH OPTIONS +.TP 10 +.B -f +Force the user's ~/.hgrc to be overwritten if one already exists +.TP 10 +.B -c +Override the path to the Cadmium extension for Mercurial to load +.TP 10 +.B -m +Override the default merge configuration, such that a single +specified tool is used. +.TP 10 +.B -n +Specify the name to use for commits (default is taken from passwd file) +.TP 10 +.B -e +Specify the email address to use for commits. +For SWAN users the default is taken from an LDAP query, otherwise -e +is mandatory. +.TP 10 +.B -p +Specify an http_proxy to use for interacting with HTTP repositories +.LP +.SH OUTPUT +.LP +Generates a .hgrc file in the user's home directory. +.LP +.SH SEE ALSO +.LP +.IR hgrc(5), +.IR hg(1), diff --git a/usr/src/tools/scripts/hgsetup.sh b/usr/src/tools/scripts/hgsetup.sh new file mode 100644 index 0000000000..422e10213b --- /dev/null +++ b/usr/src/tools/scripts/hgsetup.sh @@ -0,0 +1,187 @@ +#! /usr/bin/ksh +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +# +# Easy setup script for populating a user's ~/.hgrc +# This currently does the following: +# * Load the cadmium extension +# * Populate the author/email fields to be correct +# * Alias canonical repositories like onnv-gate +# * Configures mercurial to use appropriate merge tools +# +# See hgrc(5) for more information +# + +HGRC=$HOME/.hgrc + +usage() { + prog=$(basename "$0") + echo \ +"usage: $prog [-f] [-c cdm_path] [-m merge_path] [-n name] [-e email] [-p proxy] + -f : force overwriting $HGRC + -c cdm_path : override Cadmium path + -m merge_path : override path to merge tool + -n name : override name (for ui.username) + -e email : override email (for email.from) + -p proxy : enable use of web proxy with specified proxy + + if -e isn't provided, and you are on SWAN, an LDAP query is done + if -n isn't provided, the entry from /etc/passwd is used + + proxy should be in the form of hostname:port + if on-SWAN, $prog will lookup your email address. this can be + overridden by using the -e flag. + " + exit 1 +} + +while getopts c:e:fm:n:p: opt; do + case "$opt" in + c) cdm_path=$OPTARG;; + e) email=$OPTARG;; + f) force=1;; + m) merge_path=$OPTARG;; + n) name=$OPTARG;; + p) proxy=$OPTARG;; + *) usage;; + esac +done + +if [ -f $HGRC -a "$force" -eq 0 ]; then + echo "Error: You have an existing .hgrc in $HGRC" + echo "Please move it aside." + exit 1 +fi + +AWK="/usr/xpg4/bin/awk" +SED="/usr/bin/sed" +LDAPCLIENT="/usr/bin/ldapsearch" + +login=$(/usr/bin/id -un) + +# +# Try and determine where Cadmium is installed. In order of +# preference, look in: +# +# 1. $(whence $0), on the assumption that you want the version +# of cadmium that best matches the hgsetup script you invoked +# +# 2. /opt/onbld, because local is generally better +# +# 3. /ws/onnv-tools/onbld, it's nfs and it might be slow, but it +# should resolve from most places on-SWAN +# +paths="$(dirname $(whence $0)) /opt/onbld /ws/onnv-tools/onbld" +cdmbin="lib/python/onbld/hgext/cdm.py" + +for dir in $paths; do + if [[ -f "$dir/$cdmbin" && -z "$cdm_path" ]]; then + cdm_path="$dir/$cdmbin" + break + fi +done + +if [[ -n $proxy ]]; then + proxyConfig="[http_proxy] +host=$proxy +" +fi + +if getent hosts sunweb.central.sun.com >/dev/null; then + # on SWAN + echo "Detected SWAN connection" + ldapemail='preferredrfc822recipient' + ldapquery="uid=$login $ldapemail" + ldapcmd="$LDAPCLIENT -1 -h sun-ds -b dc=sun,dc=com $ldapquery" + if [[ -z "$email" ]]; then + echo "Looking up e-mail address in LDAP" + email=${email:=$($ldapcmd | $AWK /^$ldapemail:/'{print $2}')} + fi +fi + +if [[ -z $email ]]; then + my_id=$(id -un) + my_checkhostname=$(check-hostname) + my_fqhn=${my_checkhostname##* } + email="$my_id@$my_fqhn" + echo "No e-mail address provided, defaulting to $email" +fi + +if [[ -z "$name" ]]; then + name=${name:=$(getent passwd $login | awk -F: '{print $5}')} +fi +username="$name <$email>" + +echo "Configured the following:" +if [[ -n $proxy ]]; then + echo " proxy: $proxy" +fi +echo " email: $email" +echo " username: $name" +echo " cadmium: $cdm_path" + +if [[ -z "$cdm_path" ]]; then + echo "Warning: you will need to edit your .hgrc file\n" \ + "to specify a path for cadmium." +fi + +if [[ -n $merge_path ]]; then + echo " merge: $merge_path" +fi + +cat <<EOF >$HGRC +$proxyConfig[extensions] +hgext.cdm=$cdm_path + +[email] +from=$email + +[paths] +onnv-gate=ssh://anon@hg.opensolaris.org/hg/onnv/onnv-gate + +[merge-tools] +filemerge.gui=True +filemerge.args=-a \$base \$local \$other \$output +filemerge.priority=1 + +meld.gui=True +meld.priority=0 + +gpyfm.gui=True +gpyfm.priority=0 + +[ui] +username=$username +EOF + +if [[ -n $merge_path ]]; then + echo "merge=$merge_path" >> $HGRC +fi + +echo "Please check $HGRC and verify everything looks correct" diff --git a/usr/src/tools/scripts/jstyle.pl b/usr/src/tools/scripts/jstyle.pl index 0b3b91a170..caf7dcc251 100644 --- a/usr/src/tools/scripts/jstyle.pl +++ b/usr/src/tools/scripts/jstyle.pl @@ -23,7 +23,7 @@ # # ident "%Z%%M% %I% %E% SMI" # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # jstyle - check for some common stylistic errors. @@ -49,7 +49,7 @@ my %opts; # anymore. if (!getopts("chpstvC", \%opts)) { print $usage; - exit 1; + exit 2; } my $check_continuation = $opts{'c'}; @@ -60,6 +60,7 @@ my $verbose = $opts{'v'}; my $ignore_hdr_comment = $opts{'C'}; my ($filename, $line, $prev); +my $err_stat = 0; # Exit status my $fmt; @@ -94,9 +95,11 @@ if ($#ARGV >= 0) { } else { &jstyle("<stdin>"); } +exit $err_stat; sub err($) { printf $fmt, $filename, $., $_[0], $line; + $err_stat = 1; } sub jstyle($) { diff --git a/usr/src/tools/scripts/nightly.1 b/usr/src/tools/scripts/nightly.1 index 04105c7f21..7dfd615525 100644 --- a/usr/src/tools/scripts/nightly.1 +++ b/usr/src/tools/scripts/nightly.1 @@ -20,7 +20,7 @@ .\" " .\" "Copyright 2008 Sun Microsystems, Inc. All rights reserved." .\" "Use is subject to license terms." -.TH nightly 1 "06 Jan 2008" +.TH nightly 1 "18 June 2008" .SH NAME .I nightly \- build an OS-Net consolidation overnight @@ -271,33 +271,68 @@ references and the meaning of each variable. .RE .B CODEMGR_WS .RS 5 -The root of your Teamware workspace, which is the directory -containing Codemgr_wsdata. This is the source to be built -.LP +The root of your workspace, including whatever metadata is kept by +the source code management system. This is the workspace in which the +build will be done. .RE +.LP .B PARENT_WS .RS 5 -The root of the Teamware workspace which is the parent of the -one being built; +The root of the workspace that is the parent of the +one being built. This is particularly relevant for configurations +with a main +workspace and build workspaces underneath it; see the +\-u and \-U +options, and the CPIODIR and PKGARCHIVE environment variables, for more +information. +.RE +.LP +.B BRINGOVER_WS +.RS 5 +This is the workspace from which .I nightly -uses this for the bringover if $CLONE_WS is not defined +will fetch sources to either populate or update your workspace; +it defaults to $CLONE_WS. +.RE .LP +.B CLOSED_BRINGOVER_WS +.RS 5 +A full Mercurial workspace has two repositories: one for open source +and one for closed source. If this variable is non-null, +.I nightly +will pull from the repository that it names to get the closed source. +It defaults to $CLOSED_CLONE_WS. +.LP +If $CODEMGR_WS already exists and contains only the open repository, +.I nightly +will ignore this variable; you'll need to pull the closed repository +by hand if you want it. .RE +.LP .B CLONE_WS .RS 5 -The clone of the parent Teamware workspace; +This is the workspace from which .I nightly -uses this for the bringover if it is defined, to avoid locking out -updates to the parent for the duration of the bringover +will fetch sources by default. This is +often distinct from the parent, particularly if the parent is a gate. +.RE .LP +.B CLOSED_CLONE_WS +.RS 5 +This is the default closed-source Mercurial repository that +.I nightly +might pull from (see +.B CLOSED_BRINGOVER_WS +for details). .RE +.LP .B SRC .RS 5 Root of OS-Net source code, referenced by the Makefiles. It is the starting point of build activity. It should be expressed -in terms of $CODEMGR_WS -.LP +in terms of $CODEMGR_WS. .RE +.LP .B ROOT .RS 5 Root of the proto area for the build. The makefiles direct @@ -312,188 +347,191 @@ $ROOT-nd contains the non-DEBUG build. For OpenSolaris deliveries (\fB\-O\fR), $ROOT-open contains the DEBUG build of just the open source tree, and $ROOT-open-nd contains the non-DEBUG build. -.LP .RE +.LP .B MACH .RS 5 The instruction set architecture of the build machine as given -by \fIuname -p\fP, e.g. sparc, i386 -.LP +by \fIuname -p\fP, e.g. sparc, i386. .RE +.LP .B LOCKNAME .RS 5 The name of the file used to lock out multiple runs of .I nightly. -This should generally be left to the default setting -.LP +This should generally be left to the default setting. .RE +.LP .B ATLOG .RS 5 The location of the log directory maintained by .I nightly -This should generally be left to the default setting -.LP +This should generally be left to the default setting. .RE +.LP .B LOGFILE .RS 5 The name of the log file in the $ATLOG directory maintained by .I nightly -This should generally be left to the default setting -.LP +This should generally be left to the default setting. .RE +.LP .B STAFFER .RS 5 -The non-root user identity to use for the bringover from the -clone or parent workspace -.LP +The non-root account to use on the build machine for the +bringover from the clone or parent workspace. +This may not be the same identify used by the SCM. .RE +.LP .B MAILTO .RS 5 The address to be used to send completion e-mail at the end of -the build (for the -m option) -.LP +the build (for the \-m option). .RE +.LP .B REF_PROTO_LIST .RS 5 -Name of file used with protocmp to compare proto area contents -.LP +Name of file used with protocmp to compare proto area contents. .RE +.LP .B CPIODIR .RS 5 The destination for cpio archives. This may be relative to $CODEMGR_WS for private archives or relative to $PARENT_WS if you have different workspaces for different architectures -but want one hierarchy of BFU archives -.LP +but want one hierarchy of BFU archives. .RE +.LP .B PARENT_ROOT .RS 5 The parent root, which is the destination for updated headers and -libraries when using the -U option -.LP +libraries when using the \-U option. .RE +.LP .B RELEASE .RS 5 The release version number to be used; e.g., 5.10.1 (Note: this is set -in Makefile.master and should not normally be overridden) -.LP +in Makefile.master and should not normally be overridden). .RE +.LP .B VERSION .RS 5 -The version text string to be used; e.g., "onnv:`date '+%Y-%m-%d'`" -.LP +The version text string to be used; e.g., "onnv:`date '+%Y-%m-%d'`". .RE +.LP .B RELEASE_DATE .RS 5 -The release date text to be used; e.g., October 2007 -.LP +The release date text to be used; e.g., October 2007. .RE +.LP .B INTERNAL_RELEASE_BUILD .RS 5 See Makefile.master - but it mostly controls id strings. Generally, let .I nightly set this for you. -.LP .RE +.LP .B RELEASE_BUILD .RS 5 Define this to build a release with a non-DEBUG kernel. Generally, let .I nightly set this for you based on its options. -.LP .RE +.LP .B PKGDEFS .RS 5 Points to "$SRC/pkgdefs." Not used these days. -.LP .RE +.LP .B PKGARCHIVE .RS 5 The destination for packages. This may be relative to $CODEMGR_WS for private archives or relative to $PARENT_WS if you have different workspaces for different architectures -but want one hierarchy of BFU archives -.LP +but want one hierarchy of BFU archives. .RE +.LP .B MAKEFLAGS .RS 5 Set default flags to make; e.g., -k to build all targets regardless of errors. -.LP .RE +.LP .B UT_NO_USAGE_TRACKING .RS 5 Disables usage reporting by listed Devpro tools. Otherwise it sends mail to some Devpro machine every time the tools are used. -.LP .RE +.LP .B LINTDIRS .RS 5 -Directories to lint with the -l option -.LP +Directories to lint with the \-l option. .RE +.LP .B BUILD_TOOLS .RS 5 BUILD_TOOLS is the root of all tools including the compilers; e.g., /ws/onnv-tools. It is used by the makefile system, but not nightly. -.LP .RE +.LP .B ONBLD_TOOLS .RS 5 ONBLD_TOOLS is the root of all the tools that are part of SUNWonbld; e.g., /ws/onnv-tools/onbld. By default, it is derived from .BR BUILD_TOOLS . It is used by the makefile system, but not nightly. -.LP .RE +.LP .B SPRO_ROOT .RS 5 The gate-defined default location for the Sun compilers, e.g. /ws/onnv-tools/SUNWspro. By default, it is derived from .BR BUILD_TOOLS . It is used by the makefile system, but not nightly. -.LP .RE +.LP .B JAVA_ROOT .RS 5 The location for the java compilers for the build, generally /usr/java. -.LP .RE +.LP .B OPTHOME .RS 5 The gate-defined default location of things formerly in /opt; e.g., /ws/onnv-tools. This is used by nightly, but not the makefiles. -.LP .RE +.LP .B TEAMWARE .RS 5 The gate-defined default location for the Teamware tools; e.g., /ws/onnv-tools/SUNWspro. By default, it is derived from .BR OPTHOME . -This is used by nightly, but not the makefiles. -.LP +This is used by nightly, but not the makefiles. There is no +corresponding variable for Mercurial or Subversion, which are assumed +to be installed in the default path. .RE +.LP .B EXPORT_SRC .RS 5 The source product has no SCCS history, and is modified to remove source that cannot be shipped. EXPORT_SRC is where the clear files are copied, then -modified with 'make EXPORT_SRC' -.LP +modified with 'make EXPORT_SRC'. .RE +.LP .B CRYPT_SRC .RS 5 CRYPT_SRC is similar to EXPORT_SRC, but after 'make CRYPT_SRC' the files in xmod/cry_files are saved. They are dropped on the exportable source to create -the domestic build -.RE +the domestic build. .LP +.RE .B OPEN_SRCDIR .RS 5 The open source tree is copied to this directory when simulating an OpenSolaris build (\fB\-S O\fR). It defaults to $CODEMGR_WS/open_src. -.RE .LP +.RE .B ON_CLOSED_BINS .RS 5 OpenSolaris builds do not contain the closed source tree. Instead, @@ -502,8 +540,8 @@ the developer downloads a closed binaries tree and unpacks it. tells nightly where to find these closed binaries, so that it can add them into the build. -.RE .LP +.RE .B CHECK_PATHS .RS 5 Normally, nightly runs the 'checkpaths' script to check for @@ -564,7 +602,7 @@ Run just after bringover completes; not run if no bringover is done. .RS 5 Run after the build completes, with the return status of nightly - one of "Completed", "Interrupted", or "Failed" - available in the -environment variable NIGHTLY_STATUS +environment variable NIGHTLY_STATUS. .RE .LP .B SYS_POST_NIGHTLY diff --git a/usr/src/tools/scripts/nightly.sh b/usr/src/tools/scripts/nightly.sh index f2c50a14cd..3a2883f312 100644 --- a/usr/src/tools/scripts/nightly.sh +++ b/usr/src/tools/scripts/nightly.sh @@ -59,6 +59,21 @@ # unset CDPATH +# Get the absolute path of the nightly script that the user invoked. This +# may be a relative path, and we need to do this before changing directory. +nightly_path=`whence $0` + +# +# Keep track of where we found nightly so we can invoke the matching +# which_scm script. If that doesn't work, don't go guessing, just rely +# on the $PATH settings, which will generally give us either /opt/onbld +# or the user's workspace. +# +WHICH_SCM=$(dirname $nightly_path)/which_scm +if [[ ! -x $WHICH_SCM ]]; then + WHICH_SCM=which_scm +fi + # # Print the tag string used to identify a build (e.g., "DEBUG # open-only") @@ -268,6 +283,9 @@ rename_files() { # # Copy some or all of the source tree. +# +# Returns 0 for success, non-zero for failure. +# # usage: copy_source CODEMGR_WS DESTDIR LABEL SRCROOT # copy_source() { @@ -276,20 +294,123 @@ copy_source() { label=$3 srcroot=$4 - echo "\n==== Creating ${DEST} source from ${WS} ($label) ====\n" | \ - tee -a $mail_msg_file >> $LOGFILE + printf "\n==== Creating %s source from %s (%s) ====\n\n" \ + "$DEST" "$WS" "$label" | tee -a $mail_msg_file >> $LOGFILE - echo "cleaning out ${DEST}." >> $LOGFILE - rm -rf "${DEST}" >> $LOGFILE 2>&1 + printf "cleaning out %s\n" "$DEST." >> $LOGFILE + rm -rf "$DEST" >> $LOGFILE 2>&1 - mkdir -p ${DEST} - cd ${WS} + printf "creating %s\n" "$DEST." >> $LOGFILE + mkdir -p "$DEST" 2>> $LOGFILE - echo "creating ${DEST}." >> $LOGFILE - find $srcroot -name 's\.*' -a -type f -print | \ - sed -e 's,SCCS\/s.,,' | \ - grep -v '/\.del-*' | \ - cpio -pd ${DEST} >>$LOGFILE 2>&1 + if (( $? != 0 )) ; then + printf "failed to create %s\n" "$DEST" | + tee -a $mail_msg_file >> $LOGFILE + build_ok=n + return 1 + fi + cd "$WS" + + printf "populating %s\n" "$DEST." >> $LOGFILE + + case "$SCM_TYPE" in + teamware) + find $srcroot -name 's\.*' -a -type f -print | \ + sed -e 's,SCCS\/s.,,' | \ + grep -v '/\.del-*' | \ + cpio -pd $DEST >>$LOGFILE 2>&1 + if (( $? != 0 )) ; then + printf "cpio failed for %s\n" "$DEST" | + tee -a $mail_msg_file >> $LOGFILE + build_ok=n + return 1 + fi + ;; + mercurial) + copy_source_mercurial $DEST $srcroot + if (( $? != 0 )) ; then + build_ok=n + return 1 + fi + ;; + *) + build_ok=n + echo "Tree copy is not supported for workspace type" \ + "$SCM_TYPE" | tee -a $mail_msg_file >> $LOGFILE + return 1 + ;; + esac + + return 0 +} + +# +# Mercurial-specific copy code for copy_source(). Handles the +# combined open and closed trees. +# +# Returns 0 for success, non-zero for failure. +# +# usage: copy_source_mercurial destdir srcroot +# +function copy_source_mercurial { + typeset dest=$1 + typeset srcroot=$2 + typeset open_top closed_top + + case $srcroot in + usr) + open_top=usr + if [[ "$CLOSED_IS_PRESENT" = yes ]]; then + closed_top=usr/closed + fi + ;; + usr/closed*) + if [[ "$CLOSED_IS_PRESENT" = no ]]; then + printf "can't copy %s: closed tree not present.\n" \ + "$srcroot" | tee -a $mail_msg_file >> $LOGFILE + return 1 + fi + closed_top="$srcroot" + ;; + *) + open_top="$srcroot" + ;; + esac + + if [[ -n "$open_top" ]]; then + hg locate -I "$open_top" | cpio -pd "$dest" >>$LOGFILE 2>&1 + if (( $? != 0 )) ; then + printf "cpio failed for %s\n" "$dest" | + tee -a $mail_msg_file >> $LOGFILE + return 1 + fi + fi + + if [[ -n "$closed_top" ]]; then + mkdir -p "$dest/usr/closed" || return 1 + if [[ "$closed_top" = usr/closed ]]; then + (cd usr/closed; hg locate | + cpio -pd "$dest/usr/closed") >>$LOGFILE 2>&1 + if (( $? != 0 )) ; then + printf "cpio failed for %s/usr/closed\n" \ + "$dest" | tee -a $mail_msg_file >> $LOGFILE + return 1 + fi + else + # copy subtree of usr/closed + closed_top=${closed_top#usr/closed/} + (cd usr/closed; hg locate -I "$closed_top" | + cpio -pd "$dest/usr/closed") >>$LOGFILE 2>&1 + if (( $? != 0 )) ; then + printf "cpio failed for %s/usr/closed/%s\n" \ + "$dest" "$closed_top" | + tee -a $mail_msg_file >> $LOGFILE + return 1 + fi + fi + fi + + return 0 } # @@ -304,6 +425,13 @@ set_up_source_build() { MAKETARG=$3 copy_source $WS $DEST $MAKETARG usr + if (( $? != 0 )); then + echo "\nCould not copy source tree for source build." | + tee -a $mail_msg_file >> $LOGFILE + build_ok=n + return + fi + SRC=${DEST}/usr/src cd $SRC @@ -448,9 +576,11 @@ build() { /bin/time $MAKE -e install 2>&1 | \ tee -a $SRC/${INSTALLOG}.out >> $LOGFILE - echo "\n==== SCCS Noise ($LABEL) ====\n" >> $mail_msg_file - - egrep 'sccs(check:| get)' $SRC/${INSTALLOG}.out >> $mail_msg_file + if [[ "$SCM_TYPE" = teamware ]]; then + echo "\n==== SCCS Noise ($LABEL) ====\n" >> $mail_msg_file + egrep 'sccs(check:| *get)' $SRC/${INSTALLOG}.out >> \ + $mail_msg_file + fi echo "\n==== Build errors ($LABEL) ====\n" >> $mail_msg_file egrep ":" $SRC/${INSTALLOG}.out | @@ -565,7 +695,7 @@ build() { echo "\n==== Crypto module signing errors ($LABEL) ====\n" \ >> $mail_msg_file egrep 'WARNING|ERROR' ${signing_file} >> $mail_msg_file - if [ $? = 0 ]; then + if (( $? == 0 )) ; then build_ok=n this_build_ok=n fi @@ -671,7 +801,8 @@ dolint() { # Remove all .ln files to ensure a full reference file # rm -f Nothing_to_remove \ - `find . -name SCCS -prune -o -type f -name '*.ln' -print ` + `find . \( -name SCCS -o -name .hg -o -name .svn \) \ + -prune -o -type f -name '*.ln' -print ` /bin/time $MAKE -ek lint 2>&1 | \ tee -a $LINTOUT >> $LOGFILE @@ -895,6 +1026,7 @@ check_closed_tree() { echo "If the closed sources are not present," \ "ON_CLOSED_BINS" echo "must point to the closed binaries tree." + build_ok=n exit 1 fi fi @@ -1217,6 +1349,13 @@ if [ "$BRINGOVER_WS" = "" ]; then fi # +# If CLOSED_BRINGOVER_WS was not specified, let it default to CLOSED_CLONE_WS +# +if [ "$CLOSED_BRINGOVER_WS" = "" ]; then + CLOSED_BRINGOVER_WS=$CLOSED_CLONE_WS +fi + +# # If BRINGOVER_FILES was not specified, default to usr # if [ "$BRINGOVER_FILES" = "" ]; then @@ -1279,7 +1418,7 @@ do ;; o ) o_FLAG=y ;; - P ) P_FLAG=y + P ) P_FLAG=y ;; # obsolete p ) p_FLAG=y ;; @@ -1613,10 +1752,10 @@ logshuffle() { run_hook POST_NIGHTLY $state run_hook SYS_POST_NIGHTLY $state - cat $build_time_file $mail_msg_file > ${LLOG}/mail_msg + cat $build_time_file $build_environ_file $mail_msg_file \ + > ${LLOG}/mail_msg if [ "$m_FLAG" = "y" ]; then - cat $build_time_file $mail_msg_file | - /usr/bin/mailx -s \ + cat ${LLOG}/mail_msg | /usr/bin/mailx -s \ "Nightly ${MACH} Build of `basename ${CODEMGR_WS}` ${state}." \ ${MAILTO} fi @@ -1663,6 +1802,7 @@ trap cleanup_signal 1 2 3 15 # doesn't, then make sure we can create it. Clean up locks that are # known to be stale (assumes host name is unique among build systems # for the workspace). +# create_lock() { lockf=$1 lockvar=$2 @@ -1743,6 +1883,8 @@ newdirlist= mail_msg_file="${TMPDIR}/mail_msg" touch $mail_msg_file build_time_file="${TMPDIR}/build_time" +build_environ_file="${TMPDIR}/build_environ" +touch $build_environ_file # # Move old LOGFILE aside # ATLOG directory already made by 'create_lock' above @@ -1758,6 +1900,9 @@ SECONDS=0 echo "\n==== Nightly $maketype build started: $START_DATE ====" \ | tee -a $LOGFILE > $build_time_file +echo "\nBuild project: $build_project\nBuild taskid: $build_taskid" | \ + tee -a $mail_msg_file >> $LOGFILE + # make sure we log only to the nightly build file build_noise_file="${TMPDIR}/build_noise" exec </dev/null >$build_noise_file 2>&1 @@ -1894,81 +2039,6 @@ yes|no) ;; ;; esac -echo "==== Build environment ====\n" | tee -a $mail_msg_file >> $LOGFILE - -# System -whence uname | tee -a $mail_msg_file >> $LOGFILE -uname -a 2>&1 | tee -a $mail_msg_file >> $LOGFILE -echo | tee -a $mail_msg_file >> $LOGFILE - -# nightly (will fail in year 2100 due to SCCS flaw) -echo "$0 $@" | tee -a $mail_msg_file >> $LOGFILE -echo "%M% version %I% 20%E%\n" | tee -a $mail_msg_file >> $LOGFILE - -# make -whence $MAKE | tee -a $mail_msg_file >> $LOGFILE -$MAKE -v | tee -a $mail_msg_file >> $LOGFILE -echo "number of concurrent jobs = $DMAKE_MAX_JOBS" | - tee -a $mail_msg_file >> $LOGFILE - -# -# Report the compiler versions. -# -if [ -f $SRC/Makefile ]; then - srcroot=$SRC -elif [ -f $BRINGOVER_WS/usr/src/Makefile ]; then - srcroot=$BRINGOVER_WS/usr/src -else - echo "\nUnable to find \"Makefile\" in $BRINGOVER_WS/usr/src or $SRC." | - tee -a $mail_msg_file >> $LOGFILE - exit 1 -fi - -( cd $srcroot - for target in cc-version cc64-version java-version; do - echo - # - # Put statefile somewhere we know we can write to rather than trip - # over a read-only $srcroot. - # - rm -f $TMPDIR/make-state - export SRC=$srcroot - if $MAKE -K $TMPDIR/make-state -e $target 2>/dev/null; then - continue - fi - touch $TMPDIR/nocompiler - done - echo -) | tee -a $mail_msg_file >> $LOGFILE - -if [ -f $TMPDIR/nocompiler ]; then - rm -f $TMPDIR/nocompiler - build_ok=n - echo "Aborting due to missing compiler." | - tee -a $mail_msg_file >> $LOGFILE - exit 1 -fi - -# as -whence as | tee -a $mail_msg_file >> $LOGFILE -as -V 2>&1 | head -1 | tee -a $mail_msg_file >> $LOGFILE -echo | tee -a $mail_msg_file >> $LOGFILE - -# Check that we're running a capable link-editor -whence ld | tee -a $mail_msg_file >> $LOGFILE -LDVER=`ld -V 2>&1` -echo $LDVER | tee -a $mail_msg_file >> $LOGFILE -LDVER=`echo $LDVER | sed -e "s/.*-1\.//" -e "s/:.*//"` -if [ `expr $LDVER \< 422` -eq 1 ]; then - echo "The link-editor needs to be at version 422 or higher to build" | \ - tee -a $mail_msg_file >> $LOGFILE - echo "the latest stuff, hope your build works." | \ - tee -a $mail_msg_file >> $LOGFILE -fi - -echo "\nBuild project: $build_project\nBuild taskid: $build_taskid" | \ - tee -a $mail_msg_file >> $LOGFILE - echo "\n==== Build version ====\n" | tee -a $mail_msg_file >> $LOGFILE echo $VERSION | tee -a $mail_msg_file >> $LOGFILE @@ -2001,8 +2071,9 @@ if [ "$i_FLAG" = "n" -a -d "$SRC" ]; then # Remove all .make.state* files, just in case we are restarting # the build after having interrupted a previous 'make clobber'. - find . \( -name SCCS -o -name 'interfaces.*' \) -prune \ - -o -name '.make.*' -print | xargs rm -f + find . \( -name SCCS -o -name .hg -o -name .svn \ + -o -name 'interfaces.*' \) -prune \ + -o -name '.make.*' -print | xargs rm -f $MAKE -ek clobber 2>&1 | tee -a $SRC/clobber-${MACH}.out >> $LOGFILE echo "\n==== Make clobber ERRORS ====\n" >> $mail_msg_file @@ -2030,10 +2101,11 @@ if [ "$i_FLAG" = "n" -a -d "$SRC" ]; then # problems that only occur on fresh workspaces. # Remove all .make.state* files, libraries, and .o's that may # have been omitted from clobber. A couple of libraries are - # under SCCS, so leave them alone. + # under source code control, so leave them alone. # We should probably blow away temporary directories too. cd $SRC - find $relsrcdirs \( -name SCCS -o -name 'interfaces.*' \) -prune -o \ + find $relsrcdirs \( -name SCCS -o -name .hg -o -name .svn \ + -o -name 'interfaces.*' \) -prune -o \ \( -name '.make.*' -o -name 'lib*.a' -o -name 'lib*.so*' -o \ -name '*.o' \) -print | \ grep -v 'tools/ctf/dwarf/.*/libdwarf' | xargs rm -f @@ -2041,13 +2113,7 @@ else echo "\n==== No clobber at `date` ====\n" >> $LOGFILE fi -# -# Decide whether to bringover to the codemgr workspace -# -if [ "$n_FLAG" = "n" ]; then - run_hook PRE_BRINGOVER - - echo "\n==== bringover to $CODEMGR_WS at `date` ====\n" >> $LOGFILE +type bringover_teamware > /dev/null 2>&1 || bringover_teamware() { # sleep on the parent workspace's lock while egrep -s write $BRINGOVER_WS/Codemgr_wsdata/locks do @@ -2057,20 +2123,246 @@ if [ "$n_FLAG" = "n" ]; then if [[ -z $BRINGOVER ]]; then BRINGOVER=$TEAMWARE/bin/bringover fi - echo "\n==== BRINGOVER LOG ====\n" >> $mail_msg_file - (staffer $BRINGOVER -c "nightly update" -p $BRINGOVER_WS \ + staffer $BRINGOVER -c "nightly update" -p $BRINGOVER_WS \ -w $CODEMGR_WS $BRINGOVER_FILES < /dev/null 2>&1 || touch $TMPDIR/bringover_failed - staffer bringovercheck $CODEMGR_WS >$TMPDIR/bringovercheck.out 2>&1 - - if [ -s $TMPDIR/bringovercheck.out ]; then + staffer bringovercheck $CODEMGR_WS >$TMPDIR/bringovercheck.out 2>&1 + if [ -s $TMPDIR/bringovercheck.out ]; then echo "\n==== POST-BRINGOVER CLEANUP NOISE ====\n" cat $TMPDIR/bringovercheck.out - fi + fi +} - ) | tee -a $mail_msg_file >> $LOGFILE +type bringover_mercurial > /dev/null 2>&1 || bringover_mercurial() { + typeset -x PATH=$PATH + + # If the repository doesn't exist yet, then we want to populate it. + # We only initially populate the closed repository if the open + # repository doesn't also exist (e.g.: don't bringover closed if + # only usr/src exists) + if [[ ! -d $CODEMGR_WS/.hg ]]; then + staffer hg init $CODEMGR_WS + # If the user set CLOSED_BRINGOVER_WS, then we'll want to + # initialise the closed repository + if [[ -n $CLOSED_BRINGOVER_WS ]]; then + staffer mkdir -p $CODEMGR_WS/usr + staffer hg init $CODEMGR_WS/usr/closed + CLOSED_IS_PRESENT="yes" + fi + fi + + typeset -x HGMERGE="/bin/false" + + # Do the bringover, along with an update. If a merge is necessary, + # this will not fail properly: + # http://www.selenic.com/mercurial/bts/issue186 + # so we grep through the output for signs of a merge. + # + # Note that pulling even non-conflicting changes on top of local + # changes (committed or not) requires a merge. + staffer hg --cwd $CODEMGR_WS pull -u $BRINGOVER_WS 2>&1 | \ + tee $TMPDIR/pull_open.out + hgstatus=$? + if [ $hgstatus -ne 0 ]; then + touch $TMPDIR/bringover_failed + return + fi + + # We never want to clone usr/closed by default. If the usr/closed + # repository exists already and CLOSED_BRINGOVER_WS is set, then + # we update (pull -u). + if [[ -d $SRC/../closed && -n $CLOSED_BRINGOVER_WS ]]; then + staffer hg --cwd $SRC/../closed pull -u \ + $CLOSED_BRINGOVER_WS 2>&1 | + tee -a $TMPDIR/pull_closed.out + hgstatus=$? + if [ $hgstatus -ne 0 ]; then + touch $TMPDIR/bringover_failed + return + fi + fi + + # If there were uncommitted changes, the pull -u would have + # attempted a merge. In the likely event that it failed, fail the + # bringover. + if grep "^merging.*failed" $TMPDIR/pull_open.out > /dev/null 2>&1 || \ + grep "^merging.*failed" $TMPDIR/pull_closed.out >/dev/null 2>&1; + then + touch $TMPDIR/bringover_failed + return + fi + + # If heads were added, then a merge is required. We attempt the + # merge, in case the branches touch different files (something that + # teamware wouldn't balk at). If the merge fails, fail the + # bringover, leaving the conflicts unresolved. + # + # Note that even if the merge succeeds, the result of the merge + # will need to be committed, and not doing so will block any + # further pulls. + if grep "not updating" $TMPDIR/pull_open.out > /dev/null 2>&1; then + hg --cwd $CODEMGR_WS merge 2>&1 | tee $TMPDIR/merge.out + if grep "^merging.*failed" $TMPDIR/merge.out >/dev/null 2>&1; + then + touch $TMPDIR/bringover_failed + fi + fi + if grep "not updating" $TMPDIR/pull_closed.out > /dev/null 2>&1; then + hg --cwd $SRC/../closed merge 2>&1 | tee $TMPDIR/merge.out + if grep "^merging.*failed" $TMPDIR/merge.out >/dev/null 2>&1; + then + touch $TMPDIR/bringover_failed + fi + fi +} + +type bringover_subversion > /dev/null 2>&1 || bringover_subversion() { + typeset -x PATH=$PATH + + if [[ ! -d $CODEMGR_WS/.svn ]]; then + staffer svn checkout $BRINGOVER_WS $CODEMGR_WS || + touch $TMPDIR/bringover_failed + else + typeset root + root=$(staffer svn info $CODEMGR_WS | + nawk '/^Repository Root:/ {print $NF}') + if [[ $root != $BRINGOVER_WS ]]; then + # We fail here because there's no way to update + # from a named repo. + cat <<-EOF + \$BRINGOVER_WS doesn't match repository root: + \$BRINGOVER_WS: $BRINGOVER_WS + Repository root: $root + EOF + touch $TMPDIR/bringover_failed + else + # If a conflict happens, svn still exits 0. + staffer svn update $CODEMGR_WS | tee $TMPDIR/pull.out || + touch $TMPDIR/bringover_failed + if grep "^C" $TMPDIR/pull.out > /dev/null 2>&1; then + touch $TMPDIR/bringover_failed + fi + fi + fi +} + +type bringover_none > /dev/null 2>&1 || bringover_none() { + echo "Couldn't figure out what kind of SCM to use for $BRINGOVER_WS." + touch $TMPDIR/bringover_failed +} + +# Parse the URL. +# The other way to deal with empty components is to echo a string that can +# be eval'ed by the caller to associate values (possibly empty) with +# variables. In that case, passing in a printf string would let the caller +# choose the variable names. +parse_url() { + typeset url method host port path + + url=$1 + method=${url%%://*} + host=${url#$method://} + path=${host#*/} + host=${host%%/*} + if [[ $host == *:* ]]; then + port=${host#*:} + host=${host%:*} + fi + + # method can never be empty. host can only be empty if method is + # file, and that implies it's localhost. path can default to / if + # it's otherwise empty, leaving port as the only component without + # a default, so it has to go last. + echo $method ${host:-localhost} ${path:-/} $port +} + +http_get() { + typeset url method host port path + + url=$1 + + if [[ -n $http_proxy ]]; then + parse_url $http_proxy | read method host path port + echo "GET $url HTTP/1.0\r\n" | + mconnect -p ${port:-8080} $host + else + parse_url $url | read method host path port + echo "GET $path HTTP/1.0\r\n" | + mconnect -p ${port:-80} $host + fi +} + +# Echo a string name for the workspace SCM (teamware, hg, or svn). +function wstype { + typeset rtype ltype + + env CODEMGR_WS=$BRINGOVER_WS $WHICH_SCM 2>/dev/null | read rtype junk + if [[ -z "$rtype" || "$rtype" == unknown ]]; then + # Probe BRINGOVER_WS to determine its type + if [[ $BRINGOVER_WS == svn*://* ]]; then + rtype="subversion" + elif [[ $BRINGOVER_WS == file://* ]] && + egrep -s "This is a Subversion repository" \ + ${BRINGOVER_WS#file://}/README.txt 2> /dev/null; then + rtype="subversion" + elif [[ $BRINGOVER_WS == ssh://* ]]; then + rtype="mercurial" + elif svn info $BRINGOVER_WS > /dev/null 2>&1; then + rtype="subversion" + elif [[ $BRINGOVER_WS == http://* ]] && \ + http_get "$BRINGOVER_WS/?cmd=heads" | \ + egrep -s "application/mercurial" 2> /dev/null; then + rtype="mercurial" + else + rtype="none" + fi + fi + + # Make sure that the repository is one we support. If not, then + # call it "none." + case "$rtype" in + none|subversion|teamware|mercurial) + ;; + *) rtype=none + ;; + esac + + # Probe CODEMGR_WS to determine its type + if [[ -d $CODEMGR_WS ]]; then + $WHICH_SCM | read ltype junk || exit 1 + # This occurs when we have an empty build directory and nightly + # itself creates the directory. It's not an error, as long as + # we'll be doing a bringover. + if [[ "$ltype" == unknown ]]; then + ltype=$rtype + fi + fi + + # If BRINGOVER_WS and CODEMGR_WS don't match, doing a bringover + # will be problematic! + if [[ -n $ltype && $rtype != $ltype ]]; then + echo "none" + else + echo $rtype + fi +} + +SCM_TYPE=$(wstype) +export SCM_TYPE + +# +# Decide whether to bringover to the codemgr workspace +# +if [ "$n_FLAG" = "n" ]; then + run_hook PRE_BRINGOVER + + echo "\n==== bringover to $CODEMGR_WS at `date` ====\n" >> $LOGFILE + echo "\n==== BRINGOVER LOG ====\n" >> $mail_msg_file + + eval "bringover_$SCM_TYPE" 2>&1 | + tee -a $mail_msg_file >> $LOGFILE if [ -f $TMPDIR/bringover_failed ]; then rm -f $TMPDIR/bringover_failed @@ -2092,6 +2384,82 @@ else echo "\n==== No bringover to $CODEMGR_WS ====\n" >> $LOGFILE fi +echo "\n==== Build environment ====\n" | tee -a $build_environ_file >> $LOGFILE + +# System +whence uname | tee -a $build_environ_file >> $LOGFILE +uname -a 2>&1 | tee -a $build_environ_file >> $LOGFILE +echo | tee -a $build_environ_file >> $LOGFILE + +# nightly +echo "$0 $@" | tee -a $build_environ_file >> $LOGFILE +if [[ $nightly_path = "/opt/onbld/bin/nightly" ]] && + pkginfo SUNWonbld > /dev/null 2>&1 ; then + pkginfo -l SUNWonbld | egrep "PKGINST:|VERSION:|PSTAMP:" +else + ls -l "$nightly_path" +fi | tee -a $build_environ_file >> $LOGFILE +echo | tee -a $build_environ_file >> $LOGFILE + +# make +whence $MAKE | tee -a $build_environ_file >> $LOGFILE +$MAKE -v | tee -a $build_environ_file >> $LOGFILE +echo "number of concurrent jobs = $DMAKE_MAX_JOBS" | + tee -a $build_environ_file >> $LOGFILE + +# +# Report the compiler versions. +# + +if [[ ! -f $SRC/Makefile ]]; then + build_ok=n + echo "\nUnable to find \"Makefile\" in $SRC." | \ + tee -a $build_environ_file >> $LOGFILE + exit 1 +fi + +( cd $SRC + for target in cc-version cc64-version java-version; do + echo + # + # Put statefile somewhere we know we can write to rather than trip + # over a read-only $srcroot. + # + rm -f $TMPDIR/make-state + export SRC + if $MAKE -K $TMPDIR/make-state -e $target 2>/dev/null; then + continue + fi + touch $TMPDIR/nocompiler + done + echo +) | tee -a $build_environ_file >> $LOGFILE + +if [ -f $TMPDIR/nocompiler ]; then + rm -f $TMPDIR/nocompiler + build_ok=n + echo "Aborting due to missing compiler." | + tee -a $build_environ_file >> $LOGFILE + exit 1 +fi + +# as +whence as | tee -a $build_environ_file >> $LOGFILE +as -V 2>&1 | head -1 | tee -a $build_environ_file >> $LOGFILE +echo | tee -a $build_environ_file >> $LOGFILE + +# Check that we're running a capable link-editor +whence ld | tee -a $build_environ_file >> $LOGFILE +LDVER=`ld -V 2>&1` +echo $LDVER | tee -a $build_environ_file >> $LOGFILE +LDVER=`echo $LDVER | sed -e "s/.*-1\.//" -e "s/:.*//"` +if [ `expr $LDVER \< 422` -eq 1 ]; then + echo "The link-editor needs to be at version 422 or higher to build" | \ + tee -a $build_environ_file >> $LOGFILE + echo "the latest stuff. Hope your build works." | \ + tee -a $build_environ_file >> $LOGFILE +fi + # # Build and use the workspace's tools if requested # @@ -2133,7 +2501,7 @@ if [ "$O_FLAG" = y -a "$build_ok" = y ]; then tee -a $mail_msg_file >> $LOGFILE mktpl usr/src/tools/opensolaris/license-list >>$LOGFILE 2>&1 - if [ $? -ne 0 ]; then + if (( $? != 0 )) ; then echo "Couldn't create THIRDPARTYLICENSE files" | tee -a $mail_msg_file >> $LOGFILE fi @@ -2161,7 +2529,7 @@ if [ "$O_FLAG" = y -a "$build_ok" = y ]; then if [ "$D_FLAG" = y ]; then mkclosed $MACH $ROOT $CODEMGR_WS/closed.skel/root_$MACH \ >>$LOGFILE 2>&1 - if [ $? -ne 0 ]; then + if (( $? != 0 )) ; then echo "Couldn't create skeleton DEBUG closed binaries." | tee -a $mail_msg_file >> $LOGFILE fi @@ -2169,7 +2537,7 @@ if [ "$O_FLAG" = y -a "$build_ok" = y ]; then if [ "$F_FLAG" = n ]; then mkclosed $MACH $ROOT-nd $CODEMGR_WS/closed.skel/root_$MACH-nd \ >>$LOGFILE 2>&1 - if [ $? -ne 0 ]; then + if (( $? != 0 )) ; then echo "Couldn't create skeleton non-DEBUG closed binaries." | tee -a $mail_msg_file >> $LOGFILE fi @@ -2190,39 +2558,25 @@ fi ORIG_SRC=$SRC BINARCHIVE=${CODEMGR_WS}/bin-${MACH}.cpio.Z -# -# For the "open" build, we don't mung any source files, so skip this -# step. -# if [ "$SE_FLAG" = "y" -o "$SD_FLAG" = "y" -o "$SH_FLAG" = "y" ]; then save_binaries - - echo "\n==== Retrieving SCCS files at `date` ====\n" >> $LOGFILE - SCCSHELPER=${TMPDIR}/sccs-helper - rm -f ${SCCSHELPER} -cat >${SCCSHELPER} <<EOF -#!/bin/ksh -cd \$1 -cd .. -sccs get SCCS >/dev/null 2>&1 -EOF - cd $SRC - chmod +x ${SCCSHELPER} - find $relsrcdirs -name SCCS | xargs -L 1 ${SCCSHELPER} - rm -f ${SCCSHELPER} fi -if [ "$SD_FLAG" = "y" ]; then - set_up_source_build ${CODEMGR_WS} ${CRYPT_SRC} CRYPT_SRC -fi # EXPORT_SRC comes after CRYPT_SRC since a domestic build will need # $SRC pointing to the export_source usr/src. + if [ "$SE_FLAG" = "y" -o "$SD_FLAG" = "y" -o "$SH_FLAG" = "y" ]; then - set_up_source_build ${CODEMGR_WS} ${EXPORT_SRC} EXPORT_SRC + if [ "$SD_FLAG" = "y" -a $build_ok = y ]; then + set_up_source_build ${CODEMGR_WS} ${CRYPT_SRC} CRYPT_SRC + fi + + if [ $build_ok = y ]; then + set_up_source_build ${CODEMGR_WS} ${EXPORT_SRC} EXPORT_SRC + fi fi -if [ "$SD_FLAG" = "y" ]; then +if [ "$SD_FLAG" = "y" -a $build_ok = y ]; then # drop the crypt files in place. cd ${EXPORT_SRC} echo "\nextracting crypt_files.cpio.Z onto export_source.\n" \ @@ -2239,14 +2593,21 @@ if [ "$SD_FLAG" = "y" ]; then fi -if [ "$SO_FLAG" = "y" ]; then +if [ "$SO_FLAG" = "y" -a $build_ok = y ]; then # # Copy the open sources into their own tree, set up the closed # binaries, and set up the environment. The build looks for # the closed binaries in a location that depends on whether # it's a DEBUG build, so we might need to make two copies. # + # If copy_source fails, it will have already generated an + # error message and set build_ok=n, so we don't need to worry + # about that here. + # copy_source $CODEMGR_WS $OPEN_SRCDIR OPEN_SOURCE usr/src +fi + +if [ "$SO_FLAG" = "y" -a $build_ok = y ]; then SRC=$OPEN_SRCDIR/usr/src # Try not to clobber any user-provided closed binaries. @@ -2258,7 +2619,7 @@ if [ "$SO_FLAG" = "y" ]; then if [ "$D_FLAG" = y ]; then mkclosed $MACH $ROOT $ON_CLOSED_BINS/root_$MACH >>$LOGFILE 2>&1 - if [ $? -ne 0 ]; then + if (( $? != 0 )) ; then build_ok=n echo "Couldn't create DEBUG closed binaries." | tee -a $mail_msg_file >> $LOGFILE @@ -2269,7 +2630,7 @@ if [ "$SO_FLAG" = "y" ]; then [ "$MULTI_PROTO" = yes ] && root=$ROOT-nd mkclosed $MACH $root $ON_CLOSED_BINS/root_$MACH-nd \ >>$LOGFILE 2>&1 - if [ $? -ne 0 ]; then + if (( $? != 0 )) ; then build_ok=n echo "Couldn't create non-DEBUG closed binaries." | tee -a $mail_msg_file >> $LOGFILE @@ -2421,19 +2782,19 @@ if [ "$U_FLAG" = "y" -a "$build_ok" = "y" ]; then # pattern, and we still want to catch other errors here, we # take the unusal step of moving aside 'nightly' from that # directory (if we're using it). - mypath=${0##*/root_$MACH/} - if [ "$mypath" = $0 ]; then - mypath=opt/onbld/bin/${0##*/} + mypath=${nightly_path##*/root_$MACH/} + if [ "$mypath" = $nightly_path ]; then + mypath=opt/onbld/bin/${nightly_path##*/} fi - if [ $0 -ef $PARENT_WS/proto/root_$MACH/$mypath ]; then - mv -f $0 $PARENT_WS/proto/root_$MACH + if [ $nightly_path -ef $PARENT_WS/proto/root_$MACH/$mypath ]; then + mv -f $nightly_path $PARENT_WS/proto/root_$MACH fi rm -rf $PARENT_WS/proto/root_$MACH/* unset Ulockfile mkdir -p $NIGHTLY_PARENT_ROOT if [[ "$MULTI_PROTO" = no || "$D_FLAG" = y ]]; then cd $ROOT - ( tar cf - . | + ( tar cf - . | ( cd $NIGHTLY_PARENT_ROOT; umask 0; tar xpf - ) ) 2>&1 | tee -a $mail_msg_file >> $LOGFILE fi @@ -2524,14 +2885,14 @@ if [ "$r_FLAG" = "y" -a "$build_ok" = "y" ]; then # Determine any processing errors that will affect the final output # and display these first. grep -l "$LDDUSAGE" $RUNTIMEOUT > /dev/null - if [ $? -eq 0 ]; then + if (( $? == 0 )) ; then echo "WARNING: ldd(1) does not support -e. The version of ldd(1)" | \ tee -a $LOGFILE >> $mail_msg_file echo "on your system is old - 4390308 (s81_30) is required.\n" | \ tee -a $LOGFILE >> $mail_msg_file fi grep -l "$LDDWRONG" $RUNTIMEOUT > /dev/null - if [ $? -eq 0 ]; then + if (( $? == 0 )) ; then echo "WARNING: wrong class message detected. ldd(1) was unable" | \ tee -a $LOGFILE >> $mail_msg_file echo "to execute an object, thus it could not be checked fully." | \ @@ -2542,7 +2903,7 @@ if [ "$r_FLAG" = "y" -a "$build_ok" = "y" ]; then tee -a $LOGFILE >> $mail_msg_file fi grep -l "$CRLECONF" $RUNTIMEOUT > /dev/null - if [ $? -eq 0 ]; then + if (( $? == 0 )) ; then echo "WARNING: creation of an alternative dependency cache failed." | \ tee -a $LOGFILE >> $mail_msg_file echo "Dependencies will bind to the base system libraries.\n" | \ @@ -2622,10 +2983,18 @@ if [ "$f_FLAG" = "y" -a "$build_ok" = "y" ]; then mv $SRC/unref-${MACH}.out $SRC/unref-${MACH}.ref fi - findunref -t $SRC/.build.tstamp $SRC/.. \ - ${TOOLS}/findunref/exception_list \ - 2>> $mail_msg_file | sort | \ - sed -e s=^./src/=./= -e s=^./closed/=../closed/= \ + # + # For any SCM other than teamware, we want to disable the + # managed-by-SCCS test in findunref + # + findunref_all="" + if [ "$SCM_TYPE" != teamware ]; then + findunref_all="-a" + fi + + findunref $findunref_all -t $SRC/.build.tstamp $SRC/.. \ + ${TOOLS}/findunref/exception_list 2>> $mail_msg_file | \ + sort | sed -e s=^./src/=./= -e s=^./closed/=../closed/= \ > $SRC/unref-${MACH}.out if [ ! -f $SRC/unref-${MACH}.ref ]; then @@ -2654,7 +3023,7 @@ if [ "$O_FLAG" = y -a "$build_ok" = y ]; then if [ "$D_FLAG" = y ]; then bindrop "$ROOT" "$ROOT-open" "$closed_basename" \ >>"$LOGFILE" 2>&1 - if [ $? -ne 0 ]; then + if (( $? != 0 )) ; then echo "Couldn't create DEBUG closed binaries." | tee -a $mail_msg_file >> $LOGFILE fi @@ -2662,7 +3031,7 @@ if [ "$O_FLAG" = y -a "$build_ok" = y ]; then if [ "$F_FLAG" = n ]; then bindrop -n "$ROOT-nd" "$ROOT-open-nd" "$closed_basename-nd" \ >>"$LOGFILE" 2>&1 - if [ $? -ne 0 ]; then + if (( $? != 0 )) ; then echo "Couldn't create non-DEBUG closed binaries." | tee -a $mail_msg_file >> $LOGFILE fi @@ -2671,7 +3040,7 @@ if [ "$O_FLAG" = y -a "$build_ok" = y ]; then echo "Generating SUNWonbld tarball..." >> $LOGFILE PKGARCHIVE=$PKGARCHIVE_ORIG onblddrop >> $LOGFILE 2>&1 - if [ $? -ne 0 ]; then + if (( $? != 0 )) ; then echo "Couldn't create SUNWonbld tarball." | tee -a $mail_msg_file >> $LOGFILE fi @@ -2679,7 +3048,7 @@ if [ "$O_FLAG" = y -a "$build_ok" = y ]; then echo "Generating README.opensolaris..." >> $LOGFILE cat $SRC/tools/opensolaris/README.opensolaris.tmpl | \ mkreadme_osol $CODEMGR_WS/README.opensolaris >> $LOGFILE 2>&1 - if [ $? -ne 0 ]; then + if (( $? != 0 )) ; then echo "Couldn't create README.opensolaris." | tee -a $mail_msg_file >> $LOGFILE fi @@ -2688,7 +3057,7 @@ if [ "$O_FLAG" = y -a "$build_ok" = y ]; then # findunref. It depends on README.opensolaris. echo "Generating source tarball..." >> $LOGFILE sdrop >>$LOGFILE 2>&1 - if [ $? -ne 0 ]; then + if (( $? != 0 )) ; then echo "Couldn't create source tarball." | tee -a "$mail_msg_file" >> "$LOGFILE" fi @@ -2698,7 +3067,7 @@ if [ "$O_FLAG" = y -a "$build_ok" = y ]; then if [ "$D_FLAG" = y ]; then makebfu_filt bfudrop "$ROOT-open" \ "$closed_basename.$MACH.tar.bz2" nightly-osol - if [ $? -ne 0 ]; then + if (( $? != 0 )) ; then echo "Couldn't create DEBUG archives tarball." | tee -a $mail_msg_file >> $LOGFILE fi @@ -2706,7 +3075,7 @@ if [ "$O_FLAG" = y -a "$build_ok" = y ]; then if [ "$F_FLAG" = n ]; then makebfu_filt bfudrop -n "$ROOT-open-nd" \ "$closed_basename-nd.$MACH.tar.bz2" nightly-osol-nd - if [ $? -ne 0 ]; then + if (( $? != 0 )) ; then echo "Couldn't create non-DEBUG archives tarball." | tee -a $mail_msg_file >> $LOGFILE fi diff --git a/usr/src/tools/scripts/rtichk.py b/usr/src/tools/scripts/rtichk.py new file mode 100644 index 0000000000..5836280008 --- /dev/null +++ b/usr/src/tools/scripts/rtichk.py @@ -0,0 +1,61 @@ +#! /usr/bin/python +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +# +# Check each bug referenced in a comments list (from stdin) has a valid RTI +# + +import sys, os, getopt + +sys.path.append(os.path.join(os.path.dirname(__file__), '../lib/python')) +sys.path.append(os.path.join(os.path.dirname(__file__), '..')) + +from onbld.Checks.Rti import rti + + +def usage(): + print 'usage: rtichk [-g gate] [-c consolidation] bugids...' + sys.exit(2) + +try: + opts, bugs = getopt.getopt(sys.argv[1:], "c:g:r:t:") +except getopt.GetoptError: + usage() + sys.exit(2) + +gate = None +consolidation = None + +for opt, arg in opts: + if opt == '-c': consolidation = arg + elif opt == '-g': gate = arg + +ret = not rti(bugs, consolidation=consolidation, gatePath=gate, + output=sys.stdout) +sys.exit(ret) diff --git a/usr/src/tools/scripts/sdrop.sh b/usr/src/tools/scripts/sdrop.sh index 7b6726dd47..494b6511bc 100644 --- a/usr/src/tools/scripts/sdrop.sh +++ b/usr/src/tools/scripts/sdrop.sh @@ -23,12 +23,15 @@ # # ident "%Z%%M% %I% %E% SMI" # -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -# Source drop generator. Based on clone_source function in nightly(1). +# Source drop generator. # +PATH=$(dirname $(whence $0)):$PATH +export PATH + tmpdir=$(mktemp -dt sdropXXXXX) cleanup() { @@ -47,16 +50,29 @@ fail() { tarfile=$CODEMGR_WS/on-src.tar cd $CODEMGR_WS +which_scm | read SCM_TYPE junk || exit 1 # -# Copy anything that's registered with SCCS, except for deleted files, +# Copy anything that's registered with source control, except for deleted files, # into a temp directory. Then tar that up. # - -find usr/src -name 's\.*' -a -type f -print | \ - sed -e 's,SCCS\/s.,,' | \ - grep -v '/\.del-*' | \ - cpio -pd $tmpdir +case "$SCM_TYPE" in +mercurial) + hg locate -X deleted_files/ | cpio -pd $tmpdir + ;; +teamware) + find usr/src -name 's\.*' -a -type f -print | \ + sed -e 's,SCCS\/s.,,' | \ + grep -v '/\.del-*' | \ + cpio -pd $tmpdir + ;; +unknown) + fail "Unknown type of SCM in use." + ;; +*) + fail "Unsupported SCM type: $SCM_TYPE" + ;; +esac [ $? -eq 0 ] || fail "Couldn't populate temp directory $tmpdir." cp README.opensolaris $tmpdir || fail "Couldn't copy README.opensolaris." diff --git a/usr/src/tools/scripts/webrev.1 b/usr/src/tools/scripts/webrev.1 index d3fc234b5d..db35275970 100644 --- a/usr/src/tools/scripts/webrev.1 +++ b/usr/src/tools/scripts/webrev.1 @@ -1,28 +1,29 @@ -.\" " -.\" " Copyright 2006 Sun Microsystems, Inc. All rights reserved. -.\" " Use is subject to license terms. -.\" " -.\" " CDDL HEADER START -.\" " -.\" " The contents of this file are subject to the terms of the -.\" " Common Development and Distribution License (the "License"). -.\" " You may not use this file except in compliance with the License. -.\" " -.\" " You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -.\" " or http://www.opensolaris.org/os/licensing. -.\" " See the License for the specific language governing permissions -.\" " and limitations under the License. -.\" " -.\" " When distributing Covered Code, include this CDDL HEADER in each -.\" " file and include the License file at usr/src/OPENSOLARIS.LICENSE. -.\" " If applicable, add the following below this CDDL HEADER, with the -.\" " fields enclosed by brackets "[]" replaced with your own identifying -.\" " information: Portions Copyright [yyyy] [name of copyright owner] -.\" " -.\" " CDDL HEADER END -.\" " +.\" +.\" CDDL HEADER START +.\" +.\" The contents of this file are subject to the terms of the +.\" Common Development and Distribution License (the "License"). +.\" You may not use this file except in compliance with the License. +.\" +.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +.\" or http://www.opensolaris.org/os/licensing. +.\" See the License for the specific language governing permissions +.\" and limitations under the License. +.\" +.\" When distributing Covered Code, include this CDDL HEADER in each +.\" file and include the License file at usr/src/OPENSOLARIS.LICENSE. +.\" If applicable, add the following below this CDDL HEADER, with the +.\" fields enclosed by brackets "[]" replaced with your own identifying +.\" information: Portions Copyright [yyyy] [name of copyright owner] +.\" +.\" CDDL HEADER END +.\" +.\" Copyright 2008 Sun Microsystems, Inc. All rights reserved. +.\" Use is subject to license terms. +.\" .\" ident "%Z%%M% %I% %E% SMI" -.TH webrev 1 "1 December 2006" +.\" +.TH webrev 1 "02 July 2008" .SH NAME webrev \- Generate HTML codereview materials .SH SYNOPSIS @@ -53,12 +54,15 @@ webrev \- Generate HTML codereview materials .B -l .I arguments to 'putback' -See OPTIONS for common-options. +See OPTIONS for common-options. +Note that the -l option is only applicable to TeamWare workspaces. .SH DESCRIPTION .B webrev builds a set of HTML files suitable for performing code review of -source changes in a web browser. At its most basic, usage is: +source changes in a web browser. +It supports Mercurial, Subversion and Teamware repositories. +At its most basic, usage is: .nf $ webrev .fi @@ -128,34 +132,60 @@ will also attempt to auto-discover. In all cases, .B webrev must either discover the list of files which have changed, or else this list must be manually specified, either in "webrev file list" format or in "wx" -format. See FILE LIST for more details. - -.SS Teamware -In the case of Teamware, if the user has already activated the workspace -with the +format. +See FILE LIST for more details. +.PP +In all cases, if the user has activated the workspace with the .BR ws (1) -command or set the -.B CODEMGR_WS -environment variable, then +or +.BR bldenv (1) +commands, \fBwebrev\fR will use the \fBCODEMGR_PARENT\fR and +\fBCODEMGR_WS\fR environment variables to identify parent and child +workspaces respectively. +To manually specify the basis for comparison, use the -p option or +specify the \fBCODEMGR_PARENT\fR variable in either the file list or +the environment. + +.SS Discovering the SCM in use. .B webrev -will use the -.B CODEMGR_WS -environment variable. To manually set the basis for -comparison, use the -p option, or specify the -.B CODEMGR_PARENT -variable in the file list. - -To direct \fBwebrev\fR to determine the file list from -.BR putback (1), +makes use of +.BR which_scm (1) +to determine the SCM in use for a given workspace. + +.SS TeamWare +In the case of TeamWare \fBwebrev\fR will use the output of "workspace +name" to discover the workspace root, if not otherwise specified. +.PP +\fBwebrev\fR will attempt to use a +.BR wx (1) +active list in +\fBCODEMGR_WS/wx/active\fR. +To direct \fBwebrev\fR to determine the file list from the output of +.BR putback "(1)," use the -l option. (Note that \fBwebrev\fR may also elect to use \fBputback\fR if it cannot determine the file list from -.BR wx (1)). +.BR wx "(1))." The -l option indicates that subsequent arguments should be treated as arguments to -.BR putback (1). +.BR putback "(1)." This can be used to prune the set of files which putback examines, or to reference a teamware flp (file list program). +.SS Mercurial +In the case of Mercurial \fBwebrev\fR will attempt to use the output +from the +.BR hg (1) +"hg root" to identify the workspace root, and the +"hg path default" command to identify the parent workspace. + +.SS Subversion +In the case of Subversion \fBwebrev\fR will attempt to use the output +from the +.BR svn (1) +"svn info" to find the workspace root and subversion repository URL. +.PP +The file list will be created from the output of the "svn status" command. + .SH OPTIONS .TP 10 .BI "-w " wx-file @@ -166,8 +196,8 @@ format expected by the \fIwx\fR package. See FILE LIST, below. .BI "-l " putback-args Extract the file list from the output of .I putback -n. -Any arguments supplied will be passed to -.BR putback (1). +Any arguments supplied will be passed to +.BR putback "(1)." See SCM INTERACTIONS. For more information about file lists, see FILE LIST. This argument should appear last. .TP 10 @@ -198,8 +228,8 @@ needs to be told or to discover which files have changed in a given workspace. By default, .B webrev will attempt to autodetect the -list of changed files by first consulting -.BR wx(1). +list of changed files by first consulting +.BR wx "(1)." If this information is not available, webrev tries to consult the SCM (Source Code Manager) currently in use. If that fails, the user must intervene by specifying either a file list or additional options specific to the SCM in use. @@ -305,6 +335,13 @@ other. The default path for this script is /ws/onnv-gate/public/bin/wdiff but WDIFF may be set to customize this to use a more convenient location. +.SH SEE ALSO +.BR putback "(1)," +.BR workspace "(1)," +.BR hg "(1)," +.BR svn "(1)," +.BR which_scm "(1)" + .SH ACKNOWLEDGEMENTS Acknowledgements to Rob Thurlow, Mike Eisler, Lin Ling, Rod Evans, Mike Kupfer, Greg Onufer, Glenn Skinner, diff --git a/usr/src/tools/scripts/webrev.sh b/usr/src/tools/scripts/webrev.sh index 2b47e4518b..c0c4cc0a45 100644 --- a/usr/src/tools/scripts/webrev.sh +++ b/usr/src/tools/scripts/webrev.sh @@ -19,12 +19,13 @@ # # CDDL HEADER END # -# # ident "%Z%%M% %I% %E% SMI" # # Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # + +# # This script takes a file list and a workspace and builds a set of html files # suitable for doing a code review of source changes via a web page. # Documentation is available via the manual page, webrev.1, or just @@ -114,6 +115,10 @@ span.new { color: blue; font-weight: bold; } +span.chmod { + font-size: 0.7em; + color: #db7800; +} a.print { font-size: x-small; } a:hover { background-color: #ffcc99; } </style> @@ -191,7 +196,7 @@ sac2url() # Deleted lines of text are replaced by a horizontal rule. Some # identical lines are retained before and after the changed lines to # provide some context. The number of these lines is controlled by the -# variable C in the nawk script below. +# variable C in the $AWK script below. # # The script detects changed lines as any line that has a "<span class=" # string embedded (unchanged lines have no particular class and are not @@ -200,9 +205,9 @@ sac2url() # strip_unchanged() { - nawk ' + $AWK ' BEGIN { C = c = 20 } - NF == 0 || /span class=/ { + NF == 0 || /<span class="/ { if (c > C) { c -= C inx = 0 @@ -304,7 +309,7 @@ sdiff_to_html() # # Now we have the diffs, generate the HTML for the old file. # - nawk ' + $AWK ' BEGIN { printf "function sp(n) {for (i=0;i<n;i++)printf \"\\n\"}\n" printf "function removed() " @@ -386,7 +391,7 @@ sdiff_to_html() # # Now generate the HTML for the new file # - nawk ' + $AWK ' BEGIN { printf "function sp(n) {for (i=0;i<n;i++)printf \"\\n\"}\n" printf "function new() " @@ -466,17 +471,17 @@ sdiff_to_html() ' /tmp/$$.diffs > /tmp/$$.file2 # - # Post-process the HTML files by running them back through nawk + # Post-process the HTML files by running them back through $AWK # - html_quote < $1 | nawk -f /tmp/$$.file1 > /tmp/$$.file1.html + html_quote < $1 | $AWK -f /tmp/$$.file1 > /tmp/$$.file1.html - html_quote < $2 | nawk -f /tmp/$$.file2 > /tmp/$$.file2.html + html_quote < $2 | $AWK -f /tmp/$$.file2 > /tmp/$$.file2.html # # Now combine into a valid HTML file and side-by-side into a table # print "$HTML<head>$STDHEAD" - print "<title>$WNAME Sdiff $TPATH </title>" + print "<title>$WNAME Sdiff $TPATH/$TNAME</title>" print "</head><body id=\"SUNWwebrev\">" print "<a class=\"print\" href=\"javascript:print()\">Print this page</a>" print "<pre>$COMMENT</pre>\n" @@ -646,7 +651,7 @@ EOF # function insert_anchors { - nawk ' + $AWK ' function ia() { printf "<a name=\"%d\" id=\"anc%d\"></a>", anc, anc++; } @@ -1018,7 +1023,7 @@ diff_to_html() <pre> EOF - html_quote | nawk ' + html_quote | $AWK ' /^--- new/ { next } /^\+\+\+ new/ { next } /^--- old/ { next } @@ -1054,15 +1059,15 @@ source_to_html() TNAME=$2 print "$HTML<head>$STDHEAD" - print "<title>$WHICH $TNAME</title>" + print "<title>$WNAME $WHICH $TNAME</title>" print "<body id=\"SUNWwebrev\">" print "<pre>" - html_quote | nawk '{line += 1 ; printf "%4d %s\n", line, $0 }' + html_quote | $AWK '{line += 1 ; printf "%4d %s\n", line, $0 }' print "</pre></body></html>" } # -# teamwarecomments {text|html} parent-file child-file +# comments_from_teamware {text|html} parent-file child-file # # Find the first delta in the child that's not in the parent. Get the # newest delta from the parent, get all deltas from the child starting @@ -1077,13 +1082,17 @@ comments_from_teamware() pfile=$PWS/$2 cfile=$CWS/$3 + if [[ ! -f $PWS/${2%/*}/SCCS/s.${2##*/} && -n $RWS ]]; then + pfile=$RWS/$2 + fi + if [[ -f $pfile ]]; then - psid=$(sccs prs -d:I: $pfile 2>/dev/null) + psid=$($SCCS prs -d:I: $pfile 2>/dev/null) else psid=1.1 fi - set -A sids $(sccs prs -l -r$psid -d:I: $cfile 2>/dev/null) + set -A sids $($SCCS prs -l -r$psid -d:I: $cfile 2>/dev/null) N=${#sids[@]} nawkprg=' @@ -1096,30 +1105,32 @@ comments_from_teamware() sid1=${sids[$((N-2))]} # Gets 2nd to last sid if [[ $fmt == "text" ]]; then - sccs prs -l -r$sid1 $cfile 2>/dev/null | \ - nawk "$nawkprg" + $SCCS prs -l -r$sid1 $cfile 2>/dev/null | \ + $AWK "$nawkprg" return fi - sccs prs -l -r$sid1 $cfile 2>/dev/null | \ - html_quote | bug2url | sac2url | nawk "$nawkprg" + $SCCS prs -l -r$sid1 $cfile 2>/dev/null | \ + html_quote | bug2url | sac2url | $AWK "$nawkprg" fi } # -# wxcomments {text|html} filepath +# comments_from_wx {text|html} filepath +# +# Given the pathname of a file, find its location in a "wx" active +# file list and print the following comment. Output is either text or +# HTML; if the latter, embedded bugids (sequence of 5 or more digits) +# are turned into URLs. # -# Given the pathname of a file, find its location in a "wx" active file -# list and print the following sccs comment. Output is either text or -# HTML; if the latter, embedded bugids (sequence of 5 or more digits) are -# turned into URLs. +# This is also used with Mercurial and the file list provided by hg-active. # comments_from_wx() { typeset fmt=$1 typeset p=$2 - comm=`nawk ' + comm=`$AWK ' $1 == "'$p'" { do getline ; while (NF > 0) getline @@ -1127,12 +1138,17 @@ comments_from_wx() exit }' < $wxfile` + if [[ -z $comm ]]; then + comm="*** NO COMMENTS ***" + fi + if [[ $fmt == "text" ]]; then - print "$comm" + print -- "$comm" return fi - print "$comm" | html_quote | bug2url | sac2url + print -- "$comm" | html_quote | bug2url | sac2url + } # @@ -1146,6 +1162,10 @@ getcomments() typeset p=$2 typeset pp=$3 + # + # Mercurial support uses a file list in wx format, so this + # will be used there, too + # if [[ -n $wxfile ]]; then comments_from_wx $fmt $p else @@ -1185,7 +1205,7 @@ function difflines integer tot mod del ins unc err typeset filename - diff -e $1 $2 | eval $( nawk ' + eval $( diff -e $1 $2 | $AWK ' # Change range of lines: N,Nc /^[0-9]*,[0-9]*c$/ { n=split(substr($1,1,length($1)-1), counts, ","); @@ -1275,7 +1295,7 @@ function difflines (c+d+a), c, d, a, error); }' ) - # End of nawk, Check to see if any trouble occurred. + # End of $AWK, Check to see if any trouble occurred. if (( $? > 0 || err > 0 )); then print "Unexpected Error occurred reading" \ "\`diff -e $1 $2\`: \$?=$?, err=" $err @@ -1288,7 +1308,7 @@ function difflines (( TDEL += del )) (( TINS += ins )) # Calculate unchanged lines - wc -l $1 | read unc filename + unc=`wc -l < $1` if (( unc > 0 )); then (( unc -= del + mod )) (( TUNC += unc )) @@ -1319,7 +1339,7 @@ function flist_from_wx wxfile=$argfile fi - nawk '{ c = 1; print; + $AWK '{ c = 1; print; while (getline) { if (NF == 0) { c = -c; continue } if (c > 0) print @@ -1340,7 +1360,7 @@ function flist_from_wx # function flist_from_teamware { - if [[ -n $codemgr_parent ]]; then + if [[ -n $codemgr_parent && -z $parent_webrev ]]; then if [[ ! -d $codemgr_parent/Codemgr_wsdata ]]; then print -u2 "parent $codemgr_parent doesn't look like a" \ "valid teamware workspace" @@ -1352,7 +1372,7 @@ function flist_from_teamware print " File list from: 'putback -n $parent_args $*' ... \c" putback -n $parent_args $* 2>&1 | - nawk ' + $AWK ' /^update:|^create:/ {print $2} /^Parent workspace:/ {printf("CODEMGR_PARENT=%s\n",$3)} /^Child workspace:/ {printf("CODEMGR_WS=%s\n",$3)} @@ -1367,53 +1387,81 @@ function flist_from_teamware print " Done." } -function env_from_flist +# +# Call hg-active to get the active list output in the wx active list format +# +function hg_active_wxfile { - [[ -r $FLIST ]] || return + typeset child=$1 + typeset parent=$2 - # - # Use "eval" to set env variables that are listed in the file - # list. Then copy those into our local versions of those - # variables if they have not been set already. - # - eval `sed -e "s/#.*$//" $FLIST | grep = ` + TMPFLIST=/tmp/$$.active + $HG_ACTIVE -w $child -p $parent > $TMPFLIST + wxfile=$TMPFLIST +} - [[ -z $codemgr_ws && -n $CODEMGR_WS ]] && codemgr_ws=$CODEMGR_WS +# +# flist_from_mercurial +# Call hg-active to get a wx-style active list, and hand it off to +# flist_from_wx +# +function flist_from_mercurial +{ + typeset child=$1 + typeset parent=$2 - # - # Check to see if CODEMGR_PARENT is set in the flist file. - # - [[ -z $codemgr_parent && -n $CODEMGR_PARENT ]] && \ - codemgr_parent=$CODEMGR_PARENT + print " File list from: hg-active -p $parent ...\c" + + if [[ ! -x $HG_ACTIVE ]]; then + print # Blank line for the \c above + print -u2 "Error: hg-active tool not found. Exiting" + exit 1 + fi + hg_active_wxfile $child $parent + + # flist_from_wx prints the Done, so we don't have to. + flist_from_wx $TMPFLIST } # -# detect_scm +# flist_from_subversion # -# We dynamically test the SCM type; this allows future extensions to -# new SCM types +# Generate the file list by extracting file names from svn status. # -function detect_scm +function flist_from_subversion { + CWS=$1 + OLDPWD=$2 + + cd $CWS + print -u2 " File list from: svn status ... \c" + svn status | $AWK '/^[ACDMR]/ { print $NF }' > $FLIST + print -u2 " Done." + cd $OLDPWD +} + +function env_from_flist +{ + [[ -r $FLIST ]] || return + # - # If CODEMGR_WS is specified in the flist file, we assume teamware. + # Use "eval" to set env variables that are listed in the file + # list. Then copy those into our local versions of those + # variables if they have not been set already. # - if [[ -r $FLIST ]]; then - egrep '^CODEMGR_WS=' $FLIST > /dev/null 2>&1 - if [[ $? -eq 0 ]]; then - print "teamware" - return - fi + eval `sed -e "s/#.*$//" $FLIST | grep = ` + + if [[ -z $codemgr_ws && -n $CODEMGR_WS ]]; then + codemgr_ws=$CODEMGR_WS + export CODEMGR_WS fi # - # The presence of $CODEMGR_WS and a Codemgr_wsdata directory - # is our clue that this is a teamware workspace. + # Check to see if CODEMGR_PARENT is set in the flist file. # - if [[ -n $CODEMGR_WS && -d "$CODEMGR_WS/Codemgr_wsdata" ]]; then - print "teamware" - else - print "unknown" + if [[ -z $codemgr_parent && -n $CODEMGR_PARENT ]]; then + codemgr_parent=$CODEMGR_PARENT + export CODEMGR_PARENT fi } @@ -1426,7 +1474,7 @@ function look_for_prog ppath=$PATH ppath=$ppath:/usr/sfw/bin:/usr/bin:/usr/sbin ppath=$ppath:/opt/teamware/bin:/opt/onbld/bin - ppath=$ppath:/opt/onbld/bin/`/usr/bin/uname -p` + ppath=$ppath:/opt/onbld/bin/`uname -p` PATH=$ppath prog=`whence $progname` if [[ -n $prog ]]; then @@ -1434,6 +1482,241 @@ function look_for_prog fi } +function get_file_mode +{ + $PERL -e ' + if (@stat = stat($ARGV[0])) { + $mode = $stat[2] & 0777; + printf "%03o\n", $mode; + exit 0; + } else { + exit 1; + } + ' $1 +} + +function build_old_new_teamware +{ + typeset olddir="$1" + typeset newdir="$2" + + # If the child's version doesn't exist then + # get a readonly copy. + + if [[ ! -f $CWS/$DIR/$F && -f $CWS/$DIR/SCCS/s.$F ]]; then + $SCCS get -s -p $CWS/$DIR/$F > $CWS/$DIR/$F + fi + + # The following two sections propagate file permissions the + # same way SCCS does. If the file is already under version + # control, always use permissions from the SCCS/s.file. If + # the file is not under SCCS control, use permissions from the + # working copy. In all cases, the file copied to the webrev + # is set to read only, and group/other permissions are set to + # match those of the file owner. This way, even if the file + # is currently checked out, the webrev will display the final + # permissions that would result after check in. + + # + # Snag new version of file. + # + rm -f $newdir/$DIR/$F + cp $CWS/$DIR/$F $newdir/$DIR/$F + if [[ -f $CWS/$DIR/SCCS/s.$F ]]; then + chmod `get_file_mode $CWS/$DIR/SCCS/s.$F` \ + $newdir/$DIR/$F + fi + chmod u-w,go=u $newdir/$DIR/$F + + # + # Get the parent's version of the file. First see whether the + # child's version is checked out and get the parent's version + # with keywords expanded or unexpanded as appropriate. + # + if [[ -f $PWS/$PDIR/$PF && ! -f $PWS/$PDIR/SCCS/s.$PF && \ + ! -f $PWS/$PDIR/SCCS/p.$PF ]]; then + # Parent is not a real workspace, but just a raw + # directory tree - use the file that's there as + # the old file. + + rm -f $olddir/$PDIR/$PF + cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF + else + if [[ -f $PWS/$PDIR/SCCS/s.$PF ]]; then + real_parent=$PWS + else + real_parent=$RWS + fi + + rm -f $olddir/$PDIR/$PF + + if [[ -f $real_parent/$PDIR/$PF ]]; then + if [ -f $CWS/$DIR/SCCS/p.$F ]; then + $SCCS get -s -p -k $real_parent/$PDIR/$PF > \ + $olddir/$PDIR/$PF + else + $SCCS get -s -p $real_parent/$PDIR/$PF > \ + $olddir/$PDIR/$PF + fi + chmod `get_file_mode $real_parent/$PDIR/SCCS/s.$PF` \ + $olddir/$PDIR/$PF + fi + fi + if [[ -f $olddir/$PDIR/$PF ]]; then + chmod u-w,go=u $olddir/$PDIR/$PF + fi +} + +function build_old_new_mercurial +{ + typeset olddir="$1" + typeset newdir="$2" + typeset old_mode= + typeset new_mode= + typeset file + + # + # Get old file mode, from the parent revision manifest entry. + # Mercurial only stores a "file is executable" flag, but the + # manifest will display an octal mode "644" or "755". + # + if [[ "$PDIR" == "." ]]; then + file="$PF" + else + file="$PDIR/$PF" + fi + file=`echo $file | sed 's#/#\\\/#g'` + # match the exact filename, and return only the permission digits + old_mode=`sed -n -e "/^\\(...\\) . ${file}$/s//\\1/p" \ + < $HG_PARENT_MANIFEST` + + # + # Get new file mode, directly from the filesystem. + # Normalize the mode to match Mercurial's behavior. + # + new_mode=`get_file_mode $CWS/$DIR/$F` + if [[ -n "$new_mode" ]]; then + if [[ "$new_mode" = *[1357]* ]]; then + new_mode=755 + else + new_mode=644 + fi + fi + + # + # new version of the file. + # + rm -rf $newdir/$DIR/$F + if [[ -e $CWS/$DIR/$F ]]; then + cp $CWS/$DIR/$F $newdir/$DIR/$F + if [[ -n $new_mode ]]; then + chmod $new_mode $newdir/$DIR/$F + else + # should never happen + print -u2 "ERROR: set mode of $newdir/$DIR/$F" + fi + fi + + # + # parent's version of the file + # + # Note that we get this from the last version common to both + # ourselves and the parent. References are via $CWS since we have no + # guarantee that the parent workspace is reachable via the filesystem. + # + if [[ -n $parent_webrev && -e $PWS/$PDIR/$PF ]]; then + cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF + elif [[ -n $HG_PARENT ]]; then + hg cat -R $CWS -r $HG_PARENT $CWS/$PDIR/$PF > \ + $olddir/$PDIR/$PF 2>/dev/null + + if [ $? -ne 0 ]; then + rm -f $olddir/$PDIR/$PF + else + if [[ -n $old_mode ]]; then + chmod $old_mode $olddir/$PDIR/$PF + else + # should never happen + print -u2 "ERROR: set mode of $olddir/$PDIR/$PF" + fi + fi + fi +} + +function build_old_new_subversion +{ + typeset olddir="$1" + typeset newdir="$2" + + # Snag new version of file. + rm -f $newdir/$DIR/$F + [[ -e $CWS/$DIR/$F ]] && cp $CWS/$DIR/$F $newdir/$DIR/$F + + if [[ -n $PWS && -e $PWS/$PDIR/$PF ]]; then + cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF + else + # Get the parent's version of the file. + svn status $CWS/$DIR/$F | read stat file + if [[ $stat != "A" ]]; then + svn cat -r BASE $CWS/$DIR/$F > $olddir/$PDIR/$PF + fi + fi +} + +function build_old_new_unknown +{ + typeset olddir="$1" + typeset newdir="$2" + + # + # Snag new version of file. + # + rm -f $newdir/$DIR/$F + [[ -e $CWS/$DIR/$F ]] && cp $CWS/$DIR/$F $newdir/$DIR/$F + + # + # Snag the parent's version of the file. + # + if [[ -f $PWS/$PDIR/$PF ]]; then + rm -f $olddir/$PDIR/$PF + cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF + fi +} + +function build_old_new +{ + typeset WDIR=$1 + typeset PWS=$2 + typeset PDIR=$3 + typeset PF=$4 + typeset CWS=$5 + typeset DIR=$6 + typeset F=$7 + + typeset olddir="$WDIR/raw_files/old" + typeset newdir="$WDIR/raw_files/new" + + mkdir -p $olddir/$PDIR + mkdir -p $newdir/$DIR + + if [[ $SCM_MODE == "teamware" ]]; then + build_old_new_teamware "$olddir" "$newdir" + elif [[ $SCM_MODE == "mercurial" ]]; then + build_old_new_mercurial "$olddir" "$newdir" + elif [[ $SCM_MODE == "subversion" ]]; then + build_old_new_subversion "$olddir" "$newdir" + elif [[ $SCM_MODE == "unknown" ]]; then + build_old_new_unknown "$olddir" "$newdir" + fi + + if [[ ! -f $olddir/$PDIR/$PF && ! -f $newdir/$DIR/$F ]]; then + print "*** Error: file not in parent or child" + return 1 + fi + return 0 +} + + # # Usage message. # @@ -1442,7 +1725,6 @@ function usage print 'Usage:\twebrev [common-options] webrev [common-options] ( <file> | - ) webrev [common-options] -w <wx file> - webrev [common-options] -l [arguments to 'putback'] Options: -O: Print bugids/arc cases suitable for OpenSolaris. @@ -1456,9 +1738,12 @@ Environment: WEBREV_BUGURL: Control the URL prefix for bugids. WEBREV_SACURL: Control the URL prefix for ARC cases. +SCM Specific Options: + TeamWare: webrev [common-options] -l [arguments to 'putback'] + SCM Environment: - Teamware: CODEMGR_WS: Workspace location. - Teamware: CODEMGR_PARENT: Parent workspace location. + CODEMGR_WS: Workspace location. + CODEMGR_PARENT: Parent workspace location. ' exit 2 @@ -1474,17 +1759,31 @@ trap "rm -f /tmp/$$.* ; exit" 0 1 2 3 15 set +o noclobber +PATH=$(dirname $(whence $0)):$PATH + [[ -z $WDIFF ]] && WDIFF=`look_for_prog wdiff` [[ -z $WX ]] && WX=`look_for_prog wx` +[[ -z $HG_ACTIVE ]] && HG_ACTIVE=`look_for_prog hg-active` +[[ -z $WHICH_SCM ]] && WHICH_SCM=`look_for_prog which_scm` [[ -z $CODEREVIEW ]] && CODEREVIEW=`look_for_prog codereview` [[ -z $PS2PDF ]] && PS2PDF=`look_for_prog ps2pdf` [[ -z $PERL ]] && PERL=`look_for_prog perl` +[[ -z $SCCS ]] && SCCS=`look_for_prog sccs` +[[ -z $AWK ]] && AWK=`look_for_prog nawk` +[[ -z $AWK ]] && AWK=`look_for_prog gawk` +[[ -z $AWK ]] && AWK=`look_for_prog awk` + if [[ ! -x $PERL ]]; then print -u2 "Error: No perl interpreter found. Exiting." exit 1 fi +if [[ ! -x $WHICH_SCM ]]; then + print -u2 "Error: Could not find which_scm. Exiting." + exit 1 +fi + # # These aren't fatal, but we want to note them to the user. # We don't warn on the absence of 'wx' until later when we've @@ -1575,13 +1874,24 @@ fi # Before we go on to further consider -l and -w, work out which SCM we think # is in use. # -SCM_MODE=`detect_scm $FLIST` -if [[ $SCM_MODE == "unknown" ]]; then - print -u2 "Unable to determine SCM type currently in use." - print -u2 "For teamware: webrev looks for \$CODEMGR_WS either in" - print -u2 " the environment or in the file list." - exit 1 -fi +$WHICH_SCM | read SCM_MODE junk || exit 1 +case "$SCM_MODE" in +teamware|mercurial|subversion) + ;; +unknown) + if [[ $flist_mode == "auto" ]]; then + print -u2 "Unable to determine SCM in use and file list not specified" + print -u2 "See which_scm(1) for SCM detection information." + exit 1 + fi + ;; +*) + if [[ $flist_mode == "auto" ]]; then + print -u2 "Unsupported SCM in use ($SCM_MODE) and file list not specified" + exit 1 + fi + ;; +esac print -u2 " SCM detected: $SCM_MODE" @@ -1592,10 +1902,14 @@ if [[ -n $lflag ]]; then # putback -n. # shift $(($OPTIND - 1)) - flist_from_teamware "$*" + if [[ $SCM_MODE == "teamware" ]]; then + flist_from_teamware "$*" + else + print -u2 -- "Error: -l option only applies to TeamWare" + exit 1 + fi flist_done=1 shift $# - elif [[ -n $wflag ]]; then # # If the -w is given then assume the file list is in Bonwick's "wx" @@ -1614,6 +1928,11 @@ elif [[ -n $wflag ]]; then [[ -z $wxfile ]] && print -u2 "wx file not specified, and could not " \ "be auto-detected (check \$CODEMGR_WS)" && exit 1 + if [[ ! -r $wxfile ]]; then + print -u2 "$wxfile: no such file or not readable" + usage + fi + print -u2 " File list from: wx 'active' file '$wxfile' ... \c" flist_from_wx $wxfile flist_done=1 @@ -1698,15 +2017,10 @@ if [[ $SCM_MODE == "teamware" ]]; then fi # - # Observe true directory name of CODEMGR_WS, as used later in - # webrev title. - # - codemgr_ws=$(cd $codemgr_ws;print $PWD) - - # # (4) If we still don't have a value for codemgr_parent, get it # from workspace. # + [[ -z $codemgr_ws ]] && codemgr_ws=`workspace name` [[ -z $codemgr_parent ]] && codemgr_parent=`workspace parent` if [[ ! -d $codemgr_parent ]]; then print -u2 "$CODEMGR_PARENT: no such parent workspace" @@ -1714,11 +2028,151 @@ if [[ $SCM_MODE == "teamware" ]]; then fi # + # Observe true directory name of CODEMGR_WS, as used later in + # webrev title. + # + codemgr_ws=$(cd $codemgr_ws;print $PWD) + + # # Reset CODEMGR_WS to make sure teamware commands are happy. # CODEMGR_WS=$codemgr_ws CWS=$codemgr_ws PWS=$codemgr_parent + + [[ -n $parent_webrev ]] && RWS=$(workspace parent $CWS) + +elif [[ $SCM_MODE == "mercurial" ]]; then + [[ -z $codemgr_ws && -n $CODEMGR_WS ]] && \ + codemgr_ws=`hg root -R $CODEMGR_WS 2>/dev/null` + + [[ -z $codemgr_ws ]] && codemgr_ws=`hg root 2>/dev/null` + + # + # Parent can either be specified with -p + # Specified with CODEMGR_PARENT in the environment + # or taken from hg's default path. + # + + if [[ -z $codemgr_parent && -n $CODEMGR_PARENT ]]; then + codemgr_parent=$CODEMGR_PARENT + fi + + if [[ -z $codemgr_parent ]]; then + codemgr_parent=`hg path -R $codemgr_ws default 2>/dev/null` + fi + + CWS_REV=`hg parent -R $codemgr_ws --template '{node|short}' 2>/dev/null` + CWS=$codemgr_ws + PWS=$codemgr_parent + + # + # If the parent is a webrev, we want to do some things against + # the natural workspace parent (file list, comments, etc) + # + if [[ -n $parent_webrev ]]; then + real_parent=$(hg path -R $codemgr_ws default 2>/dev/null) + else + real_parent=$PWS + fi + + # + # If hg-active exists, then we run it. In the case of no explicit + # flist given, we'll use it for our comments. In the case of an + # explicit flist given we'll try to use it for comments for any + # files mentioned in the flist. + # + if [[ -z $flist_done ]]; then + flist_from_mercurial $CWS $real_parent + flist_done=1 + fi + + # + # If we have a file list now, pull out any variables set + # therein. We do this now (rather than when we possibly use + # hg-active to find comments) to avoid stomping specifications + # in the user-specified flist. + # + if [[ -n $flist_done ]]; then + env_from_flist + fi + + # + # Only call hg-active if we don't have a wx formatted file already + # + if [[ -x $HG_ACTIVE && -z $wxfile ]]; then + print " Comments from: hg-active -p $real_parent ...\c" + hg_active_wxfile $CWS $real_parent + print " Done." + fi + + # + # At this point we must have a wx flist either from hg-active, + # or in general. Use it to try and find our parent revision, + # if we don't have one. + # + if [[ -z $HG_PARENT ]]; then + eval `sed -e "s/#.*$//" $wxfile | grep HG_PARENT=` + fi + + # + # If we still don't have a parent, we must have been given a + # wx-style active list with no HG_PARENT specification, run + # hg-active and pull an HG_PARENT out of it, ignore the rest. + # + if [[ -z $HG_PARENT && -x $HG_ACTIVE ]]; then + $HG_ACTIVE -w $codemgr_ws -p $real_parent | \ + eval `sed -e "s/#.*$//" | grep HG_PARENT=` + elif [[ -z $HG_PARENT ]]; then + print -u2 "Error: Cannot discover parent revision" + exit 1 + fi +elif [[ $SCM_MODE == "subversion" ]]; then + if [[ -n $CODEMGR_WS && -d $CODEMGR_WS/.svn ]]; then + CWS=$CODEMGR_WS + else + svn info | while read line; do + if [[ $line == "URL: "* ]]; then + url=${line#URL: } + elif [[ $line == "Repository Root: "* ]]; then + repo=${line#Repository Root: } + fi + done + + rel=${url#$repo} + CWS=${PWD%$rel} + fi + + # + # We only will have a real parent workspace in the case one + # was specified (be it an older webrev, or another checkout). + # + [[ -n $codemgr_parent ]] && PWS=$codemgr_parent + + if [[ -z $flist_done && $flist_mode == "auto" ]]; then + flist_from_subversion $CWS $OLDPWD + fi +else + if [[ $SCM_MODE == "unknown" ]]; then + print -u2 " Unknown type of SCM in use" + else + print -u2 " Unsupported SCM in use: $SCM_MODE" + fi + + env_from_flist + + if [[ -z $CODEMGR_WS ]]; then + print -u2 "SCM not detected/supported and CODEMGR_WS not specified" + exit 1 + fi + + if [[ -z $CODEMGR_PARENT ]]; then + print -u2 "SCM not detected/supported and CODEMGR_PARENT not specified" + exit 1 + fi + + CWS=$CODEMGR_WS + PWS=$CODEMGR_PARENT fi # @@ -1767,11 +2221,21 @@ fi # # Summarize what we're going to do. # -print " Workspace: $CWS" +if [[ -n $CWS_REV ]]; then + print " Workspace: $CWS (at $CWS_REV)" +else + print " Workspace: $CWS" +fi if [[ -n $parent_webrev ]]; then print "Compare against: webrev at $parent_webrev" else - print "Compare against: $PWS" + if [[ -n $HG_PARENT ]]; then + hg_parent_short=`echo $HG_PARENT \ + | sed -e 's/\([0-9a-f]\{12\}\).*/\1/'` + print "Compare against: $PWS (at $hg_parent_short)" + else + print "Compare against: $PWS" + fi fi [[ -n $INCLUDE_FILE ]] && print " Including: $INCLUDE_FILE" @@ -1818,6 +2282,38 @@ sed -e "s/#.*$//" -e "/=/d" -e "/^[ ]*$/d" $FLIST > /tmp/$$.flist.clean FLIST=/tmp/$$.flist.clean # +# For Mercurial, create a cache of manifest entries. +# +if [[ $SCM_MODE == "mercurial" ]]; then + # + # Transform the FLIST into a temporary sed script that matches + # relevant entries in the Mercurial manifest as follows: + # 1) The script will be used against the parent revision manifest, + # so for FLIST lines that have two filenames (a renamed file) + # keep only the old name. + # 2) Escape all forward slashes the filename. + # 3) Change the filename into another sed command that matches + # that file in "hg manifest -v" output: start of line, three + # octal digits for file permissions, space, a file type flag + # character, space, the filename, end of line. + # + SEDFILE=/tmp/$$.manifest.sed + sed ' + s#^[^ ]* ## + s#/#\\\/#g + s#^.*$#/^... . &$/p# + ' < $FLIST > $SEDFILE + + # + # Apply the generated script to the output of "hg manifest -v" + # to get the relevant subset for this webrev. + # + HG_PARENT_MANIFEST=/tmp/$$.manifest + hg -R $CWS manifest -v -r $HG_PARENT | + sed -n -f $SEDFILE > $HG_PARENT_MANIFEST +fi + +# # First pass through the files: generate the per-file webrev HTML-files. # cat $FLIST | while read LINE @@ -1868,19 +2364,11 @@ do COMM=`getcomments html $P $PP` - if [[ ! -d $CWS/$DIR ]]; then - print " $CWS/$DIR: no such directory" - continue - fi - print "\t$P$oldname\n\t\t\c" # Make the webrev mirror directory if necessary mkdir -p $WDIR/$DIR - # cd to the directory so the names are short - cd $CWS/$DIR - # # If we're in OpenSolaris mode, we enforce a minor policy: # help to make sure the reviewer doesn't accidentally publish @@ -1897,63 +2385,20 @@ do fi # - # We stash old and new files into parallel directories in /tmp + # We stash old and new files into parallel directories in $WDIR # and do our diffs there. This makes it possible to generate # clean looking diffs which don't have absolute paths present. # - olddir=$WDIR/raw_files/old - newdir=$WDIR/raw_files/new - mkdir -p $olddir - mkdir -p $newdir - mkdir -p $olddir/$PDIR - mkdir -p $newdir/$DIR - - if [[ $SCM_MODE == "teamware" ]]; then - # If the child's version doesn't exist then - # get a readonly copy. - if [[ ! -f $F && -f SCCS/s.$F ]]; then - sccs get -s $F - fi - - # - # Snag new version of file. - # - rm -f $newdir/$DIR/$F - cp $F $newdir/$DIR/$F - - # - # Get the parent's version of the file. First see whether the - # child's version is checked out and get the parent's version - # with keywords expanded or unexpanded as appropriate. - # - if [ -f "$PWS/$PDIR/SCCS/s.$PF" -o \ - -f "$PWS/$PDIR/SCCS/p.$PF" ]; then - rm -f $olddir/$PDIR/$PF - if [ -f "SCCS/p.$F" ]; then - sccs get -s -p -k $PWS/$PDIR/$PF \ - > $olddir/$PDIR/$PF - else - sccs get -s -p $PWS/$PDIR/$PF \ - > $olddir/$PDIR/$PF - fi - else - if [[ -f $PWS/$PDIR/$PF ]]; then - # Parent is not a real workspace, but just a raw - # directory tree - use the file that's there as - # the old file. - - rm -f $olddir/$DIR/$F - cp $PWS/$PDIR/$PF $olddir/$DIR/$F - fi - fi - fi - - if [[ ! -f $F && ! -f $olddir/$DIR/$F ]]; then - print "*** Error: file not in parent or child" - continue - fi + build_old_new "$WDIR" "$PWS" "$PDIR" "$PF" "$CWS" "$DIR" "$F" || \ + continue + # + # Keep the old PWD around, so we can safely switch back after + # diff generation, such that build_old_new runs in a + # consistent environment. + # + OWD=$PWD cd $WDIR/raw_files ofile=old/$PDIR/$PF nfile=new/$DIR/$F @@ -2081,8 +2526,8 @@ do fi fi - if [[ -f $ofile && -z $mv_but_nodiff ]]; then - source_to_html Old $P < $ofile > $WDIR/$DIR/$F-.html + if [[ -f $ofile ]]; then + source_to_html Old $PP < $ofile > $WDIR/$DIR/$F-.html print " old\c" fi @@ -2091,6 +2536,8 @@ do print " new\c" fi + cd $OWD + print done @@ -2102,7 +2549,6 @@ if [[ ! -f $WDIR/$WNAME.ps ]]; then elif [[ -x $CODEREVIEW && -x $PS2PDF ]]; then print " Generating PDF: \c" fix_postscript $WDIR/$WNAME.ps | $PS2PDF - > $WDIR/$WNAME.pdf - rm -f $WDIR/$WNAME.ps print "Done." else print " Generating PDF: Skipped: missing 'ps2pdf' or 'codereview'" @@ -2139,28 +2585,49 @@ print "<h2>Code Review for $WNAME</h2>" print "<table>" # -# Figure out the username and gcos name. To maintain compatibility -# with passwd(4), we must support '&' substitutions. +# Get the preparer's name: # -username=`id | cut -d '(' -f 2 | cut -d ')' -f 1` -realname=`getent passwd $username | cut -d':' -f 5` -userupper=`$PERL -e "print ucfirst $username"` -realname=`print $realname | sed s/\&/$userupper/` -date="on `date`" - -if [[ -n "$username" && -n "$realname" ]]; then - print "<tr><th>Prepared by:</th>" - print "<td>$realname ($username) $date</td></tr>" -elif [[ -n "$username" ]]; then - print "<tr><th>Prepared by:</th><td>$username $date</td></tr>" +# If the SCM detected is Mercurial, and the configuration property +# ui.username is available, use that, but be careful to properly escape +# angle brackets (HTML syntax characters) in the email address. +# +# Otherwise, use the current userid in the form "John Doe (jdoe)", but +# to maintain compatibility with passwd(4), we must support '&' substitutions. +# +preparer= +if [[ "$SCM_MODE" == mercurial ]]; then + preparer=`hg showconfig ui.username 2>/dev/null` + if [[ -n "$preparer" ]]; then + preparer="$(echo "$preparer" | html_quote)" + fi +fi +if [[ -z "$preparer" ]]; then + preparer=$( + $PERL -e ' + ($login, $pw, $uid, $gid, $quota, $cmt, $gcos) = getpwuid($<); + if ($login) { + $gcos =~ s/\&/ucfirst($login)/e; + printf "%s (%s)\n", $gcos, $login; + } else { + printf "(unknown)\n"; + } + ') fi -print "<tr><th>Workspace:</th><td>$CWS</td></tr>" +print "<tr><th>Prepared by:</th><td>$preparer on `date`</td></tr>" +print "<tr><th>Workspace:</th><td>$CWS" +if [[ -n $CWS_REV ]]; then + print "(at $CWS_REV)" +fi +print "</td></tr>" print "<tr><th>Compare against:</th><td>" if [[ -n $parent_webrev ]]; then print "webrev at $parent_webrev" else print "$PWS" + if [[ -n $hg_parent_short ]]; then + print "(at $hg_parent_short)" + fi fi print "</td></tr>" print "<tr><th>Summary of changes:</th><td>" @@ -2184,7 +2651,6 @@ fi print "</table>" print "</div>" - # # Second pass through the files: generate the rest of the index file # @@ -2195,13 +2661,18 @@ do if [[ $# == 2 ]]; then PP=$2 - oldname=" <i>(was $PP)</i>" - + oldname="$PP" else PP=$P oldname="" fi + mv_but_nodiff= + cmp $WDIR/raw_files/old/$PP $WDIR/raw_files/new/$P > /dev/null 2>&1 + if [[ $? == 0 && -n "$oldname" ]]; then + mv_but_nodiff=1 + fi + DIR=${P%/*} if [[ $DIR == $P ]]; then DIR="." # File at root of workspace @@ -2266,7 +2737,21 @@ do print " ---" fi - print "<b>$P</b> $oldname" + print "<b>$P</b>" + + # For renamed files, clearly state whether or not they are modified + if [[ -n "$oldname" ]]; then + if [[ -n "$mv_but_nodiff" ]]; then + print "<i>(renamed only, was $oldname)</i>" + else + print "<i>(modified and renamed, was $oldname)</i>" + fi + fi + + # If there's an old file, but no new file, the file was deleted + if [[ -f $F-.html && ! -f $F.html ]]; then + print " <i>(deleted)</i>" + fi # # Check for usr/closed and deleted_files/usr/closed @@ -2296,6 +2781,42 @@ do cat $F.count rm $F.count fi + + if [[ $SCM_MODE == "teamware" || + $SCM_MODE == "mercurial" || + $SCM_MODE == "unknown" ]]; then + + # Include warnings for important file mode situations: + # 1) New executable files + # 2) Permission changes of any kind + # 3) Existing executable files + + old_mode= + if [[ -f $WDIR/raw_files/old/$PP ]]; then + old_mode=`get_file_mode $WDIR/raw_files/old/$PP` + fi + + new_mode= + if [[ -f $WDIR/raw_files/new/$P ]]; then + new_mode=`get_file_mode $WDIR/raw_files/new/$P` + fi + + if [[ -z "$old_mode" && "$new_mode" = *[1357]* ]]; then + print "<span class=\"chmod\">" + print "<p>new executable file: mode $new_mode</p>" + print "</span>" + elif [[ -n "$old_mode" && -n "$new_mode" && + "$old_mode" != "$new_mode" ]]; then + print "<span class=\"chmod\">" + print "<p>mode change: $old_mode to $new_mode</p>" + print "</span>" + elif [[ "$new_mode" = *[1357]* ]]; then + print "<span class=\"chmod\">" + print "<p>executable file: mode $new_mode</p>" + print "</span>" + fi + fi + print "</blockquote>" done diff --git a/usr/src/tools/scripts/which_scm.1 b/usr/src/tools/scripts/which_scm.1 new file mode 100644 index 0000000000..4f148e26d5 --- /dev/null +++ b/usr/src/tools/scripts/which_scm.1 @@ -0,0 +1,77 @@ +.\" +.\" CDDL HEADER START +.\" +.\" The contents of this file are subject to the terms of the +.\" Common Development and Distribution License (the "License"). +.\" You may not use this file except in compliance with the License. +.\" +.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +.\" or http://www.opensolaris.org/os/licensing. +.\" See the License for the specific language governing permissions +.\" and limitations under the License. +.\" +.\" When distributing Covered Code, include this CDDL HEADER in each +.\" file and include the License file at usr/src/OPENSOLARIS.LICENSE. +.\" If applicable, add the following below this CDDL HEADER, with the +.\" fields enclosed by brackets "[]" replaced with your own identifying +.\" information: Portions Copyright [yyyy] [name of copyright owner] +.\" +.\" CDDL HEADER END +.\" +.\" Copyright 2008 Sun Microsystems, Inc. All rights reserved. +.\" Use is subject to license terms. +.\" +.\" ident "%Z%%M% %I% %E% SMI" +.\" +.TH which_scm 1 "11 April 2008" +.SH NAME +which_scm \- Report Source Code Management system +.SH SYNOPSIS +.B which_scm + +.SH DESCRIPTION +.B which_scm +detects the Source Code Management (SCM) system in use, and prints a +single line of text containing a one-word name for the SCM, followed +by a space, and then the top-level directory path for the workspace. + +The typical usage within a ksh script is: +.nf + which_scm | read SCM_TYPE CODEMGR_WS || exit 1 +.fi + +If CODEMGR_WS is set in the environment, then \fBwhich_scm\fR +checks only that directory, assuming that it is the top of the tree. + +If CODEMGR_WS is not set, then \fBwhich_scm\fR searches upwards to +find the containing workspace path, and reports that path. + +.B which_scm +can detect the following types of SCM systems (these are the keywords +used in the output format): +.nf + cvs + mercurial + rcs + sccs + subversion + teamware +.fi + +If the type of SCM in use is not known, then the string "unknown" is +printed, and the path returned is $CODEMGR_WS (if set) or the current +working directory. The command may exit with an error if the SCM +could be detected, but is unusable. + +.SH ENVIRONMENT VARIABLES +The following environment variable is used by \fBwhich_scm\fR: + +.PP +\fBCODEMGR_WS\fR path to current workspace. + +.SH SEE ALSO +.IR cvs(1) , +.IR hg(1) , +.IR sccs(1) +.IR svn(1) , +.IR workspace(1) diff --git a/usr/src/tools/scripts/which_scm.sh b/usr/src/tools/scripts/which_scm.sh new file mode 100644 index 0000000000..6abbd4a148 --- /dev/null +++ b/usr/src/tools/scripts/which_scm.sh @@ -0,0 +1,132 @@ +#!/usr/bin/ksh -p +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +# which_scm outputs two strings: one identifying the SCM in use, and +# the second giving the root directory for the SCM, if known, or just +# the current working directory if not known. + +# There are three distinct types of SCM systems we can detect. The first +# type have a control directory per directory (RCS and SCCS), with no other +# structure. The second type have a control directory in each subdirectory +# within a tree (CVS and SVN). The last type have a single control +# directory at the top of the tree (Teamware and Mercurial). + +# If the common CODEMGR_WS variable is set, then we look there for the +# SCM type and bail out if we can't determine it. + +# If that variable is not set, then we start in the current directory +# and work our way upwards until we find the top of the tree or we +# encounter an error. + +# We do handle nested SCM types, and report the innermost one, but if +# you nest one of the "second type" systems within another instance of +# itself, we'll keep going upwards and report the top of the nested +# set of trees. + + +# Check for well-known tree-type source code management (SCM) systems. +function primary_type +{ + typeset scmid + + [ -d "$1/Codemgr_wsdata" ] && scmid="$scmid teamware" + [ -d "$1/.hg" ] && scmid="$scmid mercurial" + [ -d "$1/CVS" ] && scmid="$scmid cvs" + [ -d "$1/.svn" ] && scmid="$scmid subversion" + echo $scmid +} + +if [[ -n "$CODEMGR_WS" ]]; then + if [[ ! -d "$CODEMGR_WS" ]]; then + print -u2 "which_scm: $CODEMGR_WS is not a directory." + exit 1 + fi + set -- $(primary_type "$CODEMGR_WS") + if [[ $# != 1 ]]; then + set -- unknown + fi + echo "$1 $CODEMGR_WS" + exit 0 +fi + +ORIG_CWD=$(pwd) + +if [[ -d RCS ]]; then + echo "rcs $ORIG_CWD" + exit 0 +fi + +# If it's not Teamware, it could just be local SCCS. +LOCAL_TYPE= +[[ -d SCCS ]] && LOCAL_TYPE="sccs" + +# Scan upwards looking for top of tree. +DIR=$ORIG_CWD +CWD_TYPE=$(primary_type "$DIR") +SCM_TYPE= +while [[ "$DIR" != / ]]; do + set -- $(primary_type "$DIR") + if [[ $# > 1 ]]; then + echo "unknown $ORIG_CWD" + exit 0 + fi + SCM_TYPE="$1" + # We're done searching if we hit either a change in type or the top + # of a "third type" control system. + if [[ "$SCM_TYPE" != "$CWD_TYPE" || "$SCM_TYPE" == mercurial || \ + "$SCM_TYPE" == teamware ]]; then + break + fi + PREVDIR="$DIR" + DIR=$(dirname "$DIR") +done + +# We assume here that the system root directory isn't the root of the SCM. + +# Check for the "second type" of repository. In all cases, we started +# out in the tree and stepped out on the last iteration, so we want +# $PREVDIR. +if [[ "$CWD_TYPE" == cvs || "$CWD_TYPE" == subversion ]]; then + echo "$CWD_TYPE $PREVDIR" + exit 0 +fi + +# If we still don't know what it is, then check for a local type in the +# original directory. If none, then we don't know what it is. +if [[ -z "$SCM_TYPE" ]]; then + if [[ -z "$LOCAL_TYPE" ]]; then + SCM_TYPE=unknown + else + SCM_TYPE=$LOCAL_TYPE + DIR=$ORIG_CWD + fi +fi + +echo "$SCM_TYPE $DIR" +exit 0 diff --git a/usr/src/tools/scripts/ws.sh b/usr/src/tools/scripts/ws.sh index 323b37c74f..4d5b5bb15d 100644 --- a/usr/src/tools/scripts/ws.sh +++ b/usr/src/tools/scripts/ws.sh @@ -1,11 +1,10 @@ -#!/bin/sh +#!/bin/ksh -p # # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -21,7 +20,7 @@ # CDDL HEADER END # # -# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -56,26 +55,38 @@ # The workspace name can have hostname:pathname format. # -fmtwsname(){ +fmtwsname() +{ awk -F: '$1 != $0 { print "/net/"$1$2 } \ $1 == $0 { print $0 }' } # -# function to check to see if a proto area is new or old format +# Return a valid proto area, if one exists. # check_proto() { - # Check for problematic parent specification and adjust - proto=`echo $1|fmtwsname` - # - # if proto contains a /usr/include directory we assume - # that this is an old style proto area - # - if [ -d $proto/usr/include ]; then - echo $proto - else + if [[ -z $1 ]]; then + return + fi + + if [ "$SCM_MODE" = "teamware" ]; then + # Check for problematic parent specification and adjust + proto=`echo $1|fmtwsname` echo "${proto}/root_${MACH}" + elif [ "$SCM_MODE" = "mercurial" ]; then + proto=$1 + # + # If the proto is a local repository then we can use it + # to point to the parents proto area. Don't bother to + # check if it exists or not, we never did for Teamware, + # since it might appear later anyway. + # + if [ "${proto##ssh://}" == "$proto" -a \ + "${proto##http://}" == "$proto" -a \ + "${proto##https://}" == "$proto" ]; then + echo "${proto}/root_${MACH}" + fi fi } @@ -94,29 +105,45 @@ else setenv=false fi -if [ $# -lt 1 ]; then - set -- `workspace name` - [ $# -eq 1 ] && echo "Defaulting to workspace $1" -fi +WHICH_SCM=$(dirname $(whence $0))/which_scm +# +# No workspace/repository path was given, so try and detect one from our +# current directory we're in +# if [ $# -lt 1 ]; then - echo "usage: ws [-e] [workspace_name]" >&2 - if $setenv; then - cleanup_env - return 1 + if $WHICH_SCM | read SCM_MODE tmpwsname && \ + [[ $SCM_MODE != unknown ]]; then + echo "Defaulting to $SCM_MODE repository $tmpwsname" else - exit 1 + echo "usage: ws [-e] [workspace_name]" >&2 + if $setenv; then + cleanup_env + return 1 + else + exit 1 + fi fi +else + # + # A workspace/repository path was passed in, grab it and pop + # it off the stack + # + tmpwsname=$1 + shift fi # # This variable displays the nested activations of workspaces. # This is done here to get the exact name the user entered. # -WS_STACK="$1 $WS_STACK"; export WS_STACK +WS_STACK="$tmpwsname $WS_STACK"; export WS_STACK -wsname=`echo $1|fmtwsname` -shift +# +# Set the workspace name and unset tmpwsname (as we reuse it later) +# +wsname=`echo $tmpwsname|fmtwsname` +unset tmpwsname # # Checking for CODEMGR_WSPATH @@ -136,6 +163,7 @@ then IFS=$ofs fi +# # to translate it to an absolute pathname. We need an # absolute pathname in order to set CODEMGR_WS. # @@ -145,19 +173,11 @@ then wsname="$pwd/$wsname" fi -if [ ! -d $wsname/Codemgr_wsdata ]; then - echo "Error: $wsname is not a workspace" >&2 - if $setenv; then - cleanup_env - return 1 - else - exit 1 - fi -fi - -tmpwsname=`(cd $wsname >/dev/null && workspace name)` -if [ -z "$tmpwsname" ]; then - echo "Error: $wsname is not a workspace" >&2 +# +# Check to see if this is a valid workspace +# +if [ ! -d $wsname ]; then + echo "$wsname . . . no such directory" >&2 if $setenv; then cleanup_env return 1 @@ -165,13 +185,14 @@ if [ -z "$tmpwsname" ]; then exit 1 fi fi -wsname=$tmpwsname # -# Check to see if this is a valid workspace +# This catches the case of a passed in workspace path +# Check which type of SCM is in use by $wsname. # -if [ ! -d $wsname ]; then - echo "$wsname . . . no such directory" >&2 +(cd $wsname && $WHICH_SCM) | read SCM_MODE tmpwsname +if [[ $? != 0 || "$SCM_MODE" == unknown ]]; then + echo "Error: Unable to detect a supported SCM repository in $wsname" if $setenv; then cleanup_env return 1 @@ -179,10 +200,22 @@ if [ ! -d $wsname ]; then exit 1 fi fi -if [ -d ${wsname}/Codemgr_wsdata ]; then - CM_DATA=Codemgr_wsdata + +wsname=$tmpwsname +CODEMGR_WS=$wsname ; export CODEMGR_WS +SRC=$wsname/usr/src; export SRC +TSRC=$wsname/usr/ontest; export TSRC + +if [ "$SCM_MODE" = "teamware" -a -d ${wsname}/Codemgr_wsdata ]; then + CM_DATA="Codemgr_wsdata" + wsosdir=$CODEMGR_WS/$CM_DATA/sunos + protofile=$wsosdir/protodefs +elif [ "$SCM_MODE" = "mercurial" -a -d ${wsname}/.hg ]; then + CM_DATA=".hg" + wsosdir=$CODEMGR_WS/$CM_DATA + protofile=$wsosdir/org.opensolaris.protodefs else - echo "$wsname is not a workspace" >&2 + echo "$wsname is not a supported workspace; type is $SCM_MODE" >&2 if $setenv; then cleanup_env return 1 @@ -191,13 +224,6 @@ else fi fi -CODEMGR_WS=$wsname; export CODEMGR_WS -SRC=$CODEMGR_WS/usr/src; export SRC -TSRC=$CODEMGR_WS/usr/ontest; export TSRC - -wsosdir=$CODEMGR_WS/$CM_DATA/sunos -protofile=$wsosdir/protodefs - if [ ! -f $protofile ]; then if [ ! -w $CODEMGR_WS/$CM_DATA ]; then # @@ -241,19 +267,29 @@ if [ ! -f $protofile ]; then # PROTO1=\$CODEMGR_WS/proto - +PROTOFILE_EoF + + if [ "$SCM_MODE" = "teamware" ]; then + cat << PROTOFILE_EoF >> $protofile if [ -f "\$CODEMGR_WS/Codemgr_wsdata/parent" ]; then # # If this workspace has an codemgr parent then set PROTO2 to # point to the parents proto space. # parent=\`workspace parent \$CODEMGR_WS\` - if [ -n \$parent ]; then + if [[ -n \$parent ]]; then PROTO2=\$parent/proto fi fi PROTOFILE_EoF - + elif [ "$SCM_MODE" = "mercurial" ]; then + cat << PROTOFILE_EoF >> $protofile +parent=\`(cd \$CODEMGR_WS && hg path default 2>/dev/null)\` +if [[ \$? -eq 0 && -n \$parent ]]; then + PROTO2=\$(check_proto \$parent/proto) +fi +PROTOFILE_EoF + fi fi . $protofile @@ -268,7 +304,6 @@ MAKEFLAGS=e; export MAKEFLAGS MACH=`uname -p` ROOT=/proto/root_${MACH} # default - ENVCPPFLAGS1= ENVCPPFLAGS2= ENVCPPFLAGS3= @@ -277,22 +312,23 @@ ENVLDLIBS1= ENVLDLIBS2= ENVLDLIBS3= -if [ "$PROTO1" != "" ]; then # first proto area specifed - PROTO1=`check_proto $PROTO1` +PROTO1=`check_proto $PROTO1` +if [[ -n "$PROTO1" ]]; then # first proto area specifed ROOT=$PROTO1 ENVCPPFLAGS1=-I$ROOT/usr/include export ENVCPPFLAGS1 ENVLDLIBS1="-L$ROOT/lib -L$ROOT/usr/lib" export ENVLDLIBS1 - if [ "$PROTO2" != "" ]; then # second proto area specifed - PROTO2=`check_proto $PROTO2` + PROTO2=`check_proto $PROTO2` + if [[ -n "$PROTO2" ]]; then # second proto area specifed ENVCPPFLAGS2=-I$PROTO2/usr/include export ENVCPPFLAGS2 ENVLDLIBS2="-L$PROTO2/lib -L$PROTO2/usr/lib" export ENVLDLIBS2 - if [ "$PROTO3" != "" ]; then # third proto area specifed + PROTO3=`check_proto $PROTO3` + if [[ -n "$PROTO3" ]]; then # third proto area specifed PROTO3=`check_proto $PROTO3` ENVCPPFLAGS3=-I$PROTO3/usr/include export ENVCPPFLAGS3 @@ -304,7 +340,7 @@ fi export ROOT -if [ "$TERMPROTO" != "" ]; then # fallback area specifed +if [[ -n "$TERMPROTO" ]]; then # fallback area specifed TERMPROTO=`check_proto $TERMPROTO` ENVCPPFLAGS4="-Y I,$TERMPROTO/usr/include" export ENVCPPFLAGS4 @@ -312,57 +348,43 @@ if [ "$TERMPROTO" != "" ]; then # fallback area specifed export ENVLDLIBS3 fi -# -# Now let's set those variables which are either 4.1.x specific -# or 5.0 specific -# -os_rev=`uname -r` osbld_flag=0 -if [ `expr $os_rev : "4\.1"` = "3" ]; then # This is a 4.1.x machine - # - # Enable all of the DOUBLECROSS_ROOT components for the 4.1.x compile - # - DOUBLECROSS_ROOT=${DOUBLECROSS_ROOT="/crossroot"} - PATH=$DOUBLECROSS_ROOT/usr/ccs/bin:$DOUBLECROSS_ROOT/usr/bin:$DOUBLECROSS_ROOT/usr/sbin:$PATH - export DOUBLECROSS_ROOT PATH -elif [ `expr $os_rev : "5\."` = "2" ]; then - # - # Enable any 5.x specific variables here - # - if [ ${ONBLD_DIR:-NULL} = "NULL" ]; then - if [ -d /opt/onbld/bin ]; then - ONBLD_DIR=/opt/onbld/bin - elif [ -d /usr/onbld/bin ]; then - ONBLD_DIR=/usr/onbld/bin - fi - fi - if [ -d ${ONBLD_DIR:-\\NULL} ] ; then - PATH=${ONBLD_DIR}:${PATH} - osbld_flag=1 - export PATH - fi - if [ "$PROTO2" != "" ]; then - # This should point to the parent's proto - PARENT_ROOT=$PROTO2 - export PARENT_ROOT - else - # Clear it in case it's already in the env. - PARENT_ROOT= - fi - export ONBLD_DIR - export MACH +if [[ -z "$ONBLD_DIR" ]]; then + ONBLD_DIR=$(dirname $(whence $0)) +fi + +if ! echo ":$PATH:" | grep ":${ONBLD_DIR}:" > /dev/null; then + PATH="${ONBLD_DIR}:${ONBLD_DIR}/${MACH}:${PATH}" + osbld_flag=1 +fi + +export PATH + +if [[ -n "$PROTO2" ]]; then + # This should point to the parent's proto + PARENT_ROOT=$PROTO2 + export PARENT_ROOT else + # Clear it in case it's already in the env. + PARENT_ROOT= +fi +export ONBLD_DIR +export MACH + +os_rev=`uname -r` +os_name=`uname -s` + +if [[ $os_name != "SunOS" || `expr $os_rev : "5\."` != "2" ]]; then # - # This is neither a 5.x machine nor a 4.1.x machine - something is wrong + # This is not a SunOS 5.x machine - something is wrong # - echo "***WARNING: this script is meant to be run on a 4.1.x and/or a 5.x" - echo " operating system. This machine appears to be running:" - echo " $os_rev " + echo "***WARNING: this script is meant to be run on SunOS 5.x." + echo " This machine appears to be running: $os_name $os_rev" fi echo "" -echo "Workspace (\$CODEMGR_WS) : $CODEMGR_WS" +echo "Workspace : $wsname" if [ -n "$parent" ]; then echo "Workspace Parent : $parent" fi @@ -375,10 +397,10 @@ echo "Root of test source (\$TSRC) : $TSRC" if [ $osbld_flag = "1" ]; then echo "Prepended to PATH : $ONBLD_DIR" fi -echo "Current directory (\$PWD) : $CODEMGR_WS" +echo "Current directory (\$PWD) : $wsname" echo "" -cd $CODEMGR_WS +cd $wsname if $setenv; then cleanup_env diff --git a/usr/src/tools/scripts/wx.1 b/usr/src/tools/scripts/wx.1 index 3097ea7375..032dc7271a 100644 --- a/usr/src/tools/scripts/wx.1 +++ b/usr/src/tools/scripts/wx.1 @@ -17,12 +17,12 @@ .\" .\" CDDL HEADER END .\" -.\" Copyright 2006 Sun Microsystems, Inc. All rights reserved. +.\" Copyright 2008 Sun Microsystems, Inc. All rights reserved. .\" Use is subject to license terms. .\" .\" ident "%Z%%M% %I% %E% SMI" .\" -.TH wx 1 "18 January 2006" +.TH wx 1 "16 April 2008" .SH NAME .I wx \- tool to track changes to a workspace, follow ON gate rules and much more @@ -40,8 +40,8 @@ Note, it is recommended that you use .I wx for all file manipulation instead of using sccs as this allows wx to automatically track changes in the workspace instead of having to use -the update command. See http://onnv.eng/wx.html for more -information about using wx. +the update command. See http://www.opensolaris.org/os/community/on/wx/ +for more information about using wx. .\" COMMANDS section .LP @@ -718,7 +718,8 @@ $ WXWEBREV=~/bin/webrev wx webrev .SH EXAMPLES .LP -See wx link in http://onnv.eng for examples of how to use wx. +See http://www.opensolaris.org/os/community/on/wx/ for +examples of how to use wx. .SH BUGS .LP diff --git a/usr/src/tools/scripts/wx.sh b/usr/src/tools/scripts/wx.sh index 7743b62a79..c713a125a0 100644 --- a/usr/src/tools/scripts/wx.sh +++ b/usr/src/tools/scripts/wx.sh @@ -597,7 +597,7 @@ wx_usage() { cat << EOF -See <http://onnv.eng/wx.html> for usage tips. +See <http://www.opensolaris.org/os/community/on/wx/> for usage tips. Usage: $ME command [-D] [args] @@ -2295,7 +2295,7 @@ for more info. Note, pay attention to the tabs. fi fi - if ! wx_copyright; then + if ! copyrightchk $file; then # Sound bell ring_bell cat >&2 <<-EOF @@ -2988,51 +2988,6 @@ wx_info() { echo } -wx_copyright() { - typeset _problem=0 - case $file in - *.adb) return;; - *.fdbg) return;; - *.in) return;; - esac - year=`date +%Y` - oldcopyright1='Copyright \(c\).* Sun Microsystems, Inc.' - # The backslash on the next line is just a hack so that - # 'wx copyright' on itself doesn't trigger a false positive. - oldcopyright2='Copyright\ .* by Sun Microsystems, Inc.' - copyright='Copyright '$year' Sun Microsystems, Inc.' - reserved='All rights reserved.' - license='Use is subject to license terms.' - if egrep -s ''"$oldcopyright1"'' $file ; then - echo "old copyright with '(c)' in $filepath" - _problem=1 - fi - if egrep -s ''"$oldcopyright2"'' $file; then - echo "old copyright with 'by' in $filepath" - _problem=1 - fi - if egrep -s ''"$copyright"' '"$reserved"'' $file; then - echo "Need two spaces between copyright and all rights "\ - "reserved phrases in $filepath" - _problem=1 - fi - if ! egrep -s ''"$copyright"'' $file; then - echo "Proper $year copyright missing in $filepath." - echo "Only the current year should appear." - _problem=1 - fi - if ! egrep -s ''"$reserved"'' $file; then - echo "'$reserved' message missing in $filepath" - _problem=1 - fi - if ! egrep -s ''"$license"'' $file ; then - echo "'$license' message missing in $filepath" - _problem=1 - fi - - return $_problem -} - get_multi_deltas() { # Get list of files with more that one delta when putback. # set global multi_delta_list. @@ -4187,13 +4142,11 @@ wx_fullreview() { # Check on RTI status for bug ID's found in active list comments. # -rtichk() { - typeset bug bugs[] rtidir rtifile suffix rtitype='MarketingRelease' - typeset rtibug rti project release state gatetype='MarketingRelease' +wx_rtichk() { + typeset bugs[] # gate contains the gate dir, not full path - typeset gate=${parent##*/} usewebrti='false' - typeset webrticli=$(whence webrticli 2>/dev/null) - typeset -i i j rc=0 warnhdr=0 + typeset gate=${parent##*/} + typeset -i rc=0 typeset nolookup opt if [[ -f $wxdir/rtichk.NOT ]]; then @@ -4210,199 +4163,19 @@ rtichk() { esac done - # Is the parent a patch gate? - if [[ $parent == *-patch* ]]; then - rtitype='Patch' - suffix='P' - RTIDIRS=$PRTIDIRS - gatetype='Patch' - fi - - # Is the parent a test gate? - if [[ $parent == *-stc2 || $parent == *-test ]]; then - rtitype='RTI' - gatetype='RTI' - fi - - # Use new RTI query tool if there's a gate and there is an - # executable webrticli. - # Note, webrticli needs a gate arg to correctly determine status. + # Note, rtichk needs a gate arg to correctly determine status. if [[ -z $gate ]]; then cat >&2 <<-EOF -Warning: cannot find a parent gate, skipping webrticli checking. Will -check RTI status using old style checking... +Warning: cannot find a parent gate, skipping RTI checking. EOF - else - if [[ -z $webrticli ]]; then - # if webrticli isn't in the PATH, try default path - webrticli=/net/webrti.sfbay/export/home/bin/webrticli - fi - if [[ -x $webrticli ]]; then - usewebrti='true' - else - cat >&2 <<-EOF -Warning: cannot find webrticli, skipping webrticli checking. Will check -RTI status using old style checking... - EOF - fi fi # Use wx_summary to output bug ID's in active list comments, # redirecting warnings about non-bug ID's to file for later use. set -A bugs $(wx_summary -ao $nolookup 2>$wxtmp/bugwarnings|cut -f1 -d' ') + rtichk -g $gate ${bugs[@]} + rc=$? - ((i = 0)) # init bugs array index - for bug in ${bugs[@]}; do - if [[ $bug == 'accept' ]]; then - # skip this bug since it's accepted. - # Increment bugs[] index. - ((i = i + 1)) - continue - fi - - if $usewebrti; then - # try new RTI query interface - $webrticli -g $gate RTIstatus $bug > $wxtmp/webrticli.out 2>&1 - rc=$? - - case $rc in - 0) if [[ $(wc -l < $wxtmp/webrticli.out) -ne 1 ]]; then - # paranoid: should only have 1 line - cat <<-EOF - -Warning: for bug $bug the RTI status can not be determined using webrtcli. -Please contact the gatekeeper. The output of webrtcli is: - - EOF - cat $wxtmp/webrticli.out - else - IFS=':' read rtibug rti project \ - release state rtitype \ - < $wxtmp/webrticli.out - - if [[ $gatetype != $rtitype ]]; then - cat <<-EOF - -Warning: for bug $bug the RTI $rti is a $rtitype type but the parent gate -$gate is a $gatetype gate. A $gatetype RTI must be submitted to putback -bug $bug to $gate. - EOF - elif [[ $state == 'S_ACCEPTED' ]]; then - # found accepted bug - bugs[i]='accept' - fi - fi - # skip old-style checking - ((i = i + 1)) - continue ;; - - 1) # Serious system related problem has occured - cat <<-EOF - -Warning: for bug $bug the RTI status can not be determined using webrtcli. -Please contact the gatekeeper. The output of webrtcli is: - - EOF - cat $wxtmp/webrticli.out - # skip old-style checking - ((i = i + 1)) - continue ;; - - 5) # Incorrect gate name specified. - # See if bug can be found at all. - $webrticli RTIstatus $bug > /dev/null 2>&1 - if [[ $? -ne 3 ]]; then - # If the return is something - # other than the CR - # can't be found (3), issue - # a warning. - cat <<-EOF - -Warning: for bug $bug webrticli was unable to map current parent gate $gate -to a RTI release. Please contact the gatekeeper. The output of webrtcli is: - - EOF - cat $wxtmp/webrticli.out - # skip old-style checking - ((i = i + 1)) - continue - fi ;; - # Dealing with other error codes is - # tricky because the user may be using - # the old school rtitool and we don't - # want to needlessly warn. - esac - fi # end if $usewebrti - - # If bug wasn't found above then fall back to old school rti lookup... - # XXX if it is determined at some point that everyone is - # using the new web RTI tool then the fallback code can - # be removed. - - # Old style RTI lookup... - # See if there is an accepted rti (the filename indicates state) - for rtidir in $RTIDIRS; do - # make sure the rti dir is mounted - ls -d $rtidir >/dev/null - - if [[ ! (-d $rtidir && -r $rtidir) ]]; then - cat <<-EOF - -Warning: cannot check status of RTI's. Check with the gatekeepers to see why -$rtidir -is not accessible. - - EOF - return 1 - fi - - rtifile="${rtidir}/${suffix}${bug}.accept" - - if [[ -f "$rtifile" ]]; then - # This bug was accepted since the - # rtifile exists - - bugs[i]='accept' - ((j = 0)) - while (( j < ${#bugs[@]} )); do - - # Let's see if any other bugs - # were accepted in the rti file - if [[ ${bugs[j]} != 'accept' ]] && - grep -q "^${bugs[j]} " $rtifile - then - bugs[j]='accept' - fi - ((j = j + 1)) - done # while [[ j -lt ${#bugs[@]} ]] - # stop checking in rtidirs and go to next bug - break - fi # if [[ -f "$rtifile" ]] - done # rtidir in set of rtidirs - - # Increment bugs[] index. - ((i = i + 1)) - done # for bug in ${bugs[@]} - - for bug in ${bugs[@]}; do - if [[ $bug != 'accept' ]]; then - if [[ $warnhdr -ne 1 ]]; then - cat <<-EOF - -Warning: there doesn't seem to be an approved $rtitype RTI for the -following bug IDs listed in your active list comments (see '$ME bugs'). -Make sure your $rtitype RTI is approved before putting back to an -official ON gate (hint, use either <http://webrti.sfbay> or 'rtitool' -depending on the project to submit an $rtitype RTI): - - EOF - ((warnhdr = 1)) - # set return code to indicate problem - [[ $rc -eq 0 ]] && ((rc = 1)) - fi - print $bug - fi - done if [[ -s $wxtmp/bugwarnings ]]; then cat <<-EOF @@ -4414,7 +4187,7 @@ Please fix the following and run rtichk again: cat $wxtmp/bugwarnings ((rc = 1)) fi - if [[ $i -eq 0 ]]; then + if [[ ${#bugs} -eq 0 ]]; then print "\nWarning: no bug ID's in active list." fi return $rc @@ -4499,7 +4272,7 @@ ARC case associated with your putback. print "========== End of putback comments =======" # Output warning if RTI isn't approved. - rtichk $nolookup + wx_rtichk $nolookup print "========== End of RTI check output =======" cat <<-EOF @@ -4646,6 +4419,14 @@ if [[ "$1" == version ]]; then exit 0 fi +# +# Check to make sure we're not being run from within a Mercurial repo +# +if hg root >/dev/null 2>&1; then + fail "Error: wx does not support Mercurial repositories.\n"\ +"Please see http://opensolaris.org/os/community/tools/hg" +fi + whence workspace >/dev/null || fail "Error: cannot find workspace command in \$PATH." # Note, PUTBACK can be set to "cm_env -g -o putback" to use Casper Dik's @@ -4682,9 +4463,10 @@ else fi fi -[[ -z "$workspace" ]] && +if [[ -z "$workspace" ]]; then fail "No active workspace, run \"ws <workspace>\" or"\ "\"cd <workspace>\"." +fi workspace_basename=`basename $workspace` wxdir=${WXDIR:-$workspace/wx} @@ -5198,10 +4980,24 @@ case $command in rmdelchk) echo "\nDoing sccs rmdel check:"; wx_eval rmdelchk;; - rtichk) rtichk;; + rtichk) wx_rtichk;; deltachk) echo "\nDoing multi delta check:"; wx_eval deltachk;; - copyright) echo "\nDoing copyright check:"; wx_eval wx_copyright;; + copyright) echo "\nDoing copyright check:"; + cd $workspace; + copyright_files=; + for filepath in $file_list; do + if [[ -s $wxdir/${command}.NOT ]] && + grep -q "^$(escape_re $filepath)$" \ + $wxdir/${command}.NOT + then + echo "$filepath (skipping)" + else + copyright_files="$copyright_files $filepath" + fi + done + copyrightchk $copyright_files;; + cddlchk) echo "\nDoing CDDL block check:"; cd $workspace; diff --git a/usr/src/tools/scripts/wx2hg.1 b/usr/src/tools/scripts/wx2hg.1 new file mode 100644 index 0000000000..c4799b10d6 --- /dev/null +++ b/usr/src/tools/scripts/wx2hg.1 @@ -0,0 +1,223 @@ +.\" CDDL HEADER START +.\" +.\" The contents of this file are subject to the terms of the +.\" Common Development and Distribution License (the "License"). +.\" You may not use this file except in compliance with the License. +.\" +.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +.\" or http://www.opensolaris.org/os/licensing. +.\" See the License for the specific language governing permissions +.\" and limitations under the License. +.\" +.\" When distributing Covered Code, include this CDDL HEADER in each +.\" file and include the License file at usr/src/OPENSOLARIS.LICENSE. +.\" If applicable, add the following below this CDDL HEADER, with the +.\" fields enclosed by brackets "[]" replaced with your own identifying +.\" information: Portions Copyright [yyyy] [name of copyright owner] +.\" +.\" CDDL HEADER END +.\" +.\" Copyright 2008 Sun Microsystems, Inc. All rights reserved. +.\" Use is subject to license terms. +.\" +.\" ident "%Z%%M% %I% %E% SMI" +.TH wx2hg 1 "6 Jul 2008" +.SH NAME +.I wx2hg +\- Convert a wx-managed workspace to Mercurial. +.SH SYNOPSIS +.B wx2hg +[ \fB\-u\fR ] +[ \fB\-r\fR \fIhg_rev\fR ] +[ \fB\-t\fR \fIhg_ws\fR ] +\fItw_ws\fR +.LP +.SH DESCRIPTION +.I wx2hg +takes a Teamware workspace +and converts it to a workspace that is managed by +Mercurial. It is aimed at OS/Net projects that were started under +Teamware but which expect to deliver into a +Mercurial gate. As such, it assumes the following usage model: +.LP +Suppose that you have a project workspace, which has some changes +relative to its parent workspace. +.I wx2hg +checks for the existence of, and creates if necessary, +a Mercurial workspace called +\fItw_ws\fR\-hg that is in sync with the Mercurial twin +of its parent workspace. +Then it applies the changes from your project workspace to this Mercurial +workspace. +You can review the changes +before committing them. Note that any +intermediate deltas will be lost; note also that your child workspace +must be up-to-date with respect to the parent. +.LP +.I wx2hg +uses +.BR wx (1) +to determine which files have been renamed or altered. If your +workspace is not already controlled by +.BR wx (1), +.I wx2hg +puts it under +.BR wx (1) +control. If your workspace is already under +.BR wx (1) +control, +.I wx2hg +runs +.BR wx update +to ensure that the +.BR wx (1) +state files are up-to-date. This step can take a while. If you are +sure that +.BR wx (1) +already has the right list of files, you can skip this step by using +the +.B \-u +option. +.LP +You can use the +.B \-t +.I hg_ws +option to name the Mercurial target workspace, rather than having +.I wx2hg +default to using \fItw_ws\fR\-hg. +.LP +.I wx2hg +checks the Mercurial workspace against the Teamware parent. If it +finds a discrepancy, it assumes that the Teamware parent corresponds +to an older revision within the mercurial workspace. You must rerun +.I wx2hg +and use the +.B \-r +.I hg_rev +option to specify that revision. (See below for more discussion on +recovery from errors.) +With the +.B \-r +option, +.I wx2hg +updates the Mercurial working directory +to that older revision and then applies your +changes. You will need to use mercurial to merge your changes with +later changes in the workspace before pushing your changes to a parent +workspace. +.LP +.I wx2hg +exits with an error if it detects a rename conflict. +.LP +If +.I wx2hg +exits with an error, you can discard any changes made prior to the +error, then use the +.B \-t +option to reuse the workspace. To discard changes made prior to the +error, use this command: +.LP +.RS 5 +hg \-R \fIhg_ws\fR update \-C +.RE +.LP +.SH OPTIONS +.IP "\fB\-r\fR \fIhg_rev\fR" 10 +Use +.I hg_rev +as the Mercurial changeset that corresponds to the point +in time at which your teamware workspace was synchronized with its parent. +You may specify +.I hg_rev +as a changeset id or a Mercurial tag. +.IP "\fB\-t\fR \fIhg_ws\fR" 10 +Use an existing Mercurial workspace as the target, rather than +creating one. +.IP +If omitted, +.I tw_ws +must be a child of /ws/onnv-clone, and +.I wx2hg +will create the Mercurial workspace \fItw_ws\fR\-hg. +.IP \fB\-u\fR +Skip the "wx update" step if the workspace is already under +.BR wx (1) +control. +.LP +.SH SEE ALSO +.BR hg "(1), " wx (1) +.LP +.SH DIAGNOSTICS +.LP +wx2hg: +.I tw_parent +is not recognized as a gate; please provide a Mercurial workspace (-t +hg_ws) that matches it. +.LP +.RS 5 +This means that +.I tw_parent +does not contain a Codemgr_wsdata/hg_twin file pointing at its mercurial +equivalent. If necessary, you may reparent +.I tw_ws +to a workspace that specifies an hg_twin +and rerun +.IR wx2hg . +Otherwise, you must use the +.B \-t +option to specify an existing +Mercurial workspace whose contents matches the parent of +.IR tw_ws . +.RE +.LP +teamware parent ... doesn't match its mercurial twin +.LP +.RS 5 +.I wx2hg +detected an unexpected difference between the Teamware parent and the +Mercurial workspace. This likely means that the parent of your +teamware workspace is not in synch with the mercurial parent. In that +case, ask the maintainer of the parent workspace to resynchronize +them, or use +.B \-r +to specify a revision of the Mercurial workspace that matches the +Teamware parent. +.RE +.LP +wx2hg will only migrate checked-in files; please check in these files with wx +ci and try again +.LP +.RS 5 +In order to minimize spurious conflicts due to SCCS keyword +substitution, +.I wx2hg +only migrates changes in checked-in files. Please check in your +changes with +.I wx delget +prior to migration. +.RE +.SH FILES +.IP \fItw_ws\fR/Codemgr_wsdata/hg_twin +is read by wx2hg from the parent workspace of the teamware workspace +being converted in order to find the mercurial equivalent of that +workspace. The first line of hg_twin contains the URL of the +mercurial equivalent workspace. Since a single teamware workspace may +be split into multiple mercurial repositories, the 2nd and subsequent +lines of the file contain the relative paths within the first +repository of additional child repositories. The maintainer of a gate +being converted is responsible for creating this file to allow +teamware children of the teamware gate to be converted into mercurial +children of the mercurial gate. +.RE +.SH BUGS +If a file is both renamed and updated, doing an "hg diff" in the +Mercurial workspace will +show the entire (new) contents of the file, not just the updates. +.LP +There is no attempt at automated recovery in case of a rename +conflict. +.LP +If a Teamware workspace is split into multiple Mercurial twin +workspaces (as is the case with the ON closed source tree), then +Teamware filemv commands that alter the inner workspace are not +supported. diff --git a/usr/src/tools/scripts/wx2hg.sh b/usr/src/tools/scripts/wx2hg.sh new file mode 100644 index 0000000000..64d033f70b --- /dev/null +++ b/usr/src/tools/scripts/wx2hg.sh @@ -0,0 +1,323 @@ +#! /usr/bin/ksh +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +# +# Convert a wx-based workspace to Mercurial. +# + +usage="wx2hg [-u] [-r hg_rev] [-t hg_ws] codemgr_ws" + +# +# If "yes", then give some hints about cleanup and rerunning after a +# failure. +# +can_retry=no +tail=/usr/xpg4/bin/tail + +function has_hg_twin { + [[ -f "$1"/Codemgr_wsdata/hg_twin ]] +} + +function clone_twin { + twinfile="$1"/Codemgr_wsdata/hg_twin + twin=$(head -1 "$twinfile") + ws="$2" + rev="$3" + + echo "Teamware parent $1 has an hg twin" + + clonedirs=$($tail -n +2 "$twinfile") + echo "Cloning $twin" + echo "to $ws" + set -x + hg clone -r $rev "$twin" "$ws" + set +x + for dir in $clonedirs; do + echo "Cloning from $twin/$dir" + echo "to $ws/$dir" + hg clone -r $rev "$twin"/$dir "$ws"/$dir + done +} + + +function fail { + print -u2 wx2hg: "$@" + if [[ "$can_retry" = yes ]]; then + print -u2 "Please run" + print -u2 " hg --cwd $hg_ws update -C" + print -u2 "before retrying." + fi + exit 1 +} + +function warn { + print -u2 wx2hg: warning: "$@" +} + +function note { + print -u2 wx2hg: note: "$@" +} + +# +# Command-line processing, sanity checks, and setup. +# + +[[ -n $(whence workspace) ]] || + fail "workspace command not found; please check PATH." + +# do a wx update? +do_update=yes + +# +# Mercurial workspace to populate. Default is to create, in the same +# directory as the Teamware workspace, a new Mercurial workspace cloned +# from the hg_twin of the Teamware parent. +# +hg_ws="" + +# +# Revision in the Mercurial workspace to apply the changes to. +# Default is to get the most recent revision (tip), thus avoiding +# the need for a merge unless overridden by the caller using -r. +# +hg_rev="tip" + +while getopts r:t:u opt; do + case $opt in + r) hg_rev="$OPTARG";; + t) hg_ws="$OPTARG";; + u) do_update=no;; + ?) print -u2 "usage: $usage"; exit 1;; + esac +done +shift $(($OPTIND - 1)) + +if [[ $# -ne 1 ]]; then + print -u2 "usage: $usage" + exit 1 +fi + +CODEMGR_WS="$1" +[[ "$CODEMGR_WS" = /* ]] || CODEMGR_WS="$(pwd)/$CODEMGR_WS" +export CODEMGR_WS + +if [[ -n "$hg_ws" ]]; then + if [[ -d "$hg_ws" && ! -d "$hg_ws/.hg" ]]; then + fail "$hg_ws is not a Mercurial workspace." + fi + [[ "$hg_ws" = /* ]] || hg_ws="$(pwd)/$hg_ws" +fi + +[[ -d "$CODEMGR_WS" ]] || fail "$CODEMGR_WS does not exist." +cd "$CODEMGR_WS" + +codemgr_parent=$(workspace parent) +[[ -n "$codemgr_parent" ]] || \ + fail "$CODEMGR_WS is not a Teamware workspace or does not have a parent." +[[ -d "$codemgr_parent" ]] || fail "parent ($codemgr_parent) doesn't exist." + +# +# Do this check before time-consuming operations like creating +# the target repo. +# +his=$(find Codemgr_wsdata -name history -mtime -1) +if [[ -z "$his" ]]; then + warn "history file is more than one day old; do you need to" \ + "bringover from $codemgr_parent?" +fi + +# Less time-consuming than cloning + +if [[ ! -d wx ]]; then + print "Initializing wx..." + wx init -ft +else + if [[ "$do_update" = yes ]]; then + print "Updating wx state..." + wx update + fi +fi + +wx outchk + +out_files=$(wx out) +active_files=$(wx list) + +if [[ ! -z "$out_files" ]]; then + fail "wx2hg will only migrate checked-in files;" \ + "please check in these files with wx ci and try again" +fi + +# more time-consuming than wx update and wx outchk + +if [[ -z "$hg_ws" ]]; then + ws=$(basename $(pwd)) + hg_ws=$(dirname $(pwd))/"$ws-hg" +fi + +if [[ -d "$hg_ws" ]]; then + echo "Updating preexisting Mercurial workspace $hg_ws to $hg_rev\n" + (cd "$hg_ws"; hg update -C $hg_rev) || + fail "hg update $hg_rev failed for $hg_ws" +else + if has_hg_twin "$codemgr_parent"; then + clone_twin "$codemgr_parent" "$hg_ws" $hg_rev + else + fail "$codemgr_parent is not recognized as a gate;" \ + "please provide a Mercurial workspace (-t hg_ws)" \ + "that matches it." + fi +fi + +can_retry=yes + +# Make sure hg_ws is an absolute path +[[ "$hg_ws" = /* ]] || hg_ws="$(pwd)/$hg_ws" + +# +# Do renames first, because they'll be listed with the new name by "wx +# list". There's a conflict if the new name already exists or if the +# old name does not exist. We can theoretically recover from the +# former (move the existing file out of the way, or pick a different +# new name), but not the latter. For now, just error out and let the +# user fix up the workspace so that there isn't a conflict. +# + +renamelist=/tmp/wxrename$$ +wx renamed > "$renamelist" + +# usage: do_rename oldname newname +function do_rename { + typeset old=$1 + typeset new=$2 + + print "rename $old -> $new" + [[ -f "$old" ]] || fail "can't rename: $old doesn't exist." + [[ ! -f "$new" ]] || fail "can't rename: $new already exists." + set -x + hg mv $old $new || fail "rename failed." + set +x +} + +if [[ -s "$renamelist" ]]; then + cat "$renamelist" | ( + cd "$hg_ws" + while :; do + read newname oldname + [[ -n "$newname" ]] || break + do_rename "$oldname" "$newname" + done + ) || exit 1 +fi + +# +# usage: name_in_parent fname +# If fname had been renamed, echo the old name. Otherwise echo the +# given name. +# +function name_in_parent { + typeset new old + + if [[ -s "$renamelist" ]]; then + cat "$renamelist" | while :; do + read new old + [[ -n "$new" ]] || break + if [[ "$1" = "$new" ]]; then + print "$old" + return + fi + done + fi + print "$1" +} + +# +# Now do content changes. There's a likely conflict if the file in +# Mercurial is different from the file in the Teamware parent. +# + +parentfile=/tmp/parent$$ +patchfile=/tmp/patch$$ +childfile=/tmp/child$$ + +[[ -n "$active_files" ]] || warn "no files in active list." + +for f in $active_files; do + # + # Get the name that the file appears in the parent as. + # + oldname=$(name_in_parent "$f") + + # We need unexpanded SCCS keywords for both parent and child + sccs get -skp "$f" > "$childfile" + + if [[ -f "$codemgr_parent/$oldname" ]]; then + (cd $codemgr_parent; sccs get -skp "$oldname" > "$parentfile") + else + rm -f $parentfile + fi + + if [[ ! -r "$parentfile" ]]; then + print "new file: $f" + [[ ! -f "$hg_ws/$f" ]] || fail "$f already exists in $hg_ws." + dir=$(dirname "$hg_ws/$f") + base=$(basename "$hg_ws/$f") + [[ -d "$dir" ]] || mkdir -p "$dir" || fail "mkdir failed" + cp "$childfile" "$hg_ws/$f" || fail "copy failed" + set -x + (cd "$dir" && hg add "$base") || fail "hg add failed." + set +x + elif diff "$parentfile" "$hg_ws/$f" > /dev/null 2>&1; then + if diff -u "$parentfile" "$childfile" > "$patchfile"; then + print "skipping $f (unchanged)." + continue + fi + (cd "$hg_ws"; gpatch -F0 $f < "$patchfile") + [[ $? -eq 0 ]] || fail "$f: patch failed." + else + diff -u "$parentfile" "$hg_ws/$f" + echo "" + + fail "For file:\n\n\t$f\n\nthe teamware parent:" \ + "\n\n\t$codemgr_parent" \ + "\n\ndoesn't match its mercurial twin;" \ + "specify the matching revision in mercurial\nwith" \ + "-r hg_rev, or resynchronize them.\n" + fi +done + +note "remember to commit your changes in $hg_ws" + +if [[ "$hg_rev" != "tip" ]]; then + note "before you integrate your changes, $hg_ws must be merged to tip" +fi + +rm -f "$parentfile" "$patchfile" "$renamelist" "$childfile" + +exit 0 diff --git a/usr/src/tools/scripts/xref.sh b/usr/src/tools/scripts/xref.sh index cad8be25e1..20ec192315 100644 --- a/usr/src/tools/scripts/xref.sh +++ b/usr/src/tools/scripts/xref.sh @@ -3,9 +3,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -21,7 +20,7 @@ # CDDL HEADER END # # -# Copyright 2002-2003 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -29,7 +28,10 @@ # xref: build and maintain source cross-reference databases. # -PATH=/usr/bin:/usr/ccs/bin:${BUILD_TOOLS:-/opt}/teamware/bin export PATH +ONBLDDIR=$(dirname $(whence $0)) + +PATH=/usr/bin:/usr/ccs/bin:${BUILD_TOOLS:-/opt}/teamware/bin:$ONBLDDIR +export PATH PROG=`basename $0` XREFMK=`dirname $0`/xref.mk XRMAKEFILE=Makefile export XRMAKEFILE @@ -87,28 +89,17 @@ timeinfo() info "$1 in ${min}m${sec}s" } -# -# If $CODEMGR_WS isn't set, then attempt to glean it from the workspace -# command before giving up. -# -if [ -z "$CODEMGR_WS" ]; then - if whence workspace > /dev/null; then - # - # Since ws(1) hasn't been run, set up SRC and MACH too. - # Note that other environment variables, such as - # ENVCPPFLAGS*, can also affect the resulting - # cross-reference, but we assume that if the developer - # really cared, he would've ws'd first. - # - CODEMGR_WS=`workspace name` export CODEMGR_WS - SRC=$CODEMGR_WS/usr/src export SRC - MACH=`uname -p` export MACH - else - fail "No active workspace; run \"ws <workspace_name>\"" - fi +which_scm | read SCM_MODE CODEMGR_WS || exit 1 + +if [[ $SCM_MODE == "unknown" ]];then + print -u2 "Unable to determine SCM type currently in use." + exit 1 fi -[ -d "$CODEMGR_WS" ] || fail "\$CODEMGR_WS ($CODEMGR_WS) is not a directory" +export CODEMGR_WS +SRC=$CODEMGR_WS/usr/src export SRC +MACH=`uname -p` export MACH + [ -f $XREFMK ] || fail "cannot locate xref.mk" clobber= |