summaryrefslogtreecommitdiff
path: root/eggs/mercurial-1.7.3-py2.6-linux-x86_64.egg/mercurial/context.py
diff options
context:
space:
mode:
Diffstat (limited to 'eggs/mercurial-1.7.3-py2.6-linux-x86_64.egg/mercurial/context.py')
-rw-r--r--eggs/mercurial-1.7.3-py2.6-linux-x86_64.egg/mercurial/context.py1098
1 files changed, 0 insertions, 1098 deletions
diff --git a/eggs/mercurial-1.7.3-py2.6-linux-x86_64.egg/mercurial/context.py b/eggs/mercurial-1.7.3-py2.6-linux-x86_64.egg/mercurial/context.py
deleted file mode 100644
index ff1bfa7..0000000
--- a/eggs/mercurial-1.7.3-py2.6-linux-x86_64.egg/mercurial/context.py
+++ /dev/null
@@ -1,1098 +0,0 @@
-# context.py - changeset and file context objects for mercurial
-#
-# Copyright 2006, 2007 Matt Mackall <mpm@selenic.com>
-#
-# This software may be used and distributed according to the terms of the
-# GNU General Public License version 2 or any later version.
-
-from node import nullid, nullrev, short, hex
-from i18n import _
-import ancestor, bdiff, error, util, subrepo, patch
-import os, errno, stat
-
-propertycache = util.propertycache
-
-class changectx(object):
- """A changecontext object makes access to data related to a particular
- changeset convenient."""
- def __init__(self, repo, changeid=''):
- """changeid is a revision number, node, or tag"""
- if changeid == '':
- changeid = '.'
- self._repo = repo
- if isinstance(changeid, (long, int)):
- self._rev = changeid
- self._node = self._repo.changelog.node(changeid)
- else:
- self._node = self._repo.lookup(changeid)
- self._rev = self._repo.changelog.rev(self._node)
-
- def __str__(self):
- return short(self.node())
-
- 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 != nullrev
-
- @propertycache
- def _changeset(self):
- return self._repo.changelog.read(self.node())
-
- @propertycache
- def _manifest(self):
- return self._repo.manifest.read(self._changeset[0])
-
- @propertycache
- def _manifestdelta(self):
- return self._repo.manifest.readdelta(self._changeset[0])
-
- @propertycache
- def _parents(self):
- p = self._repo.changelog.parentrevs(self._rev)
- if p[1] == nullrev:
- p = p[:-1]
- return [changectx(self._repo, x) for x in p]
-
- @propertycache
- def substate(self):
- return subrepo.state(self, self._repo.ui)
-
- def __contains__(self, key):
- return key in self._manifest
-
- def __getitem__(self, key):
- return self.filectx(key)
-
- def __iter__(self):
- for f in sorted(self._manifest):
- yield f
-
- def changeset(self):
- return self._changeset
- def manifest(self):
- return self._manifest
- def manifestnode(self):
- return self._changeset[0]
-
- def rev(self):
- return self._rev
- def node(self):
- return self._node
- def hex(self):
- return hex(self._node)
- def user(self):
- return self._changeset[1]
- def date(self):
- return self._changeset[2]
- def files(self):
- return self._changeset[3]
- def description(self):
- return self._changeset[4]
- def branch(self):
- return self._changeset[5].get("branch")
- def extra(self):
- return self._changeset[5]
- def tags(self):
- return self._repo.nodetags(self._node)
-
- def parents(self):
- """return contexts for each parent changeset"""
- 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)
-
- def children(self):
- """return contexts for each child changeset"""
- c = self._repo.changelog.children(self._node)
- return [changectx(self._repo, x) for x in c]
-
- def ancestors(self):
- for a in self._repo.changelog.ancestors(self._rev):
- yield changectx(self._repo, a)
-
- def descendants(self):
- for d in self._repo.changelog.descendants(self._rev):
- yield changectx(self._repo, d)
-
- def _fileinfo(self, path):
- if '_manifest' in self.__dict__:
- try:
- return self._manifest[path], self._manifest.flags(path)
- except KeyError:
- raise error.LookupError(self._node, path,
- _('not found in manifest'))
- if '_manifestdelta' in self.__dict__ or path in self.files():
- if path in self._manifestdelta:
- return self._manifestdelta[path], self._manifestdelta.flags(path)
- node, flag = self._repo.manifest.find(self._changeset[0], path)
- if not node:
- raise error.LookupError(self._node, path,
- _('not found in manifest'))
-
- return node, flag
-
- def filenode(self, path):
- return self._fileinfo(path)[0]
-
- def flags(self, path):
- try:
- return self._fileinfo(path)[1]
- except error.LookupError:
- return ''
-
- def filectx(self, path, fileid=None, filelog=None):
- """get a file context from this changeset"""
- if fileid is None:
- fileid = self.filenode(path)
- return filectx(self._repo, path, fileid=fileid,
- changectx=self, filelog=filelog)
-
- def ancestor(self, c2):
- """
- return the ancestor context of self and c2
- """
- # deal with workingctxs
- n2 = c2._node
- if n2 == None:
- n2 = c2._parents[0]._node
- n = self._repo.changelog.ancestor(self._node, n2)
- return changectx(self._repo, n)
-
- def walk(self, match):
- fset = set(match.files())
- # for dirstate.walk, files=['.'] means "walk the whole tree".
- # follow that here, too
- fset.discard('.')
- for fn in self:
- for ffn in fset:
- # match if the file is the exact name or a directory
- if ffn == fn or fn.startswith("%s/" % ffn):
- fset.remove(ffn)
- break
- if match(fn):
- yield fn
- for fn in sorted(fset):
- if match.bad(fn, _('no such file in rev %s') % self) and match(fn):
- yield fn
-
- def sub(self, path):
- return subrepo.subrepo(self, path)
-
- def diff(self, ctx2=None, match=None, **opts):
- """Returns a diff generator for the given contexts and matcher"""
- if ctx2 is None:
- ctx2 = self.p1()
- if ctx2 is not None and not isinstance(ctx2, changectx):
- ctx2 = self._repo[ctx2]
- diffopts = patch.diffopts(self._repo.ui, opts)
- return patch.diff(self._repo, ctx2.node(), self.node(),
- match=match, opts=diffopts)
-
-class filectx(object):
- """A filecontext object makes access to data related to a particular
- filerevision convenient."""
- def __init__(self, repo, path, changeid=None, fileid=None,
- filelog=None, changectx=None):
- """changeid can be a changeset revision, node, or tag.
- fileid can be a file revision or node."""
- self._repo = repo
- self._path = path
-
- assert (changeid is not None
- or fileid is not None
- or changectx is not None), \
- ("bad args: changeid=%r, fileid=%r, changectx=%r"
- % (changeid, fileid, changectx))
-
- if filelog:
- self._filelog = filelog
-
- if changeid is not None:
- self._changeid = changeid
- if changectx is not None:
- self._changectx = changectx
- if fileid is not None:
- self._fileid = fileid
-
- @propertycache
- def _changectx(self):
- return changectx(self._repo, self._changeid)
-
- @propertycache
- def _filelog(self):
- return self._repo.file(self._path)
-
- @propertycache
- def _changeid(self):
- if '_changectx' in self.__dict__:
- return self._changectx.rev()
- else:
- return self._filelog.linkrev(self._filerev)
-
- @propertycache
- def _filenode(self):
- if '_fileid' in self.__dict__:
- return self._filelog.lookup(self._fileid)
- else:
- return self._changectx.filenode(self._path)
-
- @propertycache
- def _filerev(self):
- return self._filelog.rev(self._filenode)
-
- @propertycache
- def _repopath(self):
- return self._path
-
- def __nonzero__(self):
- try:
- self._filenode
- return True
- except error.LookupError:
- # file is missing
- return False
-
- def __str__(self):
- return "%s@%s" % (self.path(), short(self.node()))
-
- def __repr__(self):
- return "<filectx %s>" % str(self)
-
- def __hash__(self):
- try:
- return hash((self._path, self._filenode))
- except AttributeError:
- return id(self)
-
- def __eq__(self, other):
- try:
- return (self._path == other._path
- and self._filenode == other._filenode)
- except AttributeError:
- return False
-
- def __ne__(self, other):
- return not (self == other)
-
- def filectx(self, fileid):
- '''opens an arbitrary revision of the file without
- opening a new filelog'''
- return filectx(self._repo, self._path, fileid=fileid,
- filelog=self._filelog)
-
- def filerev(self):
- return self._filerev
- def filenode(self):
- return self._filenode
- def flags(self):
- return self._changectx.flags(self._path)
- def filelog(self):
- return self._filelog
-
- def rev(self):
- if '_changectx' in self.__dict__:
- return self._changectx.rev()
- if '_changeid' in self.__dict__:
- return self._changectx.rev()
- return self._filelog.linkrev(self._filerev)
-
- def linkrev(self):
- return self._filelog.linkrev(self._filerev)
- def node(self):
- return self._changectx.node()
- def hex(self):
- return hex(self.node())
- def user(self):
- return self._changectx.user()
- def date(self):
- return self._changectx.date()
- def files(self):
- return self._changectx.files()
- def description(self):
- return self._changectx.description()
- def branch(self):
- return self._changectx.branch()
- def extra(self):
- return self._changectx.extra()
- def manifest(self):
- return self._changectx.manifest()
- def changectx(self):
- return self._changectx
-
- def data(self):
- return self._filelog.read(self._filenode)
- def path(self):
- return self._path
- def size(self):
- return self._filelog.size(self._filerev)
-
- def cmp(self, fctx):
- """compare with other file context
-
- returns True if different than fctx.
- """
- if (fctx._filerev is None and self._repo._encodefilterpats
- or self.size() == fctx.size()):
- return self._filelog.cmp(self._filenode, fctx.data())
-
- return True
-
- def renamed(self):
- """check if file was actually renamed in this changeset revision
-
- If rename logged in file revision, we report copy for changeset only
- if file revisions linkrev points back to the changeset in question
- or both changeset parents contain different file revisions.
- """
-
- renamed = self._filelog.renamed(self._filenode)
- if not renamed:
- return renamed
-
- if self.rev() == self.linkrev():
- return renamed
-
- name = self.path()
- fnode = self._filenode
- for p in self._changectx.parents():
- try:
- if fnode == p.filenode(name):
- return None
- except error.LookupError:
- pass
- return renamed
-
- def parents(self):
- p = self._path
- fl = self._filelog
- pl = [(p, n, fl) for n in self._filelog.parents(self._filenode)]
-
- r = self._filelog.renamed(self._filenode)
- if r:
- pl[0] = (r[0], r[1], None)
-
- return [filectx(self._repo, p, fileid=n, filelog=l)
- for p, n, l in pl if n != nullid]
-
- def children(self):
- # hard for renames
- c = self._filelog.children(self._filenode)
- return [filectx(self._repo, self._path, fileid=x,
- filelog=self._filelog) for x in c]
-
- def annotate(self, follow=False, linenumber=None):
- '''returns a list of tuples of (ctx, line) for each line
- in the file, where ctx is the filectx of the node where
- that line was last changed.
- This returns tuples of ((ctx, linenumber), line) for each line,
- if "linenumber" parameter is NOT "None".
- In such tuples, linenumber means one at the first appearance
- in the managed file.
- To reduce annotation cost,
- this returns fixed value(False is used) as linenumber,
- if "linenumber" parameter is "False".'''
-
- def decorate_compat(text, rev):
- return ([rev] * len(text.splitlines()), text)
-
- def without_linenumber(text, rev):
- return ([(rev, False)] * len(text.splitlines()), text)
-
- def with_linenumber(text, rev):
- size = len(text.splitlines())
- return ([(rev, i) for i in xrange(1, size + 1)], text)
-
- decorate = (((linenumber is None) and decorate_compat) or
- (linenumber and with_linenumber) or
- without_linenumber)
-
- def pair(parent, child):
- for a1, a2, b1, b2 in bdiff.blocks(parent[1], child[1]):
- child[0][b1:b2] = parent[0][a1:a2]
- return child
-
- getlog = util.lrucachefunc(lambda x: self._repo.file(x))
- def getctx(path, fileid):
- log = path == self._path and self._filelog or getlog(path)
- return filectx(self._repo, path, fileid=fileid, filelog=log)
- getctx = util.lrucachefunc(getctx)
-
- def parents(f):
- # we want to reuse filectx objects as much as possible
- p = f._path
- if f._filerev is None: # working dir
- pl = [(n.path(), n.filerev()) for n in f.parents()]
- else:
- pl = [(p, n) for n in f._filelog.parentrevs(f._filerev)]
-
- if follow:
- r = f.renamed()
- if r:
- pl[0] = (r[0], getlog(r[0]).rev(r[1]))
-
- return [getctx(p, n) for p, n in pl if n != nullrev]
-
- # use linkrev to find the first changeset where self appeared
- if self.rev() != self.linkrev():
- base = self.filectx(self.filerev())
- else:
- base = self
-
- # find all ancestors
- needed = {base: 1}
- visit = [base]
- files = [base._path]
- while visit:
- f = visit.pop(0)
- for p in parents(f):
- if p not in needed:
- needed[p] = 1
- visit.append(p)
- if p._path not in files:
- files.append(p._path)
- else:
- # count how many times we'll use this
- needed[p] += 1
-
- # sort by revision (per file) which is a topological order
- visit = []
- for f in files:
- visit.extend(n for n in needed if n._path == f)
-
- hist = {}
- for f in sorted(visit, key=lambda x: x.rev()):
- curr = decorate(f.data(), f)
- for p in parents(f):
- curr = pair(hist[p], curr)
- # trim the history of unneeded revs
- needed[p] -= 1
- if not needed[p]:
- del hist[p]
- hist[f] = curr
-
- return zip(hist[f][0], hist[f][1].splitlines(True))
-
- def ancestor(self, fc2, actx=None):
- """
- find the common ancestor file context, if any, of self, and fc2
-
- If actx is given, it must be the changectx of the common ancestor
- of self's and fc2's respective changesets.
- """
-
- if actx is None:
- actx = self.changectx().ancestor(fc2.changectx())
-
- # the trivial case: changesets are unrelated, files must be too
- if not actx:
- return None
-
- # the easy case: no (relevant) renames
- if fc2.path() == self.path() and self.path() in actx:
- return actx[self.path()]
- acache = {}
-
- # prime the ancestor cache for the working directory
- for c in (self, fc2):
- if c._filerev is None:
- pl = [(n.path(), n.filenode()) for n in c.parents()]
- acache[(c._path, None)] = pl
-
- flcache = {self._repopath:self._filelog, fc2._repopath:fc2._filelog}
- def parents(vertex):
- if vertex in acache:
- return acache[vertex]
- f, n = vertex
- if f not in flcache:
- flcache[f] = self._repo.file(f)
- fl = flcache[f]
- pl = [(f, p) for p in fl.parents(n) if p != nullid]
- re = fl.renamed(n)
- if re:
- pl.append(re)
- acache[vertex] = pl
- return pl
-
- a, b = (self._path, self._filenode), (fc2._path, fc2._filenode)
- v = ancestor.ancestor(a, b, parents)
- if v:
- f, n = v
- return filectx(self._repo, f, fileid=n, filelog=flcache[f])
-
- return None
-
- def ancestors(self):
- seen = set(str(self))
- visit = [self]
- while visit:
- for parent in visit.pop(0).parents():
- s = str(parent)
- if s not in seen:
- visit.append(parent)
- seen.add(s)
- yield parent
-
-class workingctx(changectx):
- """A workingctx object makes access to data related to
- the current working directory convenient.
- date - any valid date string or (unixtime, offset), or None.
- user - username string, or None.
- extra - a dictionary of extra values, or None.
- changes - a list of file lists as returned by localrepo.status()
- or None to use the repository status.
- """
- def __init__(self, repo, text="", user=None, date=None, extra=None,
- changes=None):
- self._repo = repo
- self._rev = None
- self._node = None
- self._text = text
- if date:
- self._date = util.parsedate(date)
- if user:
- self._user = user
- if changes:
- self._status = list(changes[:4])
- self._unknown = changes[4]
- self._ignored = changes[5]
- self._clean = changes[6]
- else:
- self._unknown = None
- self._ignored = None
- self._clean = None
-
- self._extra = {}
- if extra:
- self._extra = extra.copy()
- if 'branch' not in self._extra:
- branch = self._repo.dirstate.branch()
- try:
- branch = branch.decode('UTF-8').encode('UTF-8')
- except UnicodeDecodeError:
- raise util.Abort(_('branch name not in UTF-8!'))
- self._extra['branch'] = branch
- if self._extra['branch'] == '':
- self._extra['branch'] = 'default'
-
- def __str__(self):
- return str(self._parents[0]) + "+"
-
- def __nonzero__(self):
- return True
-
- def __contains__(self, key):
- return self._repo.dirstate[key] not in "?r"
-
- @propertycache
- def _manifest(self):
- """generate a manifest corresponding to the working directory"""
-
- if self._unknown is None:
- self.status(unknown=True)
-
- man = self._parents[0].manifest().copy()
- copied = self._repo.dirstate.copies()
- if len(self._parents) > 1:
- man2 = self.p2().manifest()
- def getman(f):
- if f in man:
- return man
- return man2
- else:
- getman = lambda f: man
- def cf(f):
- f = copied.get(f, f)
- return getman(f).flags(f)
- ff = self._repo.dirstate.flagfunc(cf)
- modified, added, removed, deleted = self._status
- unknown = self._unknown
- for i, l in (("a", added), ("m", modified), ("u", unknown)):
- for f in l:
- orig = copied.get(f, f)
- man[f] = getman(orig).get(orig, nullid) + i
- try:
- man.set(f, ff(f))
- except OSError:
- pass
-
- for f in deleted + removed:
- if f in man:
- del man[f]
-
- return man
-
- @propertycache
- def _status(self):
- return self._repo.status()[:4]
-
- @propertycache
- def _user(self):
- return self._repo.ui.username()
-
- @propertycache
- def _date(self):
- return util.makedate()
-
- @propertycache
- def _parents(self):
- p = self._repo.dirstate.parents()
- if p[1] == nullid:
- p = p[:-1]
- self._parents = [changectx(self._repo, x) for x in p]
- return self._parents
-
- def status(self, ignored=False, clean=False, unknown=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._repo.status(ignored=ignored, clean=clean, unknown=unknown)
- self._unknown = self._ignored = self._clean = None
- if unknown:
- self._unknown = stat[4]
- if ignored:
- self._ignored = stat[5]
- if clean:
- self._clean = stat[6]
- self._status = stat[:4]
- return stat
-
- def manifest(self):
- return self._manifest
- def user(self):
- return self._user or self._repo.ui.username()
- def date(self):
- return self._date
- def description(self):
- return self._text
- 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 deleted(self):
- return self._status[3]
- def unknown(self):
- assert self._unknown is not None # must call status first
- return self._unknown
- def ignored(self):
- assert self._ignored is not None # must call status first
- return self._ignored
- def clean(self):
- assert self._clean is not None # must call status first
- return self._clean
- def branch(self):
- return self._extra['branch']
- def extra(self):
- return self._extra
-
- def tags(self):
- t = []
- [t.extend(p.tags()) for p in self.parents()]
- return t
-
- def children(self):
- return []
-
- def flags(self, path):
- if '_manifest' in self.__dict__:
- try:
- return self._manifest.flags(path)
- except KeyError:
- return ''
-
- orig = self._repo.dirstate.copies().get(path, path)
-
- def findflag(ctx):
- mnode = ctx.changeset()[0]
- node, flag = self._repo.manifest.find(mnode, orig)
- ff = self._repo.dirstate.flagfunc(lambda x: flag or '')
- try:
- return ff(path)
- except OSError:
- pass
-
- flag = findflag(self._parents[0])
- if flag is None and len(self.parents()) > 1:
- flag = findflag(self._parents[1])
- if flag is None or self._repo.dirstate[path] == 'r':
- return ''
- return flag
-
- def filectx(self, path, filelog=None):
- """get a file context from the working directory"""
- return workingfilectx(self._repo, path, workingctx=self,
- filelog=filelog)
-
- def ancestor(self, c2):
- """return the ancestor context of self and c2"""
- return self._parents[0].ancestor(c2) # punt on two parents for now
-
- def walk(self, match):
- return sorted(self._repo.dirstate.walk(match, self.substate.keys(),
- True, False))
-
- def dirty(self, missing=False):
- "check whether a working directory is modified"
- # check subrepos first
- for s in self.substate:
- if self.sub(s).dirty():
- return True
- # check current working dir
- return (self.p2() or self.branch() != self.p1().branch() or
- self.modified() or self.added() or self.removed() or
- (missing and self.deleted()))
-
- def add(self, list, prefix=""):
- join = lambda f: os.path.join(prefix, f)
- wlock = self._repo.wlock()
- ui, ds = self._repo.ui, self._repo.dirstate
- try:
- rejected = []
- for f in list:
- p = self._repo.wjoin(f)
- try:
- st = os.lstat(p)
- except:
- ui.warn(_("%s does not exist!\n") % join(f))
- rejected.append(f)
- continue
- if st.st_size > 10000000:
- ui.warn(_("%s: up to %d MB of RAM may be required "
- "to manage this file\n"
- "(use 'hg revert %s' to cancel the "
- "pending addition)\n")
- % (f, 3 * st.st_size // 1000000, join(f)))
- if not (stat.S_ISREG(st.st_mode) or stat.S_ISLNK(st.st_mode)):
- ui.warn(_("%s not added: only files and symlinks "
- "supported currently\n") % join(f))
- rejected.append(p)
- elif ds[f] in 'amn':
- ui.warn(_("%s already tracked!\n") % join(f))
- elif ds[f] == 'r':
- ds.normallookup(f)
- else:
- ds.add(f)
- return rejected
- finally:
- wlock.release()
-
- def forget(self, list):
- wlock = self._repo.wlock()
- try:
- for f in list:
- if self._repo.dirstate[f] != 'a':
- self._repo.ui.warn(_("%s not added!\n") % f)
- else:
- self._repo.dirstate.forget(f)
- finally:
- wlock.release()
-
- def ancestors(self):
- for a in self._repo.changelog.ancestors(
- *[p.rev() for p in self._parents]):
- yield changectx(self._repo, a)
-
- def remove(self, list, unlink=False):
- if unlink:
- for f in list:
- try:
- util.unlink(self._repo.wjoin(f))
- except OSError, inst:
- if inst.errno != errno.ENOENT:
- raise
- wlock = self._repo.wlock()
- try:
- for f in list:
- if unlink and os.path.lexists(self._repo.wjoin(f)):
- self._repo.ui.warn(_("%s still exists!\n") % f)
- elif self._repo.dirstate[f] == 'a':
- self._repo.dirstate.forget(f)
- elif f not in self._repo.dirstate:
- self._repo.ui.warn(_("%s not tracked!\n") % f)
- else:
- self._repo.dirstate.remove(f)
- finally:
- wlock.release()
-
- def undelete(self, list):
- pctxs = self.parents()
- wlock = self._repo.wlock()
- try:
- for f in list:
- if self._repo.dirstate[f] != 'r':
- self._repo.ui.warn(_("%s not removed!\n") % f)
- else:
- fctx = f in pctxs[0] and pctxs[0][f] or pctxs[1][f]
- t = fctx.data()
- self._repo.wwrite(f, t, fctx.flags())
- self._repo.dirstate.normal(f)
- finally:
- wlock.release()
-
- def copy(self, source, dest):
- p = self._repo.wjoin(dest)
- if not os.path.lexists(p):
- self._repo.ui.warn(_("%s does not exist!\n") % dest)
- elif not (os.path.isfile(p) or os.path.islink(p)):
- self._repo.ui.warn(_("copy failed: %s is not a file or a "
- "symbolic link\n") % dest)
- else:
- wlock = self._repo.wlock()
- try:
- if self._repo.dirstate[dest] in '?r':
- self._repo.dirstate.add(dest)
- self._repo.dirstate.copy(source, dest)
- finally:
- wlock.release()
-
-class workingfilectx(filectx):
- """A workingfilectx object makes access to data related to a particular
- file in the working directory convenient."""
- def __init__(self, repo, path, filelog=None, workingctx=None):
- """changeid can be a changeset revision, node, or tag.
- fileid can be a file revision or node."""
- self._repo = repo
- self._path = path
- self._changeid = None
- self._filerev = self._filenode = None
-
- if filelog:
- self._filelog = filelog
- if workingctx:
- self._changectx = workingctx
-
- @propertycache
- def _changectx(self):
- return workingctx(self._repo)
-
- def __nonzero__(self):
- return True
-
- def __str__(self):
- return "%s@%s" % (self.path(), self._changectx)
-
- def data(self):
- return self._repo.wread(self._path)
- def renamed(self):
- rp = self._repo.dirstate.copied(self._path)
- if not rp:
- return None
- return rp, self._changectx._parents[0]._manifest.get(rp, nullid)
-
- def parents(self):
- '''return parent filectxs, following copies if necessary'''
- def filenode(ctx, path):
- return ctx._manifest.get(path, nullid)
-
- path = self._path
- fl = self._filelog
- pcl = self._changectx._parents
- renamed = self.renamed()
-
- if renamed:
- pl = [renamed + (None,)]
- else:
- pl = [(path, filenode(pcl[0], path), fl)]
-
- for pc in pcl[1:]:
- pl.append((path, filenode(pc, path), fl))
-
- return [filectx(self._repo, p, fileid=n, filelog=l)
- for p, n, l in pl if n != nullid]
-
- def children(self):
- return []
-
- def size(self):
- return os.lstat(self._repo.wjoin(self._path)).st_size
- def date(self):
- t, tz = self._changectx.date()
- try:
- return (int(os.lstat(self._repo.wjoin(self._path)).st_mtime), tz)
- except OSError, err:
- if err.errno != errno.ENOENT:
- raise
- return (t, tz)
-
- def cmp(self, fctx):
- """compare with other file context
-
- returns True if different than fctx.
- """
- # fctx should be a filectx (not a wfctx)
- # invert comparison to reuse the same code path
- return fctx.cmp(self)
-
-class memctx(object):
- """Use memctx to perform in-memory commits via localrepo.commitctx().
-
- Revision information is supplied at initialization time while
- related files data and is made available through a callback
- mechanism. 'repo' is the current localrepo, 'parents' is a
- sequence of two parent revisions identifiers (pass None for every
- missing parent), 'text' is the commit message and 'files' lists
- names of files touched by the revision (normalized and relative to
- repository root).
-
- filectxfn(repo, memctx, path) is a callable receiving the
- repository, the current memctx object and the normalized path of
- requested file, relative to repository root. It is fired by the
- commit function for every file in 'files', but calls order is
- undefined. If the file is available in the revision being
- committed (updated or added), filectxfn returns a memfilectx
- object. If the file was removed, filectxfn raises an
- IOError. Moved files are represented by marking the source file
- removed and the new file added with copy information (see
- memfilectx).
-
- user receives the committer name and defaults to current
- repository username, date is the commit date in any format
- supported by util.parsedate() and defaults to current date, extra
- is a dictionary of metadata or is left empty.
- """
- def __init__(self, repo, parents, text, files, filectxfn, user=None,
- date=None, extra=None):
- self._repo = repo
- self._rev = None
- self._node = None
- self._text = text
- self._date = date and util.parsedate(date) or util.makedate()
- self._user = user
- parents = [(p or nullid) for p in parents]
- p1, p2 = parents
- self._parents = [changectx(self._repo, p) for p in (p1, p2)]
- files = sorted(set(files))
- self._status = [files, [], [], [], []]
- self._filectxfn = filectxfn
-
- self._extra = extra and extra.copy() or {}
- if 'branch' not in self._extra:
- self._extra['branch'] = 'default'
- elif self._extra.get('branch') == '':
- self._extra['branch'] = 'default'
-
- def __str__(self):
- return str(self._parents[0]) + "+"
-
- def __int__(self):
- return self._rev
-
- def __nonzero__(self):
- return True
-
- def __getitem__(self, key):
- return self.filectx(key)
-
- def p1(self):
- return self._parents[0]
- def p2(self):
- return self._parents[1]
-
- def user(self):
- return self._user or self._repo.ui.username()
- def date(self):
- return self._date
- def description(self):
- return self._text
- def files(self):
- return self.modified()
- def modified(self):
- return self._status[0]
- def added(self):
- return self._status[1]
- def removed(self):
- return self._status[2]
- def deleted(self):
- return self._status[3]
- def unknown(self):
- return self._status[4]
- def ignored(self):
- return self._status[5]
- def clean(self):
- return self._status[6]
- def branch(self):
- return self._extra['branch']
- def extra(self):
- return self._extra
- def flags(self, f):
- return self[f].flags()
-
- def parents(self):
- """return contexts for each parent changeset"""
- return self._parents
-
- def filectx(self, path, filelog=None):
- """get a file context from the working directory"""
- return self._filectxfn(self._repo, self, path)
-
- def commit(self):
- """commit context to the repo"""
- return self._repo.commitctx(self)
-
-class memfilectx(object):
- """memfilectx represents an in-memory file to commit.
-
- See memctx for more details.
- """
- def __init__(self, path, data, islink=False, isexec=False, copied=None):
- """
- path is the normalized file path relative to repository root.
- data is the file content as a string.
- islink is True if the file is a symbolic link.
- isexec is True if the file is executable.
- copied is the source file path if current file was copied in the
- revision being committed, or None."""
- self._path = path
- self._data = data
- self._flags = (islink and 'l' or '') + (isexec and 'x' or '')
- self._copied = None
- if copied:
- self._copied = (copied, nullid)
-
- def __nonzero__(self):
- return True
- def __str__(self):
- return "%s@%s" % (self.path(), self._changectx)
- def path(self):
- return self._path
- def data(self):
- return self._data
- def flags(self):
- return self._flags
- def isexec(self):
- return 'x' in self._flags
- def islink(self):
- return 'l' in self._flags
- def renamed(self):
- return self._copied