summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Lowe <richlowe@richlowe.net>2018-01-26 19:14:28 +0000
committerRichard Lowe <richlowe@richlowe.net>2018-02-03 17:47:56 +0000
commit0f554fe53a6056402dbaf025d945afa8659af0c7 (patch)
tree13db20440711f948e8410777da5cf2ea4771744d
parenta96858a0ffbb0a37a4c126a6889a50342c8e0ac5 (diff)
downloadillumos-joyent-0f554fe53a6056402dbaf025d945afa8659af0c7.tar.gz
9001 cdm is useless, remove it
9002 webrev should know how to get the git user name Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com> Reviewed by: Joshua M. Clulow <josh@sysmgr.org> Approved by: Gordon Ross <gwr@nexenta.com>
-rw-r--r--usr/src/pkg/manifests/developer-build-onbld.mf19
-rw-r--r--usr/src/tools/Makefile1
-rw-r--r--usr/src/tools/README.tools19
-rw-r--r--usr/src/tools/onbld/Makefile1
-rw-r--r--usr/src/tools/onbld/Scm/Backup.py980
-rw-r--r--usr/src/tools/onbld/Scm/Makefile5
-rw-r--r--usr/src/tools/onbld/Scm/Version.py122
-rw-r--r--usr/src/tools/onbld/Scm/WorkSpace.py1076
-rw-r--r--usr/src/tools/onbld/hgext/Makefile58
-rw-r--r--usr/src/tools/onbld/hgext/__init__.py28
-rw-r--r--usr/src/tools/onbld/hgext/cdm.py1530
-rw-r--r--usr/src/tools/scripts/Makefile4
-rw-r--r--usr/src/tools/scripts/hg-active.py130
-rw-r--r--usr/src/tools/scripts/hgsetup.1onbld68
-rw-r--r--usr/src/tools/scripts/hgsetup.sh189
-rw-r--r--usr/src/tools/scripts/hgstyle24
-rw-r--r--usr/src/tools/scripts/webrev.1onbld10
-rw-r--r--usr/src/tools/scripts/webrev.sh294
18 files changed, 15 insertions, 4543 deletions
diff --git a/usr/src/pkg/manifests/developer-build-onbld.mf b/usr/src/pkg/manifests/developer-build-onbld.mf
index 6c3b0eddb1..fe07ff881c 100644
--- a/usr/src/pkg/manifests/developer-build-onbld.mf
+++ b/usr/src/pkg/manifests/developer-build-onbld.mf
@@ -55,7 +55,6 @@ dir path=opt/onbld/lib/python$(PYTHON_VERSION)
dir path=opt/onbld/lib/python$(PYTHON_VERSION)/onbld
dir path=opt/onbld/lib/python$(PYTHON_VERSION)/onbld/Checks
dir path=opt/onbld/lib/python$(PYTHON_VERSION)/onbld/Scm
-dir path=opt/onbld/lib/python$(PYTHON_VERSION)/onbld/hgext
dir path=opt/onbld/man
dir path=opt/onbld/man/man1onbld
dir path=opt/onbld/share
@@ -104,8 +103,6 @@ file path=opt/onbld/bin/flg.flp mode=0555
file path=opt/onbld/bin/genoffsets mode=0555
file path=opt/onbld/bin/git-pbchk mode=0555
file path=opt/onbld/bin/hdrchk mode=0555
-file path=opt/onbld/bin/hg-active mode=0555
-file path=opt/onbld/bin/hgsetup mode=0555
file path=opt/onbld/bin/interface_check mode=0555
file path=opt/onbld/bin/interface_cmp mode=0555
file path=opt/onbld/bin/jstyle mode=0555
@@ -130,7 +127,6 @@ file path=opt/onbld/env/illumos
file path=opt/onbld/etc/exception_lists/check_rtime
file path=opt/onbld/etc/exception_lists/interface_check
file path=opt/onbld/etc/exception_lists/interface_cmp
-file path=opt/onbld/etc/hgstyle
file path=opt/onbld/etc/its.conf
file path=opt/onbld/etc/its.reg
file path=opt/onbld/lib/$(ARCH)/64/libmakestate.so.1
@@ -193,28 +189,14 @@ file path=opt/onbld/lib/python$(PYTHON_VERSION)/onbld/Checks/__init__.py \
mode=0444
file path=opt/onbld/lib/python$(PYTHON_VERSION)/onbld/Checks/__init__.pyc \
mode=0444
-file path=opt/onbld/lib/python$(PYTHON_VERSION)/onbld/Scm/Backup.py mode=0444
-file path=opt/onbld/lib/python$(PYTHON_VERSION)/onbld/Scm/Backup.pyc mode=0444
file path=opt/onbld/lib/python$(PYTHON_VERSION)/onbld/Scm/Ignore.py mode=0444
file path=opt/onbld/lib/python$(PYTHON_VERSION)/onbld/Scm/Ignore.pyc mode=0444
-file path=opt/onbld/lib/python$(PYTHON_VERSION)/onbld/Scm/Version.py mode=0444
-file path=opt/onbld/lib/python$(PYTHON_VERSION)/onbld/Scm/Version.pyc \
- mode=0444
-file path=opt/onbld/lib/python$(PYTHON_VERSION)/onbld/Scm/WorkSpace.py \
- mode=0444
-file path=opt/onbld/lib/python$(PYTHON_VERSION)/onbld/Scm/WorkSpace.pyc \
- mode=0444
file path=opt/onbld/lib/python$(PYTHON_VERSION)/onbld/Scm/__init__.py \
mode=0444
file path=opt/onbld/lib/python$(PYTHON_VERSION)/onbld/Scm/__init__.pyc \
mode=0444
file path=opt/onbld/lib/python$(PYTHON_VERSION)/onbld/__init__.py mode=0444
file path=opt/onbld/lib/python$(PYTHON_VERSION)/onbld/__init__.pyc mode=0444
-file path=opt/onbld/lib/python$(PYTHON_VERSION)/onbld/hgext/__init__.py \
- mode=0444
-file path=opt/onbld/lib/python$(PYTHON_VERSION)/onbld/hgext/__init__.pyc \
- mode=0444
-file path=opt/onbld/lib/python$(PYTHON_VERSION)/onbld/hgext/cdm.py mode=0444
file path=opt/onbld/man/man1onbld/Install.1onbld
file path=opt/onbld/man/man1onbld/bldenv.1onbld
file path=opt/onbld/man/man1onbld/bringovercheck.1onbld
@@ -230,7 +212,6 @@ file path=opt/onbld/man/man1onbld/findunref.1onbld
file path=opt/onbld/man/man1onbld/flg.flp.1onbld
file path=opt/onbld/man/man1onbld/git-pbchk.1onbld
file path=opt/onbld/man/man1onbld/hdrchk.1onbld
-file path=opt/onbld/man/man1onbld/hgsetup.1onbld
file path=opt/onbld/man/man1onbld/interface_check.1onbld
file path=opt/onbld/man/man1onbld/interface_cmp.1onbld
file path=opt/onbld/man/man1onbld/jstyle.1onbld
diff --git a/usr/src/tools/Makefile b/usr/src/tools/Makefile
index 5bc163d15a..f2d7fcafb9 100644
--- a/usr/src/tools/Makefile
+++ b/usr/src/tools/Makefile
@@ -100,7 +100,6 @@ ROOTDIRS= \
$(ROOTONBLD)/lib/python$(PYTHON_VERSION) \
$(ROOTONBLD)/lib/python$(PYTHON_VERSION)/onbld \
$(ROOTONBLD)/lib/python$(PYTHON_VERSION)/onbld/Checks \
- $(ROOTONBLD)/lib/python$(PYTHON_VERSION)/onbld/hgext \
$(ROOTONBLD)/lib/python$(PYTHON_VERSION)/onbld/Scm \
$(ROOTONBLD)/env \
$(ROOTONBLD)/etc \
diff --git a/usr/src/tools/README.tools b/usr/src/tools/README.tools
index b910e73079..8612af43f7 100644
--- a/usr/src/tools/README.tools
+++ b/usr/src/tools/README.tools
@@ -49,15 +49,9 @@ Layout of /opt/onbld
/opt/onbld/lib/python<version>/
python modules used by the build tools.
-/opt/onbld/lib/python<version>/onbld/hgext
- Mercurial extensions.
-
/opt/onbld/lib/python/
symlink to the modules directory of the currently preferred
- python version. This exists to retain compatibility both for
- tools expecting only one supported version of python, and for
- user .hgrc files that expect to find cdm.py in
- /opt/onbld/lib/python/onbld/hgext.
+ python version.
/opt/onbld/man
rudimentary man pages for some of the tools.
@@ -79,10 +73,6 @@ 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
@@ -162,13 +152,6 @@ 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
diff --git a/usr/src/tools/onbld/Makefile b/usr/src/tools/onbld/Makefile
index 94ca2e97dd..8e5bb7d98f 100644
--- a/usr/src/tools/onbld/Makefile
+++ b/usr/src/tools/onbld/Makefile
@@ -28,7 +28,6 @@ include ../Makefile.tools
SUBDIRS= \
Checks \
- hgext \
Scm
PYSRCS = \
diff --git a/usr/src/tools/onbld/Scm/Backup.py b/usr/src/tools/onbld/Scm/Backup.py
deleted file mode 100644
index 6715243d95..0000000000
--- a/usr/src/tools/onbld/Scm/Backup.py
+++ /dev/null
@@ -1,980 +0,0 @@
-#
-# 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 2009 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-# Copyright 2008, 2011, Richard Lowe
-#
-
-
-'''
-Workspace backup
-
-Backup format is:
- backupdir/
- wsname/
- generation#/
- dirstate (handled by CdmUncommittedBackup)
- File containing dirstate nodeid (the changeset we need
- to update the workspace to after applying the bundle).
- This is the node to which the working copy changes
- (see 'diff', below) will be applied if applicable.
-
- 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)
-
- clear.tar.gz (handled by CdmClearBackup)
- <short node>/
- copies of each modified or added file, as it is in
- this head.
-
- ... for each outgoing head
-
- working/
- copies of each modified or added file in the
- working copy if any.
-
- latest -> generation#
- Newest backup generation.
-
-All files in a given backup generation, with the exception of
-dirstate, are optional.
-'''
-
-import grp, os, pwd, shutil, tarfile, time, traceback
-from cStringIO import StringIO
-
-from mercurial import changegroup, cmdutil, error, node, patch, util
-from onbld.Scm import Version
-
-
-class CdmNodeMissing(util.Abort):
- '''a required node is not present in the destination workspace.
-
- This may occur both in the case where the bundle contains a
- changeset which is a child of a node not present in the
- destination workspace (because the destination workspace is not as
- up-to-date as the source), or because the source and destination
- workspace are not related.
-
- It may also happen in cases where the uncommitted changes need to
- be applied onto a node that the workspace does not possess even
- after application of the bundle (on a branch not present
- in the bundle or destination workspace, for instance)'''
-
- def __init__(self, msg, name):
- #
- # If e.name is a string 20 characters long, it is
- # assumed to be a node. (Mercurial makes this
- # same assumption, when creating a LookupError)
- #
- if isinstance(name, str) and len(name) == 20:
- n = node.short(name)
- else:
- n = name
-
- util.Abort.__init__(self, "%s: changeset '%s' is missing\n"
- "Your workspace is either not "
- "sufficiently up to date,\n"
- "or is unrelated to the workspace from "
- "which the backup was taken.\n" % (msg, n))
-
-
-class CdmTarFile(tarfile.TarFile):
- '''Tar file access + simple comparison to the filesystem, and
- creation addition of files from Mercurial filectx objects.'''
-
- def __init__(self, *args, **kwargs):
- tarfile.TarFile.__init__(self, *args, **kwargs)
- self.errorlevel = 2
-
- def members_match_fs(self, rootpath):
- '''Compare the contents of the tar archive to the directory
- specified by rootpath. Return False if they differ.
-
- Every file in the archive must match the equivalent file in
- the filesystem.
-
- The existence, modification time, and size of each file are
- compared, content is not.'''
-
- def _member_matches_fs(member, rootpath):
- '''Compare a single member to its filesystem counterpart'''
- fpath = os.path.join(rootpath, member.name)
-
- if not os.path.exists(fpath):
- return False
- elif ((os.path.isfile(fpath) != member.isfile()) or
- (os.path.isdir(fpath) != member.isdir()) or
- (os.path.islink(fpath) != member.issym())):
- return False
-
- #
- # The filesystem may return a modification time with a
- # fractional component (as a float), whereas the tar format
- # only stores it to the whole second, perform the comparison
- # using integers (truncated, not rounded)
- #
- elif member.mtime != int(os.path.getmtime(fpath)):
- return False
- elif not member.isdir() and member.size != os.path.getsize(fpath):
- return False
- else:
- return True
-
- for elt in self:
- if not _member_matches_fs(elt, rootpath):
- return False
-
- return True
-
- def addfilectx(self, filectx, path=None):
- '''Add a filectx object to the archive.
-
- Use the path specified by the filectx object or, if specified,
- the PATH argument.
-
- The size, modification time, type and permissions of the tar
- member are taken from the filectx object, user and group id
- are those of the invoking user, user and group name are those
- of the invoking user if information is available, or "unknown"
- if it is not.
- '''
-
- t = tarfile.TarInfo(path or filectx.path())
- t.size = filectx.size()
- t.mtime = filectx.date()[0]
- t.uid = os.getuid()
- t.gid = os.getgid()
-
- try:
- t.uname = pwd.getpwuid(t.uid).pw_name
- except KeyError:
- t.uname = "unknown"
-
- try:
- t.gname = grp.getgrgid(t.gid).gr_name
- except KeyError:
- t.gname = "unknown"
-
- #
- # Mercurial versions symlinks by setting a flag and storing
- # the destination path in place of the file content. The
- # actual contents (in the tar), should be empty.
- #
- if 'l' in filectx.flags():
- t.type = tarfile.SYMTYPE
- t.mode = 0777
- t.linkname = filectx.data()
- data = None
- else:
- t.type = tarfile.REGTYPE
- t.mode = 'x' in filectx.flags() and 0755 or 0644
- data = StringIO(filectx.data())
-
- self.addfile(t, data)
-
-
-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 not outnodes:
- return
-
- fp = None
- try:
- try:
- fp = self.bu.open('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'''
-
- if not self.bu.exists('bundle'):
- return
-
- bpath = self.bu.backupfile('bundle')
- f = None
- try:
- try:
- f = self.bu.open('bundle')
- bundle = changegroup.readbundle(f, bpath)
- self.ws.repo.addchangegroup(bundle, 'strip',
- 'bundle:%s' % bpath)
- except EnvironmentError, e:
- raise util.Abort("couldn't restore committed changes: %s\n"
- " %s" % (bpath, e))
- except error.LookupError, e:
- raise CdmNodeMissing("couldn't restore committed changes",
- e.name)
- finally:
- if f and not f.closed:
- f.close()
-
- def need_backup(self):
- '''Compare backup of committed changes to workspace'''
-
- if self.bu.exists('nodes'):
- f = None
- try:
- try:
- f = self.bu.open('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 there are outgoing nodes not in the prior backup we need
- # to take a new backup; it's fine if there are nodes in the
- # old backup which are no longer outgoing, however.
- #
- if not outnodes <= bnodes:
- return True
-
- return False
-
- def cleanup(self):
- '''Remove backed up committed changes'''
-
- for f in self.files:
- self.bu.unlink(f)
-
-
-class CdmUncommittedBackup(object):
- '''Backup of uncommitted changes'''
-
- def __init__(self, backup, ws):
- self.ws = ws
- self.bu = backup
- self.wctx = self.ws.workingctx(worklist=True)
-
- def _clobbering_renames(self):
- '''Return a list of pairs of files representing renames/copies
- that clobber already versioned files. [(old-name new-name)...]
- '''
-
- #
- # Note that this doesn't handle uncommitted merges
- # as CdmUncommittedBackup itself doesn't.
- #
- parent = self.wctx.parents()[0]
-
- ret = []
- for fname in self.wctx.added() + self.wctx.modified():
- rn = self.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.wctx.parents()[0].node())
-
- fp = None
- try:
- try:
- fp = self.bu.open('dirstate', 'w')
- fp.write(dirstate + '\n')
- fp.close()
- except EnvironmentError, e:
- raise util.Abort("couldn't save working copy parent: %s" % e)
-
- try:
- fp = self.bu.open('renames', 'w')
- for cons in self._clobbering_renames():
- fp.write("%s %s\n" % cons)
- fp.close()
- except EnvironmentError, e:
- raise util.Abort("couldn't save clobbering copies: %s" % e)
-
- try:
- fp = self.bu.open('diff', 'w')
- match = self.ws.matcher(files=self.wctx.files())
- fp.write(self.ws.diff(opts={'git': True}, match=match))
- 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 desired working copy node from the backup'''
- fp = None
- try:
- try:
- fp = self.bu.open('dirstate')
- dirstate = fp.readline().strip()
- except EnvironmentError, e:
- raise util.Abort("couldn't read saved parent: %s" % e)
- finally:
- if fp and not fp.closed:
- fp.close()
-
- return dirstate
-
- def restore(self):
- '''Restore uncommitted changes'''
- dirstate = self._dirstate()
-
- #
- # Check that the patch's parent changeset exists.
- #
- try:
- n = node.bin(dirstate)
- self.ws.repo.changelog.lookup(n)
- except error.LookupError, e:
- raise CdmNodeMissing("couldn't restore uncommitted changes",
- e.name)
-
- try:
- self.ws.clean(rev=dirstate)
- except util.Abort, e:
- raise util.Abort("couldn't update to saved node: %s" % e)
-
- if not self.bu.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 modification time 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:
- diff = self.bu.backupfile('diff')
- 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:
- if Version.at_least("1.7"):
- cmdutil.updatedir(self.ws.ui, self.ws.repo, files)
- else:
- patch.updatedir(self.ws.ui, self.ws.repo, files)
-
- if not self.bu.exists('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 = self.bu.open('renames')
- for line in fp:
- source, dest = line.strip().split()
- self.ws.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'''
- cnode = self.wctx.parents()[0].node()
- if self._dirstate() != node.hex(cnode):
- return True
-
- fd = None
- match = self.ws.matcher(files=self.wctx.files())
- curdiff = self.ws.diff(opts={'git': True}, match=match)
-
- try:
- if self.bu.exists('diff'):
- try:
- fd = self.bu.open('diff')
- backdiff = fd.read()
- fd.close()
- except EnvironmentError, e:
- raise util.Abort("couldn't open backup diff %s\n"
- " %s" % (self.bu.backupfile('diff'), e))
- else:
- backdiff = ''
-
- if backdiff != curdiff:
- return True
-
- currrenamed = self._clobbering_renames()
- bakrenamed = None
-
- if self.bu.exists('renames'):
- try:
- fd = self.bu.open('renames')
- bakrenamed = [tuple(line.strip().split(' ')) for line in fd]
- fd.close()
- except EnvironmentError, e:
- raise util.Abort("couldn't open renames file %s: %s\n" %
- (self.bu.backupfile('renames'), e))
-
- if currrenamed != bakrenamed:
- return True
- finally:
- if fd and not fd.closed:
- fd.close()
-
- return False
-
- def cleanup(self):
- '''Remove backed up uncommitted changes'''
-
- for f in ('dirstate', 'diff', 'renames'):
- self.bu.unlink(f)
-
-
-class CdmMetadataBackup(object):
- '''Backup of workspace metadata'''
-
- def __init__(self, backup, ws):
- self.bu = backup
- self.ws = ws
- self.files = ('hgrc', 'localtags', 'patches', 'cdm')
-
- def backup(self):
- '''Backup workspace metadata'''
-
- tarpath = self.bu.backupfile('metadata.tar.gz')
-
- #
- # Files is a list of tuples (name, path), where name is as in
- # self.files, and path is the absolute path.
- #
- files = filter(lambda (name, path): os.path.exists(path),
- zip(self.files, map(self.ws.repo.join, self.files)))
-
- if not files:
- return
-
- try:
- tar = CdmTarFile.gzopen(tarpath, 'w')
- except (EnvironmentError, tarfile.TarError), e:
- raise util.Abort("couldn't open %s for writing: %s" %
- (tarpath, e))
-
- try:
- for name, path in files:
- try:
- tar.add(path, name)
- 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):
- errstr = "%s: %s" % (name, e)
- else:
- errstr = str(e)
-
- raise util.Abort("couldn't backup metadata to %s:\n"
- " %s" % (tarpath, errstr))
- finally:
- tar.close()
-
- def old_restore(self):
- '''Restore workspace metadata from an pre-tar backup'''
-
- for fname in self.files:
- if self.bu.exists(fname):
- bfile = self.bu.backupfile(fname)
- wfile = self.ws.repo.join(fname)
-
- 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 not self.bu.exists('metadata.tar.gz'):
- return
-
- tarpath = self.bu.backupfile('metadata.tar.gz')
-
- try:
- tar = CdmTarFile.gzopen(tarpath)
- except (EnvironmentError, tarfile.TarError), e:
- raise util.Abort("couldn't open %s: %s" % (tarpath, e))
-
- try:
- for elt in tar:
- try:
- 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):
- errstr = "%s: %s" % (elt.name, e)
- else:
- errstr = str(e)
-
- raise util.Abort("couldn't restore metadata from %s:\n"
- " %s" %
- (tarpath, errstr))
- finally:
- if tar and not tar.closed:
- tar.close()
-
- def restore(self):
- '''Restore workspace metadata'''
-
- if self.bu.exists('hgrc'):
- self.old_restore()
- else:
- self.tar_restore()
-
- def _walk(self):
- '''Yield the repo-relative path to each file we operate on,
- including each file within any affected directory'''
-
- for elt in self.files:
- path = self.ws.repo.join(elt)
-
- if not os.path.exists(path):
- continue
-
- if os.path.isdir(path):
- for root, dirs, files in os.walk(path, topdown=True):
- yield root
-
- for f in files:
- yield os.path.join(root, f)
- else:
- yield path
-
- def need_backup(self):
- '''Compare backed up workspace metadata to workspace'''
-
- def strip_trailing_pathsep(pathname):
- '''Remove a possible trailing path separator from PATHNAME'''
- return pathname.endswith('/') and pathname[:-1] or pathname
-
- if self.bu.exists('metadata.tar.gz'):
- tarpath = self.bu.backupfile('metadata.tar.gz')
- try:
- tar = CdmTarFile.gzopen(tarpath)
- except (EnvironmentError, tarfile.TarError), e:
- raise util.Abort("couldn't open metadata tarball: %s\n"
- " %s" % (tarpath, e))
-
- if not tar.members_match_fs(self.ws.repo.path):
- tar.close()
- return True
-
- tarnames = map(strip_trailing_pathsep, tar.getnames())
- tar.close()
- else:
- tarnames = []
-
- repopath = self.ws.repo.path
- if not repopath.endswith('/'):
- repopath += '/'
-
- for path in self._walk():
- if path.replace(repopath, '', 1) not in tarnames:
- return True
-
- return False
-
- def cleanup(self):
- '''Remove backed up workspace metadata'''
- self.bu.unlink('metadata.tar.gz')
-
-
-class CdmClearBackup(object):
- '''A backup (in tar format) of complete source files from every
- workspace head.
-
- Paths in the tarball are prefixed by the revision and node of the
- head, or "working" for the working directory.
-
- This is done purely for the benefit of the user, and as such takes
- no part in restore or need_backup checking, restore always
- succeeds, need_backup always returns False
- '''
-
- def __init__(self, backup, ws):
- self.bu = backup
- self.ws = ws
-
- def _branch_pairs(self):
- '''Return a list of tuples (parenttip, localtip) for each
- outgoing head. If the working copy contains modified files,
- it is a head, and neither of its parents are.
- '''
-
- parent = self.ws.parent()
-
- if parent:
- outgoing = self.ws.findoutgoing(parent)
- outnodes = set(self.ws.repo.changelog.nodesbetween(outgoing)[0])
-
- heads = [self.ws.repo.changectx(n) for n in self.ws.repo.heads()
- if n in outnodes]
- else:
- heads = []
- outnodes = []
-
- wctx = self.ws.workingctx()
- if wctx.files(): # We only care about file changes.
- heads = filter(lambda x: x not in wctx.parents(), heads) + [wctx]
-
- pairs = []
- for head in heads:
- if head.rev() is None:
- c = head.parents()
- else:
- c = [head]
-
- pairs.append((self.ws.parenttip(c, outnodes), head))
- return pairs
-
- def backup(self):
- '''Save a clear copy of each source file modified between each
- head and that head's parenttip (see WorkSpace.parenttip).
- '''
-
- tarpath = self.bu.backupfile('clear.tar.gz')
- branches = self._branch_pairs()
-
- if not branches:
- return
-
- try:
- tar = CdmTarFile.gzopen(tarpath, 'w')
- except (EnvironmentError, tarfile.TarError), e:
- raise util.Abort("Could not open %s for writing: %s" %
- (tarpath, e))
-
- try:
- for parent, child in branches:
- tpath = child.node() and node.short(child.node()) or "working"
-
- for fname, change in self.ws.status(parent, child).iteritems():
- if change not in ('added', 'modified'):
- continue
-
- try:
- tar.addfilectx(child.filectx(fname),
- os.path.join(tpath, fname))
- except ValueError, e:
- crev = child.rev()
- if crev is None:
- crev = "working copy"
- raise util.Abort("Could not backup clear file %s "
- "from %s: %s\n" % (fname, crev, e))
- finally:
- tar.close()
-
- def cleanup(self):
- '''Cleanup a failed Clear backup.
-
- Remove the clear tarball from the backup directory.
- '''
-
- self.bu.unlink('clear.tar.gz')
-
- def restore(self):
- '''Clear backups are never restored, do nothing'''
- pass
-
- def need_backup(self):
- '''Clear backups are never compared, return False (no backup needed).
-
- Should a backup actually be needed, one of the other
- implementation classes would notice in any situation we would.
- '''
-
- return False
-
-
-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,
- CdmClearBackup,
- 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'''
-
- 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 _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 backupfile(self, path):
- '''return full path to backup file FILE at GEN'''
- return os.path.join(self.backupdir, str(self.generation), path)
-
- def unlink(self, name):
- '''Unlink the specified path from the backup directory.
- A no-op if the path does not exist.
- '''
-
- fpath = self.backupfile(name)
- if os.path.exists(fpath):
- os.unlink(fpath)
-
- def open(self, name, mode='r'):
- '''Open the specified file in the backup directory'''
- return open(self.backupfile(name), mode)
-
- def exists(self, name):
- '''Return boolean indicating wether a given file exists in the
- backup directory.'''
- return os.path.exists(self.backupfile(name))
-
- 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 self.exists('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
-
- Calling code is expected to hold both the working copy lock
- and repository lock.'''
-
- 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)
-
- 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)
- show_traceback = self.ws.ui.configbool('ui', 'traceback',
- False)
-
- #
- # 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 show_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.
-
- Calling code is expected to hold both the working copy lock
- and repository lock of the destination workspace.'''
-
- 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 self.exists('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 may be partially restored' % e)
diff --git a/usr/src/tools/onbld/Scm/Makefile b/usr/src/tools/onbld/Scm/Makefile
index a71883c297..c3fbca605f 100644
--- a/usr/src/tools/onbld/Scm/Makefile
+++ b/usr/src/tools/onbld/Scm/Makefile
@@ -29,10 +29,7 @@ include ../../Makefile.tools
PYSRCS = \
__init__.py \
- Backup.py \
- Ignore.py \
- Version.py \
- WorkSpace.py
+ Ignore.py
PYOBJS = $(PYSRCS:%.py=%.pyc)
PYTOPDIR = $(ROOTONBLDLIB)
diff --git a/usr/src/tools/onbld/Scm/Version.py b/usr/src/tools/onbld/Scm/Version.py
deleted file mode 100644
index 017ef3e514..0000000000
--- a/usr/src/tools/onbld/Scm/Version.py
+++ /dev/null
@@ -1,122 +0,0 @@
-#
-# 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 2009 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-# Copyright 2008, 2011, Richard Lowe
-#
-
-'''
-Deal with Mercurial versioning.
-
-At a basic level, code to verify that the version of Mercurial in use
-is suitable for use with Cadmium, and compare that version for the
-sake of adapting to Mercurial API changes.
-'''
-
-#
-# It is important that this module rely on as little of Mercurial as
-# is possible.
-#
-
-#
-# Mercurial >= 1.2 has util.version(), prior versions
-# version.get_version() We discover which to use this way, rather than
-# via ImportError to account for mercurial.demandimport delaying the
-# ImportError exception.
-#
-# This code needs to remain, even though versions prior to 1.2 aren't
-# supported, to allow us to produce the error message which states that they
-# are not supported.
-#
-from mercurial import util
-if hasattr(util, 'version'):
- hg_version = util.version
-else:
- from mercurial import version
- hg_version = version.get_version
-
-
-class VersionMismatch(Exception):
- "Exception used to indicate a mismatch between SCM tools and Mercurial"
- pass
-
-#
-# List of versions that are explicitly acceptable to us
-#
-GOOD_VERSIONS = ['1.3.1', '1.4.2', '1.5.4', '1.6.2', '1.6.3', '1.7.5',
- '1.8', '1.8.1']
-
-
-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 hg_version() not in GOOD_VERSIONS:
- raise VersionMismatch("Scm expects Mercurial version %s, "
- "actual version is %s." %
- (versionstring(GOOD_VERSIONS),
- hg_version()))
-
-
-def _split_version(ver):
- '''Return the Mercurial version as a list [MAJOR, MINOR, MICRO],
- if this is not a released Mercurial return None.'''
-
- try:
- l = map(int, ver.split('.'))
- # If there's only one element, it's not really a tagged version
- if len(l) <= 1:
- return None
- else:
- return l
- except ValueError:
- return None
-
-
-def at_least(desired):
- '''Return boolean indicating if the running version is greater
- than or equal to, the version specified by major, minor, micro'''
-
- hgver = _split_version(hg_version())
- desired = map(int, desired.split('.'))
-
- #
- # If _split_version() returns None, we're running on a Mercurial that
- # has not been tagged as a release. We assume this to be newer
- # than any released version.
- #
- if hgver == None:
- return True
-
- # Pad our versions to the same overall length, appending 0's
- while len(hgver) < len(desired):
- hgver.append(0)
- while len(desired) < len(hgver):
- desired.append(0)
-
- for real, req in zip(hgver, desired):
- if real != req:
- return real > req
-
- return True
diff --git a/usr/src/tools/onbld/Scm/WorkSpace.py b/usr/src/tools/onbld/Scm/WorkSpace.py
deleted file mode 100644
index 3abd4d8149..0000000000
--- a/usr/src/tools/onbld/Scm/WorkSpace.py
+++ /dev/null
@@ -1,1076 +0,0 @@
-#
-# 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 (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
-# Copyright 2008, 2011, Richard Lowe
-#
-
-#
-# 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 of ActiveEntry objects, 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 cmdutil, context, error, hg, node, patch, repair, util
-from hgext import mq
-
-from onbld.Scm import Version
-
-
-#
-# Mercurial 1.6 moves findoutgoing into a discover module
-#
-if Version.at_least("1.6"):
- from mercurial import discovery
-
-
-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 = intern('modified')
- ADDED = intern('added')
- REMOVED = intern('removed')
-
- def __init__(self, name, change):
- self.name = name
- self.change = intern(change)
-
- assert change in (self.MODIFIED, self.ADDED, self.REMOVED)
-
- self.parentname = None
- # As opposed to copied (or neither)
- self.renamed = False
- self.comments = []
-
- def __cmp__(self, other):
- return cmp(self.name, other.name)
-
- def is_added(self):
- '''Return True if this ActiveEntry represents an added file'''
- return self.change is self.ADDED
-
- def is_modified(self):
- '''Return True if this ActiveEntry represents a modified file'''
- return self.change is self.MODIFIED
-
- def is_removed(self):
- '''Return True if this ActiveEntry represents a removed file'''
- return self.change is self.REMOVED
-
- def is_renamed(self):
- '''Return True if this ActiveEntry represents a renamed file'''
- return self.parentname and self.renamed
-
- def is_copied(self):
- '''Return True if this ActiveEntry represents a copied file'''
- return self.parentname and not self.renamed
-
-
-class ActiveList(object):
- '''Complete representation of change between two changesets.
-
- In practice, a container for ActiveEntry objects, and methods to
- create them, and deal with them as a group.'''
-
- def __init__(self, ws, parenttip, revs=None):
- '''Initialize the ActiveList
-
- parenttip is the revision with which to compare (likely to be
- from the parent), revs is a topologically sorted list of
- revisions ending with the revision to compare with (likely to
- be the child-local revisions).'''
-
- assert parenttip is not None
-
- self.ws = ws
- self.revs = revs
- self.parenttip = parenttip
- self.localtip = None
-
- self._active = {}
- self._comments = []
-
- if revs:
- self.localtip = revs[-1]
- self._build()
-
- def _status(self):
- '''Return the status of any file mentioned in any of the
- changesets making up this active list.'''
-
- files = set()
- for c in self.revs:
- files.update(c.files())
-
- #
- # Any file not in the parenttip or the localtip is ephemeral
- # and can be ignored. Mercurial will complain regarding these
- # files if the localtip is a workingctx, so remove them in
- # that case.
- #
- # Compare against the dirstate because a workingctx manifest
- # is created on-demand and is particularly expensive.
- #
- if self.localtip.rev() is None:
- for f in files.copy():
- if f not in self.parenttip and f not in self.ws.repo.dirstate:
- files.remove(f)
-
- return self.ws.status(self.parenttip, self.localtip, files=files)
-
- def _build(self):
- '''Construct ActiveEntry objects for each changed file.
-
- This works in 3 stages:
-
- - Create entries for every changed file with
- semi-appropriate change type
-
- - Track renames/copies, and set change comments (both
- ActiveList-wide, and per-file).
-
- - Cleanup
- - Drop circular renames
- - Drop the removal of the old name of any rename
- - Drop entries for modified files that haven't actually changed'''
-
- #
- # Keep a cache of filectx objects (keyed on pathname) so that
- # we can avoid opening filelogs numerous times.
- #
- fctxcache = {}
-
- def oldname(ctx, fname):
- '''Return the name 'fname' held prior to any possible
- rename/copy in the given changeset.'''
- try:
- if fname in fctxcache:
- octx = fctxcache[fname]
- fctx = ctx.filectx(fname, filelog=octx.filelog())
- else:
- fctx = ctx.filectx(fname)
- #
- # workingfilectx objects may not refer to the
- # right filelog (in case of rename). Don't cache
- # them.
- #
- if not isinstance(fctx, context.workingfilectx):
- fctxcache[fname] = fctx
- except error.LookupError:
- return None
-
- rn = fctx.renamed()
- return rn and rn[0] or fname
-
- status = self._status()
- self._active = dict((fname, ActiveEntry(fname, kind))
- for fname, kind in status.iteritems()
- if kind in ('modified', 'added', 'removed'))
-
- #
- # We do two things:
- # - Gather checkin comments (for the entire ActiveList, and
- # per-file)
- # - Set the .parentname of any copied/renamed file
- #
- # renames/copies:
- # We walk the list of revisions backward such that only files
- # that ultimately remain active need be considered.
- #
- # At each iteration (revision) we update the .parentname of
- # any active file renamed or copied in that revision (the
- # current .parentname if set, or .name otherwise, reflects
- # the name of a given active file in the revision currently
- # being looked at)
- #
- for ctx in reversed(self.revs):
- desc = ctx.description().splitlines()
- self._comments = desc + self._comments
- cfiles = set(ctx.files())
-
- for entry in self:
- fname = entry.parentname or entry.name
- if fname not in cfiles:
- continue
-
- entry.comments = desc + entry.comments
-
- #
- # We don't care about the name history of any file
- # that ends up being removed, since that trumps any
- # possible renames or copies along the way.
- #
- # Changes that we may care about involving an
- # intermediate name of a removed file will appear
- # separately (related to the eventual name along
- # that line)
- #
- if not entry.is_removed():
- entry.parentname = oldname(ctx, fname)
-
- for entry in self._active.values():
- #
- # For any file marked as copied or renamed, clear the
- # .parentname if the copy or rename is cyclic (source ==
- # destination) or if the .parentname did not exist in the
- # parenttip.
- #
- # If the parentname is marked as removed, set the renamed
- # flag and remove any ActiveEntry we may have for the
- # .parentname.
- #
- if entry.parentname:
- if (entry.parentname == entry.name or
- entry.parentname not in self.parenttip):
- entry.parentname = None
- elif status.get(entry.parentname) == 'removed':
- entry.renamed = True
-
- if entry.parentname in self:
- del self[entry.parentname]
-
- #
- # There are cases during a merge where a file will be seen
- # as modified by status but in reality be an addition (not
- # in the parenttip), so we have to check whether the file
- # is in the parenttip and set it as an addition, if not.
- #
- # If a file is modified (and not a copy or rename), we do
- # a full comparison to the copy in the parenttip and
- # ignore files that are parts of active revisions but
- # unchanged.
- #
- if entry.name not in self.parenttip:
- entry.change = ActiveEntry.ADDED
- elif entry.is_modified():
- if not self._changed_file(entry.name):
- del self[entry.name]
-
- 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):
- return self._active.itervalues()
-
- def files(self):
- '''Return the list of pathnames of all files touched by this
- ActiveList
-
- Where files have been renamed, this will include both their
- current name and the name which they had in the parent tip.
- '''
-
- ret = self._active.keys()
- ret.extend(x.parentname for x in self if x.is_renamed())
- return set(ret)
-
- def comments(self):
- '''Return the full set of changeset comments associated with
- this ActiveList'''
-
- return self._comments
-
- def bases(self):
- '''Return the list of changesets that are roots of the ActiveList.
-
- This is the set of active changesets where neither parent
- changeset is itself active.'''
-
- revset = set(self.revs)
- return filter(lambda ctx: not [p for p in ctx.parents() if p in revset],
- self.revs)
-
- 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.'''
-
- def colliding_tags(iterable, nodes, local):
- for nd, name in [line.rstrip().split(' ', 1) for line in iterable]:
- if nd in nodes:
- yield (name, self.ws.repo.lookup(nd), local)
-
- tags = []
- nodes = set(node.hex(ctx.node()) for ctx in self.revs)
-
- if os.path.exists(self.ws.repo.join('localtags')):
- fh = self.ws.repo.opener('localtags')
- tags.extend(colliding_tags(fh, nodes, True))
- fh.close()
-
- # We want to use the tags file from the localtip
- if '.hgtags' in self.localtip:
- data = self.localtip.filectx('.hgtags').data().splitlines()
- tags.extend(colliding_tags(data, nodes, False))
-
- return tags
-
- def prune_tags(self, data):
- '''Return a copy of data, which should correspond to the
- contents of a Mercurial tags file, with any tags that refer to
- changesets which are components of the ActiveList removed.'''
-
- nodes = set(node.hex(ctx.node()) for ctx in self.revs)
- return [t for t in data if t.split(' ', 1)[0] not in nodes]
-
- def _changed_file(self, path):
- '''Compare the parent and local versions of a given file.
- Return True if file changed, False otherwise.
-
- Note that this compares the given path in both versions, not the given
- entry; renamed and copied files are compared by name, not history.
-
- The fast path compares file metadata, slow path is a
- real comparison of file content.'''
-
- if ((path in self.parenttip) != (path in self.localtip)):
- return True
-
- parentfile = self.parenttip.filectx(path)
- localfile = self.localtip.filectx(path)
-
- #
- # 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.flags() != localfile.flags():
- return True
-
- if Version.at_least("1.7"):
- if parentfile.cmp(localfile):
- return True
- else:
- if parentfile.cmp(localfile.data()):
- return True
-
- def context(self, message, user):
- '''Return a Mercurial context object representing the entire
- ActiveList as one change.'''
- return activectx(self, message, user)
-
- def as_text(self, paths):
- '''Return the ActiveList as a block of text in a format
- intended to aid debugging and simplify the test suite.
-
- paths should be a list of paths for which file-level data
- should be included. If it is empty, the whole active list is
- included.'''
-
- cstr = cStringIO.StringIO()
-
- cstr.write('parent tip: %s:%s\n' % (self.parenttip.rev(),
- self.parenttip))
- if self.localtip:
- rev = self.localtip.rev()
- cstr.write('local tip: %s:%s\n' %
- (rev is None and "working" or rev, self.localtip))
- else:
- cstr.write('local tip: None\n')
-
- cstr.write('entries:\n')
- for entry in self:
- if paths and self.ws.filepath(entry.name) not in paths:
- continue
-
- cstr.write(' - %s\n' % entry.name)
- cstr.write(' parentname: %s\n' % entry.parentname)
- cstr.write(' change: %s\n' % entry.change)
- cstr.write(' renamed: %s\n' % entry.renamed)
- cstr.write(' comments:\n')
- cstr.write(' ' + '\n '.join(entry.comments) + '\n')
- cstr.write('\n')
-
- return cstr.getvalue()
-
-
-class WorkList(object):
- '''A (user-maintained) list of files changed in this workspace as
- compared to any parent workspace.
-
- Internally, the WorkList is stored in .hg/cdm/worklist as a list
- of file pathnames, one per-line.
-
- This may only safely be used as a hint regarding possible
- modifications to the working copy, it should not be relied upon to
- suggest anything about committed changes.'''
-
- def __init__(self, ws):
- '''Load the WorkList for the specified WorkSpace from disk.'''
-
- self._ws = ws
- self._repo = ws.repo
- self._file = os.path.join('cdm', 'worklist')
- self._files = set()
- self._valid = False
-
- if os.path.exists(self._repo.join(self._file)):
- self.load()
-
- def __nonzero__(self):
- '''A WorkList object is true if it was loaded from disk,
- rather than freshly created.
- '''
-
- return self._valid
-
- def list(self):
- '''List of pathnames contained in the WorkList
- '''
-
- return list(self._files)
-
- def status(self):
- '''Return the status (in tuple form) of files from the
- WorkList as they are in the working copy
- '''
-
- match = self._ws.matcher(files=self.list())
- return self._repo.status(match=match)
-
- def add(self, fname):
- '''Add FNAME to the WorkList.
- '''
-
- self._files.add(fname)
-
- def write(self):
- '''Write the WorkList out to disk.
- '''
-
- dirn = os.path.split(self._file)[0]
-
- if dirn and not os.path.exists(self._repo.join(dirn)):
- try:
- os.makedirs(self._repo.join(dirn))
- except EnvironmentError, e:
- raise util.Abort("Couldn't create directory %s: %s" %
- (self._repo.join(dirn), e))
-
- fh = self._repo.opener(self._file, 'w', atomictemp=True)
-
- for name in self._files:
- fh.write("%s\n" % name)
-
- fh.rename()
- fh.close()
-
- def load(self):
- '''Read in the WorkList from disk.
- '''
-
- fh = self._repo.opener(self._file, 'r')
- self._files = set(l.rstrip('\n') for l in fh)
- self._valid = True
- fh.close()
-
- def delete(self):
- '''Empty the WorkList
-
- Remove the on-disk WorkList and clear the file-list of the
- in-memory copy
- '''
-
- if os.path.exists(self._repo.join(self._file)):
- os.unlink(self._repo.join(self._file))
-
- self._files = set()
- self._valid = False
-
-
-class activectx(context.memctx):
- '''Represent an ActiveList as a Mercurial context object.
-
- Part of the WorkSpace.squishdeltas implementation.'''
-
- def __init__(self, active, message, user):
- '''Build an activectx object.
-
- active - The ActiveList object used as the source for all data.
- message - Changeset description
- user - Committing user'''
-
- def filectxfn(repository, ctx, fname):
- fctx = active.localtip.filectx(fname)
- data = fctx.data()
-
- #
- # .hgtags is a special case, tags referring to active list
- # component changesets should be elided.
- #
- if fname == '.hgtags':
- data = '\n'.join(active.prune_tags(data.splitlines()))
-
- return context.memfilectx(fname, data, 'l' in fctx.flags(),
- 'x' in fctx.flags(),
- active[fname].parentname)
-
- self.__active = active
- parents = (active.parenttip.node(), node.nullid)
- extra = {'branch': active.localtip.branch()}
- context.memctx.__init__(self, active.ws.repo, parents, message,
- active.files(), filectxfn, user=user,
- extra=extra)
-
- def modified(self):
- return [entry.name for entry in self.__active if entry.is_modified()]
-
- def added(self):
- return [entry.name for entry in self.__active if entry.is_added()]
-
- def removed(self):
- ret = set(entry.name for entry in self.__active if entry.is_removed())
- ret.update(set(x.parentname for x in self.__active if x.is_renamed()))
- return list(ret)
-
- def files(self):
- return self.__active.files()
-
-
-class WorkSpace(object):
-
- def __init__(self, repository):
- self.repo = repository
- self.ui = self.repo.ui
- self.name = self.repo.root
-
- self.activecache = {}
-
- def parent(self, spec=None):
- '''Return the canonical workspace parent, either SPEC (which
- will be expanded) if provided or the default parent
- otherwise.'''
-
- if spec:
- return self.ui.expandpath(spec)
-
- p = self.ui.expandpath('default')
- if p == 'default':
- return None
- else:
- return p
-
- def _localtip(self, outgoing, wctx):
- '''Return the most representative changeset to act as the
- localtip.
-
- If the working directory is modified (has file changes, is a
- merge, or has switched branches), this will be a workingctx.
-
- If the working directory is unmodified, this will be the most
- recent (highest revision number) local (outgoing) head on the
- current branch, if no heads are determined to be outgoing, it
- will be the most recent head on the current branch.
- '''
-
- if (wctx.files() or len(wctx.parents()) > 1 or
- wctx.branch() != wctx.parents()[0].branch()):
- return wctx
-
- heads = self.repo.heads(start=wctx.parents()[0].node())
- headctxs = [self.repo.changectx(n) for n in heads]
- localctxs = [c for c in headctxs if c.node() in outgoing]
-
- ltip = sorted(localctxs or headctxs, key=lambda x: x.rev())[-1]
-
- if len(heads) > 1:
- self.ui.warn('The current branch has more than one head, '
- 'using %s\n' % ltip.rev())
-
- return ltip
-
- def parenttip(self, heads, outgoing):
- '''Return the highest-numbered, non-outgoing changeset that is
- an ancestor of a changeset in heads.
-
- This returns the most recent changeset on a given branch that
- is shared between a parent and child workspace, in effect the
- common ancestor of the chosen local tip and the parent
- workspace.
- '''
-
- def tipmost_shared(head, outnodes):
- '''Return the changeset on the same branch as head that is
- not in outnodes and is closest to the tip.
-
- Walk outgoing changesets from head to the bottom of the
- workspace (revision 0) and return the the first changeset
- we see that is not in outnodes.
-
- If none is found (all revisions >= 0 are outgoing), the
- only possible parenttip is the null node (node.nullid)
- which is returned explicitly.
- '''
- for ctx in self._walkctxs(head, self.repo.changectx(0),
- follow=True,
- pick=lambda c: c.node() not in outnodes):
- return ctx
-
- return self.repo.changectx(node.nullid)
-
- nodes = set(outgoing)
- ptips = map(lambda x: tipmost_shared(x, nodes), heads)
- return sorted(ptips, key=lambda x: x.rev(), reverse=True)[0]
-
- def status(self, base='.', head=None, files=None):
- '''Translate from the hg 6-tuple status format to a hash keyed
- on change-type'''
-
- states = ['modified', 'added', 'removed', 'deleted', 'unknown',
- 'ignored']
-
- match = self.matcher(files=files)
- chngs = self.repo.status(base, head, match=match)
-
- ret = {}
- for paths, change in zip(chngs, states):
- ret.update((f, change) for f in paths)
- return ret
-
- def findoutgoing(self, parent):
- '''Return the base set of outgoing nodes.
-
- A caching wrapper around mercurial.localrepo.findoutgoing().
- Complains (to the user), if the parent workspace is
- non-existent or inaccessible'''
-
- self.ui.pushbuffer()
- try:
- try:
- ui = self.ui
- if hasattr(cmdutil, 'remoteui'):
- ui = cmdutil.remoteui(ui, {})
- pws = hg.repository(ui, parent)
- if Version.at_least("1.6"):
- return discovery.findoutgoing(self.repo, pws)
- else:
- return self.repo.findoutgoing(pws)
- except error.RepoError:
- self.ui.warn("Warning: Parent workspace '%s' is not "
- "accessible\n"
- "active list will be incomplete\n\n" % parent)
- return []
- finally:
- self.ui.popbuffer()
- findoutgoing = util.cachefunc(findoutgoing)
-
- def modified(self):
- '''Return a list of files modified in the workspace'''
-
- wctx = self.workingctx()
- return sorted(wctx.files() + wctx.deleted()) or None
-
- def merged(self):
- '''Return boolean indicating whether the workspace has an uncommitted
- merge'''
-
- wctx = self.workingctx()
- return len(wctx.parents()) > 1
-
- def branched(self):
- '''Return boolean indicating whether the workspace has an
- uncommitted named branch'''
-
- wctx = self.workingctx()
- return wctx.branch() != wctx.parents()[0].branch()
-
- def active(self, parent=None, thorough=False):
- '''Return an ActiveList describing changes between workspace
- and parent workspace (including uncommitted changes).
- If the workspace has no parent, ActiveList will still describe any
- uncommitted changes.
-
- If thorough is True use neither the WorkList nor any cached
- results (though the result of this call will be cached for
- future, non-thorough, calls).'''
-
- parent = self.parent(parent)
-
- #
- # Use the cached copy if we can (we have one, and weren't
- # asked to be thorough)
- #
- if not thorough and parent in self.activecache:
- return self.activecache[parent]
-
- #
- # outbases: The set of outgoing nodes with no outgoing ancestors
- # outnodes: The full set of outgoing nodes
- #
- if parent:
- outbases = self.findoutgoing(parent)
- outnodes = self.repo.changelog.nodesbetween(outbases)[0]
- else: # No parent, no outgoing nodes
- outbases = []
- outnodes = []
-
- wctx = self.workingctx(worklist=not thorough)
- localtip = self._localtip(outnodes, wctx)
-
- if localtip.rev() is None:
- heads = localtip.parents()
- else:
- heads = [localtip]
-
- parenttip = self.parenttip(heads, outnodes)
-
- #
- # 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 parenttip == None:
- raise util.Abort('repository is unrelated')
-
- headnodes = [h.node() for h in heads]
- ctxs = [self.repo.changectx(n) for n in
- self.repo.changelog.nodesbetween(outbases, headnodes)[0]]
-
- if localtip.rev() is None:
- ctxs.append(localtip)
-
- act = ActiveList(self, parenttip, ctxs)
- self.activecache[parent] = act
-
- return act
-
- def squishdeltas(self, active, message, user=None):
- '''Create a single conglomerate changeset based on a given
- active list. Removes the original changesets comprising the
- given active list, and any tags pointing to them.
-
- Operation:
-
- - Commit an activectx object representing the specified
- active list,
-
- - Remove any local tags pointing to changesets in the
- specified active list.
-
- - Remove the changesets comprising the specified active
- list.
-
- - Remove any metadata that may refer to changesets that were
- removed.
-
- Calling code is expected to hold both the working copy lock
- and repository lock of the destination workspace
- '''
-
- def strip_local_tags(active):
- '''Remove any local tags referring to the specified nodes.'''
-
- if os.path.exists(self.repo.join('localtags')):
- fh = None
- try:
- fh = self.repo.opener('localtags')
- tags = active.prune_tags(fh)
- fh.close()
-
- fh = self.repo.opener('localtags', 'w', atomictemp=True)
- fh.writelines(tags)
- fh.rename()
- finally:
- if fh and not fh.closed:
- fh.close()
-
- if active.files():
- for entry in active:
- #
- # Work around Mercurial issue #1666, if the source
- # file of a rename exists in the working copy
- # Mercurial will complain, and remove the file.
- #
- # We preemptively remove the file to avoid the
- # complaint (the user was asked about this in
- # cdm_recommit)
- #
- if entry.is_renamed():
- path = self.repo.wjoin(entry.parentname)
- if os.path.exists(path):
- os.unlink(path)
-
- self.repo.commitctx(active.context(message, user))
- wsstate = "recommitted"
- destination = self.repo.changelog.tip()
- 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"
- destination = active.parenttip.node()
-
- self.clean(destination)
-
- #
- # Tags were elided by the activectx object. Local tags,
- # however, must be removed manually.
- #
- try:
- strip_local_tags(active)
- except EnvironmentError, e:
- raise util.Abort('Could not recommit tags: %s\n' % e)
-
- # Silence all the strip and update fun
- self.ui.pushbuffer()
-
- #
- # Remove the previous child-local changes by stripping the
- # nodes that form the base of the ActiveList (removing their
- # children in the process).
- #
- try:
- try:
- for base in active.bases():
- #
- # Any cached information about the repository is
- # likely to be invalid during the strip. The
- # caching of branch tags is especially
- # problematic.
- #
- self.repo.invalidate()
- repair.strip(self.ui, self.repo, base.node(), 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 changeset.\n" % wsstate)
- raise # Re-raise the exception
- finally:
- self.clean()
- self.repo.dirstate.write() # Flush the dirstate
- self.repo.invalidate() # Invalidate caches
-
- #
- # We need to remove Hg's undo information (used for rollback),
- # since it refers to data that will probably not exist after
- # the strip.
- #
- 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()
-
- 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
-
- def workingctx(self, worklist=False):
- '''Return a workingctx object representing the working copy.
-
- If worklist is true, return a workingctx object created based
- on the status of files in the workspace's worklist.'''
-
- wl = WorkList(self)
-
- if worklist and wl:
- return context.workingctx(self.repo, changes=wl.status())
- else:
- return self.repo.changectx(None)
-
- def matcher(self, pats=None, opts=None, files=None):
- '''Return a match object suitable for Mercurial based on
- specified criteria.
-
- If files is specified it is a list of pathnames relative to
- the repository root to be matched precisely.
-
- If pats and/or opts are specified, these are as to
- cmdutil.match'''
-
- of_patterns = pats is not None or opts is not None
- of_files = files is not None
- opts = opts or {} # must be a dict
-
- assert not (of_patterns and of_files)
-
- if of_patterns:
- return cmdutil.match(self.repo, pats, opts)
- elif of_files:
- return cmdutil.matchfiles(self.repo, files)
- else:
- return cmdutil.matchall(self.repo)
-
- def diff(self, node1=None, node2=None, match=None, opts=None):
- '''Return the diff of changes between two changesets as a string'''
-
- #
- # Retain compatibility by only calling diffopts() if it
- # obviously has not already been done.
- #
- if isinstance(opts, dict):
- opts = patch.diffopts(self.ui, opts)
-
- ret = cStringIO.StringIO()
- for chunk in patch.diff(self.repo, node1, node2, match=match,
- opts=opts):
- ret.write(chunk)
-
- return ret.getvalue()
-
- if Version.at_least("1.6"):
- def copy(self, src, dest):
- '''Copy a file from src to dest
- '''
-
- self.workingctx().copy(src, dest)
- else:
- def copy(self, src, dest):
- '''Copy a file from src to dest
- '''
-
- self.repo.copy(src, dest)
-
-
- if Version.at_least("1.4"):
-
- def _walkctxs(self, base, head, follow=False, pick=None):
- '''Generate changectxs between BASE and HEAD.
-
- Walk changesets between BASE and HEAD (in the order implied by
- their relation), following a given branch if FOLLOW is a true
- value, yielding changectxs where PICK (if specified) returns a
- true value.
-
- PICK is a function of one argument, a changectx.'''
-
- chosen = {}
-
- def prep(ctx, fns):
- chosen[ctx.rev()] = not pick or pick(ctx)
-
- opts = {'rev': ['%s:%s' % (base.rev(), head.rev())],
- 'follow': follow}
- matcher = cmdutil.matchall(self.repo)
-
- for ctx in cmdutil.walkchangerevs(self.repo, matcher, opts, prep):
- if chosen[ctx.rev()]:
- yield ctx
- else:
-
- def _walkctxs(self, base, head, follow=False, pick=None):
- '''Generate changectxs between BASE and HEAD.
-
- Walk changesets between BASE and HEAD (in the order implied by
- their relation), following a given branch if FOLLOW is a true
- value, yielding changectxs where PICK (if specified) returns a
- true value.
-
- PICK is a function of one argument, a changectx.'''
-
- opts = {'rev': ['%s:%s' % (base.rev(), head.rev())],
- 'follow': follow}
-
- changectx = self.repo.changectx
- getcset = util.cachefunc(lambda r: changectx(r).changeset())
-
- #
- # 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.
- #
- changeiter = cmdutil.walkchangerevs(self.ui, self.repo,
- [], getcset, opts)[0]
-
- matched = {}
- for st, rev, fns in changeiter:
- if st == 'add':
- ctx = changectx(rev)
- if not pick or pick(ctx):
- matched[rev] = ctx
- elif st == 'iter':
- if rev in matched:
- yield matched[rev]
diff --git a/usr/src/tools/onbld/hgext/Makefile b/usr/src/tools/onbld/hgext/Makefile
deleted file mode 100644
index 2247cb1f45..0000000000
--- a/usr/src/tools/onbld/hgext/Makefile
+++ /dev/null
@@ -1,58 +0,0 @@
-#
-# 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 (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
-#
-
-include $(SRC)/Makefile.master
-include ../../Makefile.tools
-
-PYSRCS = \
- __init__.py \
- cdm.py
-
-#
-# We deliver .pyc files specific to the python version, with the
-# exception of cdm.pyc, which we don't deliver at all.
-#
-# An exception to this is cdm.py, which is typically loaded using an
-# extension path in an .hgrc. This path might refer to a Python
-# version that's different from the one Mercurial is using. If we
-# delivered a cdm.pyc, differing Pythons running Mercurial could cause
-# it to be overwritten, causing packaging noise. Logic within cdm.py
-# causes modules loaded from there to be those built by the correct
-# version of Python.
-#
-PYSRC2 = $(PYSRCS:cdm.py=)
-PYOBJS = $(PYSRC2:%.py=%.pyc)
-PYTOPDIR = $(ROOTONBLDLIB)
-PYMODDIR = onbld/hgext
-
-include ../../Makefile.python
-
-all: $(PYVERSOBJS)
-
-install: all $(ROOTPYFILES)
-
-clean:
-
-clobber: clean pyclobber
diff --git a/usr/src/tools/onbld/hgext/__init__.py b/usr/src/tools/onbld/hgext/__init__.py
deleted file mode 100644
index f45ecbc95f..0000000000
--- a/usr/src/tools/onbld/hgext/__init__.py
+++ /dev/null
@@ -1,28 +0,0 @@
-#! /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
deleted file mode 100644
index 28e45ed9a0..0000000000
--- a/usr/src/tools/onbld/hgext/cdm.py
+++ /dev/null
@@ -1,1530 +0,0 @@
-#
-# 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 (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
-# Copyright 2008, 2011 Richard Lowe
-# Copyright 2014 Garrett D'Amore <garrett@damore.org>
-# Copyright (c) 2014, Joyent, Inc.
-#
-
-'''OpenSolaris extensions to Mercurial
-
- This extension contains a number of commands to help you work with
-the OpenSolaris consolidations. It provides commands to check your
-changes against the various style rules used for OpenSolaris, to
-backup and restore your changes, to generate code reviews, and to
-prepare your changes for integration.
-
-
-The Parent
-
- To provide a uniform notion of parent workspace regardless of
-filesystem-based access, Cadmium uses the highest numbered changeset
-on the current branch that is also in the parent workspace to
-represent the parent workspace.
-
-
-The Active List
-
- Many Cadmium commands operate on the active list, the set of
-files ('active files') you have changed in this workspace in relation
-to its parent workspace, and the metadata (commentary, primarily)
-associated with those changes.
-
-
-NOT Files
-
- Many of Cadmium's commands to check that your work obeys the
-various stylistic rules of the OpenSolaris consolidations (such as
-those run by 'hg nits') allow files to be excluded from this checking
-by means of NOT files kept in the .hg/cdm/ directory of the Mercurial
-repository for one-time exceptions, and in the exception_lists
-directory at the repository root for permanent exceptions. (For ON,
-these would mean one in $CODEMGR_WS and one in
-$CODEMGR_WS/usr/closed).
-
- These files are in the same format as the Mercurial hgignore
-file, a description of which is available in the hgignore(5) manual
-page.
-
-
-Common Tasks
-
- - Show diffs relative to parent workspace - pdiffs
- - Check source style rules - nits
- - Run pre-integration checks - pbchk
- - Collapse all your changes into a single changeset - recommit
-'''
-
-import atexit, os, re, sys, stat, termios
-
-
-#
-# Adjust the load path based on the location of cdm.py and the version
-# of python into which it is being loaded. This assumes the normal
-# onbld directory structure, where cdm.py is in
-# lib/python(version)?/onbld/hgext/. If that changes so too must
-# this.
-#
-# This and the case below are not equivalent. In this case we may be
-# loading a cdm.py in python2.X/ via the lib/python/ symlink but need
-# python2.Y in sys.path.
-#
-sys.path.insert(1, os.path.join(os.path.dirname(__file__), "..", "..", "..",
- "python%d.%d" % sys.version_info[:2]))
-
-#
-# Add the relative path from cdm.py to usr/src/tools to the load path,
-# such that a cdm.py loaded from the source tree uses the modules also
-# within the source tree.
-#
-sys.path.insert(2, os.path.join(os.path.dirname(__file__), "..", ".."))
-
-from onbld.Scm import Version
-from onbld.Scm import Ignore
-from mercurial import util
-
-try:
- Version.check_version()
-except Version.VersionMismatch, badversion:
- raise util.Abort("Version Mismatch:\n %s\n" % badversion)
-
-from mercurial import cmdutil, node, patch
-
-from onbld.Scm.WorkSpace import WorkSpace, WorkList
-from onbld.Scm.Backup import CdmBackup
-from onbld.Checks import Cddl, Comments, Copyright, CStyle, HdrChk
-from onbld.Checks import JStyle, Keywords, ManLint, Mapfile
-
-
-def yes_no(ui, msg, default):
- if default:
- prompt = ' [Y/n]:'
- defanswer = 'y'
- else:
- prompt = ' [y/N]:'
- defanswer = 'n'
-
- if Version.at_least("1.4"):
- index = ui.promptchoice(msg + prompt, ['&yes', '&no'],
- default=['y', 'n'].index(defanswer))
- resp = ('y', 'n')[index]
- else:
- resp = ui.prompt(msg + prompt, ['&yes', '&no'], default=defanswer)
-
- return resp[0] in ('Y', 'y')
-
-
-def buildfilelist(ws, parent, files):
- '''Build a list of files in which we're interested.
-
- If no files are specified take files from the active list relative
- to 'parent'.
-
- Return a list of 2-tuples the first element being a path relative
- to the current directory and the second an entry from the active
- list, or None if an explicit file list was given.'''
-
- if files:
- return [(path, None) for path in sorted(files)]
- else:
- active = ws.active(parent=parent)
- return [(ws.filepath(e.name), e) for e in sorted(active)]
-buildfilelist = util.cachefunc(buildfilelist)
-
-
-def not_check(repo, cmd):
- '''return a function which returns boolean indicating whether a file
- should be skipped for CMD.'''
-
- #
- # The ignore routines need a canonical path to the file (relative to the
- # repo root), whereas the check commands get paths relative to the cwd.
- #
- # Wrap our argument such that the path is canonified before it is checked.
- #
- def canonified_check(ignfunc):
- def f(path):
- cpath = util.canonpath(repo.root, repo.getcwd(), path)
- return ignfunc(cpath)
- return f
-
- ignorefiles = []
-
- for f in [repo.join('cdm/%s.NOT' % cmd),
- repo.wjoin('exception_lists/%s' % cmd)]:
- if os.path.exists(f):
- ignorefiles.append(f)
-
- if ignorefiles:
- ign = Ignore.ignore(repo.root, ignorefiles)
- return canonified_check(ign)
- else:
- return util.never
-
-
-def abort_if_dirty(ws):
- '''Abort if the workspace has uncommitted changes, merges,
- branches, or has Mq patches applied'''
-
- if ws.modified():
- raise util.Abort('workspace has uncommitted changes')
- if ws.merged():
- raise util.Abort('workspace contains uncommitted merge')
- if ws.branched():
- raise util.Abort('workspace contains uncommitted branch')
- if ws.mq_applied():
- raise util.Abort('workspace has Mq patches applied')
-
-
-#
-# 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)
-
- if ui.interactive() and sys.stdin.isatty():
- ui.setconfig('hooks', 'preoutgoing.cdm_pbconfirm',
- 'python:hgext_cdm.pbconfirm')
-
-
-def pbconfirm(ui, repo, hooktype, source):
- def wrapper(settings=None):
- termios.tcsetattr(sys.stdin.fileno(), termios.TCSANOW, settings)
-
- if source == 'push':
- if not yes_no(ui, "Are you sure you wish to push?", False):
- return 1
- else:
- settings = termios.tcgetattr(sys.stdin.fileno())
- orig = list(settings)
- atexit.register(wrapper, orig)
- settings[3] = settings[3] & (~termios.ISIG) # c_lflag
- termios.tcsetattr(sys.stdin.fileno(), termios.TCSANOW, settings)
-
-
-def cdm_pdiffs(ui, repo, *pats, **opts):
- '''diff workspace against its parent
-
- Show differences between this workspace and its parent workspace
- in the same manner as 'hg diff'.
-
- For a description of the changeset used to represent the parent
- workspace, see The Parent in the extension documentation ('hg help
- cdm').
- '''
-
- act = wslist[repo].active(opts.get('parent'))
- if not act.revs:
- return
-
- #
- # If no patterns were specified, either explicitly or via -I or -X
- # use the active list files to avoid a workspace walk.
- #
- if pats or opts.get('include') or opts.get('exclude'):
- matchfunc = wslist[repo].matcher(pats=pats, opts=opts)
- else:
- matchfunc = wslist[repo].matcher(files=act.files())
-
- opts = patch.diffopts(ui, opts)
- diffs = wslist[repo].diff(act.parenttip.node(), act.localtip.node(),
- match=matchfunc, opts=opts)
- if diffs:
- ui.write(diffs)
-
-
-def cdm_list(ui, repo, **opts):
- '''list active files (those changed in this workspace)
-
- Display a list of files changed in this workspace as compared to
- its parent workspace.
-
- File names are displayed one-per line, grouped by manner in which
- they changed (added, modified, removed). Information about
- renames or copies is output in parentheses following the file
- name.
-
- For a description of the changeset used to represent the parent
- workspace, see The Parent in the extension documentation ('hg help
- cdm').
-
- Output can be filtered by change type with --added, --modified,
- and --removed. By default, all files are shown.
- '''
-
- act = wslist[repo].active(opts['parent'])
- wanted = set(x for x in ('added', 'modified', 'removed') if opts[x])
- changes = {}
-
- for entry in act:
- if wanted and (entry.change not in wanted):
- continue
-
- if entry.change not in changes:
- changes[entry.change] = []
- changes[entry.change].append(entry)
-
- for change in sorted(changes.keys()):
- ui.write(change + ':\n')
-
- for entry in sorted(changes[change]):
- if entry.is_renamed():
- ui.write('\t%s (renamed from %s)\n' % (entry.name,
- entry.parentname))
- elif entry.is_copied():
- ui.write('\t%s (copied from %s)\n' % (entry.name,
- entry.parentname))
- else:
- ui.write('\t%s\n' % entry.name)
-
-
-def cdm_bugs(ui, repo, parent=None):
- '''show all bug IDs referenced in changeset 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 changeset commentary for all active changesets'''
- 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::
-
- new-name old-name
-
- 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 active changeset comment formatting
-
- Check that active changeset comments conform to O/N rules.
-
- Each comment line must contain either one bug or ARC case ID
- followed by its synopsis, or credit an external contributor.
- '''
-
- active = wslist[repo].active(opts.get('parent'))
-
- ui.write('Comments check:\n')
-
- check_db = not opts.get('nocheck')
- return Comments.comchk(active.comments(), check_db=check_db, output=ui)
-
-
-def cdm_cddlchk(ui, repo, *args, **opts):
- '''check for a valid CDDL header comment in all active files.
-
- Check active files for a valid Common Development and Distribution
- License (CDDL) block comment.
-
- Newly added files are checked for a copy of the CDDL header
- comment. Modified files are only checked if they contain what
- appears to be an existing CDDL header comment.
-
- Files can be excluded from this check using the cddlchk.NOT file.
- See NOT Files in the extension documentation ('hg help cdm').
- '''
-
- filelist = buildfilelist(wslist[repo], opts.get('parent'), args)
- exclude = not_check(repo, 'cddlchk')
- lenient = True
- ret = 0
-
- ui.write('CDDL block check:\n')
-
- for f, e in filelist:
- if e and e.is_removed():
- continue
- elif (e or opts.get('honour_nots')) and exclude(f):
- ui.status('Skipping %s...\n' % f)
- continue
- elif e and e.is_added():
- lenient = False
- else:
- lenient = True
-
- fh = open(f, 'r')
- ret |= Cddl.cddlchk(fh, lenient=lenient, output=ui)
- fh.close()
- return ret
-
-
-def cdm_manlintchk(ui, repo, *args, **opts):
- '''check for mandoc lint
-
- Check for man page formatting errors.
-
- Files can be excluded from this check using the manlint.NOT
- file. See NOT Files in the extension documentation ('hg help
- cdm').
- '''
-
- filelist = buildfilelist(wslist[repo], opts.get('parent'), args)
- exclude = not_check(repo, 'manlint')
- ret = 0
-
- # Man pages are identified as having a suffix starting with a digit.
- ManfileRE = re.compile(r'.*\.[0-9][a-z]*$', re.IGNORECASE)
-
- ui.write('Man format check:\n')
-
- for f, e in filelist:
- if e and e.is_removed():
- continue
- elif (not ManfileRE.match(f)):
- continue
- elif (e or opts.get('honour_nots')) and exclude(f):
- ui.status('Skipping %s...\n' % f)
- continue
-
- fh = open(f, 'r')
- ret |= ManLint.manlint(fh, output=ui, picky=True)
- fh.close()
- return ret
-
-
-def cdm_mapfilechk(ui, repo, *args, **opts):
- '''check for a valid mapfile header block in active files
-
- Check that all link-editor mapfiles contain the standard mapfile
- header comment directing the reader to the document containing
- Solaris object versioning rules (README.mapfile).
-
- Files can be excluded from this check using the mapfilechk.NOT
- file. See NOT Files in the extension documentation ('hg help
- cdm').
- '''
-
- filelist = buildfilelist(wslist[repo], opts.get('parent'), args)
- exclude = not_check(repo, 'mapfilechk')
- ret = 0
-
- # We are interested in examining any file that has the following
- # in its final path segment:
- # - Contains the word 'mapfile'
- # - Begins with 'map.'
- # - Ends with '.map'
- # We don't want to match unless these things occur in final path segment
- # because directory names with these strings don't indicate a mapfile.
- # We also ignore files with suffixes that tell us that the files
- # are not mapfiles.
- MapfileRE = re.compile(r'.*((mapfile[^/]*)|(/map\.+[^/]*)|(\.map))$',
- re.IGNORECASE)
- NotMapSuffixRE = re.compile(r'.*\.[ch]$', re.IGNORECASE)
-
- ui.write('Mapfile comment check:\n')
-
- for f, e in filelist:
- if e and e.is_removed():
- continue
- elif (not MapfileRE.match(f)) or NotMapSuffixRE.match(f):
- continue
- elif (e or opts.get('honour_nots')) and exclude(f):
- ui.status('Skipping %s...\n' % f)
- continue
-
- fh = open(f, 'r')
- ret |= Mapfile.mapfilechk(fh, output=ui)
- fh.close()
- return ret
-
-
-def cdm_copyright(ui, repo, *args, **opts):
- '''check each active file for a current and correct copyright notice
-
- Check that all active files have a correctly formed copyright
- notice containing the current year.
-
- See the Non-Formatting Considerations section of the OpenSolaris
- Developer's Reference for more info on the correct form of
- copyright notice.
- (http://hub.opensolaris.org/bin/view/Community+Group+on/devref_7#H723NonFormattingConsiderations)
-
- Files can be excluded from this check using the copyright.NOT file.
- See NOT Files in the extension documentation ('hg help cdm').
- '''
-
- filelist = buildfilelist(wslist[repo], opts.get('parent'), args)
- exclude = not_check(repo, 'copyright')
- ret = 0
-
- ui.write('Copyright check:\n')
-
- for f, e in filelist:
- if e and e.is_removed():
- continue
- elif (e or opts.get('honour_nots')) and exclude(f):
- ui.status('Skipping %s...\n' % f)
- continue
-
- fh = open(f, 'r')
- ret |= Copyright.copyright(fh, output=ui)
- fh.close()
- return ret
-
-
-def cdm_hdrchk(ui, repo, *args, **opts):
- '''check active C header files conform to the O/N header rules
-
- Check that any added or modified C header files conform to the O/N
- header rules.
-
- See the section 'HEADER STANDARDS' in the hdrchk(1) manual page
- for more information on the rules for O/N header file formatting.
-
- Files can be excluded from this check using the hdrchk.NOT file.
- See NOT Files in the extension documentation ('hg help cdm').
- '''
-
- filelist = buildfilelist(wslist[repo], opts.get('parent'), args)
- exclude = not_check(repo, 'hdrchk')
- ret = 0
-
- ui.write('Header format check:\n')
-
- for f, e in filelist:
- if e and e.is_removed():
- continue
- elif not f.endswith('.h'):
- continue
- elif (e or opts.get('honour_nots')) and exclude(f):
- ui.status('Skipping %s...\n' % f)
- continue
-
- fh = open(f, 'r')
- ret |= HdrChk.hdrchk(fh, lenient=True, output=ui)
- fh.close()
- return ret
-
-
-def cdm_cstyle(ui, repo, *args, **opts):
- '''check active C source files conform to the C Style Guide
-
- Check that any added or modified C source file conform to the C
- Style Guide.
-
- See the C Style Guide for more information about correct C source
- formatting.
- (http://hub.opensolaris.org/bin/download/Community+Group+on/WebHome/cstyle.ms.pdf)
-
- Files can be excluded from this check using the cstyle.NOT file.
- See NOT Files in the extension documentation ('hg help cdm').
- '''
-
- filelist = buildfilelist(wslist[repo], opts.get('parent'), args)
- exclude = not_check(repo, 'cstyle')
- ret = 0
-
- ui.write('C style check:\n')
-
- for f, e in filelist:
- if e and e.is_removed():
- continue
- elif not (f.endswith('.c') or f.endswith('.h')):
- continue
- elif (e or opts.get('honour_nots')) and exclude(f):
- ui.status('Skipping %s...\n' % f)
- continue
-
- fh = open(f, '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, *args, **opts):
- '''check active Java source files for common stylistic errors
-
- Files can be excluded from this check using the jstyle.NOT file.
- See NOT Files in the extension documentation ('hg help cdm').
- '''
-
- filelist = buildfilelist(wslist[repo], opts.get('parent'), args)
- exclude = not_check(repo, 'jstyle')
- ret = 0
-
- ui.write('Java style check:\n')
-
- for f, e in filelist:
- if e and e.is_removed():
- continue
- elif not f.endswith('.java'):
- continue
- elif (e or opts.get('honour_nots')) and exclude(f):
- ui.status('Skipping %s...\n' % f)
- continue
-
- fh = open(f, 'r')
- ret |= JStyle.jstyle(fh, output=ui, picky=True)
- fh.close()
- return ret
-
-
-def cdm_permchk(ui, repo, *args, **opts):
- '''check the permissions of each active file
-
- Check that the file permissions of each added or modified file do not
- contain the executable bit.
-
- Files can be excluded from this check using the permchk.NOT file.
- See NOT Files in the extension documentation ('hg help cdm').
- '''
-
- filelist = buildfilelist(wslist[repo], opts.get('parent'), args)
- exclude = not_check(repo, 'permchk')
- exeFiles = []
-
- ui.write('File permission check:\n')
-
- for f, e in filelist:
- if e and e.is_removed():
- continue
- elif (e or opts.get('honour_nots')) and exclude(f):
- ui.status('Skipping %s...\n' % f)
- continue
-
- mode = stat.S_IMODE(os.stat(f)[stat.ST_MODE])
- if mode & stat.S_IEXEC:
- exeFiles.append(f)
-
- 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 modification of workspace tags
-
- Check for any modification of the repository's .hgtags file.
-
- With the exception of the gatekeepers, nobody should introduce or
- modify a repository's tags.
- '''
-
- active = wslist[repo].active(opts.get('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 for changes in number or name of branches
-
- Check that the workspace contains only a single head, that it is
- on the branch 'default', and that no new branches have been
- introduced.
- '''
-
- ui.write('Checking for multiple heads (or branches):\n')
-
- heads = set(repo.heads())
- parents = set([x.node() for x in wslist[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 repo.dirstate.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" %
- (repo.dirstate.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_keywords(ui, repo, *args, **opts):
- '''check active files for SCCS keywords
-
- Check that any added or modified files do not contain SCCS keywords
- (#ident lines, etc.).
-
- Files can be excluded from this check using the keywords.NOT file.
- See NOT Files in the extension documentation ('hg help cdm').
- '''
-
- filelist = buildfilelist(wslist[repo], opts.get('parent'), args)
- exclude = not_check(repo, 'keywords')
- ret = 0
-
- ui.write('Keywords check:\n')
-
- for f, e in filelist:
- if e and e.is_removed():
- continue
- elif (e or opts.get('honour_nots')) and exclude(f):
- ui.status('Skipping %s...\n' % f)
- continue
-
- fh = open(f, '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 = wslist[repo].active(opts.get('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, *args, **opts):
- '''Run CMDS (with OPTS) over active files in WS'''
-
- 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, honour_nots=True, *args, **opts)
- output = ws.ui.popbuffer()
-
- ret |= result
-
- if not ws.ui.quiet or result != 0:
- ws.ui.write(output, '\n')
- return ret
-
-
-def cdm_nits(ui, repo, *args, **opts):
- '''check for stylistic nits in active files
-
- Check each active file for basic stylistic errors.
-
- The following checks are run over each active file (see 'hg help
- <check>' for more information about each):
-
- - copyright (copyright statements)
- - cstyle (C source style)
- - hdrchk (C header style)
- - jstyle (java source style)
- - manlint (man page formatting)
- - mapfilechk (link-editor mapfiles)
- - permchk (file permissions)
- - keywords (SCCS keywords)
-
- With the global -q/--quiet option, only provide output for those
- checks which fail.
- '''
-
- cmds = [cdm_copyright,
- cdm_cstyle,
- cdm_hdrchk,
- cdm_jstyle,
- cmd_manlintchk,
- cdm_mapfilechk,
- cdm_permchk,
- cdm_keywords]
-
- return run_checks(wslist[repo], cmds, *args, **opts)
-
-
-def cdm_pbchk(ui, repo, **opts):
- '''run pre-integration checks on this workspace
-
- Check this workspace for common errors prior to integration.
-
- The following checks are run over the active list (see 'hg help
- <check>' for more information about each):
-
- - branchchk (addition/modification of branches)
- - comchk (changeset descriptions)
- - copyright (copyright statements)
- - cstyle (C source style)
- - hdrchk (C header style)
- - jstyle (java source style)
- - keywords (SCCS keywords)
- - manlint (man page formatting)
- - mapfilechk (link-editor mapfiles)
- - permchk (file permissions)
- - tagchk (addition/modification of tags)
-
- Additionally, the workspace is checked for outgoing merges (which
- should be removed with 'hg recommit'), and uncommitted changes.
-
- With the global -q/--quiet option, only provide output for those
- checks which fail.
- '''
-
- #
- # 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 are run.
- #
- cmds = [cdm_copyright,
- cdm_cstyle,
- cdm_hdrchk,
- cdm_jstyle,
- cdm_manlintchk,
- cdm_mapfilechk,
- cdm_permchk,
- cdm_keywords,
- cdm_comchk,
- cdm_tagchk,
- cdm_branchchk,
- cdm_outchk,
- cdm_mergechk]
-
- return run_checks(wslist[repo], cmds, **opts)
-
-
-def cdm_recommit(ui, repo, **opts):
- '''replace outgoing changesets with a single equivalent changeset
-
- Replace all outgoing changesets with a single changeset containing
- equivalent changes. This removes uninteresting changesets created
- during development that would only serve as noise in the gate.
-
- Any changed file that is now identical in content to that in the
- parent workspace (whether identical in history or otherwise) will
- not be included in the new changeset. Any merges information will
- also be removed.
-
- If no files are changed in comparison to the parent workspace, the
- outgoing changesets will be removed, but no new changeset created.
-
- recommit will refuse to run if the workspace contains more than
- one outgoing head, even if those heads are on the same branch. To
- recommit with only one branch containing outgoing changesets, your
- workspace must be on that branch and at that branch head.
-
- recommit will prompt you to take a backup if your workspace has
- been changed since the last backup was taken. In almost all
- cases, you should allow it to take one (the default).
-
- recommit cannot be run if the workspace contains any uncommitted
- changes, applied Mq patches, or has multiple outgoing heads (or
- branches).
- '''
-
- ws = wslist[repo]
-
- if not os.getcwd().startswith(repo.root):
- raise util.Abort('recommit is not safe to run with -R')
-
- abort_if_dirty(ws)
-
- wlock = repo.wlock()
- lock = repo.lock()
-
- try:
- parent = ws.parent(opts['parent'])
- between = repo.changelog.nodesbetween(ws.findoutgoing(parent))[2]
- heads = set(between) & set(repo.heads())
-
- if len(heads) > 1:
- ui.warn('Workspace has multiple outgoing heads (or branches):\n')
- for head in sorted(map(repo.changelog.rev, heads), reverse=True):
- ui.warn('\t%d\n' % head)
- raise util.Abort('you must merge before recommitting')
-
- #
- # We can safely use the worklist here, as we know (from the
- # abort_if_dirty() check above) that the working copy has not been
- # modified.
- #
- active = ws.active(parent)
-
- if filter(lambda b: len(b.parents()) > 1, active.bases()):
- raise util.Abort('Cannot recommit a merge of two non-outgoing '
- 'changesets')
-
- 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()
- comments = '\n'.join(active.comments())
-
- message = cmdutil.logmessage(opts) or ui.edit(comments, user)
- if not message:
- raise util.Abort('empty commit message')
-
- bk = CdmBackup(ui, ws, backup_name(repo.root))
- 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()]
-
- ws.squishdeltas(active, message, user=user)
- finally:
- lock.release()
- wlock.release()
-
- if clearedtags:
- ui.write("Removed tags:\n")
- for name, nd, rev, local in sorted(clearedtags,
- key=lambda x: x[0].lower()):
- ui.write(" %5s:%s:\t%s%s\n" % (rev, node.short(nd),
- name, (local and ' (local)' or '')))
-
- for ntag, nnode in sorted(repo.tags().items(),
- key=lambda x: x[0].lower()):
- 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 specified command for each active file
-
- Run the command specified on the command line for each active
- file, with the following variables present in the environment:
-
- :$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 specified command to all active files
-
- Run the command specified on the command line over each active
- file.
-
- For example 'hg apply "wc -l"' will output a count of the lines in
- each active file.
- '''
-
- 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
-
- Update the 'default' path alias that is used as the default source
- for 'hg pull' and the default destination for 'hg push' (unless
- there is a 'default-push' alias). This is also the path all
- Cadmium commands treat as your parent workspace.
- '''
-
- def append_new_parent(parent):
- fp = None
- try:
- fp = repo.opener('hgrc', 'a', atomictemp=True)
- if fp.tell() != 0:
- fp.write('\n')
- fp.write('[paths]\n'
- 'default = %s\n\n' % parent)
- fp.rename()
- finally:
- if fp and not fp.closed:
- fp.close()
-
- def update_parent(path, line, parent):
- line = line - 1 # The line number we're passed will be 1-based
- fp = None
-
- try:
- fp = open(path)
- data = fp.readlines()
- finally:
- if fp and not fp.closed:
- fp.close()
-
- #
- # line will be the last line of any continued block, go back
- # to the first removing the continuation as we go.
- #
- while data[line][0].isspace():
- data.pop(line)
- line -= 1
-
- assert data[line].startswith('default')
-
- data[line] = "default = %s\n" % parent
- if data[-1] != '\n':
- data.append('\n')
-
- try:
- fp = util.atomictempfile(path, 'w', 0644)
- fp.writelines(data)
- fp.rename()
- finally:
- if fp and not fp.closed:
- fp.close()
-
- from mercurial import config
- parent = ui.expandpath(parent)
-
- if not os.path.exists(repo.join('hgrc')):
- append_new_parent(parent)
- return
-
- cfg = config.config()
- cfg.read(repo.join('hgrc'))
- source = cfg.source('paths', 'default')
-
- if not source:
- append_new_parent(parent)
- return
- else:
- path, target = source.rsplit(':', 1)
-
- if path != repo.join('hgrc'):
- raise util.Abort("Cannot edit path specification not in repo hgrc\n"
- "default path is from: %s" % source)
-
- update_parent(path, int(target), parent)
-
-
-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):
- '''backup workspace changes and metadata
-
- Create a backup copy of changes made in this workspace as compared
- to its parent workspace, as well as important metadata of this
- workspace.
-
- NOTE: Only changes as compared to the parent workspace are backed
- up. If you lose this workspace and its parent, you will not be
- able to restore a backup into a clone of the grandparent
- workspace.
-
- By default, backups are stored in the cdm.backup/ directory in
- your home directory. This is configurable using the cdm.backupdir
- configuration variable, for example:
-
- hg backup --config cdm.backupdir=/net/foo/backups
-
- or place the following in an appropriate hgrc file::
-
- [cdm]
- backupdir = /net/foo/backups
-
- Backups have the same name as the workspace in which they were
- taken, with '-closed' appended in the case of O/N's usr/closed.
- '''
-
- name = backup_name(repo.root)
- bk = CdmBackup(ui, wslist[repo], name)
-
- wlock = repo.wlock()
- lock = repo.lock()
-
- try:
- if if_newer and not bk.need_backup():
- ui.status('backup is up-to-date\n')
- else:
- bk.backup()
- finally:
- lock.release()
- wlock.release()
-
-
-def cdm_restore(ui, repo, backup, **opts):
- '''restore workspace from backup
-
- Restore this workspace from a backup (taken by 'hg backup').
-
- If the specified backup directory does not exist, it is assumed to
- be relative to the cadmium backup directory (~/cdm.backup/ by
- default).
-
- For example::
-
- % hg restore on-rfe - Restore the latest backup of ~/cdm.backup/on-rfe
- % hg restore -g3 on-rfe - Restore the 3rd backup of ~/cdm.backup/on-rfe
- % hg restore /net/foo/backup/on-rfe - Restore from an explicit path
- '''
-
- if not os.getcwd().startswith(repo.root):
- raise util.Abort('restore is not safe to run with -R')
-
- abort_if_dirty(wslist[repo])
-
- if opts['generation']:
- gen = int(opts['generation'])
- else:
- gen = None
-
- if os.path.exists(backup):
- backup = os.path.abspath(backup)
-
- wlock = repo.wlock()
- lock = repo.lock()
-
- try:
- bk = CdmBackup(ui, wslist[repo], backup)
- bk.restore(gen)
- finally:
- lock.release()
- wlock.release()
-
-
-def cdm_webrev(ui, repo, **opts):
- '''generate web-based code review and optionally upload it
-
- Generate a web-based code review using webrev(1) and optionally
- upload it. All known arguments are passed through to webrev(1).
- '''
-
- webrev_args = ""
- for key in opts.keys():
- if opts[key]:
- if type(opts[key]) == type(True):
- webrev_args += '-' + key + ' '
- else:
- webrev_args += '-' + key + ' ' + opts[key] + ' '
-
- retval = os.system('webrev ' + webrev_args)
- if retval != 0:
- return retval - 255
-
- return 0
-
-
-def cdm_debugcdmal(ui, repo, *pats, **opts):
- '''dump the active list for the sake of debugging/testing'''
-
- ui.write(wslist[repo].active(opts['parent']).as_text(pats))
-
-
-def cdm_changed(ui, repo, *pats, **opts):
- '''mark a file as changed in the working copy
-
- Maintain a list of files checked for modification in the working
- copy. If the list exists, most cadmium commands will only check
- the working copy for changes to those files, rather than checking
- the whole workspace (this does not apply to committed changes,
- which are always seen).
-
- Since this list functions only as a hint as to where in the
- working copy to look for changes, entries that have not actually
- been modified (in the working copy, or in general) are not
- problematic.
-
-
- Note: If such a list exists, it must be kept up-to-date.
-
-
- Renamed files can be added with reference only to their new name:
- $ hg mv foo bar
- $ hg changed bar
-
- Without arguments, 'hg changed' will list all files recorded as
- altered, such that, for instance:
- $ hg status $(hg changed)
- $ hg diff $(hg changed)
- Become useful (generally faster than their unadorned counterparts)
-
- To create an initially empty list:
- $ hg changed -i
- Until files are added to the list it is equivalent to saying
- "Nothing has been changed"
-
- Update the list based on the current active list:
- $ hg changed -u
- The old list is emptied, and replaced with paths from the
- current active list.
-
- Remove the list entirely:
- $ hg changed -d
- '''
-
- def modded_files(repo, parent):
- out = wslist[repo].findoutgoing(wslist[repo].parent(parent))
- outnodes = repo.changelog.nodesbetween(out)[0]
-
- files = set()
- for n in outnodes:
- files.update(repo.changectx(n).files())
-
- files.update(wslist[repo].status().keys())
- return files
-
- #
- # specced_pats is convenient to treat as a boolean indicating
- # whether any file patterns or paths were specified.
- #
- specced_pats = pats or opts['include'] or opts['exclude']
- if len(filter(None, [opts['delete'], opts['update'], opts['init'],
- specced_pats])) > 1:
- raise util.Abort("-d, -u, -i and patterns are mutually exclusive")
-
- wl = WorkList(wslist[repo])
-
- if (not wl and specced_pats) or opts['init']:
- wl.delete()
- if yes_no(ui, "Create a list based on your changes thus far?", True):
- map(wl.add, modded_files(repo, opts.get('parent')))
-
- if opts['delete']:
- wl.delete()
- elif opts['update']:
- wl.delete()
- map(wl.add, modded_files(repo, opts.get('parent')))
- wl.write()
- elif opts['init']: # Any possible old list was deleted above
- wl.write()
- elif specced_pats:
- sources = []
-
- match = wslist[repo].matcher(pats=pats, opts=opts)
- for abso in repo.walk(match):
- if abso in repo.dirstate:
- wl.add(abso)
- #
- # Store the source name of any copy. We use this so
- # both the add and delete of a rename can be entered
- # into the WorkList with only the destination name
- # explicitly being mentioned.
- #
- fctx = wslist[repo].workingctx().filectx(abso)
- rn = fctx.renamed()
- if rn:
- sources.append(rn[0])
- else:
- ui.warn("%s is not version controlled -- skipping\n" %
- match.rel(abso))
-
- if sources:
- for fname, chng in wslist[repo].status(files=sources).iteritems():
- if chng == 'removed':
- wl.add(fname)
- wl.write()
- else:
- for elt in sorted(wl.list()):
- ui.write("%s\n" % wslist[repo].filepath(elt))
-
-
-cmdtable = {
- 'apply': (cdm_apply, [('p', 'parent', '', 'parent workspace'),
- ('r', 'remain', None, 'do not change directory')],
- 'hg apply [-p PARENT] [-r] command...'),
- '^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]'),
- 'changed': (cdm_changed, [('d', 'delete', None, 'delete the file list'),
- ('u', 'update', None, 'mark all changed files'),
- ('i', 'init', None, 'create an empty file list'),
- ('p', 'parent', '', 'parent workspace'),
- ('I', 'include', [],
- 'include names matching the given patterns'),
- ('X', 'exclude', [],
- 'exclude names matching the given patterns')],
- 'hg changed -d\n'
- 'hg changed -u\n'
- 'hg changed -i\n'
- 'hg changed [-I PATTERN...] [-X PATTERN...] [FILE...]'),
- '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]'),
- 'debugcdmal': (cdm_debugcdmal, [('p', 'parent', '', 'parent workspace')],
- 'hg debugcdmal [-p PARENT] [FILE...]'),
- 'eval': (cdm_eval, [('p', 'parent', '', 'parent workspace'),
- ('r', 'remain', None, 'do not change directory')],
- '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'),
- ('a', 'added', None, 'show added files'),
- ('m', 'modified', None, 'show modified files'),
- ('r', 'removed', None, 'show removed files')],
- 'hg list [-amrRu] [-p PARENT]'),
- 'manlint': (cdm_manlintchk, [('p', 'parent', '', 'parent workspace')],
- 'hg manlint [-p PARENT]'),
- 'mapfilechk': (cdm_mapfilechk, [('p', 'parent', '', 'parent workspace')],
- 'hg mapfilechk [-p PARENT]'),
- '^nits': (cdm_nits, [('p', 'parent', '', 'parent workspace')],
- 'hg nits [-p PARENT]'),
- '^pbchk': (cdm_pbchk, [('p', 'parent', '', 'parent workspace'),
- ('N', 'nocheck', None, 'skip database checks')],
- 'hg pbchk [-N] [-p PARENT]'),
- 'permchk': (cdm_permchk, [('p', 'parent', '', 'parent workspace')],
- 'hg permchk [-p PARENT]'),
- '^pdiffs': (cdm_pdiffs, [('p', 'parent', '', 'parent workspace'),
- ('a', 'text', None, 'treat all files as text'),
- ('g', 'git', None, 'use extended git diff format'),
- ('w', 'ignore-all-space', None,
- 'ignore white space when comparing lines'),
- ('b', 'ignore-space-change', None,
- 'ignore changes in the amount of white space'),
- ('B', 'ignore-blank-lines', None,
- 'ignore changes whose lines are all blank'),
- ('U', 'unified', 3,
- 'number of lines of context to show'),
- ('I', 'include', [],
- 'include names matching the given patterns'),
- ('X', 'exclude', [],
- 'exclude names matching the given patterns')],
- 'hg pdiffs [OPTION...] [-p PARENT] [FILE...]'),
- '^recommit|reci': (cdm_recommit, [('p', 'parent', '', 'parent workspace'),
- ('m', 'message', '',
- 'use <text> as commit message'),
- ('l', 'logfile', '',
- 'read commit message from file'),
- ('u', 'user', '',
- 'record user as committer')],
- 'hg recommit [-m TEXT] [-l FILE] [-u USER] [-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'),
- 'tagchk': (cdm_tagchk, [('p', 'parent', '', 'parent workspace')],
- 'hg tagchk [-p PARENT]'),
- 'webrev': (cdm_webrev, [('C', 'C', '', 'ITS priority file'),
- ('D', 'D', '', 'delete remote webrev'),
- ('I', 'I', '', 'ITS configuration file'),
- ('i', 'i', '', 'include file'),
- ('N', 'N', None, 'suppress comments'),
- ('n', 'n', None, 'do not generate webrev'),
- ('O', 'O', None, 'OpenSolaris mode'),
- ('o', 'o', '', 'output directory'),
- ('p', 'p', '', 'use specified parent'),
- ('t', 't', '', 'upload target'),
- ('U', 'U', None, 'upload the webrev'),
- ('w', 'w', '', 'use wx active file')],
- 'hg webrev [WEBREV_OPTIONS]'),
-}
diff --git a/usr/src/tools/scripts/Makefile b/usr/src/tools/scripts/Makefile
index fe847412e2..e254a76a08 100644
--- a/usr/src/tools/scripts/Makefile
+++ b/usr/src/tools/scripts/Makefile
@@ -35,7 +35,6 @@ SHFILES= \
elfcmp \
flg.flp \
genoffsets \
- hgsetup \
nightly \
onu \
protocmp.terse \
@@ -65,7 +64,6 @@ PYFILES= \
copyrightchk \
git-pbchk \
hdrchk \
- hg-active \
mapfilechk \
validate_pkg \
wsdiff
@@ -87,7 +85,6 @@ MAN1ONBLDFILES= \
hdrchk.1onbld \
interface_check.1onbld \
interface_cmp.1onbld \
- hgsetup.1onbld \
jstyle.1onbld \
mapfilechk.1onbld \
nightly.1onbld \
@@ -106,7 +103,6 @@ MAKEFILES= \
xref.mk
ETCFILES= \
- hgstyle \
its.conf \
its.reg
diff --git a/usr/src/tools/scripts/hg-active.py b/usr/src/tools/scripts/hg-active.py
deleted file mode 100644
index 495cdfc0db..0000000000
--- a/usr/src/tools/scripts/hg-active.py
+++ /dev/null
@@ -1,130 +0,0 @@
-#!@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 (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
-#
-
-'''
-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, os.path.join(os.path.dirname(__file__), "..", "lib",
- "python%d.%d" % sys.version_info[:2]))
-
-# Allow running from the source tree, using the modules in the source tree
-sys.path.insert(2, os.path.join(os.path.dirname(__file__), ".."))
-
-from onbld.Scm import Version
-
-try:
- Version.check_version()
-except Version.VersionMismatch, versionerror:
- sys.stderr.write("Error: %s\n" % versionerror)
- sys.exit(1)
-
-
-import getopt, binascii
-from mercurial import error, hg, ui, util
-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 = getopt.getopt(argv, 'w:o:p:')[0]
- except getopt.GetoptError, e:
- sys.stderr.write(str(e) + '\n')
- usage()
-
- parentpath = None
- wspath = None
- outputfile = None
-
- for opt, arg in opts:
- if opt == '-w':
- wspath = arg
- elif opt == '-o':
- outputfile = arg
- elif opt == '-p':
- parentpath = arg
-
- if not wspath:
- usage()
-
- try:
- repository = hg.repository(ui.ui(), wspath)
- except error.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)
-
- fh = None
- if outputfile:
- try:
- fh = open(outputfile, 'w')
- except EnvironmentError, e:
- sys.stderr.write("could not open output file: %s\n" % e)
- sys.exit(1)
- else:
- fh = sys.stdout
-
- fh.write("HG_PARENT=%s\n" % parenttip)
-
- entries = [i for i in act]
- entries.sort()
-
- for entry in entries:
- if entry.is_renamed() or entry.is_copied():
- fh.write("%s %s\n" % (entry.name, entry.parentname))
- else:
- fh.write("%s\n" % entry.name)
-
- # Strip blank lines.
- comments = filter(lambda x: x and not x.isspace(),
- entry.comments)
-
- fh.write('\n')
- if comments:
- fh.write('%s\n' % '\n'.join(comments))
- else:
- fh.write("*** NO COMMENTS ***\n")
- fh.write('\n')
-
-if __name__ == '__main__':
- try:
- main(sys.argv[1:])
- except KeyboardInterrupt:
- sys.exit(1)
- except util.Abort, msg:
- sys.stderr.write("Abort: %s\n" % msg)
- sys.exit(1)
diff --git a/usr/src/tools/scripts/hgsetup.1onbld b/usr/src/tools/scripts/hgsetup.1onbld
deleted file mode 100644
index 022c1a4ce3..0000000000
--- a/usr/src/tools/scripts/hgsetup.1onbld
+++ /dev/null
@@ -1,68 +0,0 @@
-.\" 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."
-.\"
-.TH HGSETUP 1ONBLD "Oct 2, 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] [-s \fIstyle_path\fP]
-.SH DESCRIPTION
-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
-.TP 10
-.B -s
-Override the path to the Mercurial style file
-.SH OUTPUT
-.LP
-Generates a .hgrc file in the user's home directory.
-.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
deleted file mode 100644
index ba087a9c76..0000000000
--- a/usr/src/tools/scripts/hgsetup.sh
+++ /dev/null
@@ -1,189 +0,0 @@
-#! /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 2009 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-
-# Copyright 2010, Richard Lowe
-
-#
-# 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] [-s style_path]
- -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
- -s style_path : override path to style file
-
- if -n isn't provided, the entry from /etc/passwd is used
-
- proxy should be in the form of hostname:port
- "
- exit 1
-}
-
-while getopts c:e:fm:n:p:s: 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;;
- s) style_path=$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 SUNWonbld is installed. In order of
-# preference, look in:
-#
-# 1. $(whence $0), on the assumption that you want the version
-# of SUNWonbld 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 $(dirname $(whence $0))) /opt/onbld /ws/onnv-tools/onbld"
-cdmbin="lib/python/onbld/hgext/cdm.py"
-stylefile="etc/hgstyle"
-
-for dir in $paths; do
- if [[ -f "$dir/$cdmbin" && -z "$cdm_path" ]]; then
- cdm_path="$dir/$cdmbin"
- fi
-
- if [[ -f "$dir/$stylefile" && -z "$style_path" ]]; then
- style_path="$dir/$stylefile"
- fi
-
- if [[ -n "$cdm_path" && -n "$style_path" ]]; then
- break
- fi
-done
-
-if [[ -n $proxy ]]; then
- proxyConfig="[http_proxy]
-host=$proxy
-"
-fi
-
-if [[ -z $email ]]; then
- my_id=$(id -un)
- my_hostname=$(hostname)
- possible_fqhns=$(getent hosts $my_hostname | cut -f 2-)
- my_fqhn=`for i in $possible_fqhns; do case $i in *.*) echo $i; break;; esac; done`
- 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 " style: $style_path"
-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
-illumos-gate=ssh://anonhg@hg.illumos.org/illumos-gate
-
-[merge-tools]
-filemerge.gui=True
-filemerge.args=-a \$base \$local \$other \$output
-filemerge.priority=1
-filemerge.premerge=False
-
-meld.gui=True
-meld.priority=0
-meld.premerge=False
-
-gpyfm.gui=True
-gpyfm.priority=0
-gpyfm.premerge=False
-
-[ui]
-username=$username
-style=$style_path
-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/hgstyle b/usr/src/tools/scripts/hgstyle
deleted file mode 100644
index 61b4d34cde..0000000000
--- a/usr/src/tools/scripts/hgstyle
+++ /dev/null
@@ -1,24 +0,0 @@
-changeset = 'changeset: {rev}:{node|short}\n{branches}{tags}{parents}user: {author}\ndate: {date|date}\ndescription:\n\t{desc|strip|tabindent}\n\n'
-changeset_quiet = '{rev}:{node|short}\n'
-changeset_verbose = '\nchangeset: {rev}:{node|short}\n{branches}{tags}{parents}user: {author}\ndate: {date|date}\n\ndescription:\n\t{desc|strip|tabindent}\n\n{file_mods}{file_adds}{file_dels}{file_copies}\n'
-changeset_debug = 'changeset: {rev}:{node}\n{branches}{tags}{parents}{manifest}{extras}user: {author}\ndate: {date|date}\ndescription:\n\t{desc|strip|tabindent}\n\n{file_mods}{file_adds}{file_dels}{file_copies}\n'
-start_files = 'files:\n'
-file = ' {file}\n'
-end_files = ''
-start_file_mods = 'modified:\n'
-file_mod = ' {file_mod}\n'
-end_file_mods = ''
-start_file_adds = 'added:\n'
-file_add = ' {file_add}\n'
-end_file_adds = ''
-start_file_dels = 'removed:\n'
-file_del = ' {file_del}\n'
-end_file_dels = ''
-start_file_copies = 'copied:\n'
-file_copy = ' {name}\n (from {source})\n'
-end_file_copies = ''
-parent = 'parent: {rev}:{node|formatnode}\n'
-manifest = 'manifest: {rev}:{node}\n'
-branch = 'branch: {branch}\n'
-tag = 'tag: {tag}\n'
-extra = 'extra: {key}={value|stringescape}\n'
diff --git a/usr/src/tools/scripts/webrev.1onbld b/usr/src/tools/scripts/webrev.1onbld
index 0bb65d4850..c166ea8cfa 100644
--- a/usr/src/tools/scripts/webrev.1onbld
+++ b/usr/src/tools/scripts/webrev.1onbld
@@ -50,7 +50,7 @@ webrev \- Generate HTML codereview materials
.B webrev
builds a set of HTML files suitable for performing code review of
source changes in a web browser.
-It supports Mercurial, Git and Subversion repositories.
+It supports Git and Subversion repositories.
At its most basic, usage is:
.nf
$ webrev
@@ -140,13 +140,6 @@ makes use of
.BR which_scm (1ONBLD)
to determine the SCM in use for a given workspace.
-.SS Mercurial
-In the case of Mercurial \fBwebrev\fR will attempt to use the output
-from the
-.BR hg (1)
-"hg root" command to identify the workspace root, and the
-"hg path default" command to identify the parent workspace.
-
.SS Git
In the case of Git \fBwebrev\fR will attempt to use the output from the
.BR git (1)
@@ -436,7 +429,6 @@ For the nested directory case it is necessary to specify the full target:
This will remove just the \fIbugfix.onnv\fR directory.
.SH SEE ALSO
-.BR hg "(1),"
.BR git "(1),"
.BR ssh_config "(4),"
.BR svn "(1),"
diff --git a/usr/src/tools/scripts/webrev.sh b/usr/src/tools/scripts/webrev.sh
index 934bb86129..d0fbde262c 100644
--- a/usr/src/tools/scripts/webrev.sh
+++ b/usr/src/tools/scripts/webrev.sh
@@ -1569,8 +1569,6 @@ source_to_html()
# 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
@@ -1611,10 +1609,7 @@ getcomments()
if [[ -n $Nflag ]]; then
return
fi
- #
- # 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
fi
@@ -1795,41 +1790,6 @@ function flist_from_wx
}
#
-# Call hg-active to get the active list output in the wx active list format
-#
-function hg_active_wxfile
-{
- typeset child=$1
- typeset parent=$2
-
- TMPFLIST=/tmp/$$.active
- $HG_ACTIVE -w $child -p $parent -o $TMPFLIST
- wxfile=$TMPFLIST
-}
-
-#
-# 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
-
- 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
-}
-
-#
# Transform a specified 'git log' output format into a wx-like active list.
#
function git_wxfile
@@ -1979,82 +1939,6 @@ function get_file_mode
' $1
}
-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 (( $? != 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_git
{
typeset olddir="$1"
@@ -2169,9 +2053,7 @@ function build_old_new
mkdir -p $olddir/$PDIR
mkdir -p $newdir/$DIR
- if [[ $SCM_MODE == "mercurial" ]]; then
- build_old_new_mercurial "$olddir" "$newdir"
- elif [[ $SCM_MODE == "git" ]]; then
+ if [[ $SCM_MODE == "git" ]]; then
build_old_new_git "$olddir" "$newdir"
elif [[ $SCM_MODE == "subversion" ]]; then
build_old_new_subversion "$olddir" "$newdir"
@@ -2237,7 +2119,6 @@ PATH=$(/bin/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 $GIT ]] && GIT=`look_for_prog git`
[[ -z $WHICH_SCM ]] && WHICH_SCM=`look_for_prog which_scm`
[[ -z $CODEREVIEW ]] && CODEREVIEW=`look_for_prog codereview`
@@ -2310,10 +2191,6 @@ Uflag=
wflag=
remote_target=
-#
-# NOTE: when adding/removing options it is necessary to sync the list
-# with usr/src/tools/onbld/hgext/cdm.py
-#
while getopts "c:C:Dh:i:I:lnNo:Op:t:Uw" opt
do
case $opt in
@@ -2384,32 +2261,8 @@ fi
# logic.
#
$WHICH_SCM | read SCM_MODE junk || exit 1
-if [[ $SCM_MODE == "mercurial" ]]; then
- #
- # Mercurial priorities:
- # 1. hg root from CODEMGR_WS environment variable
- # 1a. hg root from CODEMGR_WS/usr/closed if we're somewhere under
- # usr/closed when we run webrev
- # 2. hg root from directory of invocation
- #
- if [[ ${PWD} =~ "usr/closed" ]]; then
- testparent=${CODEMGR_WS}/usr/closed
- # If we're in OpenSolaris mode, we enforce a minor policy:
- # help to make sure the reviewer doesn't accidentally publish
- # source which is under usr/closed
- if [[ -n "$Oflag" ]]; then
- print -u2 "OpenSolaris output not permitted with" \
- "usr/closed changes"
- exit 1
- fi
- else
- testparent=${CODEMGR_WS}
- fi
- [[ -z $codemgr_ws && -n $testparent ]] && \
- codemgr_ws=$(hg root -R $testparent 2>/dev/null)
- [[ -z $codemgr_ws ]] && codemgr_ws=$(hg root 2>/dev/null)
- CWS=$codemgr_ws
-elif [[ $SCM_MODE == "git" ]]; then
+
+if [[ $SCM_MODE == "git" ]]; then
#
# Git priorities:
# 1. git rev-parse --git-dir from CODEMGR_WS environment variable
@@ -2512,7 +2365,7 @@ fi
# is in use.
#
case "$SCM_MODE" in
-mercurial|git|subversion)
+git|subversion)
;;
unknown)
if [[ $flist_mode == "auto" ]]; then
@@ -2570,95 +2423,8 @@ if [[ $# -gt 0 ]]; then
print -u2 "WARNING: unused arguments: $*"
fi
-#
-# Before we entered the DO_EVERYTHING loop, we should have already set CWS
-# and CODEMGR_WS as needed. Here, we set the parent workspace.
-#
-if [[ $SCM_MODE == "mercurial" ]]; then
- #
- # 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
-
- 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
- pnode=$(trim_digest $HG_PARENT)
- PRETTY_PWS="${PWS} (at ${pnode})"
- cnode=$(hg parent -R $codemgr_ws --template '{node|short}' \
- 2>/dev/null)
- PRETTY_CWS="${CWS} (at ${cnode})"}
-elif [[ $SCM_MODE == "git" ]]; then
+if [[ $SCM_MODE == "git" ]]; then
# Check that "head" revision specified with -c or -h is sane
if [[ -n $cflag || -n $hflag ]]; then
head_rev=$($GIT rev-parse --verify --quiet "$codemgr_head")
@@ -3075,41 +2841,6 @@ $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.
- # 4) Eliminate any duplicate entries. (This can occur if a
- # file has been used as the source of an hg cp and it's
- # also been modified in the same changeset.)
- #
- SEDFILE=/tmp/$$.manifest.sed
- $SED '
- s#^[^ ]* ##
- s#/#\\\/#g
- s#^.*$#/^... . &$/p#
- ' < $FLIST | $SORT -u > $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
@@ -3423,16 +3154,16 @@ print "<table>"
#
# Get the preparer's name:
#
-# 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.
+# If the SCM detected is Git, and the configuration property user.name 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 [[ "$SCM_MODE" == git ]]; then
+ preparer=$(git config user.name 2>/dev/null)
if [[ -n "$preparer" ]]; then
preparer="$(echo "$preparer" | html_quote)"
fi
@@ -3660,8 +3391,7 @@ do
rm $F.count
fi
- if [[ $SCM_MODE == "mercurial" ||
- $SCM_MODE == "unknown" ]]; then
+ if [[ $SCM_MODE == "unknown" ]]; then
# Include warnings for important file mode situations:
# 1) New executable files
# 2) Permission changes of any kind