diff --git a/mercurial/context.py b/mercurial/context.py --- a/mercurial/context.py +++ b/mercurial/context.py @@ -7,6 +7,7 @@ from __future__ import absolute_import +import abc import errno import filecmp import os @@ -717,7 +718,36 @@ def matches(self, match): return self.walk(match) -class basefilectx(object): +class abstractfilectx(object): + """Defines the mininum required methods for filectxs""" + __metaclass__ = abc.ABCMeta + + @abc.abstractmethod + def data(self): pass + @abc.abstractmethod + def cmp(self, other): pass + @abc.abstractmethod + def changectx(self): pass + @abc.abstractmethod + def flags(self): pass + @abc.abstractmethod + def path(self): pass + @abc.abstractmethod + def size(self): pass + @abc.abstractmethod + def isbinary(self): pass + @abc.abstractmethod + def islink(self): pass + @abc.abstractmethod + def isexec(self): pass + @abc.abstractmethod + def isabsent(self): pass + @abc.abstractmethod + def write(self, data, flags): pass + @abc.abstractmethod + def setflags(self, l, x): pass + +class basefilectx(abstractfilectx): """A filecontext object represents the common logic for its children: filectx: read-only access to a filerevision that is already present in the repo, @@ -1302,6 +1332,12 @@ return [filectx(self._repo, self._path, fileid=x, filelog=self._filelog) for x in c] + def setflags(self, l, x): + raise error.ProgrammingError("filectx is immutable") + + def write(self, data, flags): + raise error.ProgrammingError("filectx is immutable") + class committablectx(basectx): """A committablectx object provides common functionality for a context that wants the ability to commit, e.g. workingctx or memctx.""" @@ -2408,6 +2444,9 @@ """wraps repo.wwrite""" self._data = data + def setflags(self, l, x): + raise NotImplementedError + class overlayfilectx(committablefilectx): """Like memfilectx but take an original filectx and optional parameters to override parts of it. This is useful when fctx.data() is expensive (i.e. @@ -2577,7 +2616,7 @@ return scmutil.status(modified, added, removed, [], [], [], []) -class arbitraryfilectx(object): +class arbitraryfilectx(abstractfilectx): """Allows you to use filectx-like functions on a file in an arbitrary location on disk, possibly not in the working directory. """ @@ -2597,12 +2636,36 @@ return not filecmp.cmp(self.path(), self._repo.wjoin(fctx.path())) return self.data() != fctx.data() + def changectx(self): + raise error.ProgrammingError("an arbitraryfilectx cannot have a " + "changectx") + + def isabsent(self): + return False + + # TODO deduplicate these from ``basefilectx`` + def isbinary(self): + try: + return util.binary(self.data()) + except IOError: + return False + def isexec(self): + return 'x' in self.flags() + def islink(self): + return 'l' in self.flags() + + def size(self): + return os.stat(self._path).st_size + def path(self): return self._path def flags(self): return '' + def setflags(self, l, x): + raise NotImplementedError + def data(self): return util.readfile(self._path) diff --git a/mercurial/filemerge.py b/mercurial/filemerge.py --- a/mercurial/filemerge.py +++ b/mercurial/filemerge.py @@ -104,6 +104,18 @@ def isabsent(self): return True + def isexec(self): + return False + + def islink(self): + return False + + def setflags(self, l, x): + raise error.ProgrammingError("absentfilectx is immutable") + + def write(self, data, flags): + raise error.ProgrammingError("absentfilectx is immutable") + def _findtool(ui, tool): if tool in internals: return tool