diff --git a/hgext/lfs/wrapper.py b/hgext/lfs/wrapper.py --- a/hgext/lfs/wrapper.py +++ b/hgext/lfs/wrapper.py @@ -20,6 +20,7 @@ ) from mercurial.utils import ( + storageutil, stringutil, ) @@ -76,13 +77,13 @@ name = k[len('x-hg-'):] hgmeta[name] = p[k] if hgmeta or text.startswith('\1\n'): - text = revlog.packmeta(hgmeta, text) + text = storageutil.packmeta(hgmeta, text) return (text, True) def writetostore(self, text): # hg filelog metadata (includes rename, etc) - hgmeta, offset = revlog.parsemeta(text) + hgmeta, offset = storageutil.parsemeta(text) if offset and offset > 0: # lfs blob does not contain hg filelog metadata text = text[offset:] @@ -132,7 +133,7 @@ if lfstrack: textlen = len(text) # exclude hg rename meta from file size - meta, offset = revlog.parsemeta(text) + meta, offset = storageutil.parsemeta(text) if offset: textlen -= offset diff --git a/mercurial/filelog.py b/mercurial/filelog.py --- a/mercurial/filelog.py +++ b/mercurial/filelog.py @@ -14,6 +14,7 @@ ) from .utils import ( interfaceutil, + storageutil, ) @interfaceutil.implementer(repository.ifilestorage) @@ -120,14 +121,14 @@ def add(self, text, meta, transaction, link, p1=None, p2=None): if meta or text.startswith('\1\n'): - text = revlog.packmeta(meta, text) + text = storageutil.packmeta(meta, text) return self.addrevision(text, transaction, link, p1, p2) def renamed(self, node): if self.parents(node)[0] != revlog.nullid: return False t = self.revision(node) - m = revlog.parsemeta(t)[0] + m = storageutil.parsemeta(t)[0] # 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: diff --git a/mercurial/revlog.py b/mercurial/revlog.py --- a/mercurial/revlog.py +++ b/mercurial/revlog.py @@ -17,7 +17,6 @@ import contextlib import errno import os -import re import struct import zlib @@ -127,27 +126,8 @@ ellipsisrawprocessor, ) -_mdre = re.compile('\1\n') -def parsemeta(text): - """return (metadatadict, metadatasize)""" - # text can be buffer, so we can't use .startswith or .index - if text[:2] != '\1\n': - return None, None - s = _mdre.search(text, 2).start() - mtext = text[2:s] - meta = {} - for l in mtext.splitlines(): - k, v = l.split(": ", 1) - meta[k] = v - return meta, (s + 2) - -def packmeta(meta, text): - keys = sorted(meta) - metatext = "".join("%s: %s\n" % (k, meta[k]) for k in keys) - return "\1\n%s\1\n%s" % (metatext, text) - def _censoredtext(text): - m, offs = parsemeta(text) + m, offs = storageutil.parsemeta(text) return m and "censored" in m def addflagprocessor(flag, processor): @@ -2516,7 +2496,7 @@ self.version) rev = self.rev(node) - tombstone = packmeta({b'censored': tombstone}, b'') + tombstone = storageutil.packmeta({b'censored': tombstone}, b'') if len(tombstone) > self.rawsize(rev): raise error.Abort(_('censor tombstone must be no longer than ' diff --git a/mercurial/testing/storage.py b/mercurial/testing/storage.py --- a/mercurial/testing/storage.py +++ b/mercurial/testing/storage.py @@ -19,6 +19,9 @@ mdiff, revlog, ) +from ..utils import ( + storageutil, +) class basetestcase(unittest.TestCase): if not getattr(unittest.TestCase, r'assertRaisesRegex', False): @@ -880,7 +883,7 @@ def testcensored(self): f = self._makefilefn() - stored1 = revlog.packmeta({ + stored1 = storageutil.packmeta({ b'censored': b'tombstone', }, b'') diff --git a/mercurial/utils/storageutil.py b/mercurial/utils/storageutil.py --- a/mercurial/utils/storageutil.py +++ b/mercurial/utils/storageutil.py @@ -8,6 +8,7 @@ from __future__ import absolute_import import hashlib +import re from ..node import ( nullid, @@ -39,3 +40,28 @@ s.update(b) s.update(text) return s.digest() + +METADATA_RE = re.compile(b'\x01\n') + +def parsemeta(text): + """Parse metadata header from revision data. + + Returns a 2-tuple of (metadata, offset), where both can be None if there + is no metadata. + """ + # text can be buffer, so we can't use .startswith or .index + if text[:2] != b'\x01\n': + return None, None + s = METADATA_RE.search(text, 2).start() + mtext = text[2:s] + meta = {} + for l in mtext.splitlines(): + k, v = l.split(b': ', 1) + meta[k] = v + return meta, s + 2 + +def packmeta(meta, text): + """Add metadata to fulltext to produce revision text.""" + keys = sorted(meta) + metatext = b''.join(b'%s: %s\n' % (k, meta[k]) for k in keys) + return b'\x01\n%s\x01\n%s' % (metatext, text) diff --git a/tests/simplestorerepo.py b/tests/simplestorerepo.py --- a/tests/simplestorerepo.py +++ b/tests/simplestorerepo.py @@ -326,7 +326,7 @@ return False fulltext = self.revision(node) - m = revlog.parsemeta(fulltext)[0] + m = storageutil.parsemeta(fulltext)[0] if m and 'copy' in m: return m['copy'], bin(m['copyrev']) @@ -411,7 +411,7 @@ def add(self, text, meta, transaction, linkrev, p1, p2): if meta or text.startswith(b'\1\n'): - text = revlog.packmeta(meta, text) + text = storageutil.packmeta(meta, text) return self.addrevision(text, transaction, linkrev, p1, p2)