forked from mirrors/gecko-dev
		
	--HG-- rename : third_party/python/hglib/LICENSE => third_party/python/python-hglib/LICENSE rename : third_party/python/hglib/hglib/__init__.py => third_party/python/python-hglib/hglib/__init__.py rename : third_party/python/hglib/hglib/client.py => third_party/python/python-hglib/hglib/client.py rename : third_party/python/hglib/hglib/context.py => third_party/python/python-hglib/hglib/context.py rename : third_party/python/hglib/hglib/error.py => third_party/python/python-hglib/hglib/error.py rename : third_party/python/hglib/hglib/merge.py => third_party/python/python-hglib/hglib/merge.py rename : third_party/python/hglib/hglib/templates.py => third_party/python/python-hglib/hglib/templates.py rename : third_party/python/hglib/hglib/util.py => third_party/python/python-hglib/hglib/util.py rename : third_party/python/hglib/setup.py => third_party/python/python-hglib/setup.py extra : rebase_source : 552d93c9e90c04171c8b627c8f4f4fa5ec506cc3
		
			
				
	
	
		
			1717 lines
		
	
	
	
		
			64 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			1717 lines
		
	
	
	
		
			64 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
import struct, re, datetime
 | 
						|
import hglib
 | 
						|
from hglib import error, util, templates, merge, context
 | 
						|
 | 
						|
from hglib.util import b, cmdbuilder, BytesIO, strtobytes
 | 
						|
 | 
						|
class revision(tuple):
 | 
						|
    def __new__(cls, rev, node, tags, branch, author, desc, date):
 | 
						|
        return tuple.__new__(cls, (rev, node, tags, branch, author, desc, date))
 | 
						|
 | 
						|
    @property
 | 
						|
    def rev(self):
 | 
						|
        return self[0]
 | 
						|
 | 
						|
    @property
 | 
						|
    def node(self):
 | 
						|
        return self[1]
 | 
						|
 | 
						|
    @property
 | 
						|
    def tags(self):
 | 
						|
        return self[2]
 | 
						|
 | 
						|
    @property
 | 
						|
    def branch(self):
 | 
						|
        return self[3]
 | 
						|
 | 
						|
    @property
 | 
						|
    def author(self):
 | 
						|
        return self[4]
 | 
						|
 | 
						|
    @property
 | 
						|
    def desc(self):
 | 
						|
        return self[5]
 | 
						|
 | 
						|
    @property
 | 
						|
    def date(self):
 | 
						|
        return self[6]
 | 
						|
 | 
						|
