diff options
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.py | 1098 |
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 |