##// END OF EJS Templates
storageutil: move metadata parsing and packing from revlog (API)...
Gregory Szorc -
r39914:3e896b51 default
parent child Browse files
Show More
@@ -20,6 +20,7 b' from mercurial import ('
20 )
20 )
21
21
22 from mercurial.utils import (
22 from mercurial.utils import (
23 storageutil,
23 stringutil,
24 stringutil,
24 )
25 )
25
26
@@ -76,13 +77,13 b' def readfromstore(self, text):'
76 name = k[len('x-hg-'):]
77 name = k[len('x-hg-'):]
77 hgmeta[name] = p[k]
78 hgmeta[name] = p[k]
78 if hgmeta or text.startswith('\1\n'):
79 if hgmeta or text.startswith('\1\n'):
79 text = revlog.packmeta(hgmeta, text)
80 text = storageutil.packmeta(hgmeta, text)
80
81
81 return (text, True)
82 return (text, True)
82
83
83 def writetostore(self, text):
84 def writetostore(self, text):
84 # hg filelog metadata (includes rename, etc)
85 # hg filelog metadata (includes rename, etc)
85 hgmeta, offset = revlog.parsemeta(text)
86 hgmeta, offset = storageutil.parsemeta(text)
86 if offset and offset > 0:
87 if offset and offset > 0:
87 # lfs blob does not contain hg filelog metadata
88 # lfs blob does not contain hg filelog metadata
88 text = text[offset:]
89 text = text[offset:]
@@ -132,7 +133,7 b' def filelogaddrevision(orig, self, text,'
132 if lfstrack:
133 if lfstrack:
133 textlen = len(text)
134 textlen = len(text)
134 # exclude hg rename meta from file size
135 # exclude hg rename meta from file size
135 meta, offset = revlog.parsemeta(text)
136 meta, offset = storageutil.parsemeta(text)
136 if offset:
137 if offset:
137 textlen -= offset
138 textlen -= offset
138
139
@@ -14,6 +14,7 b' from . import ('
14 )
14 )
15 from .utils import (
15 from .utils import (
16 interfaceutil,
16 interfaceutil,
17 storageutil,
17 )
18 )
18
19
19 @interfaceutil.implementer(repository.ifilestorage)
20 @interfaceutil.implementer(repository.ifilestorage)
@@ -120,14 +121,14 b' class filelog(object):'
120
121
121 def add(self, text, meta, transaction, link, p1=None, p2=None):
122 def add(self, text, meta, transaction, link, p1=None, p2=None):
122 if meta or text.startswith('\1\n'):
123 if meta or text.startswith('\1\n'):
123 text = revlog.packmeta(meta, text)
124 text = storageutil.packmeta(meta, text)
124 return self.addrevision(text, transaction, link, p1, p2)
125 return self.addrevision(text, transaction, link, p1, p2)
125
126
126 def renamed(self, node):
127 def renamed(self, node):
127 if self.parents(node)[0] != revlog.nullid:
128 if self.parents(node)[0] != revlog.nullid:
128 return False
129 return False
129 t = self.revision(node)
130 t = self.revision(node)
130 m = revlog.parsemeta(t)[0]
131 m = storageutil.parsemeta(t)[0]
131 # copy and copyrev occur in pairs. In rare cases due to bugs,
132 # copy and copyrev occur in pairs. In rare cases due to bugs,
132 # one can occur without the other.
133 # one can occur without the other.
133 if m and "copy" in m and "copyrev" in m:
134 if m and "copy" in m and "copyrev" in m:
@@ -17,7 +17,6 b' import collections'
17 import contextlib
17 import contextlib
18 import errno
18 import errno
19 import os
19 import os
20 import re
21 import struct
20 import struct
22 import zlib
21 import zlib
23
22
@@ -127,27 +126,8 b' ellipsisprocessor = ('
127 ellipsisrawprocessor,
126 ellipsisrawprocessor,
128 )
127 )
129
128
130 _mdre = re.compile('\1\n')
131 def parsemeta(text):
132 """return (metadatadict, metadatasize)"""
133 # text can be buffer, so we can't use .startswith or .index
134 if text[:2] != '\1\n':
135 return None, None
136 s = _mdre.search(text, 2).start()
137 mtext = text[2:s]
138 meta = {}
139 for l in mtext.splitlines():
140 k, v = l.split(": ", 1)
141 meta[k] = v
142 return meta, (s + 2)
143
144 def packmeta(meta, text):
145 keys = sorted(meta)
146 metatext = "".join("%s: %s\n" % (k, meta[k]) for k in keys)
147 return "\1\n%s\1\n%s" % (metatext, text)
148
149 def _censoredtext(text):
129 def _censoredtext(text):
150 m, offs = parsemeta(text)
130 m, offs = storageutil.parsemeta(text)
151 return m and "censored" in m
131 return m and "censored" in m
152
132
153 def addflagprocessor(flag, processor):
133 def addflagprocessor(flag, processor):
@@ -2516,7 +2496,7 b' class revlog(object):'
2516 self.version)
2496 self.version)
2517
2497
2518 rev = self.rev(node)
2498 rev = self.rev(node)
2519 tombstone = packmeta({b'censored': tombstone}, b'')
2499 tombstone = storageutil.packmeta({b'censored': tombstone}, b'')
2520
2500
2521 if len(tombstone) > self.rawsize(rev):
2501 if len(tombstone) > self.rawsize(rev):
2522 raise error.Abort(_('censor tombstone must be no longer than '
2502 raise error.Abort(_('censor tombstone must be no longer than '
@@ -19,6 +19,9 b' from .. import ('
19 mdiff,
19 mdiff,
20 revlog,
20 revlog,
21 )
21 )
22 from ..utils import (
23 storageutil,
24 )
22
25
23 class basetestcase(unittest.TestCase):
26 class basetestcase(unittest.TestCase):
24 if not getattr(unittest.TestCase, r'assertRaisesRegex', False):
27 if not getattr(unittest.TestCase, r'assertRaisesRegex', False):
@@ -882,7 +885,7 b' class ifiledatatests(basetestcase):'
882 def testcensored(self):
885 def testcensored(self):
883 f = self._makefilefn()
886 f = self._makefilefn()
884
887
885 stored1 = revlog.packmeta({
888 stored1 = storageutil.packmeta({
886 b'censored': b'tombstone',
889 b'censored': b'tombstone',
887 }, b'')
890 }, b'')
888
891
@@ -8,6 +8,7 b''
8 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import hashlib
10 import hashlib
11 import re
11
12
12 from ..node import (
13 from ..node import (
13 nullid,
14 nullid,
@@ -39,3 +40,28 b' def hashrevisionsha1(text, p1, p2):'
39 s.update(b)
40 s.update(b)
40 s.update(text)
41 s.update(text)
41 return s.digest()
42 return s.digest()
43
44 METADATA_RE = re.compile(b'\x01\n')
45
46 def parsemeta(text):
47 """Parse metadata header from revision data.
48
49 Returns a 2-tuple of (metadata, offset), where both can be None if there
50 is no metadata.
51 """
52 # text can be buffer, so we can't use .startswith or .index
53 if text[:2] != b'\x01\n':
54 return None, None
55 s = METADATA_RE.search(text, 2).start()
56 mtext = text[2:s]
57 meta = {}
58 for l in mtext.splitlines():
59 k, v = l.split(b': ', 1)
60 meta[k] = v
61 return meta, s + 2
62
63 def packmeta(meta, text):
64 """Add metadata to fulltext to produce revision text."""
65 keys = sorted(meta)
66 metatext = b''.join(b'%s: %s\n' % (k, meta[k]) for k in keys)
67 return b'\x01\n%s\x01\n%s' % (metatext, text)
@@ -326,7 +326,7 b' class filestorage(object):'
326 return False
326 return False
327
327
328 fulltext = self.revision(node)
328 fulltext = self.revision(node)
329 m = revlog.parsemeta(fulltext)[0]
329 m = storageutil.parsemeta(fulltext)[0]
330
330
331 if m and 'copy' in m:
331 if m and 'copy' in m:
332 return m['copy'], bin(m['copyrev'])
332 return m['copy'], bin(m['copyrev'])
@@ -411,7 +411,7 b' class filestorage(object):'
411
411
412 def add(self, text, meta, transaction, linkrev, p1, p2):
412 def add(self, text, meta, transaction, linkrev, p1, p2):
413 if meta or text.startswith(b'\1\n'):
413 if meta or text.startswith(b'\1\n'):
414 text = revlog.packmeta(meta, text)
414 text = storageutil.packmeta(meta, text)
415
415
416 return self.addrevision(text, transaction, linkrev, p1, p2)
416 return self.addrevision(text, transaction, linkrev, p1, p2)
417
417
General Comments 0
You need to be logged in to leave comments. Login now