class hgclient(object):
 | 
						|
    inputfmt = '>I'
 | 
						|
    outputfmt = '>cI'
 | 
						|
    outputfmtsize = struct.calcsize(outputfmt)
 | 
						|
    retfmt = '>i'
 | 
						|
 | 
						|
    def __init__(self, path, encoding, configs, connect=True):
 | 
						|
        self._args = [hglib.HGPATH, 'serve', '--cmdserver', 'pipe',
 | 
						|
                '--config', 'ui.interactive=True']
 | 
						|
        if path:
 | 
						|
            self._args += ['-R', path]
 | 
						|
        if configs:
 | 
						|
            for config in configs:
 | 
						|
                self._args += ['--config', config]
 | 
						|
        self._env = {'HGPLAIN': '1'}
 | 
						|
        if encoding:
 | 
						|
            self._env['HGENCODING'] = encoding
 | 
						|
 | 
						|
        self.server = None
 | 
						|
        self._version = None
 | 
						|
        # include the hidden changesets if True
 | 
						|
        self.hidden = None
 | 
						|
 | 
						|
        self._cbout = None
 | 
						|
        self._cberr = None
 | 
						|
        self._cbprompt = None
 | 
						|
 | 
						|
        if connect:
 | 
						|
            self.open()
 | 
						|
 | 
						|
        self._protocoltracefn = None
 | 
						|
 | 
						|
    def setcbout(self, cbout):
 | 
						|
        """
 | 
						|
        cbout is a function that will be called with the stdout data of
 | 
						|
        the command as it runs. Call with None to stop getting call backs.
 | 
						|
        """
 | 
						|
        self._cbout = cbout
 | 
						|
 | 
						|
    def setcberr(self, cberr):
 | 
						|
        """
 | 
						|
        cberr is a function that will be called with the stderr data of
 | 
						|
        the command as it runs.Call with None to stop getting call backs.
 | 
						|
        """
 | 
						|
        self._cberr = cberr
 | 
						|
 | 
						|
    def setcbprompt(self, cbprompt):
 | 
						|
        """
 | 
						|
        cbprompt is used to reply to prompts by the server
 | 
						|
        It receives the max number of bytes to return and the
 | 
						|
        contents of stdout received so far.
 | 
						|
 | 
						|
        Call with None to stop getting call backs.
 | 
						|
 | 
						|
        cbprompt is never called from merge() or import_()
 | 
						|
        which already handle the prompt.
 | 
						|
        """
 | 
						|
        self._cbprompt = cbprompt
 | 
						|
 | 
						|
    def setprotocoltrace(self, tracefn=None):
 | 
						|
        """
 | 
						|
        if tracefn is None no trace calls will be made.
 | 
						|
        Otherwise tracefn is call as tracefn( direction, channel, data )
 | 
						|
        direction is 'r' for read from server and 'w' for write to server
 | 
						|
        channel is always None when direction is 'w'
 | 
						|
        and the channel-identified when the direction is 'r'
 | 
						|
        """
 | 
						|
        self._protocoltracefn = tracefn
 | 
						|
 | 
						|
    def __enter__(self):
 | 
						|
        if self.server is None:
 | 
						|
            self.open()
 | 
						|
        return self
 | 
						|
 | 
						|
    def __exit__(self, exc_type, exc_val, exc_tb):
 | 
						|
        self.close()
 | 
						|
 | 
						|
    def _readhello(self):
 | 
						|
        """ read the hello message the server sends when started """
 | 
						|
        ch, msg = self._readchannel()
 | 
						|
        assert ch == b('o')
 | 
						|
 | 
						|
        msg = msg.split(b('\n'))
 | 
						|
 | 
						|
        self.capabilities = msg[0][len(b('capabilities: ')):]
 | 
						|
        if not self.capabilities:
 | 
						|
            raise error.ResponseError(
 | 
						|
                "bad hello message: expected 'capabilities: '"
 | 
						|
                ", got %r" % msg[0])
 | 
						|
 | 
						|
        self.capabilities = set(self.capabilities.split())
 | 
						|
 | 
						|
        # at the very least the server should be able to run commands
 | 
						|
        assert b('runcommand') in self.capabilities
 | 
						|
 | 
						|
        self._encoding = msg[1][len(b('encoding: ')):]
 | 
						|
        if not self._encoding:
 | 
						|
            raise error.ResponseError("bad hello message: expected 'encoding: '"
 | 
						|
                                      ", got %r" % msg[1])
 | 
						|
 | 
						|
    def _readchannel(self):
 | 
						|
        data = self.server.stdout.read(hgclient.outputfmtsize)
 | 
						|
        if not data:
 | 
						|
            raise error.ServerError()
 | 
						|
        channel, length = struct.unpack(hgclient.outputfmt, data)
 | 
						|
        if channel in b('IL'):
 | 
						|
            return channel, length
 | 
						|
        else:
 | 
						|
            return channel, self.server.stdout.read(length)
 | 
						|
 | 
						|
    @staticmethod
 | 
						|
    def _parserevs(splitted):
 | 
						|
        '''splitted is a list of fields according to our rev.style, where
 | 
						|
        each 6 fields compose one revision.
 | 
						|
        '''
 | 
						|
        revs = []
 | 
						|
        for rev in util.grouper(7, splitted):
 | 
						|
            # truncate the timezone and convert to a local datetime
 | 
						|
            posixtime = float(rev[6].split(b('.'), 1)[0])
 | 
						|
            dt = datetime.datetime.fromtimestamp(posixtime)
 | 
						|
            revs.append(revision(rev[0], rev[1], rev[2], rev[3],
 | 
						|
                                 rev[4], rev[5], dt))
 | 
						|
        return revs
 | 
						|
 | 
						|
    def runcommand(self, args, inchannels, outchannels):
 | 
						|
        def writeblock(data):
 | 
						|
            if self._protocoltracefn is not None:
 | 
						|
                self._protocoltracefn('w', None, data)
 | 
						|
            self.server.stdin.write(struct.pack(self.inputfmt, len(data)))
 | 
						|
            self.server.stdin.write(data)
 | 
						|
            self.server.stdin.flush()
 | 
						|
 | 
						|
        if not self.server:
 | 
						|
            raise ValueError("server not connected")
 | 
						|
 | 
						|
        self.server.stdin.write(b('runcommand\n'))
 | 
						|
        writeblock(b('\0').join(args))
 | 
						|
 | 
						|
        while True:
 | 
						|
            channel, data = self._readchannel()
 | 
						|
            if self._protocoltracefn is not None:
 | 
						|
                self._protocoltracefn('r', channel, data)
 | 
						|
 | 
						|
            # input channels
 | 
						|
            if channel in inchannels:
 | 
						|
                writeblock(inchannels[channel](data))
 | 
						|
            # output channels
 | 
						|
            elif channel in outchannels:
 | 
						|
                outchannels[channel](data)
 | 
						|
            # result channel, command finished
 | 
						|
            elif channel == b('r'):
 | 
						|
                return struct.unpack(hgclient.retfmt, data)[0]
 | 
						|
            # a channel that we don't know and can't ignore
 | 
						|
            elif channel.isupper():
 | 
						|
                raise error.ResponseError(
 | 
						|
                    "unexpected data on required channel '%s'" % channel)
 | 
						|
            # optional channel
 | 
						|
            else:
 | 
						|
                pass
 | 
						|
 | 
						|
    def rawcommand(self, args, eh=None, prompt=None, input=None):
 | 
						|
        """
 | 
						|
        args is the cmdline (usually built using util.cmdbuilder)
 | 
						|
 | 
						|
        eh is an error handler that is passed the return code, stdout and stderr
 | 
						|
        If no eh is given, we raise a CommandError if ret != 0
 | 
						|
 | 
						|
        prompt is used to reply to prompts by the server
 | 
						|
        It receives the max number of bytes to return and the contents of stdout
 | 
						|
        received so far
 | 
						|
 | 
						|
        input is used to reply to bulk data requests by the server
 | 
						|
        It receives the max number of bytes to return
 | 
						|
        """
 | 
						|
        out, err = BytesIO(), BytesIO()
 | 
						|
        outchannels = {}
 | 
						|
        if self._cbout is None:
 | 
						|
            outchannels[b('o')] = out.write
 | 
						|
        else:
 | 
						|
            def out_handler(data):
 | 
						|
                out.write(data)
 | 
						|
                self._cbout(data)
 | 
						|
            outchannels[b('o')] = out_handler
 | 
						|
        if self._cberr is None:
 | 
						|
            outchannels[b('e')] = err.write
 | 
						|
        else:
 | 
						|
            def err_handler(data):
 | 
						|
                err.write(data)
 | 
						|
                self._cberr(data)
 | 
						|
            outchannels[b('e')] = err_handler
 | 
						|
 | 
						|
        inchannels = {}
 | 
						|
        if prompt is None:
 | 
						|
            prompt = self._cbprompt
 | 
						|
        if prompt is not None:
 | 
						|
            def func(size):
 | 
						|
                reply = prompt(size, out.getvalue())
 | 
						|
                return reply
 | 
						|
            inchannels[b('L')] = func
 | 
						|
        if input is not None:
 | 
						|
            inchannels[b('I')] = input
 | 
						|
 | 
						|
        ret = self.runcommand(args, inchannels, outchannels)
 | 
						|
        out, err = out.getvalue(), err.getvalue()
 | 
						|
 | 
						|
        if ret:
 | 
						|
            if eh is None:
 | 
						|
                raise error.CommandError(args, ret, out, err)
 | 
						|
            else:
 | 
						|
                return eh(ret, out, err)
 | 
						|
        return out
 | 
						|
 | 
						|
    def open(self):
 | 
						|
        if self.server is not None:
 | 
						|
            raise ValueError('server already open')
 | 
						|
 | 
						|
        self.server = util.popen(self._args, self._env)
 | 
						|
        try:
 | 
						|
            self._readhello()
 | 
						|
        except error.ServerError:
 | 
						|
            ret, serr = self._close()
 | 
						|
            raise error.ServerError('server exited with status %d: %s'
 | 
						|
                                    % (ret, serr.strip()))
 | 
						|
        return self
 | 
						|
 | 
						|
    def close(self):
 | 
						|
        """Closes the command server instance and waits for it to exit,
 | 
						|
        returns the exit code.
 | 
						|
 | 
						|
        Attempting to call any function afterwards that needs to
 | 
						|
        communicate with the server will raise a ValueError.
 | 
						|
        """
 | 
						|
        return self._close()[0]
 | 
						|
 | 
						|
    def _close(self):
 | 
						|
        _sout, serr = self.server.communicate()
 | 
						|
        ret = self.server.returncode
 | 
						|
        self.server = None
 | 
						|
        return ret, serr
 | 
						|
 | 
						|
    def add(self, files=[], dryrun=False, subrepos=False, include=None,
 | 
						|
            exclude=None):
 | 
						|
        """
 | 
						|
        Add the specified files on the next commit.
 | 
						|
        If no files are given, add all files to the repository.
 | 
						|
 | 
						|
        dryrun - do no perform actions
 | 
						|
        subrepos - recurse into subrepositories
 | 
						|
        include - include names matching the given patterns
 | 
						|
        exclude - exclude names matching the given patterns
 | 
						|
 | 
						|
        Return whether all given files were added.
 | 
						|
        """
 | 
						|
        if not isinstance(files, list):
 | 
						|
            files = [files]
 | 
						|
 | 
						|
        args = cmdbuilder(b('add'), n=dryrun, S=subrepos, I=include, X=exclude,
 | 
						|
                          *files)
 | 
						|
 | 
						|
        eh = util.reterrorhandler(args)
 | 
						|
        self.rawcommand(args, eh=eh)
 | 
						|
 | 
						|
        return bool(eh)
 | 
						|
 | 
						|
    def addremove(self, files=[], similarity=None, dryrun=False, include=None,
 | 
						|
                  exclude=None):
 | 
						|
        """Add all new files and remove all missing files from the repository.
 | 
						|
 | 
						|
        New files are ignored if they match any of the patterns in
 | 
						|
        ".hgignore". As with add, these changes take effect at the
 | 
						|
        next commit.
 | 
						|
 | 
						|
        similarity - used to detect renamed files. With a parameter
 | 
						|
        greater than 0, this compares every removed file with every
 | 
						|
        added file and records those similar enough as renames. This
 | 
						|
        option takes a percentage between 0 (disabled) and 100 (files
 | 
						|
        must be identical) as its parameter. Detecting renamed files
 | 
						|
        this way can be expensive. After using this option, "hg status
 | 
						|
        -C" can be used to check which files were identified as moved
 | 
						|
        or renamed.
 | 
						|
 | 
						|
        dryrun - do no perform actions
 | 
						|
        include - include names matching the given patterns
 | 
						|
        exclude - exclude names matching the given patterns
 | 
						|
 | 
						|
        Return True if all files are successfully added.
 | 
						|
 | 
						|
        """
 | 
						|
        if not isinstance(files, list):
 | 
						|
            files = [files]
 | 
						|
 | 
						|
        args = cmdbuilder(b('addremove'), s=similarity, n=dryrun, I=include,
 | 
						|
                          X=exclude, *files)
 | 
						|
 | 
						|
        eh = util.reterrorhandler(args)
 | 
						|
        self.rawcommand(args, eh=eh)
 | 
						|
 | 
						|
        return bool(eh)
 | 
						|
 | 
						|
    def annotate(self, files, rev=None, nofollow=False, text=False, user=False,
 | 
						|
                 file=False, date=False, number=False, changeset=False,
 | 
						|
                 line=False, verbose=False, include=None, exclude=None):
 | 
						|
        """
 | 
						|
        Show changeset information by line for each file in files.
 | 
						|
 | 
						|
        rev - annotate the specified revision
 | 
						|
        nofollow - don't follow copies and renames
 | 
						|
        text - treat all files as text
 | 
						|
        user - list the author (long with -v)
 | 
						|
        file - list the filename
 | 
						|
        date - list the date
 | 
						|
        number - list the revision number (default)
 | 
						|
        changeset - list the changeset
 | 
						|
        line - show line number at the first appearance
 | 
						|
        include - include names matching the given patterns
 | 
						|
        exclude - exclude names matching the given patterns
 | 
						|
 | 
						|
        Yields a (info, contents) tuple for each line in a file. Info is a space
 | 
						|
        separated string according to the given options.
 | 
						|
        """
 | 
						|
        if not isinstance(files, list):
 | 
						|
            files = [files]
 | 
						|
 | 
						|
        args = cmdbuilder(b('annotate'), r=rev, no_follow=nofollow, a=text,
 | 
						|
                          u=user, f=file, d=date, n=number, c=changeset,
 | 
						|
                          l=line, v=verbose, I=include, X=exclude,
 | 
						|
                          hidden=self.hidden, *files)
 | 
						|
 | 
						|
        out = self.rawcommand(args)
 | 
						|
 | 
						|
        for line in out.splitlines():
 | 
						|
            yield tuple(line.split(b(': '), 1))
 | 
						|
 | 
						|
    def archive(self, dest, rev=None, nodecode=False, prefix=None, type=None,
 | 
						|
                subrepos=False, include=None, exclude=None):
 | 
						|
        """Create an unversioned archive of a repository revision.
 | 
						|
 | 
						|
        The exact name of the destination archive or directory is given using a
 | 
						|
        format string; see export for details.
 | 
						|
 | 
						|
        Each member added to an archive file has a directory prefix
 | 
						|
        prepended. Use prefix to specify a format string for the
 | 
						|
        prefix. The default is the basename of the archive, with
 | 
						|
        suffixes removed.
 | 
						|
 | 
						|
        dest - destination path
 | 
						|
        rev - revision to distribute. The revision used is the parent of the
 | 
						|
        working directory if one isn't given.
 | 
						|
 | 
						|
        nodecode - do not pass files through decoders
 | 
						|
        prefix - directory prefix for files in archive
 | 
						|
        type - type of distribution to create. The archive type is automatically
 | 
						|
        detected based on file extension if one isn't given.
 | 
						|
 | 
						|
        Valid types are:
 | 
						|
 | 
						|
        "files"  a directory full of files (default)
 | 
						|
        "tar"    tar archive, uncompressed
 | 
						|
        "tbz2"   tar archive, compressed using bzip2
 | 
						|
        "tgz"    tar archive, compressed using gzip
 | 
						|
        "uzip"   zip archive, uncompressed
 | 
						|
        "zip"    zip archive, compressed using deflate
 | 
						|
 | 
						|
        subrepos - recurse into subrepositories
 | 
						|
        include - include names matching the given patterns
 | 
						|
        exclude - exclude names matching the given patterns
 | 
						|
 | 
						|
        """
 | 
						|
        args = cmdbuilder(b('archive'), dest, r=rev,
 | 
						|
                          no_decode=nodecode, p=prefix,
 | 
						|
                          t=type, S=subrepos, I=include, X=exclude,
 | 
						|
                          hidden=self.hidden)
 | 
						|
 | 
						|
        self.rawcommand(args)
 | 
						|
 | 
						|
    def backout(self, rev, merge=False, parent=None, tool=None, message=None,
 | 
						|
                logfile=None, date=None, user=None):
 | 
						|
        """Prepare a new changeset with the effect of rev undone in the current
 | 
						|
        working directory.
 | 
						|
 | 
						|
        If rev is the parent of the working directory, then this new
 | 
						|
        changeset is committed automatically. Otherwise, hg needs to
 | 
						|
        merge the changes and the merged result is left uncommitted.
 | 
						|
 | 
						|
        rev - revision to backout
 | 
						|
        merge - merge with old dirstate parent after backout
 | 
						|
        parent - parent to choose when backing out merge
 | 
						|
        tool - specify merge tool
 | 
						|
        message - use text as commit message
 | 
						|
        logfile - read commit message from file
 | 
						|
        date - record the specified date as commit date
 | 
						|
        user - record the specified user as committer
 | 
						|
 | 
						|
        """
 | 
						|
        if message and logfile:
 | 
						|
            raise ValueError("cannot specify both a message and a logfile")
 | 
						|
 | 
						|
        args = cmdbuilder(b('backout'), r=rev, merge=merge, parent=parent,
 | 
						|
                          t=tool, m=message, l=logfile, d=date, u=user,
 | 
						|
                          hidden=self.hidden)
 | 
						|
 | 
						|
        self.rawcommand(args)
 | 
						|
 | 
						|
    def bookmark(self, name, rev=None, force=False, delete=False,
 | 
						|
                 inactive=False, rename=None):
 | 
						|
        """
 | 
						|
        Set a bookmark on the working directory's parent revision or rev,
 | 
						|
        with the given name.
 | 
						|
 | 
						|
        name - bookmark name
 | 
						|
        rev - revision to bookmark
 | 
						|
        force - bookmark even if another bookmark with the same name exists
 | 
						|
        delete - delete the given bookmark
 | 
						|
        inactive - do not mark the new bookmark active
 | 
						|
        rename - rename the bookmark given by rename to name
 | 
						|
        """
 | 
						|
        args = cmdbuilder(b('bookmark'), name, r=rev, f=force, d=delete,
 | 
						|
                          i=inactive, m=rename)
 | 
						|
 | 
						|
        self.rawcommand(args)
 | 
						|
 | 
						|
    def bookmarks(self):
 | 
						|
        """
 | 
						|
        Return the bookmarks as a list of (name, rev, node) and the index of the
 | 
						|
        current one.
 | 
						|
 | 
						|
        If there isn't a current one, -1 is returned as the index.
 | 
						|
        """
 | 
						|
        args = cmdbuilder(b('bookmarks'), hidden=self.hidden)
 | 
						|
        out = self.rawcommand(args)
 | 
						|
 | 
						|
        bms = []
 | 
						|
        current = -1
 | 
						|
        if out.rstrip() != b('no bookmarks set'):
 | 
						|
            for line in out.splitlines():
 | 
						|
                iscurrent, line = line[0:3], line[3:]
 | 
						|
                if b('*') in iscurrent:
 | 
						|
                    current = len(bms)
 | 
						|
                name, line = line.split(b(' '), 1)
 | 
						|
                rev, node = line.split(b(':'))
 | 
						|
                bms.append((name, int(rev), node))
 | 
						|
        return bms, current
 | 
						|
 | 
						|
    def branch(self, name=None, clean=False, force=False):
 | 
						|
        """When name isn't given, return the current branch name. Otherwise
 | 
						|
        set the working directory branch name (the branch will not
 | 
						|
        exist in the repository until the next commit). Standard
 | 
						|
        practice recommends that primary development take place on the
 | 
						|
        'default' branch.
 | 
						|
 | 
						|
        When clean is True, reset and return the working directory
 | 
						|
        branch to that of the parent of the working directory,
 | 
						|
        negating a previous branch change.
 | 
						|
 | 
						|
        name - new branch name
 | 
						|
        clean - reset branch name to parent branch name
 | 
						|
        force - set branch name even if it shadows an existing branch
 | 
						|
 | 
						|
        """
 | 
						|
        if name and clean:
 | 
						|
            raise ValueError('cannot use both name and clean')
 | 
						|
 | 
						|
        args = cmdbuilder(b('branch'), name, f=force, C=clean)
 | 
						|
        out = self.rawcommand(args).rstrip()
 | 
						|
 | 
						|
        if name:
 | 
						|
            return name
 | 
						|
        elif not clean:
 | 
						|
            return out
 | 
						|
        else:
 | 
						|
            # len('reset working directory to branch ') == 34
 | 
						|
            return out[34:]
 | 
						|
 | 
						|
    def branches(self, active=False, closed=False):
 | 
						|
        """
 | 
						|
        Returns the repository's named branches as a list of (name, rev, node).
 | 
						|
 | 
						|
        active - show only branches that have unmerged heads
 | 
						|
        closed - show normal and closed branches
 | 
						|
        """
 | 
						|
        args = cmdbuilder(b('branches'), a=active, c=closed, hidden=self.hidden)
 | 
						|
        out = self.rawcommand(args)
 | 
						|
 | 
						|
        branches = []
 | 
						|
        for line in out.rstrip().splitlines():
 | 
						|
            namerev, node = line.rsplit(b(':'), 1)
 | 
						|
            name, rev = namerev.rsplit(b(' '), 1)
 | 
						|
            name = name.rstrip()
 | 
						|
            node = node.split()[0] # get rid of ' (inactive)'
 | 
						|
            branches.append((name, int(rev), node))
 | 
						|
        return branches
 | 
						|
 | 
						|
    def bundle(self, file, destrepo=None, rev=[], branch=[], base=[], all=False,
 | 
						|
               force=False, type=None, ssh=None, remotecmd=None,
 | 
						|
               insecure=False):
 | 
						|
        """Generate a compressed changegroup file collecting changesets not
 | 
						|
        known to be in another repository.
 | 
						|
 | 
						|
        If destrepo isn't given, then hg assumes the destination will have all
 | 
						|
        the nodes you specify with base. To create a bundle containing all
 | 
						|
        changesets, use all (or set base to 'null').
 | 
						|
 | 
						|
        file - destination file name
 | 
						|
        destrepo - repository to look for changes
 | 
						|
        rev - a changeset intended to be added to the destination
 | 
						|
        branch - a specific branch you would like to bundle
 | 
						|
        base - a base changeset assumed to be available at the destination
 | 
						|
        all - bundle all changesets in the repository
 | 
						|
        type - bundle compression type to use, available compression
 | 
						|
         methods are: none, bzip2, and gzip (default: bzip2)
 | 
						|
 | 
						|
        force - run even when the destrepo is unrelated
 | 
						|
        ssh - specify ssh command to use
 | 
						|
        remotecmd - specify hg command to run on the remote side
 | 
						|
        insecure - do not verify server certificate (ignoring
 | 
						|
         web.cacerts config)
 | 
						|
 | 
						|
        Return True if a bundle was created, False if no changes were found.
 | 
						|
 | 
						|
        """
 | 
						|
        args = cmdbuilder(b('bundle'), file, destrepo, f=force, r=rev, b=branch,
 | 
						|
                          base=base, a=all, t=type, e=ssh, remotecmd=remotecmd,
 | 
						|
                          insecure=insecure, hidden=self.hidden)
 | 
						|
 | 
						|
        eh = util.reterrorhandler(args)
 | 
						|
        self.rawcommand(args, eh=eh)
 | 
						|
 | 
						|
        return bool(eh)
 | 
						|
 | 
						|
    def cat(self, files, rev=None, output=None):
 | 
						|
        """Return a string containing the specified files as they were at the
 | 
						|
        given revision. If no revision is given, the parent of the working
 | 
						|
        directory is used, or tip if no revision is checked out.
 | 
						|
 | 
						|
        If output is given, writes the contents to the specified file.
 | 
						|
        The name of the file is given using a format string. The
 | 
						|
        formatting rules are the same as for the export command, with
 | 
						|
        the following additions:
 | 
						|
 | 
						|
        "%s"  basename of file being printed
 | 
						|
        "%d"  dirname of file being printed, or '.' if in repository root
 | 
						|
        "%p"  root-relative path name of file being printed
 | 
						|
 | 
						|
        """
 | 
						|
        args = cmdbuilder(b('cat'), r=rev, o=output, hidden=self.hidden, *files)
 | 
						|
        out = self.rawcommand(args)
 | 
						|
 | 
						|
        if not output:
 | 
						|
            return out
 | 
						|
 | 
						|
    def clone(self, source=b('.'), dest=None, branch=None, updaterev=None,
 | 
						|
              revrange=None):
 | 
						|
        """
 | 
						|
        Create a copy of an existing repository specified by source in a new
 | 
						|
        directory dest.
 | 
						|
 | 
						|
        If dest isn't specified, it defaults to the basename of source.
 | 
						|
 | 
						|
        branch - clone only the specified branch
 | 
						|
        updaterev - revision, tag or branch to check out
 | 
						|
        revrange - include the specified changeset
 | 
						|
        """
 | 
						|
        args = cmdbuilder(b('clone'), source, dest, b=branch,
 | 
						|
                          u=updaterev, r=revrange)
 | 
						|
        self.rawcommand(args)
 | 
						|
 | 
						|
    def init(self, dest, ssh=None, remotecmd=None, insecure=False):
 | 
						|
        args = util.cmdbuilder('init', dest, e=ssh, remotecmd=remotecmd,
 | 
						|
                               insecure=insecure)
 | 
						|
        self.rawcommand(args)
 | 
						|
 | 
						|
    def commit(self, message=None, logfile=None, addremove=False,
 | 
						|
               closebranch=False, date=None, user=None, include=None,
 | 
						|
               exclude=None, amend=False):
 | 
						|
        """
 | 
						|
        Commit changes reported by status into the repository.
 | 
						|
 | 
						|
        message - the commit message
 | 
						|
        logfile - read commit message from file
 | 
						|
        addremove - mark new/missing files as added/removed before committing
 | 
						|
        closebranch - mark a branch as closed, hiding it from the branch list
 | 
						|
        date - record the specified date as commit date
 | 
						|
        user - record the specified user as committer
 | 
						|
        include - include names matching the given patterns
 | 
						|
        exclude - exclude names matching the given patterns
 | 
						|
        amend - amend the parent of the working dir
 | 
						|
        """
 | 
						|
        if amend and message is None and logfile is None:
 | 
						|
            # retrieve current commit message
 | 
						|
            message = self.log(b('.'))[0][5]
 | 
						|
        if message is None and logfile is None and not amend:
 | 
						|
            raise ValueError("must provide at least a message or a logfile")
 | 
						|
        elif message and logfile:
 | 
						|
            raise ValueError("cannot specify both a message and a logfile")
 | 
						|
 | 
						|
        # --debug will print the committed cset
 | 
						|
        args = cmdbuilder(b('commit'), debug=True, m=message, A=addremove,
 | 
						|
                          close_branch=closebranch, d=date, u=user, l=logfile,
 | 
						|
                          I=include, X=exclude, amend=amend)
 | 
						|
        out = self.rawcommand(args)
 | 
						|
        m = re.search(b(r'^committed changeset (\d+):([0-9a-f]+)'), out,
 | 
						|
                      re.MULTILINE)
 | 
						|
        if not m:
 | 
						|
            raise ValueError('revision and node not found in hg output: %r'
 | 
						|
                             % out)
 | 
						|
        rev, node = m.groups()
 | 
						|
        return int(rev), node
 | 
						|
 | 
						|
    def config(self, names=[], untrusted=False, showsource=False):
 | 
						|
        """Return a list of (section, key, value) config settings from all
 | 
						|
        hgrc files
 | 
						|
 | 
						|
        When showsource is specified, return (source, section, key, value) where
 | 
						|
        source is of the form filename:[line]
 | 
						|
 | 
						|
        """
 | 
						|
        def splitline(s):
 | 
						|
            k, value = s.rstrip().split(b('='), 1)
 | 
						|
            section, key = k.split(b('.'), 1)
 | 
						|
            return section, key, value
 | 
						|
 | 
						|
        if not isinstance(names, list):
 | 
						|
            names = [names]
 | 
						|
 | 
						|
        args = cmdbuilder(b('showconfig'), u=untrusted, debug=showsource,
 | 
						|
                          *names)
 | 
						|
        out = self.rawcommand(args)
 | 
						|
 | 
						|
        conf = []
 | 
						|
        if showsource:
 | 
						|
            out = util.skiplines(out, b('read config from: '))
 | 
						|
            for line in out.splitlines():
 | 
						|
                m = re.match(b(r"(.+?:(?:\d+:)?) (.*)"), line)
 | 
						|
                t = splitline(m.group(2))
 | 
						|
                conf.append((m.group(1)[:-1], t[0], t[1], t[2]))
 | 
						|
        else:
 | 
						|
            for line in out.splitlines():
 | 
						|
                conf.append(splitline(line))
 | 
						|
 | 
						|
        return conf
 | 
						|
 | 
						|
    @property
 | 
						|
    def encoding(self):
 | 
						|
        """
 | 
						|
        Return the server's encoding (as reported in the hello message).
 | 
						|
        """
 | 
						|
        if not b('getencoding') in self.capabilities:
 | 
						|
            raise CapabilityError('getencoding')
 | 
						|
 | 
						|
        if not self._encoding:
 | 
						|
            self.server.stdin.write(b('getencoding\n'))
 | 
						|
            self._encoding = self._readfromchannel('r')
 | 
						|
 | 
						|
        return self._encoding
 | 
						|
 | 
						|
    def copy(self, source, dest, after=False, force=False, dryrun=False,
 | 
						|
             include=None, exclude=None):
 | 
						|
        """Mark dest as having copies of source files. If dest is a
 | 
						|
        directory, copies are put in that directory. If dest is a
 | 
						|
        file, then source must be a string.
 | 
						|
 | 
						|
        Returns True on success, False if errors are encountered.
 | 
						|
 | 
						|
        source - a file or a list of files
 | 
						|
        dest - a destination file or directory
 | 
						|
        after - record a copy that has already occurred
 | 
						|
        force - forcibly copy over an existing managed file
 | 
						|
        dryrun - do not perform actions, just print output
 | 
						|
        include - include names matching the given patterns
 | 
						|
        exclude - exclude names matching the given patterns
 | 
						|
 | 
						|
        """
 | 
						|
        if not isinstance(source, list):
 | 
						|
            source = [source]
 | 
						|
 | 
						|
        source.append(dest)
 | 
						|
        args = cmdbuilder(b('copy'), A=after, f=force, n=dryrun,
 | 
						|
                          I=include, X=exclude, *source)
 | 
						|
 | 
						|
        eh = util.reterrorhandler(args)
 | 
						|
        self.rawcommand(args, eh=eh)
 | 
						|
 | 
						|
        return bool(eh)
 | 
						|
 | 
						|
    def diff(self, files=[], revs=[], change=None, text=False,
 | 
						|
             git=False, nodates=False, showfunction=False,
 | 
						|
             reverse=False, ignoreallspace=False,
 | 
						|
             ignorespacechange=False, ignoreblanklines=False,
 | 
						|
             unified=None, stat=False, subrepos=False, include=None,
 | 
						|
             exclude=None):
 | 
						|
        """
 | 
						|
        Return differences between revisions for the specified files.
 | 
						|
 | 
						|
        revs - a revision or a list of two revisions to diff
 | 
						|
        change - change made by revision
 | 
						|
        text - treat all files as text
 | 
						|
        git - use git extended diff format
 | 
						|
        nodates - omit dates from diff headers
 | 
						|
        showfunction - show which function each change is in
 | 
						|
        reverse - produce a diff that undoes the changes
 | 
						|
        ignoreallspace - ignore white space when comparing lines
 | 
						|
        ignorespacechange - ignore changes in the amount of white space
 | 
						|
        ignoreblanklines - ignore changes whose lines are all blank
 | 
						|
        unified - number of lines of context to show
 | 
						|
        stat - output diffstat-style summary of changes
 | 
						|
        subrepos - recurse into subrepositories
 | 
						|
        include - include names matching the given patterns
 | 
						|
        exclude - exclude names matching the given patterns
 | 
						|
        """
 | 
						|
        if change and revs:
 | 
						|
            raise ValueError('cannot specify both change and rev')
 | 
						|
 | 
						|
        args = cmdbuilder(b('diff'), r=list(map(strtobytes, revs)), c=change,
 | 
						|
                          a=text, g=git, nodates=nodates,
 | 
						|
                          p=showfunction, reverse=reverse,
 | 
						|
                          w=ignoreallspace, b=ignorespacechange,
 | 
						|
                          B=ignoreblanklines, U=unified, stat=stat,
 | 
						|
                          S=subrepos, I=include, X=exclude, hidden=self.hidden,
 | 
						|
                          *files)
 | 
						|
 | 
						|
        return self.rawcommand(args)
 | 
						|
 | 
						|
    def export(self, revs, output=None, switchparent=False,
 | 
						|
               text=False, git=False, nodates=False):
 | 
						|
        """Return the header and diffs for one or more changesets. When
 | 
						|
        output is given, dumps to file. The name of the file is given
 | 
						|
        using a format string. The formatting rules are as follows:
 | 
						|
 | 
						|
        "%%"  literal "%" character
 | 
						|
        "%H"  changeset hash (40 hexadecimal digits)
 | 
						|
        "%N"  number of patches being generated
 | 
						|
        "%R"  changeset revision number
 | 
						|
        "%b"  basename of the exporting repository
 | 
						|
        "%h"  short-form changeset hash (12 hexadecimal digits)
 | 
						|
        "%n"  zero-padded sequence number, starting at 1
 | 
						|
        "%r"  zero-padded changeset revision number
 | 
						|
 | 
						|
        output - print output to file with formatted name
 | 
						|
        switchparent - diff against the second parent
 | 
						|
        rev - a revision or list of revisions to export
 | 
						|
        text - treat all files as text
 | 
						|
        git - use git extended diff format
 | 
						|
        nodates - omit dates from diff headers
 | 
						|
 | 
						|
        """
 | 
						|
        if not isinstance(revs, list):
 | 
						|
            revs = [revs]
 | 
						|
        args = cmdbuilder(b('export'), o=output, switch_parent=switchparent,
 | 
						|
                          a=text, g=git, nodates=nodates, hidden=self.hidden,
 | 
						|
                          *revs)
 | 
						|
 | 
						|
        out = self.rawcommand(args)
 | 
						|
 | 
						|
        if output is None:
 | 
						|
            return out
 | 
						|
 | 
						|
    def forget(self, files, include=None, exclude=None):
 | 
						|
        """Mark the specified files so they will no longer be tracked after
 | 
						|
        the next commit.
 | 
						|
 | 
						|
        This only removes files from the current branch, not from the entire
 | 
						|
        project history, and it does not delete them from the working directory.
 | 
						|
 | 
						|
        Returns True on success.
 | 
						|
 | 
						|
        include - include names matching the given patterns
 | 
						|
        exclude - exclude names matching the given patterns
 | 
						|
 | 
						|
        """
 | 
						|
        if not isinstance(files, list):
 | 
						|
            files = [files]
 | 
						|
 | 
						|
        args = cmdbuilder(b('forget'), I=include, X=exclude, *files)
 | 
						|
 | 
						|
        eh = util.reterrorhandler(args)
 | 
						|
        self.rawcommand(args, eh=eh)
 | 
						|
 | 
						|
        return bool(eh)
 | 
						|
 | 
						|
    def grep(self, pattern, files=[], all=False, text=False, follow=False,
 | 
						|
             ignorecase=False, fileswithmatches=False, line=False, user=False,
 | 
						|
             date=False, include=None, exclude=None):
 | 
						|
        """Search for a pattern in specified files and revisions.
 | 
						|
 | 
						|
        This behaves differently than Unix grep. It only accepts Python/Perl
 | 
						|
        regexps. It searches repository history, not the working directory.
 | 
						|
        It always prints the revision number in which a match appears.
 | 
						|
 | 
						|
        Yields (filename, revision, [line, [match status, [user,
 | 
						|
        [date, [match]]]]]) per match depending on the given options.
 | 
						|
 | 
						|
        all - print all revisions that match
 | 
						|
        text - treat all files as text
 | 
						|
        follow - follow changeset history, or file history across
 | 
						|
         copies and renames
 | 
						|
        ignorecase - ignore case when matching
 | 
						|
        fileswithmatches - return only filenames and revisions that match
 | 
						|
        line - return line numbers in the result tuple
 | 
						|
        user - return the author in the result tuple
 | 
						|
        date - return the date in the result tuple
 | 
						|
        include - include names matching the given patterns
 | 
						|
        exclude - exclude names matching the given patterns
 | 
						|
 | 
						|
        """
 | 
						|
        if not isinstance(files, list):
 | 
						|
            files = [files]
 | 
						|
 | 
						|
        args = cmdbuilder(b('grep'), all=all, a=text, f=follow, i=ignorecase,
 | 
						|
                          l=fileswithmatches, n=line, u=user, d=date,
 | 
						|
                          I=include, X=exclude, hidden=self.hidden,
 | 
						|
                          *[pattern] + files)
 | 
						|
        args.append(b('-0'))
 | 
						|
 | 
						|
        def eh(ret, out, err):
 | 
						|
            if ret != 1:
 | 
						|
                raise error.CommandError(args, ret, out, err)
 | 
						|
            return b('')
 | 
						|
 | 
						|
        out = self.rawcommand(args, eh=eh).split(b('\0'))
 | 
						|
 | 
						|
        fieldcount = 3
 | 
						|
        if user:
 | 
						|
            fieldcount += 1
 | 
						|
        if date:
 | 
						|
            fieldcount += 1
 | 
						|
        if line:
 | 
						|
            fieldcount += 1
 | 
						|
        if all:
 | 
						|
            fieldcount += 1
 | 
						|
        if fileswithmatches:
 | 
						|
            fieldcount -= 1
 | 
						|
 | 
						|
        return util.grouper(fieldcount, out)
 | 
						|
 | 
						|
    def heads(self, rev=[], startrev=[], topological=False, closed=False):
 | 
						|
        """Return a list of current repository heads or branch heads.
 | 
						|
 | 
						|
        rev - return only branch heads on the branches associated with
 | 
						|
        the specified changesets.
 | 
						|
 | 
						|
        startrev - return only heads which are descendants of the given revs.
 | 
						|
        topological - named branch mechanics will be ignored and only changesets
 | 
						|
        without children will be shown.
 | 
						|
 | 
						|
        closed - normal and closed branch heads.
 | 
						|
 | 
						|
        """
 | 
						|
        if not isinstance(rev, list):
 | 
						|
            rev = [rev]
 | 
						|
 | 
						|
        args = cmdbuilder(b('heads'), r=startrev, t=topological, c=closed,
 | 
						|
                          template=templates.changeset, hidden=self.hidden,
 | 
						|
                          *rev)
 | 
						|
 | 
						|
        def eh(ret, out, err):
 | 
						|
            if ret != 1:
 | 
						|
                raise error.CommandError(args, ret, out, err)
 | 
						|
            return b('')
 | 
						|
 | 
						|
        out = self.rawcommand(args, eh=eh).split(b('\0'))[:-1]
 | 
						|
        return self._parserevs(out)
 | 
						|
 | 
						|
    def identify(self, rev=None, source=None, num=False, id=False, branch=False,
 | 
						|
                 tags=False, bookmarks=False):
 | 
						|
        """Return a summary string identifying the repository state at rev
 | 
						|
        using one or two parent hash identifiers, followed by a "+" if
 | 
						|
        the working directory has uncommitted changes, the branch name
 | 
						|
        (if not default), a list of tags, and a list of bookmarks.
 | 
						|
 | 
						|
        When rev is not given, return a summary string of the current
 | 
						|
        state of the repository.
 | 
						|
 | 
						|
        Specifying source as a repository root or Mercurial bundle will cause
 | 
						|
        lookup to operate on that repository/bundle.
 | 
						|
 | 
						|
        num - show local revision number
 | 
						|
        id - show global revision id
 | 
						|
        branch - show branch
 | 
						|
        tags - show tags
 | 
						|
        bookmarks - show bookmarks
 | 
						|
 | 
						|
        """
 | 
						|
        args = cmdbuilder(b('identify'), source, r=rev, n=num, i=id,
 | 
						|
                          b=branch, t=tags, B=bookmarks,
 | 
						|
                          hidden=self.hidden)
 | 
						|
 | 
						|
        return self.rawcommand(args)
 | 
						|
 | 
						|
    def import_(self, patches, strip=None, force=False, nocommit=False,
 | 
						|
                bypass=False, exact=False, importbranch=False, message=None,
 | 
						|
                date=None, user=None, similarity=None):
 | 
						|
        """Import the specified patches which can be a list of file names or a
 | 
						|
        file-like object and commit them individually (unless nocommit is
 | 
						|
        specified).
 | 
						|
 | 
						|
        strip - directory strip option for patch. This has the same
 | 
						|
        meaning as the corresponding patch option (default: 1)
 | 
						|
 | 
						|
        force - skip check for outstanding uncommitted changes
 | 
						|
        nocommit - don't commit, just update the working directory
 | 
						|
        bypass - apply patch without touching the working directory
 | 
						|
        exact - apply patch to the nodes from which it was generated
 | 
						|
        importbranch - use any branch information in patch (implied by exact)
 | 
						|
        message - the commit message
 | 
						|
        date - record the specified date as commit date
 | 
						|
        user - record the specified user as committer
 | 
						|
        similarity - guess renamed files by similarity (0<=s<=100)
 | 
						|
 | 
						|
        """
 | 
						|
        if hasattr(patches, 'read') and hasattr(patches, 'readline'):
 | 
						|
            patch = patches
 | 
						|
 | 
						|
            def readline(size, output):
 | 
						|
                return patch.readline(size)
 | 
						|
 | 
						|
            stdin = True
 | 
						|
            patches = ()
 | 
						|
            prompt = readline
 | 
						|
            input = patch.read
 | 
						|
        else:
 | 
						|
            stdin = False
 | 
						|
            prompt = None
 | 
						|
            input = None
 | 
						|
 | 
						|
        args = cmdbuilder(b('import'), strip=strip, force=force,
 | 
						|
                          no_commit=nocommit, bypass=bypass, exact=exact,
 | 
						|
                          import_branch=importbranch, message=message,
 | 
						|
                          date=date, user=user, similarity=similarity, _=stdin,
 | 
						|
                          *patches)
 | 
						|
 | 
						|
        self.rawcommand(args, prompt=prompt, input=input)
 | 
						|
 | 
						|
    def incoming(self, revrange=None, path=None, force=False, newest=False,
 | 
						|
                 bundle=None, bookmarks=False, branch=None, limit=None,
 | 
						|
                 nomerges=False, subrepos=False):
 | 
						|
        """Return new changesets found in the specified path or the default pull
 | 
						|
        location.
 | 
						|
 | 
						|
        When bookmarks=True, return a list of (name, node) of incoming
 | 
						|
        bookmarks.
 | 
						|
 | 
						|
        revrange - a remote changeset or list of changesets intended to be added
 | 
						|
        force - run even if remote repository is unrelated
 | 
						|
        newest - show newest record first
 | 
						|
        bundle - avoid downloading the changesets twice and store the
 | 
						|
         bundles into the specified file.
 | 
						|
 | 
						|
        bookmarks - compare bookmarks (this changes the return value)
 | 
						|
        branch - a specific branch you would like to pull
 | 
						|
        limit - limit number of changes returned
 | 
						|
        nomerges - do not show merges
 | 
						|
        ssh - specify ssh command to use
 | 
						|
        remotecmd - specify hg command to run on the remote side
 | 
						|
        insecure- do not verify server certificate (ignoring web.cacerts config)
 | 
						|
        subrepos - recurse into subrepositories
 | 
						|
 | 
						|
        """
 | 
						|
        args = cmdbuilder(b('incoming'), path,
 | 
						|
                          template=templates.changeset, r=revrange,
 | 
						|
                          f=force, n=newest, bundle=bundle,
 | 
						|
                          B=bookmarks, b=branch, l=limit, M=nomerges,
 | 
						|
                          S=subrepos)
 | 
						|
 | 
						|
        def eh(ret, out, err):
 | 
						|
            if ret != 1:
 | 
						|
                raise error.CommandError(args, ret, out, err)
 | 
						|
 | 
						|
        out = self.rawcommand(args, eh=eh)
 | 
						|
        if not out:
 | 
						|
            return []
 | 
						|
 | 
						|
        out = util.eatlines(out, 2)
 | 
						|
        if bookmarks:
 | 
						|
            bms = []
 | 
						|
            for line in out.splitlines():
 | 
						|
                bms.append(tuple(line.split()))
 | 
						|
            return bms
 | 
						|
        else:
 | 
						|
            out = out.split(b('\0'))[:-1]
 | 
						|
            return self._parserevs(out)
 | 
						|
 | 
						|
    def log(self, revrange=None, files=[], follow=False,
 | 
						|
            followfirst=False, date=None, copies=False, keyword=None,
 | 
						|
            removed=False, onlymerges=False, user=None, branch=None,
 | 
						|
            prune=None, hidden=None, limit=None, nomerges=False,
 | 
						|
            include=None, exclude=None):
 | 
						|
        """Return the revision history of the specified files or the entire
 | 
						|
        project.
 | 
						|
 | 
						|
        File history is shown without following rename or copy history of files.
 | 
						|
        Use follow with a filename to follow history across renames and copies.
 | 
						|
        follow without a filename will only show ancestors or descendants of the
 | 
						|
        starting revision. followfirst only follows the first parent of merge
 | 
						|
        revisions.
 | 
						|
 | 
						|
        If revrange isn't specified, the default is "tip:0" unless
 | 
						|
        follow is set, in which case the working directory parent is
 | 
						|
        used as the starting revision.
 | 
						|
 | 
						|
        The returned changeset is a named tuple with the following
 | 
						|
        string fields:
 | 
						|
 | 
						|
            - rev
 | 
						|
            - node
 | 
						|
            - tags (space delimited)
 | 
						|
            - branch
 | 
						|
            - author
 | 
						|
            - desc
 | 
						|
 | 
						|
        follow - follow changeset history, or file history across
 | 
						|
         copies and renames
 | 
						|
        followfirst - only follow the first parent of merge changesets
 | 
						|
        date - show revisions matching date spec
 | 
						|
        copies - show copied files
 | 
						|
        keyword - do case-insensitive search for a given text
 | 
						|
        removed - include revisions where files were removed
 | 
						|
        onlymerges - show only merges
 | 
						|
        user - revisions committed by user
 | 
						|
        branch - show changesets within the given named branch
 | 
						|
        prune - do not display revision or any of its ancestors
 | 
						|
        hidden - show hidden changesets
 | 
						|
        limit - limit number of changes displayed
 | 
						|
        nomerges - do not show merges
 | 
						|
        include - include names matching the given patterns
 | 
						|
        exclude - exclude names matching the given patterns
 | 
						|
 | 
						|
        """
 | 
						|
        if hidden is None:
 | 
						|
            hidden = self.hidden
 | 
						|
        args = cmdbuilder(b('log'), template=templates.changeset,
 | 
						|
                          r=revrange, f=follow, follow_first=followfirst,
 | 
						|
                          d=date, C=copies, k=keyword, removed=removed,
 | 
						|
                          m=onlymerges, u=user, b=branch, P=prune,
 | 
						|
                          l=limit, M=nomerges, I=include, X=exclude,
 | 
						|
                          hidden=hidden, *files)
 | 
						|
 | 
						|
        out = self.rawcommand(args)
 | 
						|
        out = out.split(b('\0'))[:-1]
 | 
						|
 | 
						|
        return self._parserevs(out)
 | 
						|
 | 
						|
    def manifest(self, rev=None, all=False):
 | 
						|
        """Yields (nodeid, permission, executable, symlink, file path) tuples
 | 
						|
        for version controlled files for the given revision. If no
 | 
						|
        revision is given, the first parent of the working directory
 | 
						|
        is used, or the null revision if no revision is checked out.
 | 
						|
 | 
						|
        When all is True, all files from all revisions are yielded
 | 
						|
        (just the name). This includes deleted and renamed files.
 | 
						|
 | 
						|
        """
 | 
						|
        args = cmdbuilder(b('manifest'), r=rev, all=all, debug=True,
 | 
						|
                          hidden=self.hidden)
 | 
						|
 | 
						|
        out = self.rawcommand(args)
 | 
						|
 | 
						|
        if all:
 | 
						|
            for line in out.splitlines():
 | 
						|
                yield line
 | 
						|
        else:
 | 
						|
            for line in out.splitlines():
 | 
						|
                node = line[0:40]
 | 
						|
                perm = line[41:44]
 | 
						|
                symlink = line[45:46] == b('@')
 | 
						|
                executable = line[45:46] == b('*')
 | 
						|
                yield node, perm, executable, symlink, line[47:]
 | 
						|
 | 
						|
    def merge(self, rev=None, force=False, tool=None, cb=merge.handlers.abort):
 | 
						|
        """Merge working directory with rev. If no revision is specified, the
 | 
						|
        working directory's parent is a head revision, and the current
 | 
						|
        branch contains exactly one other head, the other head is
 | 
						|
        merged with by default.
 | 
						|
 | 
						|
        The current working directory is updated with all changes made in the
 | 
						|
        requested revision since the last common predecessor revision.
 | 
						|
 | 
						|
        Files that changed between either parent are marked as changed for the
 | 
						|
        next commit and a commit must be performed before any further updates to
 | 
						|
        the repository are allowed. The next commit will have two parents.
 | 
						|
 | 
						|
        force - force a merge with outstanding changes
 | 
						|
        tool - can be used to specify the merge tool used for file merges. It
 | 
						|
        overrides the HGMERGE environment variable and your configuration files.
 | 
						|
 | 
						|
        cb - controls the behaviour when Mercurial prompts what to do
 | 
						|
        with regard to a specific file, e.g. when one parent modified
 | 
						|
        a file and the other removed it. It can be one of
 | 
						|
        merge.handlers, or a function that gets a single argument
 | 
						|
        which are the contents of stdout. It should return one of the
 | 
						|
        expected choices (a single character).
 | 
						|
 | 
						|
        """
 | 
						|
        # we can't really use --preview since merge doesn't support --template
 | 
						|
        args = cmdbuilder(b('merge'), r=rev, f=force, t=tool)
 | 
						|
 | 
						|
        prompt = None
 | 
						|
        if cb is merge.handlers.abort:
 | 
						|
            prompt = cb
 | 
						|
        elif cb is merge.handlers.noninteractive:
 | 
						|
            args.append(b('-y'))
 | 
						|
        else:
 | 
						|
            prompt = lambda size, output: cb(output) + b('\n')
 | 
						|
 | 
						|
        self.rawcommand(args, prompt=prompt)
 | 
						|
 | 
						|
    def move(self, source, dest, after=False, force=False, dryrun=False,
 | 
						|
             include=None, exclude=None):
 | 
						|
        """Mark dest as copies of source; mark source for deletion. If dest
 | 
						|
        is a directory, copies are put in that directory. If dest is a
 | 
						|
        file, then source must be a string.
 | 
						|
 | 
						|
        Returns True on success, False if errors are encountered.
 | 
						|
 | 
						|
        source - a file or a list of files
 | 
						|
        dest - a destination file or directory
 | 
						|
        after - record a rename that has already occurred
 | 
						|
        force - forcibly copy over an existing managed file
 | 
						|
        dryrun - do not perform actions, just print output
 | 
						|
        include - include names matching the given patterns
 | 
						|
        exclude - exclude names matching the given patterns
 | 
						|
 | 
						|
        """
 | 
						|
        if not isinstance(source, list):
 | 
						|
            source = [source]
 | 
						|
 | 
						|
        source.append(dest)
 | 
						|
        args = cmdbuilder(b('move'), A=after, f=force, n=dryrun,
 | 
						|
                          I=include, X=exclude, *source)
 | 
						|
 | 
						|
        eh = util.reterrorhandler(args)
 | 
						|
        self.rawcommand(args, eh=eh)
 | 
						|
 | 
						|
        return bool(eh)
 | 
						|
 | 
						|
    def outgoing(self, revrange=None, path=None, force=False, newest=False,
 | 
						|
                 bookmarks=False, branch=None, limit=None, nomerges=False,
 | 
						|
                 subrepos=False):
 | 
						|
        """Return changesets not found in the specified path or the default push
 | 
						|
        location.
 | 
						|
 | 
						|
        When bookmarks=True, return a list of (name, node) of
 | 
						|
        bookmarks that will be pushed.
 | 
						|
 | 
						|
        revrange - a (list of) changeset intended to be included in
 | 
						|
        the destination force - run even when the destination is
 | 
						|
        unrelated newest - show newest record first branch - a
 | 
						|
        specific branch you would like to push limit - limit number of
 | 
						|
        changes displayed nomerges - do not show merges ssh - specify
 | 
						|
        ssh command to use remotecmd - specify hg command to run on
 | 
						|
        the remote side insecure - do not verify server certificate
 | 
						|
        (ignoring web.cacerts config) subrepos - recurse into
 | 
						|
        subrepositories
 | 
						|
 | 
						|
        """
 | 
						|
        args = cmdbuilder(b('outgoing'),
 | 
						|
                          path,
 | 
						|
                          template=templates.changeset, r=revrange,
 | 
						|
                          f=force, n=newest, B=bookmarks,
 | 
						|
                          b=branch, S=subrepos)
 | 
						|
 | 
						|
        def eh(ret, out, err):
 | 
						|
            if ret != 1:
 | 
						|
                raise error.CommandError(args, ret, out, err)
 | 
						|
 | 
						|
        out = self.rawcommand(args, eh=eh)
 | 
						|
        if not out:
 | 
						|
            return []
 | 
						|
 | 
						|
        out = util.eatlines(out, 2)
 | 
						|
        if bookmarks:
 | 
						|
            bms = []
 | 
						|
            for line in out.splitlines():
 | 
						|
                bms.append(tuple(line.split()))
 | 
						|
            return bms
 | 
						|
        else:
 | 
						|
            out = out.split(b('\0'))[:-1]
 | 
						|
            return self._parserevs(out)
 | 
						|
 | 
						|
    def parents(self, rev=None, file=None):
 | 
						|
        """Return the working directory's parent revisions. If rev is given,
 | 
						|
        the parent of that revision will be printed. If file is given,
 | 
						|
        the revision in which the file was last changed (before the
 | 
						|
        working directory revision or the revision specified by rev)
 | 
						|
        is returned.
 | 
						|
 | 
						|
        """
 | 
						|
        args = cmdbuilder(b('parents'), file, template=templates.changeset,
 | 
						|
                          r=rev, hidden=self.hidden)
 | 
						|
 | 
						|
        out = self.rawcommand(args)
 | 
						|
        if not out:
 | 
						|
            return
 | 
						|
 | 
						|
        out = out.split(b('\0'))[:-1]
 | 
						|
 | 
						|
        return self._parserevs(out)
 | 
						|
 | 
						|
    def paths(self, name=None):
 | 
						|
        """
 | 
						|
        Return the definition of given symbolic path name. If no name is given,
 | 
						|
        return a dictionary of pathname : url of all available names.
 | 
						|
 | 
						|
        Path names are defined in the [paths] section of your configuration file
 | 
						|
        and in "/etc/mercurial/hgrc". If run inside a repository, ".hg/hgrc" is
 | 
						|
        used, too.
 | 
						|
        """
 | 
						|
        if not name:
 | 
						|
            out = self.rawcommand([b('paths')])
 | 
						|
            if not out:
 | 
						|
                return {}
 | 
						|
 | 
						|
            return dict([s.split(b(' = '))
 | 
						|
                         for s in out.rstrip().split(b('\n'))])
 | 
						|
        else:
 | 
						|
            args = cmdbuilder(b('paths'), name)
 | 
						|
            out = self.rawcommand(args)
 | 
						|
            return out.rstrip()
 | 
						|
 | 
						|
    def pull(self, source=None, rev=None, update=False, force=False,
 | 
						|
             bookmark=None, branch=None, ssh=None, remotecmd=None,
 | 
						|
             insecure=False, tool=None):
 | 
						|
        """Pull changes from a remote repository.
 | 
						|
 | 
						|
        This finds all changes from the repository specified by source
 | 
						|
        and adds them to this repository. If source is omitted, the
 | 
						|
        'default' path will be used. By default, this does not update
 | 
						|
        the copy of the project in the working directory.
 | 
						|
 | 
						|
        Returns True on success, False if update was given and there were
 | 
						|
        unresolved files.
 | 
						|
 | 
						|
        update - update to new branch head if changesets were pulled
 | 
						|
        force - run even when remote repository is unrelated
 | 
						|
        rev - a (list of) remote changeset intended to be added
 | 
						|
        bookmark - (list of) bookmark to pull
 | 
						|
        branch - a (list of) specific branch you would like to pull
 | 
						|
        ssh - specify ssh command to use
 | 
						|
        remotecmd - specify hg command to run on the remote side
 | 
						|
        insecure - do not verify server certificate (ignoring
 | 
						|
         web.cacerts config)
 | 
						|
        tool - specify merge tool for rebase
 | 
						|
 | 
						|
        """
 | 
						|
        args = cmdbuilder(b('pull'), source, r=rev, u=update, f=force,
 | 
						|
                          B=bookmark, b=branch, e=ssh,
 | 
						|
                          remotecmd=remotecmd, insecure=insecure,
 | 
						|
                          t=tool)
 | 
						|
 | 
						|
        eh = util.reterrorhandler(args)
 | 
						|
        self.rawcommand(args, eh=eh)
 | 
						|
 | 
						|
        return bool(eh)
 | 
						|
 | 
						|
    def push(self, dest=None, rev=None, force=False, bookmark=None, branch=None,
 | 
						|
             newbranch=False, ssh=None, remotecmd=None, insecure=False):
 | 
						|
        """Push changesets from this repository to the specified destination.
 | 
						|
 | 
						|
        This operation is symmetrical to pull: it is identical to a pull in the
 | 
						|
        destination repository from the current one.
 | 
						|
 | 
						|
        Returns True if push was successful, False if nothing to push.
 | 
						|
 | 
						|
        rev - the (list of) specified revision and all its ancestors
 | 
						|
        will be pushed to the remote repository.
 | 
						|
 | 
						|
        force - override the default behavior and push all changesets on all
 | 
						|
        branches.
 | 
						|
 | 
						|
        bookmark - (list of) bookmark to push
 | 
						|
        branch - a (list of) specific branch you would like to push
 | 
						|
        newbranch - allows push to create a new named branch that is
 | 
						|
         not present at the destination. This allows you to only create
 | 
						|
         a new branch without forcing other changes.
 | 
						|
 | 
						|
        ssh - specify ssh command to use
 | 
						|
        remotecmd - specify hg command to run on the remote side
 | 
						|
        insecure - do not verify server certificate (ignoring
 | 
						|
         web.cacerts config)
 | 
						|
 | 
						|
        """
 | 
						|
        args = cmdbuilder(b('push'), dest, r=rev, f=force, B=bookmark, b=branch,
 | 
						|
                          new_branch=newbranch, e=ssh, remotecmd=remotecmd,
 | 
						|
                          insecure=insecure)
 | 
						|
 | 
						|
        eh = util.reterrorhandler(args)
 | 
						|
        self.rawcommand(args, eh=eh)
 | 
						|
 | 
						|
        return bool(eh)
 | 
						|
 | 
						|
    def remove(self, files, after=False, force=False, include=None,
 | 
						|
               exclude=None):
 | 
						|
        """Schedule the indicated files for removal from the repository. This
 | 
						|
        only removes files from the current branch, not from the
 | 
						|
        entire project history.
 | 
						|
 | 
						|
        Returns True on success, False if any warnings encountered.
 | 
						|
 | 
						|
        after - used to remove only files that have already been deleted
 | 
						|
        force - remove (and delete) file even if added or modified
 | 
						|
        include - include names matching the given patterns
 | 
						|
        exclude - exclude names matching the given patterns
 | 
						|
 | 
						|
        """
 | 
						|
        if not isinstance(files, list):
 | 
						|
            files = [files]
 | 
						|
 | 
						|
        args = cmdbuilder(b('remove'), A=after, f=force, I=include, X=exclude,
 | 
						|
                          *files)
 | 
						|
 | 
						|
        eh = util.reterrorhandler(args)
 | 
						|
        self.rawcommand(args, eh=eh)
 | 
						|
 | 
						|
        return bool(eh)
 | 
						|
 | 
						|
    def resolve(self, file=[], all=False, listfiles=False, mark=False,
 | 
						|
                unmark=False, tool=None, include=None, exclude=None):
 | 
						|
        """
 | 
						|
        Redo merges or set/view the merge status of given files.
 | 
						|
 | 
						|
        Returns True on success, False if any files fail a resolve attempt.
 | 
						|
 | 
						|
        When listfiles is True, returns a list of (code, file path) of resolved
 | 
						|
        and unresolved files. Code will be 'R' or 'U' accordingly.
 | 
						|
 | 
						|
        all - select all unresolved files
 | 
						|
        mark - mark files as resolved
 | 
						|
        unmark - mark files as unresolved
 | 
						|
        tool - specify merge tool
 | 
						|
        include - include names matching the given patterns
 | 
						|
        exclude - exclude names matching the given patterns
 | 
						|
        """
 | 
						|
        if not isinstance(file, list):
 | 
						|
            file = [file]
 | 
						|
 | 
						|
        args = cmdbuilder(b('resolve'), a=all, l=listfiles, m=mark, u=unmark,
 | 
						|
                          t=tool, I=include, X=exclude, *file)
 | 
						|
 | 
						|
        out = self.rawcommand(args)
 | 
						|
 | 
						|
        if listfiles:
 | 
						|
            l = []
 | 
						|
            for line in out.splitlines():
 | 
						|
                l.append(tuple(line.split(b(' '), 1)))
 | 
						|
            return l
 | 
						|
 | 
						|
    def revert(self, files, rev=None, all=False, date=None, nobackup=False,
 | 
						|
               dryrun=False, include=None, exclude=None):
 | 
						|
        """With no revision specified, revert the specified files or
 | 
						|
        directories to the contents they had in the parent of the
 | 
						|
        working directory. This restores the contents of files to an
 | 
						|
        unmodified state and unschedules adds, removes, copies, and
 | 
						|
        renames. If the working directory has two parents, you must
 | 
						|
        explicitly specify a revision.
 | 
						|
 | 
						|
        Specifying rev or date will revert the given files or
 | 
						|
        directories to their states as of a specific revision. Because
 | 
						|
        revert does not change the working directory parents, this
 | 
						|
        will cause these files to appear modified. This can be helpful
 | 
						|
        to "back out" some or all of an earlier change.
 | 
						|
 | 
						|
        Modified files are saved with a .orig suffix before reverting.
 | 
						|
        To disable these backups, use nobackup.
 | 
						|
 | 
						|
        Returns True on success.
 | 
						|
 | 
						|
        all - revert all changes when no arguments given
 | 
						|
        date - tipmost revision matching date
 | 
						|
        rev - revert to the specified revision
 | 
						|
        nobackup - do not save backup copies of files
 | 
						|
        include - include names matching the given patterns
 | 
						|
        exclude - exclude names matching the given patterns
 | 
						|
        dryrun - do not perform actions, just print output
 | 
						|
 | 
						|
        """
 | 
						|
        if not isinstance(files, list):
 | 
						|
            files = [files]
 | 
						|
 | 
						|
        args = cmdbuilder(b('revert'), r=rev, a=all, d=date,
 | 
						|
                          no_backup=nobackup, n=dryrun, I=include, X=exclude,
 | 
						|
                          hidden=self.hidden, *files)
 | 
						|
 | 
						|
        eh = util.reterrorhandler(args)
 | 
						|
        self.rawcommand(args, eh=eh)
 | 
						|
 | 
						|
        return bool(eh)
 | 
						|
 | 
						|
    def root(self):
 | 
						|
        """
 | 
						|
        Return the root directory of the current repository.
 | 
						|
        """
 | 
						|
        return self.rawcommand([b('root')]).rstrip()
 | 
						|
 | 
						|
    def status(self, rev=None, change=None, all=False, modified=False,
 | 
						|
               added=False, removed=False, deleted=False, clean=False,
 | 
						|
               unknown=False, ignored=False, copies=False,
 | 
						|
               subrepos=False, include=None, exclude=None):
 | 
						|
        """
 | 
						|
        Return status of files in the repository as a list of (code, file path)
 | 
						|
        where code can be:
 | 
						|
 | 
						|
                M = modified
 | 
						|
                A = added
 | 
						|
                R = removed
 | 
						|
                C = clean
 | 
						|
                ! = missing (deleted by non-hg command, but still tracked)
 | 
						|
                ? = untracked
 | 
						|
                I = ignored
 | 
						|
                  = origin of the previous file listed as A (added)
 | 
						|
 | 
						|
        rev - show difference from (list of) revision
 | 
						|
        change - list the changed files of a revision
 | 
						|
        all - show status of all files
 | 
						|
        modified - show only modified files
 | 
						|
        added - show only added files
 | 
						|
        removed - show only removed files
 | 
						|
        deleted - show only deleted (but tracked) files
 | 
						|
        clean - show only files without changes
 | 
						|
        unknown - show only unknown (not tracked) files
 | 
						|
        ignored - show only ignored files
 | 
						|
        copies - show source of copied files
 | 
						|
        subrepos - recurse into subrepositories
 | 
						|
        include - include names matching the given patterns
 | 
						|
        exclude - exclude names matching the given patterns
 | 
						|
        """
 | 
						|
        if rev and change:
 | 
						|
            raise ValueError('cannot specify both rev and change')
 | 
						|
 | 
						|
        args = cmdbuilder(b('status'), rev=rev, change=change, A=all,
 | 
						|
                          m=modified, a=added, r=removed, d=deleted, c=clean,
 | 
						|
                          u=unknown, i=ignored, C=copies, S=subrepos, I=include,
 | 
						|
                          X=exclude, hidden=self.hidden)
 | 
						|
 | 
						|
        args.append(b('-0'))
 | 
						|
 | 
						|
        out = self.rawcommand(args)
 | 
						|
        l = []
 | 
						|
 | 
						|
        for entry in out.split(b('\0')):
 | 
						|
            if entry:
 | 
						|
                if entry[0:1] == b(' '):
 | 
						|
                    l.append((b(' '), entry[2:]))
 | 
						|
                else:
 | 
						|
                    l.append(tuple(entry.split(b(' '), 1)))
 | 
						|
 | 
						|
        return l
 | 
						|
 | 
						|
    def tag(self, names, rev=None, message=None, force=False, local=False,
 | 
						|
            remove=False, date=None, user=None):
 | 
						|
        """Add one or more tags specified by names for the current or given
 | 
						|
        revision.
 | 
						|
 | 
						|
        Changing an existing tag is normally disallowed; use force to override.
 | 
						|
 | 
						|
        Tag commits are usually made at the head of a branch. If the
 | 
						|
        parent of the working directory is not a branch head, a
 | 
						|
        CommandError will be raised. force can be specified to force
 | 
						|
        the tag commit to be based on a non-head changeset.
 | 
						|
 | 
						|
        local - make the tag local
 | 
						|
        rev - revision to tag
 | 
						|
        remove - remove a tag
 | 
						|
        message - set commit message
 | 
						|
        date - record the specified date as commit date
 | 
						|
        user - record the specified user as committer
 | 
						|
 | 
						|
        """
 | 
						|
        if not isinstance(names, list):
 | 
						|
            names = [names]
 | 
						|
 | 
						|
        args = cmdbuilder(b('tag'), r=rev, m=message, f=force, l=local,
 | 
						|
                          remove=remove, d=date, u=user, hidden=self.hidden,
 | 
						|
                          *names)
 | 
						|
 | 
						|
        self.rawcommand(args)
 | 
						|
 | 
						|
    def tags(self):
 | 
						|
        """
 | 
						|
        Return a list of repository tags as: (name, rev, node, islocal)
 | 
						|
        """
 | 
						|
        args = cmdbuilder(b('tags'), v=True)
 | 
						|
 | 
						|
        out = self.rawcommand(args)
 | 
						|
 | 
						|
        t = []
 | 
						|
        for line in out.splitlines():
 | 
						|
            taglocal = line.endswith(b(' local'))
 | 
						|
            if taglocal:
 | 
						|
                line = line[:-6]
 | 
						|
            name, rev = line.rsplit(b(' '), 1)
 | 
						|
            rev, node = rev.split(b(':'))
 | 
						|
            t.append((name.rstrip(), int(rev), node, taglocal))
 | 
						|
        return t
 | 
						|
 | 
						|
    def phase(self, revs=(), secret=False, draft=False, public=False,
 | 
						|
              force=False):
 | 
						|
        '''Set or show the current phase name.
 | 
						|
 | 
						|
        revs - target revision(s)
 | 
						|
        public - set changeset phase to public
 | 
						|
        draft - set changeset phase to draft
 | 
						|
        secret - set changeset phase to secret
 | 
						|
        force - allow to move boundary backward
 | 
						|
 | 
						|
        output format: [(id, phase) ...] for each changeset
 | 
						|
 | 
						|
        The arguments match the mercurial API.
 | 
						|
        '''
 | 
						|
        if not isinstance(revs, (list, tuple)):
 | 
						|
            revs = [revs]
 | 
						|
        args = util.cmdbuilder(b('phase'), secret=secret, draft=draft,
 | 
						|
                               public=public, force=force,
 | 
						|
                               hidden=self.hidden, *revs)
 | 
						|
        out = self.rawcommand(args)
 | 
						|
        if draft or public or secret:
 | 
						|
            return
 | 
						|
        else:
 | 
						|
            output = [i.split(b(': '))for i in out.strip().split(b('\n'))]
 | 
						|
            return [(int(num), phase) for (num, phase) in output]
 | 
						|
 | 
						|
    def summary(self, remote=False):
 | 
						|
        """
 | 
						|
        Return a dictionary with a brief summary of the working directory state,
 | 
						|
        including parents, branch, commit status, and available updates.
 | 
						|
 | 
						|
            'parent' : a list of (rev, node, tags, message)
 | 
						|
            'branch' : the current branch
 | 
						|
            'commit' : True if the working directory is clean, False otherwise
 | 
						|
            'update' : number of available updates,
 | 
						|
            ['remote' : (in, in bookmarks, out, out bookmarks),]
 | 
						|
            ['mq': (applied, unapplied) mq patches,]
 | 
						|
 | 
						|
            unparsed entries will be of them form key : value
 | 
						|
        """
 | 
						|
        args = cmdbuilder(b('summary'), remote=remote, hidden=self.hidden)
 | 
						|
 | 
						|
        out = self.rawcommand(args).splitlines()
 | 
						|
 | 
						|
        d = {}
 | 
						|
        while out:
 | 
						|
            line = out.pop(0)
 | 
						|
            name, value = line.split(b(': '), 1)
 | 
						|
 | 
						|
            if name == b('parent'):
 | 
						|
                parent, tags = value.split(b(' '), 1)
 | 
						|
                rev, node = parent.split(b(':'))
 | 
						|
 | 
						|
                if tags:
 | 
						|
                    tags = tags.replace(b(' (empty repository)'), b(''))
 | 
						|
                else:
 | 
						|
                    tags = None
 | 
						|
 | 
						|
                value = d.get(name, [])
 | 
						|
 | 
						|
                if rev == b('-1'):
 | 
						|
                    value.append((int(rev), node, tags, None))
 | 
						|
                else:
 | 
						|
                    message = out.pop(0)[1:]
 | 
						|
                    value.append((int(rev), node, tags, message))
 | 
						|
            elif name == b('branch'):
 | 
						|
                pass
 | 
						|
            elif name == b('commit'):
 | 
						|
                value = value == b('(clean)')
 | 
						|
            elif name == b('update'):
 | 
						|
                if value == b('(current)'):
 | 
						|
                    value = 0
 | 
						|
                else:
 | 
						|
                    value = int(value.split(b(' '), 1)[0])
 | 
						|
            elif remote and name == b('remote'):
 | 
						|
                if value == b('(synced)'):
 | 
						|
                    value = 0, 0, 0, 0
 | 
						|
                else:
 | 
						|
                    inc = incb = out_ = outb = 0
 | 
						|
 | 
						|
                    for v in value.split(b(', ')):
 | 
						|
                        count, v = v.split(b(' '), 1)
 | 
						|
                        if v == b('outgoing'):
 | 
						|
                            out_ = int(count)
 | 
						|
                        elif v.endswith(b('incoming')):
 | 
						|
                            inc = int(count)
 | 
						|
                        elif v == b('incoming bookmarks'):
 | 
						|
                            incb = int(count)
 | 
						|
                        elif v == b('outgoing bookmarks'):
 | 
						|
                            outb = int(count)
 | 
						|
 | 
						|
                    value = inc, incb, out_, outb
 | 
						|
            elif name == b('mq'):
 | 
						|
                applied = unapplied = 0
 | 
						|
                for v in value.split(b(', ')):
 | 
						|
                    count, v = v.split(b(' '), 1)
 | 
						|
                    if v == b('applied'):
 | 
						|
                        applied = int(count)
 | 
						|
                    elif v == b('unapplied'):
 | 
						|
                        unapplied = int(count)
 | 
						|
                value = applied, unapplied
 | 
						|
 | 
						|
            d[name] = value
 | 
						|
 | 
						|
        return d
 | 
						|
 | 
						|
    def tip(self):
 | 
						|
        """
 | 
						|
        Return the tip revision (usually just called the tip) which is the
 | 
						|
        changeset most recently added to the repository (and therefore the most
 | 
						|
        recently changed head).
 | 
						|
        """
 | 
						|
        args = cmdbuilder(b('tip'), template=templates.changeset,
 | 
						|
                          hidden=self.hidden)
 | 
						|
        out = self.rawcommand(args)
 | 
						|
        out = out.split(b('\0'))
 | 
						|
 | 
						|
        return self._parserevs(out)[0]
 | 
						|
 | 
						|
    def update(self, rev=None, clean=False, check=False, date=None):
 | 
						|
        """
 | 
						|
        Update the repository's working directory to changeset specified by rev.
 | 
						|
        If rev isn't specified, update to the tip of the current named branch.
 | 
						|
 | 
						|
        Return the number of files (updated, merged, removed, unresolved)
 | 
						|
 | 
						|
        clean - discard uncommitted changes (no backup)
 | 
						|
        check - update across branches if no uncommitted changes
 | 
						|
        date - tipmost revision matching date
 | 
						|
        """
 | 
						|
        if clean and check:
 | 
						|
            raise ValueError('clean and check cannot both be True')
 | 
						|
 | 
						|
        args = cmdbuilder(b('update'), r=rev, C=clean, c=check, d=date,
 | 
						|
                          hidden=self.hidden)
 | 
						|
 | 
						|
        def eh(ret, out, err):
 | 
						|
            if ret == 1:
 | 
						|
                return out
 | 
						|
 | 
						|
            raise error.CommandError(args, ret, out, err)
 | 
						|
 | 
						|
 | 
						|
        out = self.rawcommand(args, eh=eh)
 | 
						|
 | 
						|
        m = re.search(b(r'^(\d+).+, (\d+).+, (\d+).+, (\d+)'), out,
 | 
						|
                      re.MULTILINE)
 | 
						|
        return tuple(map(int, list(m.groups())))
 | 
						|
 | 
						|
    @property
 | 
						|
    def version(self):
 | 
						|
        """Return hg version that runs the command server as a 4 fielded
 | 
						|
        tuple: major, minor, micro and local build info. e.g. (1, 9,
 | 
						|
        1, '+4-3095db9f5c2c')
 | 
						|
        """
 | 
						|
        if self._version is None:
 | 
						|
            v = self.rawcommand(cmdbuilder(b('version'), q=True))
 | 
						|
            v = list(re.match(b(r'.*?(\d+)\.(\d+)\.?(\d+)?(\+[0-9a-f-]+)?'),
 | 
						|
                              v).groups())
 | 
						|
 | 
						|
            for i in range(3):
 | 
						|
                try:
 | 
						|
                    v[i] = int(v[i])
 | 
						|
                except TypeError:
 | 
						|
                    v[i] = 0
 | 
						|
 | 
						|
            self._version = tuple(v)
 | 
						|
 | 
						|
        return self._version
 | 
						|
 | 
						|
    def __getitem__(self, changeid):
 | 
						|
        try:
 | 
						|
            return context.changectx(self, changeid)
 | 
						|
        except ValueError as e:
 | 
						|
            raise KeyError(*e.args)
 | 
						|
 | 
						|
    def __contains__(self, changeid):
 | 
						|
        """
 | 
						|
        check if changeid, which can be either a local revision number or a
 | 
						|
        changeset id, matches a changeset in the client.
 | 
						|
        """
 | 
						|
        try:
 | 
						|
            context.changectx(self, changeid)
 | 
						|
            return True
 | 
						|
        except ValueError:
 | 
						|
            return False
 |