filelog.py
227 lines
| 6.6 KiB
| text/x-python
|
PythonLexer
/ mercurial / filelog.py
mpm@selenic.com
|
r1089 | # filelog.py - file history class for mercurial | ||
# | ||||
Thomas Arendsen Hein
|
r4635 | # Copyright 2005-2007 Matt Mackall <mpm@selenic.com> | ||
mpm@selenic.com
|
r1089 | # | ||
Martin Geisler
|
r8225 | # This software may be used and distributed according to the terms of the | ||
Matt Mackall
|
r10263 | # GNU General Public License version 2 or any later version. | ||
mpm@selenic.com
|
r1089 | |||
Gregory Szorc
|
r25948 | from __future__ import absolute_import | ||
from . import ( | ||||
Gregory Szorc
|
r37515 | error, | ||
Gregory Szorc
|
r37459 | repository, | ||
Gregory Szorc
|
r25948 | revlog, | ||
) | ||||
Gregory Szorc
|
r37828 | from .utils import ( | ||
interfaceutil, | ||||
) | ||||
mpm@selenic.com
|
r1089 | |||
Gregory Szorc
|
r37828 | @interfaceutil.implementer(repository.ifilestorage) | ||
Gregory Szorc
|
r37515 | class filelog(object): | ||
Matt Mackall
|
r4258 | def __init__(self, opener, path): | ||
Gregory Szorc
|
r37515 | self._revlog = revlog.revlog(opener, | ||
'/'.join(('data', path + '.i')), | ||||
censorable=True) | ||||
Matt Harbison
|
r35583 | # full name of the user visible file, relative to the repository root | ||
self.filename = path | ||||
Gregory Szorc
|
r37515 | self.index = self._revlog.index | ||
self.version = self._revlog.version | ||||
self._generaldelta = self._revlog._generaldelta | ||||
def __len__(self): | ||||
return len(self._revlog) | ||||
def __iter__(self): | ||||
return self._revlog.__iter__() | ||||
def revs(self, start=0, stop=None): | ||||
return self._revlog.revs(start=start, stop=stop) | ||||
def parents(self, node): | ||||
return self._revlog.parents(node) | ||||
def parentrevs(self, rev): | ||||
return self._revlog.parentrevs(rev) | ||||
def rev(self, node): | ||||
return self._revlog.rev(node) | ||||
def node(self, rev): | ||||
return self._revlog.node(rev) | ||||
def lookup(self, node): | ||||
return self._revlog.lookup(node) | ||||
def linkrev(self, rev): | ||||
return self._revlog.linkrev(rev) | ||||
def flags(self, rev): | ||||
return self._revlog.flags(rev) | ||||
def commonancestorsheads(self, node1, node2): | ||||
return self._revlog.commonancestorsheads(node1, node2) | ||||
def descendants(self, revs): | ||||
return self._revlog.descendants(revs) | ||||
def headrevs(self): | ||||
return self._revlog.headrevs() | ||||
def heads(self, start=None, stop=None): | ||||
return self._revlog.heads(start, stop) | ||||
def children(self, node): | ||||
return self._revlog.children(node) | ||||
def deltaparent(self, rev): | ||||
return self._revlog.deltaparent(rev) | ||||
def iscensored(self, rev): | ||||
return self._revlog.iscensored(rev) | ||||
def rawsize(self, rev): | ||||
return self._revlog.rawsize(rev) | ||||
def checkhash(self, text, node, p1=None, p2=None, rev=None): | ||||
return self._revlog.checkhash(text, node, p1=p1, p2=p2, rev=rev) | ||||
def revision(self, node, _df=None, raw=False): | ||||
return self._revlog.revision(node, _df=_df, raw=raw) | ||||
def revdiff(self, rev1, rev2): | ||||
return self._revlog.revdiff(rev1, rev2) | ||||
Gregory Szorc
|
r39267 | def emitrevisiondeltas(self, requests): | ||
return self._revlog.emitrevisiondeltas(requests) | ||||
Gregory Szorc
|
r37515 | def addrevision(self, revisiondata, transaction, linkrev, p1, p2, | ||
node=None, flags=revlog.REVIDX_DEFAULT_FLAGS, | ||||
cachedelta=None): | ||||
return self._revlog.addrevision(revisiondata, transaction, linkrev, | ||||
p1, p2, node=node, flags=flags, | ||||
cachedelta=cachedelta) | ||||
def addgroup(self, deltas, linkmapper, transaction, addrevisioncb=None): | ||||
return self._revlog.addgroup(deltas, linkmapper, transaction, | ||||
addrevisioncb=addrevisioncb) | ||||
def getstrippoint(self, minlink): | ||||
return self._revlog.getstrippoint(minlink) | ||||
def strip(self, minlink, transaction): | ||||
return self._revlog.strip(minlink, transaction) | ||||
def files(self): | ||||
return self._revlog.files() | ||||
def checksize(self): | ||||
return self._revlog.checksize() | ||||
mpm@selenic.com
|
r1089 | |||
def read(self, node): | ||||
t = self.revision(node) | ||||
if not t.startswith('\1\n'): | ||||
return t | ||||
Benoit Boissinot
|
r2579 | s = t.index('\1\n', 2) | ||
Matt Mackall
|
r10282 | return t[s + 2:] | ||
mpm@selenic.com
|
r1089 | |||
def add(self, text, meta, transaction, link, p1=None, p2=None): | ||||
if meta or text.startswith('\1\n'): | ||||
Gregory Szorc
|
r37460 | text = revlog.packmeta(meta, text) | ||
mpm@selenic.com
|
r1089 | return self.addrevision(text, transaction, link, p1, p2) | ||
mpm@selenic.com
|
r1116 | def renamed(self, node): | ||
Matt Mackall
|
r7634 | if self.parents(node)[0] != revlog.nullid: | ||
mpm@selenic.com
|
r1116 | return False | ||
Matt Mackall
|
r13240 | t = self.revision(node) | ||
Gregory Szorc
|
r37460 | m = revlog.parsemeta(t)[0] | ||
Gregory Szorc
|
r37854 | # copy and copyrev occur in pairs. In rare cases due to bugs, | ||
# one can occur without the other. | ||||
if m and "copy" in m and "copyrev" in m: | ||||
Matt Mackall
|
r7634 | return (m["copy"], revlog.bin(m["copyrev"])) | ||
mpm@selenic.com
|
r1116 | return False | ||
Matt Mackall
|
r2898 | def size(self, rev): | ||
"""return the size of a given revision""" | ||||
# for revisions with renames, we have to go the slow way | ||||
node = self.node(rev) | ||||
if self.renamed(node): | ||||
return len(self.read(node)) | ||||
Mike Edgar
|
r24118 | if self.iscensored(rev): | ||
Mike Edgar
|
r22597 | return 0 | ||
Matt Mackall
|
r2898 | |||
Nicolas Dumazet
|
r11540 | # XXX if self.read(node).startswith("\1\n"), this returns (size+4) | ||
Gregory Szorc
|
r37515 | return self._revlog.size(rev) | ||
Matt Mackall
|
r2898 | |||
Matt Mackall
|
r2887 | def cmp(self, node, text): | ||
Nicolas Dumazet
|
r11539 | """compare text with a given file revision | ||
returns True if text is different than what is stored. | ||||
""" | ||||
Matt Mackall
|
r2887 | |||
Nicolas Dumazet
|
r11541 | t = text | ||
if text.startswith('\1\n'): | ||||
t = '\1\n\1\n' + text | ||||
Gregory Szorc
|
r37515 | samehashes = not self._revlog.cmp(node, t) | ||
Nicolas Dumazet
|
r11541 | if samehashes: | ||
return False | ||||
Mike Edgar
|
r22597 | # censored files compare against the empty file | ||
Mike Edgar
|
r24118 | if self.iscensored(self.rev(node)): | ||
Mike Edgar
|
r22597 | return text != '' | ||
Nicolas Dumazet
|
r11541 | # renaming a file produces a different hash, even if the data | ||
# remains unchanged. Check if it's the case (slow): | ||||
if self.renamed(node): | ||||
Matt Mackall
|
r2887 | t2 = self.read(node) | ||
Matt Mackall
|
r2895 | return t2 != text | ||
Matt Mackall
|
r2887 | |||
Nicolas Dumazet
|
r11541 | return True | ||
Gregory Szorc
|
r37515 | |||
@property | ||||
def filename(self): | ||||
return self._revlog.filename | ||||
@filename.setter | ||||
def filename(self, value): | ||||
self._revlog.filename = value | ||||
# TODO these aren't part of the interface and aren't internal methods. | ||||
# Callers should be fixed to not use them. | ||||
@property | ||||
def indexfile(self): | ||||
return self._revlog.indexfile | ||||
@indexfile.setter | ||||
def indexfile(self, value): | ||||
self._revlog.indexfile = value | ||||
@property | ||||
def datafile(self): | ||||
return self._revlog.datafile | ||||
@property | ||||
def opener(self): | ||||
return self._revlog.opener | ||||
def clone(self, tr, destrevlog, **kwargs): | ||||
if not isinstance(destrevlog, filelog): | ||||
raise error.ProgrammingError('expected filelog to clone()') | ||||
return self._revlog.clone(tr, destrevlog._revlog, **kwargs) | ||||
def start(self, rev): | ||||
return self._revlog.start(rev) | ||||
def end(self, rev): | ||||
return self._revlog.end(rev) | ||||
def length(self, rev): | ||||
return self._revlog.length(rev) | ||||
def compress(self, data): | ||||
return self._revlog.compress(data) | ||||
def _addrevision(self, *args, **kwargs): | ||||
return self._revlog._addrevision(*args, **kwargs) | ||||