summaryrefslogtreecommitdiffstats
path: root/third_party/python/python-hglib/hglib/context.py
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/python/python-hglib/hglib/context.py')
-rw-r--r--third_party/python/python-hglib/hglib/context.py238
1 files changed, 238 insertions, 0 deletions
diff --git a/third_party/python/python-hglib/hglib/context.py b/third_party/python/python-hglib/hglib/context.py
new file mode 100644
index 0000000000..3ba9abb890
--- /dev/null
+++ b/third_party/python/python-hglib/hglib/context.py
@@ -0,0 +1,238 @@
+import hglib.client # Circular dependency.
+from hglib import util, templates
+from hglib.error import CommandError
+from hglib.util import b, strtobytes, integertypes
+
+_nullcset = [b('-1'), b('0000000000000000000000000000000000000000'), b(''),
+ b(''), b(''), b(''), b('')]
+
+class changectx(object):
+ """A changecontext object makes access to data related to a particular
+ changeset convenient."""
+ def __init__(self, repo, changeid=b('')):
+ """changeid is a revision number, node, or tag"""
+ if changeid == b(''):
+ changeid = b('.')
+ self._repo = repo
+ if isinstance(changeid, hglib.client.revision):
+ cset = changeid
+ elif changeid == -1:
+ cset = _nullcset
+ else:
+ if isinstance(changeid, integertypes):
+ changeid = b('rev(') + strtobytes(changeid) + b(')')
+
+ notfound = False
+ try:
+ cset = self._repo.log(changeid)
+ # hg bbf4f3dfd700 gave a null result for tip+1
+ if (cset and cset[0][1] == _nullcset[1]
+ and cset[0][0] != _nullcset[0]):
+ notfound = True
+ except CommandError:
+ notfound = True
+
+ if notfound or not len(cset):
+ raise ValueError('changeid %r not found in repo' % changeid)
+ if len(cset) > 1:
+ raise ValueError('changeid must yield a single changeset')
+ cset = cset[0]
+
+ self._rev, self._node, self._tags = cset[:3]
+ self._branch, self._author, self._description, self._date = cset[3:]
+
+ self._rev = int(self._rev)
+
+ self._tags = self._tags.split()
+ try:
+ self._tags.remove(b('tip'))
+ except ValueError:
+ pass
+
+ self._ignored = None
+ self._clean = None
+
+ def __str__(self):
+ return self._node[:12].decode('latin-1')
+
+ def __int__(self):
+ return self._rev
+
+ def __repr__(self):
+ return "<changectx %s>" % str(self)
+
+ def __hash__(self):
+ try:
+ return hash(self._rev)
+ except AttributeError:
+ return id(self)
+
+ def __eq__(self, other):
+ try:
+ return self._rev == other._rev
+ except AttributeError:
+ return False
+
+ def __ne__(self, other):
+ return not (self == other)
+
+ def __nonzero__(self):
+ return self._rev != -1
+
+ def __bool__(self):
+ return self.__nonzero__()
+
+ def __contains__(self, key):
+ return key in self._manifest
+
+ def __iter__(self):
+ for f in sorted(self._manifest):
+ yield f
+
+ @util.propertycache
+ def _status(self):
+ return self._parsestatus(self._repo.status(change=strtobytes(self)))[:4]
+
+ def _parsestatus(self, stat):
+ d = dict((c, [])
+ for c in (b('M'), b('A'), b('R'), b('!'), b('?'), b('I'),
+ b('C'), b(' ')))
+ for k, path in stat:
+ d[k].append(path)
+ return (d[b('M')], d[b('A')], d[b('R')], d[b('!')], d[b('?')],
+ d[b('I')], d[b('C')])
+
+ def status(self, ignored=False, clean=False):
+ """Explicit status query
+ Unless this method is used to query the working copy status, the
+ _status property will implicitly read the status using its default
+ arguments."""
+ stat = self._parsestatus(self._repo.status(change=strtobytes(self),
+ ignored=ignored,
+ clean=clean))
+ self._unknown = self._ignored = self._clean = None
+ if ignored:
+ self._ignored = stat[5]
+ if clean:
+ self._clean = stat[6]
+ self._status = stat[:4]
+ return stat
+
+ def rev(self):
+ return self._rev
+
+ def node(self):
+ return self._node
+
+ def tags(self):
+ return self._tags
+
+ def branch(self):
+ return self._branch
+
+ def author(self):
+ return self._author
+
+ def user(self):
+ return self._author
+
+ def date(self):
+ return self._date
+
+ def description(self):
+ return self._description
+
+ def files(self):
+ return sorted(self._status[0] + self._status[1] + self._status[2])
+
+ def modified(self):
+ return self._status[0]
+
+ def added(self):
+ return self._status[1]
+
+ def removed(self):
+ return self._status[2]
+
+ def ignored(self):
+ if self._ignored is None:
+ self.status(ignored=True)
+ return self._ignored
+
+ def clean(self):
+ if self._clean is None:
+ self.status(clean=True)
+ return self._clean
+
+ @util.propertycache
+ def _manifest(self):
+ d = {}
+ for node, p, e, s, path in self._repo.manifest(rev=strtobytes(self)):
+ d[path] = node
+ return d
+
+ def manifest(self):
+ return self._manifest
+
+ def hex(self):
+ return hex(self._node)
+
+ @util.propertycache
+ def _parents(self):
+ """return contexts for each parent changeset"""
+ par = self._repo.parents(rev=strtobytes(self))
+ if not par:
+ return [changectx(self._repo, -1)]
+ return [changectx(self._repo, int(cset.rev)) for cset in par]
+
+ def parents(self):
+ return self._parents
+
+ def p1(self):
+ return self._parents[0]
+
+ def p2(self):
+ if len(self._parents) == 2:
+ return self._parents[1]
+ return changectx(self._repo, -1)
+
+ @util.propertycache
+ def _bookmarks(self):
+ books = [bm for bm in self._repo.bookmarks()[0] if bm[1] == self._rev]
+
+ bms = []
+ for name, r, n in books:
+ bms.append(name)
+ return bms
+
+ def bookmarks(self):
+ return self._bookmarks
+
+ def hidden(self):
+ """return True if the changeset is hidden, else False"""
+ return bool(self._repo.log(revrange=self._node + b(' and hidden()'),
+ hidden=True))
+
+ def phase(self):
+ """return the phase of the changeset (public, draft or secret)"""
+ return self._repo.phase(strtobytes(self._rev))[0][1]
+
+ def children(self):
+ """return contexts for each child changeset"""
+ for c in self._repo.log(b('children(') + self._node + b(')')):
+ yield changectx(self._repo, c)
+
+ def ancestors(self):
+ for a in self._repo.log(b('ancestors(') + self._node + b(')')):
+ yield changectx(self._repo, a)
+
+ def descendants(self):
+ for d in self._repo.log(b('descendants(') + self._node + b(')')):
+ yield changectx(self._repo, d)
+
+ def ancestor(self, c2):
+ """
+ return the ancestor context of self and c2
+ """
+ return changectx(self._repo,
+ b('ancestor(') + self + b(', ') + c2 + b(')'))